/**
  * Run a test case.
  *
  * @param   unittest.TestCase test
  * @param   unittest.TestResult result
  * @return  void
  * @throws  lang.MethodNotImplementedException
  */
 protected function runInternal($test, $result)
 {
     $class = $test->getClass();
     $method = $class->getMethod($test->name);
     $this->notifyListeners('testStarted', [$test]);
     // Check for @ignore
     if ($method->hasAnnotation('ignore')) {
         $this->notifyListeners('testNotRun', [$result->set($test, new TestNotRun($test, new IgnoredBecause($method->getAnnotation('ignore'))))]);
         return;
     }
     // Check for @expect
     $expected = null;
     if ($method->hasAnnotation('expect', 'class')) {
         $message = $method->getAnnotation('expect', 'withMessage');
         if ('' === $message || '/' === $message[0]) {
             $pattern = $message;
         } else {
             $pattern = '/' . preg_quote($message, '/') . '/';
         }
         $expected = [XPClass::forName($method->getAnnotation('expect', 'class')), $pattern];
     } else {
         if ($method->hasAnnotation('expect')) {
             $expected = [XPClass::forName($method->getAnnotation('expect')), null];
         }
     }
     // Check for @limit
     $eta = 0;
     if ($method->hasAnnotation('limit')) {
         $eta = $method->getAnnotation('limit', 'time');
     }
     // Check for @values
     if ($method->hasAnnotation('values')) {
         $annotation = $method->getAnnotation('values');
         $variation = true;
         $values = $this->valuesFor($test, $annotation);
     } else {
         $variation = false;
         $values = [[]];
     }
     // Check for @actions
     $actions = array_merge($this->actionsFor($class, 'unittest.TestAction'), $this->actionsFor($method, 'unittest.TestAction'));
     $timer = new Timer();
     $report = function ($type, $outcome, $arg) use($result, $timer, &$t) {
         $timer->stop();
         $this->notifyListeners($type, [$result->set($t, new $outcome($t, $arg, $timer->elapsedTime()))]);
         \xp::gc();
     };
     \xp::gc();
     foreach ($values as $args) {
         $t = $variation ? new TestVariation($test, $args) : $test;
         $timer->start();
         $tearDown = function ($test, $error) {
             return $error;
         };
         try {
             // Before and after tests
             foreach ($actions as $action) {
                 $this->invoke([$action, 'beforeTest'], $test);
                 $tearDown = function ($test, $error) use($tearDown, $action) {
                     $propagated = $tearDown($test, $error);
                     try {
                         $this->invoke([$action, 'afterTest'], $test);
                         return $propagated;
                     } catch (Throwable $t) {
                         $propagated && $t->setCause($propagated);
                         return $t;
                     }
                 };
             }
             // Setup and teardown
             $this->invoke([$test, 'setUp'], $test);
             $tearDown = function ($test, $error) use($tearDown) {
                 try {
                     $this->invoke([$test, 'tearDown'], null);
                     return $tearDown($test, $error);
                 } catch (Throwable $t) {
                     $error && $t->setCause($error);
                     return $tearDown($test, $t);
                 }
             };
             // Run test
             $method->invoke($test, is_array($args) ? $args : [$args]);
             $e = $tearDown($test, null);
         } catch (TargetInvocationException $invoke) {
             $e = $tearDown($test, $invoke->getCause());
         } catch (PrerequisitesNotMetError $skipped) {
             $tearDown($test, $skipped);
             $report('testSkipped', TestPrerequisitesNotMet::class, $skipped);
             continue;
         } catch (AssertionFailedError $failed) {
             $tearDown($test, $failed);
             $report('testFailed', TestAssertionFailed::class, $failed);
             continue;
         } catch (Throwable $error) {
             $tearDown($test, $error);
             $report('testError', TestError::class, $error);
             continue;
         }
         $timer->stop();
         if ($e) {
             if ($expected && $expected[0]->isInstance($e)) {
                 if ($eta && $timer->elapsedTime() > $eta) {
                     $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Test runtime of %.3f seconds longer than eta of %.3f seconds', [$timer->elapsedTime(), $eta])));
                 } else {
                     if ($expected[1] && !preg_match($expected[1], $e->getMessage())) {
                         $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Expected %s\'s message "%s" differs from expected %s', [nameof($e), $e->getMessage(), $expected[1]])));
                     } else {
                         if (sizeof(\xp::$errors) > 0) {
                             $report('testWarning', TestWarning::class, $this->formatErrors(\xp::$errors));
                         } else {
                             $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]);
                         }
                     }
                 }
             } else {
                 if ($expected && !$expected[0]->isInstance($e)) {
                     $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Caught %s instead of expected %s', [$e->compoundMessage(), $expected[0]->getName()])));
                 } else {
                     if ($e instanceof AssertionFailedError) {
                         $report('testFailed', TestAssertionFailed::class, $e);
                     } else {
                         if ($e instanceof PrerequisitesNotMetError) {
                             $report('testSkipped', TestPrerequisitesNotMet::class, $e);
                         } else {
                             if ($e instanceof IgnoredBecause) {
                                 $report('testSkipped', TestNotRun::class, $e);
                             } else {
                                 $report('testError', TestError::class, $e);
                             }
                         }
                     }
                 }
             }
         } else {
             if ($expected) {
                 $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Expected %s not caught', [$expected[0]->getName()])));
             } else {
                 if (sizeof(\xp::$errors) > 0) {
                     $report('testWarning', TestWarning::class, $this->formatErrors(\xp::$errors));
                 } else {
                     if ($eta && $timer->elapsedTime() > $eta) {
                         $report('testFailed', TestAssertionFailed::class, new AssertionFailedError(new FormattedMessage('Test runtime of %.3f seconds longer than eta of %.3f seconds', [$timer->elapsedTime(), $eta])));
                     } else {
                         $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]);
                     }
                 }
             }
         }
     }
 }
Example #2
0
 /**
  * Run a test case.
  *
  * @param   unittest.TestCase test
  * @param   unittest.TestResult result
  * @throws  lang.MethodNotImplementedException
  */
 protected function runInternal($test, $result)
 {
     $class = $test->getClass();
     $method = $class->getMethod($test->name);
     $this->notifyListeners('testStarted', [$test]);
     // Check for @ignore
     if ($method->hasAnnotation('ignore')) {
         $this->notifyListeners('testNotRun', [$result->set($test, new TestNotRun($test, $method->getAnnotation('ignore')))]);
         return;
     }
     // Check for @expect
     $expected = null;
     if ($method->hasAnnotation('expect', 'class')) {
         $message = $method->getAnnotation('expect', 'withMessage');
         if ('/' === $message[0]) {
             $pattern = $message;
         } else {
             $pattern = '/' . preg_quote($message, '/') . '/';
         }
         $expected = [XPClass::forName($method->getAnnotation('expect', 'class')), $pattern];
     } else {
         if ($method->hasAnnotation('expect')) {
             $expected = [XPClass::forName($method->getAnnotation('expect')), null];
         }
     }
     // Check for @limit
     $eta = 0;
     if ($method->hasAnnotation('limit')) {
         $eta = $method->getAnnotation('limit', 'time');
     }
     // Check for @values
     if ($method->hasAnnotation('values')) {
         $annotation = $method->getAnnotation('values');
         $variation = true;
         $values = $this->valuesFor($test, $annotation);
     } else {
         $variation = false;
         $values = [[]];
     }
     // Check for @actions, initialize setUp and tearDown call chains
     $actions = array_merge($this->actionsFor($class, 'unittest.TestAction'), $this->actionsFor($method, 'unittest.TestAction'));
     $setUp = function ($test) use($actions) {
         foreach ($actions as $action) {
             $action->beforeTest($test);
         }
         $test->setUp();
     };
     $tearDown = function ($test) use($actions) {
         $test->tearDown();
         $raised = null;
         foreach ($actions as $action) {
             try {
                 $action->afterTest($test);
             } catch (Throwable $e) {
                 $e->setCause($raised);
                 $raised = $e;
             }
         }
         if ($raised) {
             throw $raised;
         }
     };
     $timer = new Timer();
     foreach ($values as $args) {
         $t = $variation ? new TestVariation($test, $args) : $test;
         \xp::gc();
         $timer->start();
         // Setup test
         try {
             $setUp($test);
         } catch (PrerequisitesNotMetError $e) {
             $timer->stop();
             $this->notifyListeners('testSkipped', [$result->setSkipped($t, $e, $timer->elapsedTime())]);
             \xp::gc();
             continue;
         } catch (AssertionFailedError $e) {
             $timer->stop();
             $this->notifyListeners('testFailed', [$result->setFailed($t, $e, $timer->elapsedTime())]);
             \xp::gc();
             continue;
         } catch (Throwable $x) {
             $timer->stop();
             $this->notifyListeners('testFailed', [$result->set($t, new TestError($t, $x, $timer->elapsedTime()))]);
             \xp::gc();
             continue;
         }
         // Run test
         $e = null;
         try {
             $method->invoke($test, is_array($args) ? $args : [$args]);
             $tearDown($test);
         } catch (TargetInvocationException $x) {
             $tearDown($test);
             $e = $x->getCause();
         } catch (Throwable $e) {
             // Exception inside teardown
         }
         $timer->stop();
         if ($e) {
             if ($expected && $expected[0]->isInstance($e)) {
                 if ($eta && $timer->elapsedTime() > $eta) {
                     $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Test runtime of %.3f seconds longer than eta of %.3f seconds', [$timer->elapsedTime(), $eta])), $timer->elapsedTime())]);
                 } else {
                     if ($expected[1] && !preg_match($expected[1], $e->getMessage())) {
                         $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Expected %s\'s message "%s" differs from expected %s', [nameof($e), $e->getMessage(), $expected[1]])), $timer->elapsedTime())]);
                     } else {
                         if (sizeof(\xp::$errors) > 0) {
                             $this->notifyListeners('testWarning', [$result->set($t, new TestWarning($t, $this->formatErrors(\xp::$errors), $timer->elapsedTime()))]);
                         } else {
                             $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]);
                         }
                     }
                 }
             } else {
                 if ($expected && !$expected[0]->isInstance($e)) {
                     $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Caught %s instead of expected %s', [$e->compoundMessage(), $expected[0]->getName()])), $timer->elapsedTime())]);
                 } else {
                     if ($e instanceof AssertionFailedError) {
                         $this->notifyListeners('testFailed', [$result->setFailed($t, $e, $timer->elapsedTime())]);
                     } else {
                         if ($e instanceof PrerequisitesNotMetError) {
                             $this->notifyListeners('testSkipped', [$result->setSkipped($t, $e, $timer->elapsedTime())]);
                         } else {
                             $this->notifyListeners('testError', [$result->set($t, new TestError($t, $e, $timer->elapsedTime()))]);
                         }
                     }
                 }
             }
             \xp::gc();
             continue;
         } else {
             if ($expected) {
                 $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError(new FormattedMessage('Expected %s not caught', [$expected[0]->getName()])), $timer->elapsedTime())]);
             } else {
                 if (sizeof(\xp::$errors) > 0) {
                     $this->notifyListeners('testWarning', [$result->set($t, new TestWarning($t, $this->formatErrors(\xp::$errors), $timer->elapsedTime()))]);
                 } else {
                     if ($eta && $timer->elapsedTime() > $eta) {
                         $this->notifyListeners('testFailed', [$result->setFailed($t, new AssertionFailedError('Timeout', sprintf('%.3f', $timer->elapsedTime()), sprintf('%.3f', $eta)), $timer->elapsedTime())]);
                     } else {
                         $this->notifyListeners('testSucceeded', [$result->setSucceeded($t, $timer->elapsedTime())]);
                     }
                 }
             }
         }
         \xp::gc();
     }
 }
 public function notCallable()
 {
     Timer::measure('@not-callable@');
 }
Example #4
0
 public function not_callable_argument_passed_to_measure_7()
 {
     Timer::measure('@not-callable@');
 }