summaryrefslogtreecommitdiff
path: root/sapi/phpdbg/tests
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/phpdbg/tests')
-rw-r--r--sapi/phpdbg/tests/commands/0001_basic.test8
-rw-r--r--sapi/phpdbg/tests/commands/0002_set.test21
-rw-r--r--sapi/phpdbg/tests/commands/0101_info.test19
-rw-r--r--sapi/phpdbg/tests/commands/0102_print.test28
-rw-r--r--sapi/phpdbg/tests/commands/0103_register.test28
-rw-r--r--sapi/phpdbg/tests/commands/0104_clean.test15
-rw-r--r--sapi/phpdbg/tests/commands/0105_clear.test18
-rw-r--r--sapi/phpdbg/tests/commands/0106_compile.test18
-rw-r--r--sapi/phpdbg/tests/run-tests.php597
9 files changed, 752 insertions, 0 deletions
diff --git a/sapi/phpdbg/tests/commands/0001_basic.test b/sapi/phpdbg/tests/commands/0001_basic.test
new file mode 100644
index 0000000000..08aa9ab664
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0001_basic.test
@@ -0,0 +1,8 @@
+#######################################################
+# name: basic
+# purpose: check basic functionality of phpdbg console
+# expect: TEST::EXACT
+# options: -rr
+#######################################################
+# [Nothing to execute!]
+#######################################################
diff --git a/sapi/phpdbg/tests/commands/0002_set.test b/sapi/phpdbg/tests/commands/0002_set.test
new file mode 100644
index 0000000000..468ac6d9ea
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0002_set.test
@@ -0,0 +1,21 @@
+#################################################
+# name: set
+# purpose: tests for set commands
+# expect: TEST::CISTRING
+# options: -rr
+#################################################
+# setting prompt color
+# setting error color
+# setting notice color
+# Failed to find breakpoint #0
+# oplog disabled
+# opened oplog test.log
+# nothing
+#################################################
+set color prompt none
+set color error none
+set color notice none
+set prompt promot>
+set break 0
+set oplog
+set oplog test.log
diff --git a/sapi/phpdbg/tests/commands/0101_info.test b/sapi/phpdbg/tests/commands/0101_info.test
new file mode 100644
index 0000000000..397a45c992
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0101_info.test
@@ -0,0 +1,19 @@
+#################################################
+# name: info
+# purpose: test info commands
+# expect: TEST::FORMAT
+# options: -rr
+#################################################
+#[User Classes (%d)]
+#User Class test (3)
+#|---- in phpdbginit code on line %d
+#################################################
+<:
+class test {
+ public function testMethod(){}
+ private function testPrivateMethod(){}
+ protected function testProtectedMethod(){}
+}
+:>
+info classes
+q
diff --git a/sapi/phpdbg/tests/commands/0102_print.test b/sapi/phpdbg/tests/commands/0102_print.test
new file mode 100644
index 0000000000..de4acb7651
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0102_print.test
@@ -0,0 +1,28 @@
+#################################################
+# name: print
+# purpose: test print commands
+# expect: TEST::FORMAT
+# options: -rr
+#################################################
+#[User Class: test]
+#Methods (3):
+#L%d-%d test::testMethod() %s
+# L%d %s ZEND_RETURN C%d <unused> <unused>
+# L%d-%d test::testPrivateMethod() %s
+# L%d %s ZEND_RETURN C%d <unused> <unused>
+# L%d-%d test::testProtectedMethod() %s
+# L%d %s ZEND_RETURN C%d <unused> <unused>
+#[User Method testMethod]
+# L%d-%d test::testMethod() %s
+# L%d %s ZEND_RETURN C%d <unused> <unused>
+#################################################
+<:
+class test {
+ public function testMethod(){}
+ private function testPrivateMethod(){}
+ protected function testProtectedMethod(){}
+}
+:>
+print class test
+print method test::testMethod
+q
diff --git a/sapi/phpdbg/tests/commands/0103_register.test b/sapi/phpdbg/tests/commands/0103_register.test
new file mode 100644
index 0000000000..703a12f771
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0103_register.test
@@ -0,0 +1,28 @@
+#################################################
+# name: register
+# purpose: test registration functions
+# expect: TEST::FORMAT
+# options: -rr
+#################################################
+#[Registered test_function]
+#array(5) {
+# [0]=>
+# int(1)
+# [1]=>
+# int(2)
+# [2]=>
+# int(3)
+# [3]=>
+# int(4)
+# [4]=>
+# int(5)
+#}
+#################################################
+<:
+function test_function() {
+ var_dump(func_get_args());
+}
+:>
+R test_function
+test_function 1 2 3 4 5
+q
diff --git a/sapi/phpdbg/tests/commands/0104_clean.test b/sapi/phpdbg/tests/commands/0104_clean.test
new file mode 100644
index 0000000000..c7a579be17
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0104_clean.test
@@ -0,0 +1,15 @@
+#################################################
+# name: clean
+# purpose: test cleaning environment
+# expect: TEST::FORMAT
+# options: -rr
+#################################################
+#[Cleaning Execution Environment]
+#Classes %d
+#Functions %d
+#Constants %d
+#Includes %d
+#[Nothing to execute!]
+#################################################
+clean
+quit
diff --git a/sapi/phpdbg/tests/commands/0105_clear.test b/sapi/phpdbg/tests/commands/0105_clear.test
new file mode 100644
index 0000000000..b547b0d6ba
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0105_clear.test
@@ -0,0 +1,18 @@
+#################################################
+# name: clear
+# purpose: test clearing breakpoints
+# expect: TEST::FORMAT
+# options: -rr
+#################################################
+#[Clearing Breakpoints]
+#File%w%d
+#Functions%w%d
+#Methods%w%d
+#Oplines%w%d
+#File oplines%w%d
+#Function oplines%w%d
+#Method oplines%w%d
+#Conditionals%w%d
+#################################################
+clear
+quit
diff --git a/sapi/phpdbg/tests/commands/0106_compile.test b/sapi/phpdbg/tests/commands/0106_compile.test
new file mode 100644
index 0000000000..7193600ea3
--- /dev/null
+++ b/sapi/phpdbg/tests/commands/0106_compile.test
@@ -0,0 +1,18 @@
+#################################################
+# name: compile
+# purpose: test compiling code
+# expect: TEST::FORMAT
+# options: -rr
+#################################################
+#[Attempting compilation of %s]
+#[Success]
+#Hello World
+#################################################
+<:
+define('OUT',
+ tempnam(null, "phpdbg"));
+file_put_contents(OUT, "<?php echo \"Hello World\"; ?>");
+phpdbg_exec(OUT);
+:>
+run
+quit
diff --git a/sapi/phpdbg/tests/run-tests.php b/sapi/phpdbg/tests/run-tests.php
new file mode 100644
index 0000000000..1cc31d815e
--- /dev/null
+++ b/sapi/phpdbg/tests/run-tests.php
@@ -0,0 +1,597 @@
+<?php
+namespace phpdbg\testing {
+
+ /*
+ * Workaround ...
+ */
+ if (!defined('DIR_SEP'))
+ define('DIR_SEP', '\\' . DIRECTORY_SEPARATOR);
+
+ /**
+ * TestConfigurationExceptions are thrown
+ * when the configuration prohibits tests executing
+ *
+ * @package phpdbg
+ * @subpackage testing
+ */
+ class TestConfigurationException extends \Exception {
+
+ /**
+ *
+ * @param array Tests confguration
+ * @param message Exception message
+ * @param ... formatting parameters
+ */
+ public function __construct() {
+ $argv = func_get_args();
+
+ if (count($argv)) {
+
+ $this->config = array_shift($argv);
+ $this->message = vsprintf(
+ array_shift($argv), $argv);
+ }
+ }
+ }
+
+ /**
+ *
+ * @package phpdbg
+ * @subpackage testing
+ */
+ class TestsConfiguration implements \ArrayAccess {
+
+ /**
+ *
+ * @param array basic configuration
+ * @param array argv
+ */
+ public function __construct($config, $cmd) {
+ $this->options = $config;
+ while (($key = array_shift($cmd))) {
+ switch (substr($key, 0, 1)) {
+ case '-': switch(substr($key, 1, 1)) {
+ case '-': {
+ $arg = substr($key, 2);
+ if (($e=strpos($arg, '=')) !== false) {
+ $key = substr($arg, 0, $e);
+ $value = substr($arg, $e+1);
+ } else {
+ $key = $arg;
+ $value = array_shift($cmd);
+ }
+
+ if (isset($key) && isset($value)) {
+ switch ($key) {
+ case 'phpdbg':
+ case 'width':
+ $this->options[$key] = $value;
+ break;
+
+ default: {
+ if (isset($config[$key])) {
+ if (is_array($config[$key])) {
+ $this->options[$key][] = $value;
+ } else {
+ $this->options[$key] = array($config[$key], $value);
+ }
+ } else {
+ $this->options[$key] = $value;
+ }
+ }
+ }
+
+ }
+ } break;
+
+ default:
+ $this->flags[] = substr($key, 1);
+ } break;
+ }
+ }
+
+ if (!is_executable($this->options['phpdbg'])) {
+ throw new TestConfigurationException(
+ $this->options, 'phpdbg could not be found at the specified path (%s)', $this->options['phpdbg']);
+ } else $this->options['phpdbg'] = realpath($this->options['phpdbg']);
+
+ $this->options['width'] = (integer) $this->options['width'];
+
+ /* display properly, all the time */
+ if ($this->options['width'] < 50) {
+ $this->options['width'] = 50;
+ }
+
+ /* calculate column widths */
+ $this->options['lwidth'] = ceil($this->options['width'] / 3);
+ $this->options['rwidth'] = ceil($this->options['width'] - $this->options['lwidth']) - 5;
+ }
+
+ public function hasFlag($flag) {
+ return in_array(
+ $flag, $this->flags);
+ }
+
+ public function offsetExists($offset) { return isset($this->options[$offset]); }
+ public function offsetGet($offset) { return $this->options[$offset]; }
+ public function offsetUnset($offset) { unset($this->options[$offset]); }
+ public function offsetSet($offset, $data) { $this->options[$offset] = $data; }
+
+ protected $options = array();
+ protected $flags = array();
+ }
+
+ /**
+ * Tests is the console programming API for the test suite
+ *
+ * @package phpdbg
+ * @subpackage testing
+ */
+ class Tests {
+
+ /**
+ * Construct the console object
+ *
+ * @param array basic configuration
+ * @param array command line
+ */
+ public function __construct(TestsConfiguration $config) {
+ $this->config = $config;
+
+ if ($this->config->hasFlag('help') ||
+ $this->config->hasFlag('h')) {
+ $this->showUsage();
+ exit;
+ }
+ }
+
+ /**
+ * Find valid paths as specified by configuration
+ *
+ */
+ public function findPaths($in = null) {
+ $paths = array();
+ $where = ($in != null) ? array($in) : $this->config['path'];
+
+ foreach ($where as $path) {
+ if ($path) {
+ if (is_dir($path)) {
+ $paths[] = $path;
+ foreach (scandir($path) as $child) {
+ if ($child != '.' && $child != '..') {
+ $paths = array_merge(
+ $paths, $this->findPaths("$path/$child"));
+ }
+ }
+ }
+ }
+ }
+
+ return $paths;
+ }
+
+ /**
+ *
+ * @param string the path to log
+ */
+ public function logPath($path) {
+ printf(
+ '%s [%s]%s',
+ str_repeat(
+ '-', $this->config['width'] - strlen($path)),
+ $path, PHP_EOL);
+ }
+
+ /**
+ *
+ * @param string the path to log
+ */
+ public function logPathStats($path) {
+ if (!isset($this->stats[$path])) {
+ return;
+ }
+
+ $total = array_sum($this->stats[$path]);
+
+ if ($total) {
+ @$this->totals[true] += $this->stats[$path][true];
+ @$this->totals[false] += $this->stats[$path][false];
+
+ $stats = @sprintf(
+ "%d/%d %%%d",
+ $this->stats[$path][true],
+ $this->stats[$path][false],
+ (100 / $total) * $this->stats[$path][true]);
+
+ printf(
+ '%s [%s]%s',
+ str_repeat(
+ ' ', $this->config['width'] - strlen($stats)),
+ $stats, PHP_EOL);
+
+ printf("%s%s", str_repeat('-', $this->config['width']+3), PHP_EOL);
+ printf("%s", PHP_EOL);
+ }
+ }
+
+ /**
+ *
+ */
+ public function logStats() {
+ $total = array_sum($this->totals);
+ $stats = @sprintf(
+ "%d/%d %%%d",
+ $this->totals[true],
+ $this->totals[false],
+ (100 / $total) * $this->totals[true]);
+ printf(
+ '%s [%s]%s',
+ str_repeat(
+ ' ', $this->config['width'] - strlen($stats)),
+ $stats, PHP_EOL);
+
+ }
+
+ /**
+ *
+ */
+ protected function showUsage() {
+ printf('usage: php %s [flags] [options]%s', $this->config['exec'], PHP_EOL);
+ printf('[options]:%s', PHP_EOL);
+ printf("\t--path\t\tadd a path to scan outside of tests directory%s", PHP_EOL);
+ printf("\t--width\t\tset line width%s", PHP_EOL);
+ printf("\t--options\toptions to pass to phpdbg%s", PHP_EOL);
+ printf("\t--phpdbg\tpath to phpdbg binary%s", PHP_EOL);
+ printf('[flags]:%s', PHP_EOL);
+ printf("\t-diff2stdout\t\twrite diff to stdout instead of files%s", PHP_EOL);
+ printf("\t-nodiff\t\tdo not write diffs on failure%s", PHP_EOL);
+ printf("\t-nolog\t\tdo not write logs on failure%s", PHP_EOL);
+ printf('[examples]:%s', PHP_EOL);
+ printf("\tphp %s --phpdbg=/usr/local/bin/phpdbg --path=/usr/src/phpdbg/tests --options -n%s",
+ $this->config['exec'], PHP_EOL);
+
+ }
+
+ /**
+ * Find valid tests at the specified path (assumed valid)
+ *
+ * @param string a valid path
+ */
+ public function findTests($path) {
+ $tests = array();
+
+ foreach (scandir($path) as $file) {
+ if ($file == '.' || $file == '..')
+ continue;
+
+ $test = sprintf('%s/%s', $path, $file);
+
+ if (preg_match('~\.test$~', $test)) {
+ $tests[] = new Test($this->config, $test);
+ }
+ }
+
+ return $tests;
+ }
+
+ /**
+ *
+ * @param Test the test to log
+ */
+ public function logTest($path, Test $test) {
+ @$this->stats[$path][($result=$test->getResult())]++;
+
+ printf(
+ "%-{$this->config['lwidth']}s %-{$this->config['rwidth']}s [%s]%s",
+ $test->name,
+ $test->purpose,
+ $result ? "PASS" : "FAIL",
+ PHP_EOL);
+
+ return $result;
+ }
+
+ protected $config;
+ }
+
+ class Test {
+ /*
+ * Expect exact line for line match
+ */
+ const EXACT = 0x00000001;
+
+ /*
+ * Expect strpos() !== false
+ */
+ const STRING = 0x00000010;
+
+ /*
+ * Expect stripos() !== false
+ */
+ const CISTRING = 0x00000100;
+
+ /*
+ * Formatted output
+ */
+ const FORMAT = 0x00001000;
+
+ /**
+ * Format specifiers
+ */
+ private static $format = array(
+ 'search' => array(
+ '%e',
+ '%s',
+ '%S',
+ '%a',
+ '%A',
+ '%w',
+ '%i',
+ '%d',
+ '%x',
+ '%f',
+ '%c',
+ '%t',
+ '%T'
+ ),
+ 'replace' => array(
+ DIR_SEP,
+ '[^\r\n]+',
+ '[^\r\n]*',
+ '.+',
+ '.*',
+ '\s*',
+ '[+-]?\d+',
+ '\d+',
+ '[0-9a-fA-F]+',
+ '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?',
+ '.',
+ '\t',
+ '\t+'
+ )
+ );
+
+ /**
+ * Constructs a new Test object given a specilized phpdbginit file
+ *
+ * @param array configuration
+ * @param string file
+ */
+ public function __construct(TestsConfiguration $config, $file) {
+ if (($handle = fopen($file, 'r'))) {
+ while (($line = fgets($handle))) {
+ $trim = trim($line);
+
+ switch (substr($trim, 0, 1)) {
+ case '#': if (($chunks = array_map('trim', preg_split('~:~', substr($trim, 1), 2)))) {
+ if (property_exists($this, $chunks[0])) {
+ switch ($chunks[0]) {
+ case 'expect': {
+ if ($chunks[1]) {
+ switch (strtoupper($chunks[1])) {
+ case 'TEST::EXACT':
+ case 'EXACT': { $this->expect = TEST::EXACT; } break;
+
+ case 'TEST::STRING':
+ case 'STRING': { $this->expect = TEST::STRING; } break;
+
+ case 'TEST::CISTRING':
+ case 'CISTRING': { $this->expect = TEST::CISTRING; } break;
+
+ case 'TEST::FORMAT':
+ case 'FORMAT': { $this->expect = TEST::FORMAT; } break;
+
+ default:
+ throw new TestConfigurationException(
+ $this->config, "unknown type of expectation (%s)", $chunks[1]);
+ }
+ }
+ } break;
+
+ default: {
+ $this->$chunks[0] = $chunks[1];
+ }
+ }
+ } else switch(substr($trim, 1, 1)) {
+ case '#': { /* do nothing */ } break;
+
+ default: {
+ $line = preg_replace(
+ "~(\r\n)~", "\n", substr($trim, 1));
+
+ $line = trim($line);
+
+ switch ($this->expect) {
+ case TEST::FORMAT:
+ $this->match[] = str_replace(
+ self::$format['search'],
+ self::$format['replace'], preg_quote($line));
+ break;
+
+ default: $this->match[] = $line;
+ }
+ }
+ }
+ } break;
+
+ default:
+ break 2;
+ }
+ }
+ fclose($handle);
+
+ $this->config = $config;
+ $this->file = $file;
+ }
+ }
+
+ /**
+ * Obvious!!
+ *
+ */
+ public function getResult() {
+ $options = sprintf('-i%s -nqb', $this->file);
+
+ if ($this->options) {
+ $options = sprintf(
+ '%s %s %s',
+ $options,
+ $this->config['options'],
+ $this->options
+ );
+ } else {
+ $options = sprintf(
+ '%s %s', $options, $this->config['options']
+ );
+ }
+
+ $result = `{$this->config['phpdbg']} {$options}`;
+
+ if ($result) {
+ foreach (preg_split('~(\r|\n)~', $result) as $num => $line) {
+ if (!$line && !isset($this->match[$num]))
+ continue;
+
+ switch ($this->expect) {
+ case TEST::EXACT: {
+ if (strcmp($line, $this->match[$num]) !== 0) {
+ $this->diff['wants'][$num] = &$this->match[$num];
+ $this->diff['gets'][$num] = $line;
+ }
+ } continue 2;
+
+ case TEST::STRING: {
+ if (strpos($line, $this->match[$num]) === false) {
+ $this->diff['wants'][$num] = &$this->match[$num];
+ $this->diff['gets'][$num] = $line;
+ }
+ } continue 2;
+
+ case TEST::CISTRING: {
+ if (stripos($line, $this->match[$num]) === false) {
+ $this->diff['wants'][$num] = &$this->match[$num];
+ $this->diff['gets'][$num] = $line;
+ }
+ } continue 2;
+
+ case TEST::FORMAT: {
+ $line = trim($line);
+ if (!preg_match("/^{$this->match[$num]}\$/s", $line)) {
+ $this->diff['wants'][$num] = &$this->match[$num];
+ $this->diff['gets'][$num] = $line;
+ }
+ } continue 2;
+ }
+ }
+ }
+
+ $this->writeLog($result);
+ $this->writeDiff();
+
+ return (count($this->diff) == 0);
+ }
+
+ /**
+ * Write diff to disk if configuration allows it
+ *
+ */
+ protected function writeDiff() {
+ if (count($this->diff['wants'])) {
+ if (!$this->config->hasFlag('nodiff')) {
+ if ($this->config->hasFlag('diff2stdout')) {
+ $difffile = "php://stdout";
+ file_put_contents($difffile, "====DIFF====\n");
+ } else {
+ $difffile = sprintf(
+ '%s/%s.diff',
+ dirname($this->file), basename($this->file));
+ }
+
+ if (($diff = fopen($difffile, 'w+'))) {
+
+ foreach ($this->diff['wants'] as $line => $want) {
+ $got = $this->diff['gets'][$line];
+
+ fprintf(
+ $diff, '(%d) -%s%s', $line+1, $want, PHP_EOL);
+ fprintf(
+ $diff, '(%d) +%s%s', $line+1, $got, PHP_EOL);
+ }
+
+ fclose($diff);
+ }
+ }
+ } else unlink($diff);
+ }
+
+ /**
+ * Write log to disk if configuration allows it
+ *
+ */
+ protected function writeLog($result = null) {
+ $log = sprintf(
+ '%s/%s.log',
+ dirname($this->file), basename($this->file));
+
+ if (count($this->diff) && $result) {
+ if (!in_array('nolog', $this->config['flags'])) {
+ @file_put_contents(
+ $log, $result);
+ }
+ } else unlink($log);
+ }
+
+ public $name;
+ public $purpose;
+ public $file;
+ public $options;
+ public $expect;
+
+ protected $match;
+ protected $diff;
+ protected $stats;
+ protected $totals;
+ }
+}
+
+namespace {
+ use \phpdbg\Testing\Test;
+ use \phpdbg\Testing\Tests;
+ use \phpdbg\Testing\TestsConfiguration;
+
+ $cwd = dirname(__FILE__);
+ $cmd = $_SERVER['argv'];
+
+ $retval = 0;
+
+ {
+ $config = new TestsConfiguration(array(
+ 'exec' => realpath(array_shift($cmd)),
+ 'phpdbg' => realpath(sprintf(
+ '%s/../phpdbg', $cwd
+ )),
+ 'path' => array(
+ realpath(dirname(__FILE__))
+ ),
+ 'flags' => array(),
+ 'width' => 75
+ ), $cmd);
+
+ $tests = new Tests($config);
+
+ foreach ($tests->findPaths() as $path) {
+ $tests->logPath($path);
+
+ foreach ($tests->findTests($path) as $test) {
+ $retval |= !$tests->logTest($path, $test);
+ }
+
+ $tests->logPathStats($path);
+ }
+
+ $tests->logStats();
+ }
+
+ die($retval);
+}
+?>