]> granicus.if.org Git - php/commitdiff
Adding new tests = making sure we're in sync with the 5_3 branch
authorUlf Wendel <uw@php.net>
Wed, 10 Oct 2007 10:43:39 +0000 (10:43 +0000)
committerUlf Wendel <uw@php.net>
Wed, 10 Oct 2007 10:43:39 +0000 (10:43 +0000)
16 files changed:
ext/mysqli/tests/mysqli_change_user_get_lock.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_change_user_insert_id.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_change_user_locks_temporary.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_change_user_oo.phpt
ext/mysqli/tests/mysqli_change_user_prepared_statements.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_change_user_rollback.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_change_user_set_names.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_debug.phpt
ext/mysqli/tests/mysqli_debug_append.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_debug_control_string.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_debug_ini.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_debug_mysqlnd_control_string.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_fetch_field.phpt
ext/mysqli/tests/mysqli_fetch_field_flags.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_fetch_field_types.phpt [new file with mode: 0644]

diff --git a/ext/mysqli/tests/mysqli_change_user_get_lock.phpt b/ext/mysqli/tests/mysqli_change_user_get_lock.phpt
new file mode 100644 (file)
index 0000000..437e393
--- /dev/null
@@ -0,0 +1,102 @@
+--TEST--
+mysqli_change_user() - GET_LOCK()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+die("skip - is the server still buggy?");
+?>
+--INI--
+max_execution_time=240
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       // We need this little hack to be able to re-run the test
+       $lock = 'phptest_' . mt_rand(0, 100000);
+       $thread_id = mysqli_thread_id($link);
+
+       printf("Testing GET_LOCK()...\n");
+
+       if (!$res = mysqli_query($link, sprintf('SELECT GET_LOCK("%s", 2) AS _ok', $lock)))
+               printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_ok'] != 1)
+               printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       else
+               printf("... lock '%s' acquired by thread %d\n", $lock, $thread_id);
+
+       mysqli_free_result($res);
+
+
+       // GET_LOCK("phptest") should be released
+       /* From the mysql_change_user documentation:
+This command resets the state as if one had done a new connect. (See Section 25.2.13, “Controlling Automatic Reconnect Behavior”.) It always performs a ROLLBACK of any active transactions, closes and drops all temporary tables, and unlocks all locked tables. Session system variables are reset to the values of the corresponding global system variables. Prepared statements are released and HANDLER variables are closed. Locks acquired with GET_LOCK() are released. These effects occur even if the user didn't change.
+       */
+       mysqli_change_user($link, $user, $passwd, $db);
+sleep(5);
+       $new_thread_id = mysqli_thread_id($link);
+
+       printf("... calling IS_USED_LOCK() on '%s' using thread '%d'\n", $lock, $new_thread_id);
+       if (!$res = mysqli_query($link, 'SELECT IS_USED_LOCK("phptest") AS _ok'))
+               printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_ok'] != NULL)
+               printf("[006] Lock '%s' should have been released, [%d] %s\n",
+                       $lock,
+                       mysqli_errno($link), mysqli_error($link));
+
+       printf("... calling IS_FREE_LOCK() on '%s' using thread '%d'\n", $lock, $new_thread_id);
+       if (!$res = mysqli_query($link, 'SELECT IS_FREE_LOCK("phptest") AS _ok'))
+               printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_ok'] != 1)
+               printf("[009] Lock '%s' should have been released, [%d] %s\n",
+                       $lock,
+                       mysqli_errno($link), mysqli_error($link));
+
+       mysqli_free_result($res);
+
+       /* Ok, let's try a NEW connection and a NEW lock! */
+       mysqli_close($link);
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[010] Cannot open new connection, [%d] %s\n",
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       do {
+               $newlock = 'phptest_' . mt_rand(0, 100000);
+       } while ($lock == $newlock);
+
+       $new_thread_id = mysqli_thread_id($link);
+       printf("... calling IS_USED_LOCK() on '%s' using new connection with thread '%d'\n", $newlock, $new_thread_id);
+       if (!$res = mysqli_query($link, 'SELECT IS_USED_LOCK("phptest") AS _ok'))
+               printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_ok'] != NULL)
+               printf("[013] Lock '%s' should have been released, [%d] %s\n",
+                       $lock,
+                       mysqli_errno($link), mysqli_error($link));
+
+       print "done!";
+?>
+--EXPECTF--
+Testing GET_LOCK()...
+... lock 'phptest_%d' acquired by thread %d
+... calling IS_USED_LOCK() on 'phptest_%d' using thread '%d'
+... calling IS_FREE_LOCK() on 'phptest_%d' using thread '%d'
+... calling IS_USED_LOCK() on 'phptest_%d' using new connection with thread '%d'
+done!
diff --git a/ext/mysqli/tests/mysqli_change_user_insert_id.phpt b/ext/mysqli/tests/mysqli_change_user_insert_id.phpt
new file mode 100644 (file)
index 0000000..243eab0
--- /dev/null
@@ -0,0 +1,56 @@
+--TEST--
+mysqli_change_user() - LAST_INSERT_ID()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+               printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!mysqli_query($link, 'CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, label CHAR(10))'))
+               printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!mysqli_query($link, 'INSERT INTO test(id, label) VALUES (100, "z")'))
+               printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (($insert_id = mysqli_insert_id($link)) !== 100)
+               printf("[005] Expecting 100, got %d, [%d] %s\n",
+                       $insert_id,
+                       mysqli_errno($link), mysqli_error($link));
+
+       // LAST_INSERT_ID should be reset
+       mysqli_change_user($link, $user, $passwd, $db);
+
+       if (($insert_id = mysqli_insert_id($link)) !== 0)
+               printf("[006] Expecting 0, got %d, [%d] %s\n",
+                       $insert_id,
+                       mysqli_errno($link), mysqli_error($link));
+
+       if (!$res = mysqli_query($link, 'SELECT LAST_INSERT_ID() as _insert_id'))
+               printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       if ($row['_insert_id'] != $insert_id)
+               printf("LAST_INSERT_ID() [%d] and mysqli_insert_id [%d] differ!\n",
+                       $row['_insert_id'], $insert_id);
+
+       if ($row['_insert_id'] != 0)
+               printf("Expecting 0 got %d\n", $row['_insert_id']);
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_locks_temporary.phpt b/ext/mysqli/tests/mysqli_change_user_locks_temporary.phpt
new file mode 100644 (file)
index 0000000..43fa433
--- /dev/null
@@ -0,0 +1,103 @@
+--TEST--
+mysqli_change_user() - table locks, GET_LOCK(), temporary tables
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+die("skip - is the server still buggy?");
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       if (!$link2 = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] Cannot create second connection handle, [%d] %s\n",
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!mysqli_query($link, 'LOCK TABLE test WRITE'))
+               printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       /*
+       if ($res = mysqli_query($link2, 'SELECT COUNT(*) AS _num FROM test')) {
+               printf("[003] Reading from test should not be possible due to a lock, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link2));
+               mysqli_free_result($res);
+       }
+       */
+
+       // LOCKS should be removed
+       mysqli_change_user($link, $user, $passwd, $db);
+
+       if (!$res = mysqli_query($link2, 'SELECT COUNT(*) AS _num FROM test'))
+               printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_num'] < 1)
+               printf("[005] There should be some rows in the table test\n");
+
+       mysqli_free_result($res);
+       mysqli_close($link2);
+
+       if (!mysqli_query($link, 'DROP TABLE test'))
+               printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!mysqli_query($link, 'CREATE TEMPORARY TABLE test(id INT)'))
+               printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1), (2), (3)'))
+               printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+               printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_num'] != 3)
+               printf("[011] There should be three rows in the table test\n");
+
+       mysqli_free_result($res);
+
+       // Temporary tables should be dropped
+       mysqli_change_user($link, $user, $passwd, $db);
+
+       if ($res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test')) {
+               printf("[012] There should be no table test any more, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+               mysqli_free_result($res);
+       }
+
+       if (!$res = mysqli_query($link, 'SELECT GET_LOCK("phptest", 2) AS _ok'))
+               printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_ok'] != 1)
+               printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       mysqli_free_result($res);
+
+       // GET_LOCK("phptest") should be released
+       mysqli_change_user($link, $user, $passwd, $db);
+
+       if (!$res = mysqli_query($link, 'SELECT IS_FREE_LOCK("phptest") AS _ok'))
+               printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_ok'] != 1)
+               printf("[018] Lock 'phptest' should have been released, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       mysqli_free_result($res);
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
index 2bd73aca518fe8bfc871f86f9e25d6f41a80f27f..cb7bcf7e8fedb282d6266538a453ec84c495a0c3 100644 (file)
@@ -8,7 +8,7 @@ require_once('skipifconnectfailure.inc');
 
 require_once('table.inc');
 if (!$IS_MYSQLND && (mysqli_get_server_version($link) < 50118 && mysqli_get_server_version($link) > 50100)) {
-       die("skip Your MySQL Server version has a known but that will cause a crash");
+       die("skip Your MySQL Server version has a known bug that will cause a crash");
 }
 ?>
 --FILE--
diff --git a/ext/mysqli/tests/mysqli_change_user_prepared_statements.phpt b/ext/mysqli/tests/mysqli_change_user_prepared_statements.phpt
new file mode 100644 (file)
index 0000000..ad3ed04
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+mysqli_change_user() - Prepared Statement
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!$stmt = mysqli_prepare($link, 'SELECT "prepared statements should be released"'))
+               printf("[002] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+       mysqli_change_user($link, $user, $passwd, $db);
+
+       $wrong = null;
+       if ($stmt->execute() && $stmt->bind_result($wrong) && $stmt->fetch()) {
+               printf("This is wrong, because after a mysqli_change_user() %s\n", $wrong);
+       } else {
+               if ($stmt->errno == 0)
+                       printf("Error code 2013, 1243 or similar should have been set\n");
+       }
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_rollback.phpt b/ext/mysqli/tests/mysqli_change_user_rollback.phpt
new file mode 100644 (file)
index 0000000..ae1d911
--- /dev/null
@@ -0,0 +1,70 @@
+--TEST--
+mysqli_change_user() - ROLLBACK
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket);
+$result = mysqli_query($link, "SHOW VARIABLES LIKE 'have_innodb'");
+$row = mysqli_fetch_row($result);
+mysqli_free_result($result);
+mysqli_close($link);
+
+if ($row[1] == 'NO') {
+       printf ("skip ROLLBACK requires transactional engine InnoDB");
+}
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       if (!mysqli_query($link, 'ALTER TABLE test ENGINE=InnoDB'))
+               printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       mysqli_autocommit($link, false);
+
+       if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+               printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       $num = $row['_num'];
+       assert($num > 0);
+
+       if (!$res = mysqli_query($link, 'DELETE FROM test'))
+               printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+               printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       if (0 != $row['_num'])
+               printf("[007] Rows should have been deleted in this transaction\n");
+
+       // DELETE should be rolled back
+       mysqli_change_user($link, $user, $passwd, $db);
+
+       if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test'))
+               printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ($row['_num'] != $num)
+               printf("[010] Expecting %d rows in the table test, found %d rows\n",
+                       $num, $row['_num']);
+
+       mysqli_free_result($res);
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_set_names.phpt b/ext/mysqli/tests/mysqli_change_user_set_names.phpt
new file mode 100644 (file)
index 0000000..1ac2d3d
--- /dev/null
@@ -0,0 +1,165 @@
+--TEST--
+mysqli_change_user() - SET NAMES
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+       die(sprintf("skip [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!$res = mysqli_query($link, 'SELECT version() AS server_version'))
+       die(sprintf("skip [%d] %s\n", mysqli_errno($link), mysqli_error($link)));
+
+$tmp = mysqli_fetch_assoc($res);
+mysqli_free_result($res);
+$version = explode('.', $tmp['server_version']);
+if (empty($version))
+       die(sprintf("skip Cannot determine server version, need MySQL Server 4.1+ for the test!"));
+
+if ($version[0] <= 4 && $version[1] < 1)
+       die(sprintf("ski Need MySQL Server 4.1+ for the test!"));
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!$res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin%"'))
+               printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       $charsets = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $charsets[$row['Charset']] = $row['Default collation'];
+
+       mysqli_free_result($res);
+       if (!mysqli_query($link, 'SET NAMES DEFAULT'))
+               printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$res = mysqli_query($link, 'SELECT
+               @@character_set_client AS charset_client,
+               @@character_set_connection AS charset_connection,
+               @@character_set_results AS charset_results,
+               @@collation_connection AS collation_connection,
+               @@collation_database AS collation_database,
+               @@collation_server AS collation_server'))
+               printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$defaults = mysqli_fetch_assoc($res))
+               printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       $not_changed = $defaults;
+       foreach ($charsets as $charset => $collation) {
+
+               if (isset($not_changed['charset_client']) &&
+                               $charset != $not_changed['charset_client'] &&
+                               mysqli_query($link, sprintf('SET @@character_set_client = "%s"', $charset)))
+                       unset($not_changed['charset_client']);
+
+               if (isset($not_changed['charset_connection']) &&
+                               $charset != $not_changed['charset_connection'] &&
+                               mysqli_query($link, sprintf('SET @@character_connection = "%s"', $charset)))
+                       unset($not_changed['charset_connection']);
+
+               if (isset($not_changed['charset_results']) &&
+                               $charset != $not_changed['charset_results'] &&
+                               mysqli_query($link, sprintf('SET @@character_set_results = "%s"', $charset)))
+                       unset($not_changed['charset_results']);
+
+               if (isset($not_changed['collation_connection']) &&
+                               $collation != $not_changed['collation_connection'] &&
+                               mysqli_query($link, sprintf('SET @@collation_connection = "%s"', $collation)))
+                       unset($not_changed['collation_connection']);
+
+               if (isset($not_changed['collation_database']) &&
+                               $collation != $not_changed['collation_database'] &&
+                               mysqli_query($link, sprintf('SET @@collation_database = "%s"', $collation)))
+                       unset($not_changed['collation_database']);
+
+               if (isset($not_changed['collation_server']) &&
+                               $collation != $not_changed['collation_server'] &&
+                               mysqli_query($link, sprintf('SET @@collation_server = "%s"', $collation)))
+                       unset($not_changed['collation_server']);
+
+               if (empty($not_changed))
+                       break;
+       }
+
+       if (!$res = mysqli_query($link, 'SELECT
+               @@character_set_client AS charset_client,
+               @@character_set_connection AS charset_connection,
+               @@character_set_results AS charset_results,
+               @@collation_connection AS collation_connection,
+               @@collation_database AS collation_database,
+               @@collation_server AS collation_server'))
+               printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$modified = mysqli_fetch_assoc($res))
+               printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       if ($modified == $defaults)
+               printf("[008] Not all settings have been changed\n");
+
+       // LAST_INSERT_ID should be reset
+       mysqli_change_user($link, $user, $passwd, $db);
+
+       if (!$res = mysqli_query($link, 'SELECT
+               @@character_set_client AS charset_client,
+               @@character_set_connection AS charset_connection,
+               @@character_set_results AS charset_results,
+               @@collation_connection AS collation_connection,
+               @@collation_database AS collation_database,
+               @@collation_server AS collation_server'))
+               printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$new = mysqli_fetch_assoc($res))
+               printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       if ($new == $modified) {
+               printf("[011] Charsets/collations have not been reset.\n");
+               printf("Got:\n");
+               var_dump($new);
+               printf("Expected:\n");
+               var_dump($defaults);
+       }
+
+       if (ini_get('unicode.semantics')) {
+               // charsets cannot take any other value but utf8 in unicode mode
+               $defaults['charset_client'] = 'utf8';
+               $defaults['charset_connection'] = 'utf8';
+               $defaults['charset_results'] = 'utf8';
+               $defaults['collation_connection'] = 'utf8_general_ci';
+       }
+
+       if ($new != $defaults) {
+               printf("[012] Charsets/collations have not been reset to their defaults.\n");
+               printf("Got:\n");
+               var_dump($new);
+               printf("Expected:\n");
+               var_dump($defaults);
+       }
+
+       if (!is_object($charset = mysqli_get_charset($link)))
+               printf("[013] Expecting object/std_class, got %s/%s\n", gettype($charset), $charset);
+
+       if ($charset->charset != $defaults['charset_connection'])
+               printf("[014] Expecting connection charset to be %s got %s\n",
+                       $defaults['charset_connection'],
+                       $charset->charset);
+
+       if ($charset->collation != $defaults['collation_connection'])
+               printf("[015] Expecting collation to be %s got %s\n",
+                       $defaults['collation_connection'],
+                       $charset->collation);
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
index 88f7b9d970daa5fa25af9ebfbe8a1ccece331ad5..6db6a45e44861effc36f2b65c896c72e15b7bff1 100644 (file)
@@ -10,19 +10,49 @@ if (!function_exists('mysqli_debug'))
 ?>
 --FILE--
 <?php
-       include "connect.inc";
-
-       $tmp    = NULL;
-       $link   = NULL;
+       require_once('connect.inc');;
 
        if (NULL !== ($tmp = @mysqli_debug()))
                printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
 
        // NOTE: documentation is not clear on this: function always return NULL or TRUE
-       if (true !== ($tmp = mysqli_debug("d:t:O,/tmp/client.trace")))
+       if (true !== ($tmp = mysqli_debug(sprintf('d:t:O,%s/mysqli_debug_phpt.trace', sys_get_temp_dir()))))
                printf("[002] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
 
+       if ($IS_MYSQLND) {
+               // let's make this mysqlnd only - for libmysql we need debug installation
+
+               // table.inc will create a database connection and run some SQL queries, therefore
+               // the debug file should have entries
+               require_once('table.inc');
+
+               clearstatcache();
+               $trace_file = sprintf('%s/mysqli_debug_phpt.trace', sys_get_temp_dir());
+               if (!file_exists($trace_file))
+                       printf("[003] Trace file '%s' has not been created\n", $trace_file);
+               if (filesize($trace_file) < 50)
+                       printf("[004] Trace file '%s' is very small. filesize() reports only %d bytes. Please check.\n",
+                               $trace_file,
+                               filesize($trace_file));
+
+               // will mysqli_debug() mind if the trace file gets removed?
+               unlink($trace_file);
+               clearstatcache();
+
+               if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+                               printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+                       else
+                               mysqli_free_result($res);
+
+               mysqli_close($link);
+
+               clearstatcache();
+               if (!file_exists($trace_file))
+                       printf("[006] Trace file '%s' does not exist\n", $trace_file);
+               unlink($trace_file);
+       }
+
        print "done!";
 ?>
 --EXPECTF--
-done!
\ No newline at end of file
+done%s
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_debug_append.phpt b/ext/mysqli/tests/mysqli_debug_append.phpt
new file mode 100644 (file)
index 0000000..90f6d6f
--- /dev/null
@@ -0,0 +1,79 @@
+--TEST--
+mysqli_debug() - append to trace file
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+
+if (!function_exists('mysqli_debug'))
+       die("skip: mysqli_debug() not available");
+?>
+--FILE--
+<?php
+       require_once('connect.inc');;
+
+       if (true !== ($tmp = mysqli_debug(sprintf('d:t:O,%s/mysqli_debug_phpt.trace', sys_get_temp_dir()))))
+               printf("[001] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+       // table.inc will create a database connection and run some SQL queries, therefore
+       // the debug file should have entries
+       require_once('table.inc');
+
+       clearstatcache();
+       $trace_file = sprintf('%s/mysqli_debug_phpt.trace', sys_get_temp_dir());
+       if (!file_exists($trace_file))
+               printf("[002] Trace file '%s' has not been created\n", $trace_file);
+       if (filesize($trace_file) < 50)
+               printf("[003] Trace file '%s' is very small. filesize() reports only %d bytes. Please check.\n",
+                       $trace_file,
+                       filesize($trace_file));
+
+       // will mysqli_debug() mind if the trace file gets removed?
+       unlink($trace_file);
+       clearstatcache();
+
+       if (!$fp = fopen($trace_file, 'w')) {
+               printf("[004] Cannot create trace file to test append mode\n");
+       } else {
+
+               if (!fwrite($fp, (binary) 'mysqli_debug.phpt test line'))
+                       printf("[005] Cannot write to trace file.\n");
+               fclose($fp);
+
+               if (true !== ($tmp = mysqli_debug(sprintf('d:a,%s', $trace_file))))
+                       printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+               if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+                       printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+               else
+                       mysqli_free_result($res);
+
+               $trace = file_get_contents($trace_file);
+               if (!strstr($trace, 'mysqli_debug.phpt test line'))
+                       printf("[008] Cannot find original file content any more. Seems that the trace file got overwritten and not appended. Please check.");
+
+               if (true !== ($tmp = mysqli_debug(sprintf('d:A,%s', $trace_file))))
+                       printf("[009] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+               if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+                       printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+               else
+                       mysqli_free_result($res);
+
+               if (!strstr(file_get_contents($trace_file), $trace))
+                       printf("[011] Cannot find original file content any more. Seems that the trace file got overwritten and not appended. Please check.");
+       }
+
+       // what will happen if we create new trace entries...?
+       unlink($trace_file);
+       clearstatcache();
+       if (file_exists($trace_file))
+               printf("[012] Could not remove trace file '%s'.\n", $trace_file);
+
+       mysqli_close($link);
+       print "done";
+       if ($IS_MYSQLND)
+               print "libmysql/DBUG package prints some debug info here."
+?>
+--EXPECTF--
+done%s
diff --git a/ext/mysqli/tests/mysqli_debug_control_string.phpt b/ext/mysqli/tests/mysqli_debug_control_string.phpt
new file mode 100644 (file)
index 0000000..4b869dc
--- /dev/null
@@ -0,0 +1,67 @@
+--TEST--
+mysqli_debug() - invalid debug control strings
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+
+if (!function_exists('mysqli_debug'))
+       die("skip: mysqli_debug() not available");
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       function try_control_string($link, $control_string, $trace_file, $offset) {
+
+               if (true !== ($tmp = mysqli_debug($control_string))) {
+                       printf("[%03d][control string '%s'] Expecting boolean/true, got %s/%s.\n",
+                               $offset + 1,
+                               $control_string,
+                               gettype($tmp),
+                               $tmp);
+                       return false;
+               }
+
+               if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+                       printf("[%03d][control string '%s'] [%d] %s.\n",
+                               $offset + 2,
+                               $control_string,
+                               mysqli_errno($link),
+                               mysqli_error($link));
+                       return false;
+               }
+
+               clearstatcache();
+               if (!file_exists($trace_file)) {
+                       printf("[%03d][control string '%s'] Trace file has not been written.\n",
+                               $offset + 3,
+                               $control_string,
+                               gettype($tmp),
+                               $tmp);
+                       return false;
+               }
+
+               unlink($trace_file);
+       }
+
+       $trace_file = sprintf('%s%s%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, 'mysqli_debug_phpt.trace');
+       try_control_string($link, 't:,,:o,' . $trace_file, $trace_file, 10);
+       try_control_string($link, ':' . chr(0) . 'A,' . $trace_file, $trace_file, 20);
+       try_control_string($link, 't:o,' . $trace_file . ':abc', $trace_file, 30);
+       try_control_string($link, 't:o,' . $trace_file . ':ABC,123:b', $trace_file, 40);
+       try_control_string($link, 't:ABC,123:b;:o,' . $trace_file, $trace_file, 50);
+       try_control_string($link, 't:A;BC,123:b;:o,' . $trace_file, $trace_file, 60);
+       try_control_string($link, 't:p:o,' . $trace_file, $trace_file, 70);
+       try_control_string($link, 't:p,1,,2:o,' . $trace_file, $trace_file, 80);
+       try_control_string($link, 't:z,1,,2:o,' . $trace_file, $trace_file, 90);#
+
+       mysqli_close($link);
+       print "done";
+       if ($IS_MYSQLND)
+               print "libmysql/DBUG package prints some debug info here."
+?>
+--EXPECTF--
+[023][control string '%s'] Trace file has not been written.
+done%s
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_debug_ini.phpt b/ext/mysqli/tests/mysqli_debug_ini.phpt
new file mode 100644 (file)
index 0000000..2d1bb08
--- /dev/null
@@ -0,0 +1,48 @@
+--TEST--
+mysqli_debug() - enabling trace with ini setting
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+
+if (!function_exists('mysqli_debug'))
+       die("skip mysqli_debug() not available");
+
+require_once('connect.inc');
+if (!$IS_MYSQLND || ($MYSQLND_VERSION < 940))
+       die("skip needs mysqlnd version/revision 940+");
+
+if (!$fp = @fopen('/tmp/mysqli_debug_phpt.trace', 'w'))
+       die("skip PHP cannot create a file in /tmp/mysqli_debug_phpt");
+else
+       fclose($fp);
+?>
+--INI--
+mysqlnd.debug="t:O,/tmp/mysqli_debug_phpt.trace"
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       var_dump(ini_get('mysqlnd.debug'));
+
+       $trace_file = '/tmp/mysqli_debug_phpt.trace';
+       clearstatcache();
+       if (!file_exists($trace_file))
+               printf("[003] Trace file '%s' has not been created\n", $trace_file);
+       if (filesize($trace_file) < 50)
+               printf("[004] Trace file '%s' is very small. filesize() reports only %d bytes. Please check.\n",
+                       $trace_file,
+                       filesize($trace_file));
+
+       mysqli_close($link);
+       unlink($trace_file);
+
+       print "done!";
+?>
+--EXPECTF--
+string(32) "t:O,/tmp/mysqli_debug_phpt.trace"
+done!
+--UEXPECTF--
+unicode(32) "t:O,/tmp/mysqli_debug_phpt.trace"
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_debug_mysqlnd_control_string.phpt b/ext/mysqli/tests/mysqli_debug_mysqlnd_control_string.phpt
new file mode 100644 (file)
index 0000000..06feebf
--- /dev/null
@@ -0,0 +1,216 @@
+--TEST--
+mysqli_debug() - all control string options supported by both mysqlnd and libmysql except oOaA
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+
+if (!function_exists('mysqli_debug'))
+       die("skip: mysqli_debug() not available");
+?>
+--FILE--
+<?php
+       require_once('connect.inc');;
+       require_once('table.inc');
+
+       function try_control_string($link, $control_string, $trace_file, $offset) {
+
+               @unlink($trace_file);
+               if (true !== ($tmp = @mysqli_debug($control_string))) {
+                       printf("[%03d][control string '%s'] Expecting boolean/true, got %s/%s.\n",
+                               $offset + 1,
+                               $control_string,
+                               gettype($tmp),
+                               $tmp);
+                       return false;
+               }
+
+               if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+                       printf("[%03d][control string '%s'] [%d] %s.\n",
+                               $offset + 2,
+                               $control_string,
+                               mysqli_errno($link),
+                               mysqli_error($link));
+                       return false;
+               }
+               while ($row = mysqli_fetch_assoc($res))
+                       ;
+               mysqli_free_result($res);
+
+               clearstatcache();
+               if (!file_exists($trace_file)) {
+                       printf("[%03d][control string '%s'] Trace file has not been written.\n",
+                               $offset + 3,
+                               $control_string,
+                               gettype($tmp),
+                               $tmp);
+                       return false;
+               }
+
+               return trim(substr(file_get_contents($trace_file), 0, 100024));
+       }
+
+       $trace_file = sprintf('%s%s%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, 'mysqli_debug_phpt.trace');
+
+       $trace = try_control_string($link, 't:O,' . $trace_file, $trace_file, 10);
+       if (!strstr($trace, 'SELECT * FROM test') && !strstr($trace, 'mysql_real_query'))
+               printf("[015] SELECT query cannot be found in trace. Trace contents seems wrong.\n");
+
+       // T - gettimeofday() system call, system dependent format
+       // 16:57:03.350734 >mysql_real_query
+       $trace = try_control_string($link, 't:O,' . $trace_file . ':T', $trace_file, 20);
+       if (!preg_match('@^[012]{0,1}[0-9]{1}:[0-5]{0,1}[0-9]{1}:[0-5]{0,1}[0-9]{1}@ismU', $trace))
+               printf("[025] Timestamp not found. One reason could be that the test is borked and does not recognize the format of the gettimeofday() system call. Check manually (and fix the test, if needed :-)). First characters from trace are '%s'\n", substr($trace, 0, 80));
+
+       // i - add PID of the current process
+       // currently PHP is not multi-threaded, so it should be save to test for the PID of this PHP process
+       if (false === ($pid = getmypid()))
+               $pid = "[\d]+";
+
+       $trace = try_control_string($link, 't:O,' . $trace_file . ':i', $trace_file, 30);
+       if (!preg_match("@^" . $pid . "*@ismU", $trace))
+               printf("[035] Process ID has not been found, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+       // L - line numbers
+       $trace = try_control_string($link, 't:O,' . $trace_file . ':L', $trace_file, 40);
+       if (!preg_match("@^[\d]+@ismU", $trace))
+               printf("[045] Line numbers have not been found, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+       // F - file name
+       $trace = try_control_string($link, 't:O,' . $trace_file . ':F', $trace_file, 50);
+       // hopefully we'll never see a file name that's not covered by this regular expression...
+       if (!preg_match("@^\s*[/\w\\\\d\.\-]+\.[ch]@ismU", $trace))
+               printf("[055] File names seem to be missing, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+       // -n - print function nesting depth
+       $trace = try_control_string($link, 't:O,' . $trace_file . ':n', $trace_file, 60);
+       if (!preg_match("@^\d+:@ismU", $trace))
+               printf("[065] Nesting level seem to be missing, first characters from trace are '%s'\n", substr($trace, 0, 80));
+
+       // -t,[N] - maximum nesting level
+       $trace = try_control_string($link, 't,1:n:O,' . $trace_file, $trace_file, 70);
+       $lines = explode("\n", $trace);
+       foreach ($lines as $k => $line) {
+               $line = trim($line);
+               if (!preg_match("@^(\d+):+@ismU", $line, $matches)) {
+                       printf("[075] Nesting level seem to be missing, first characters from trace are '%s'\n", substr($line, 0, 80));
+               } else {
+                       if (!isset($matches[1]) || ((int)$matches[1] > 1)) {
+                               printf("[076] Nesting level seem to be %d, should not be higher than 1, first characters from trace are '%s'\n",
+                                       $matches[1],
+                                       substr($line, 0, 80));
+                       }
+               }
+       }
+
+       // omitting t
+       $trace = try_control_string($link, 'n:O,' . $trace_file, $trace_file, 80);
+       $lines = explode("\n", $trace);
+       foreach ($lines as $k => $line) {
+               $line = trim($line);
+               if (preg_match("@^[|\s]*>[\w]+@ism", $line, $matches)) {
+                       printf("[085] Looks like a function call, but there should be none in the trace file, first characters from trace are '%s'\n",
+                               substr($line, 0, 80));
+               }
+       }
+
+       // -f[,functions] - Limit debugger list to specified functions. Empty list -> all functions
+       $lines_all_funcs = explode("\n", try_control_string($link, 't:O,' . $trace_file, $trace_file, 90));
+       $functions_all_funcs = array();
+       foreach ($lines_all_funcs as $k => $line) {
+               $line = trim($line);
+               if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+                       $functions_all_funcs[$matches[1]] = $matches[1];
+               }
+       }
+
+       $lines_trace = explode("\n", try_control_string($link, 't:f:O,' . $trace_file, $trace_file, 100));
+       $functions_trace = array();
+       foreach ($lines_trace as $k => $line) {
+               $line = trim($line);
+               if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+                       $functions_trace[$matches[1]] = $matches[1];
+               }
+       }
+
+       $tmp = array_diff($functions_all_funcs, $functions_trace);
+       if (!empty($tmp)) {
+               printf("[105] Looks like not all functions are listed in the trace. Check manually, dumping diff.");
+               var_dump($tmp);
+       }
+
+       // get two or three function names to play with...
+       $test_functions = array('simple' => array(), 'doubledot' => array());
+
+       foreach ($functions_all_funcs as $func) {
+               if (count($test_functions['simple']) < 2 && !strstr($func, '::'))
+                       $test_functions['simple'][$func] = $func;
+               else if (count($test_functions['doubledot']) < 2 && strstr($func, '::'))
+                       $test_functions['doubledot'][$func] = $func;
+       }
+
+       $control_string = '';
+       if ($func = reset($test_functions['simple']))
+                       $control_string .= sprintf('%s,', $func);
+       if ($func = reset($test_functions['doubledot']))
+                       $control_string .= sprintf('%s,', $func);
+       if ($func = next($test_functions['simple']))
+                       $control_string .= sprintf('%s,', $func);
+       if ($func = next($test_functions['doubledot']))
+                       $control_string .= sprintf('%s,', $func);
+       $control_string = sprintf('t:f,%s:O,%s', $control_string, $trace_file);
+
+       $lines_trace = explode("\n", try_control_string($link, $control_string, $trace_file, 110));
+       $functions_trace = array();
+       foreach ($lines_trace as $k => $line) {
+               $line = trim($line);
+               if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+                       $functions_trace[$matches[1]] = $matches[1];
+               }
+       }
+
+       foreach ($test_functions['simple'] as $func)
+               if (isset($functions_trace[$func])) {
+                       unset($functions_trace[$func]);
+                       unset($test_functions['simple'][$func]);
+               }
+
+       foreach ($test_functions['doubledot'] as $func)
+               if (isset($functions_trace[$func])) {
+                       unset($functions_trace[$func]);
+                       unset($test_functions['doubledot'][$func]);
+               }
+
+       if (!empty($functions_trace)) {
+               printf("[115] Dumping list of unexpected functions which should have not been shown when using control string '%s'.\n",
+                       $control_string);
+               var_dump($functions_trace);
+       }
+       $tmp = array_merge($test_functions['doubledot'], $test_functions['simple']);
+       if (!empty($tmp)) {
+               printf("[116] Dumping list of functions which should have been shown when using control string '%s'.\n",
+                       $control_string);
+               var_dump($tmp);
+       }
+
+       if ($IS_MYSQLND) {
+               // mysqlnd only option
+               // m - trace memory allocations
+               $trace = try_control_string($link, 't:O,' . $trace_file . ':m', $trace_file, 120);
+               if (!preg_match("@^[|\s]*>\_mysqlnd_pefree@ismU", $trace, $matches) &&
+                               !preg_match("@^[|\s]*>\_mysqlnd_pemalloc@ismU", $trace, $matches)) {
+                       printf("[125] Memory dump does neither contain _mysqlnd_pefree nor _mysqlnd_pemalloc calls - check manually.\n");
+                       var_dump($trace);
+               }
+
+       }
+
+       mysqli_close($link);
+       print "done";
+       if ($IS_MYSQLND)
+               print "libmysql/DBUG package prints some debug info here.";
+       @unlink($trace_file);
+?>
+--EXPECTF--
+[083][control string 'n:O,/tmp/mysqli_debug_phpt.trace'] Trace file has not been written.
+done%s
diff --git a/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt b/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt
new file mode 100644 (file)
index 0000000..b8066be
--- /dev/null
@@ -0,0 +1,117 @@
+--TEST--
+mysqli_debug() - mysqlnd only control strings
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (!function_exists('mysqli_debug'))
+       die("skip mysqli_debug() not available");
+
+if (!$IS_MYSQLND)
+       die("skip mysqlnd only test");
+?>
+--FILE--
+<?php
+       require_once('connect.inc');;
+       require_once('table.inc');
+
+       function try_control_string($link, $control_string, $trace_file, $offset) {
+
+               @unlink($trace_file);
+               if (true !== ($tmp = @mysqli_debug($control_string))) {
+                       printf("[%03d][control string '%s'] Expecting boolean/true, got %s/%s.\n",
+                               $offset + 1,
+                               $control_string,
+                               gettype($tmp),
+                               $tmp);
+                       return false;
+               }
+
+               if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+                       printf("[%03d][control string '%s'] [%d] %s.\n",
+                               $offset + 2,
+                               $control_string,
+                               mysqli_errno($link),
+                               mysqli_error($link));
+                       return false;
+               }
+               while ($row = mysqli_fetch_assoc($res))
+                       ;
+               mysqli_free_result($res);
+
+               clearstatcache();
+               if (!file_exists($trace_file)) {
+                       printf("[%03d][control string '%s'] Trace file has not been written.\n",
+                               $offset + 3,
+                               $control_string,
+                               gettype($tmp),
+                               $tmp);
+                       return false;
+               }
+
+               return trim(substr(file_get_contents($trace_file), 0, 100024));
+       }
+
+       $memory_funcs = array(
+               '_mysqlnd_ecalloc',
+               '_mysqlnd_emalloc',
+               '_mysqlnd_palloc_free_thd_cache_reference',
+               '_mysqlnd_pecalloc',
+               '_mysqlnd_pefree',
+               '_mysqlnd_pemalloc',
+               '_mysqlnd_perealloc',
+       );
+       $trace_file = sprintf('%s%s%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, 'mysqli_debug_phpt.trace');
+
+       $trace = try_control_string($link, 't:m:O,' . $trace_file, $trace_file, 10);
+       if (!strstr($trace, 'SELECT * FROM test') && !strstr($trace, 'mysql_real_query'))
+               printf("[015] SELECT query cannot be found in trace. Trace contents seems wrong.\n");
+
+       $lines_trace = explode("\n", $trace);
+       $functions_trace = array();
+       foreach ($lines_trace as $k => $line) {
+               $line = trim($line);
+               if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+                       $functions_trace[$matches[1]] = $matches[1];
+               }
+       }
+
+       $found = 0;
+       foreach ($memory_funcs as $k => $name)
+               if (isset($functions_trace[$name]))
+                       $found++;
+
+       if ($found < (count($memory_funcs) - 2))
+               printf("[016] Only %d memory functions have been found, expecting at least %d.\n",
+                       $found, count($memory_funcs) - 2);
+
+       $trace = try_control_string($link, 't:O,' . $trace_file, $trace_file, 20);
+       if (!strstr($trace, 'SELECT * FROM test') && !strstr($trace, 'mysql_real_query'))
+               printf("[025] SELECT query cannot be found in trace. Trace contents seems wrong.\n");
+
+       $lines_trace = explode("\n", $trace);
+       $functions_trace = array();
+       foreach ($lines_trace as $k => $line) {
+               $line = trim($line);
+               if (preg_match("@^[|\s]*>([\w:]+)@ism", $line, $matches)) {
+                       $functions_trace[$matches[1]] = $matches[1];
+               }
+       }
+
+       $found = 0;
+       foreach ($memory_funcs as $k => $name)
+               if (isset($functions_trace[$name]))
+                       $found++;
+
+       if ($found > 2)
+               printf("[026] More than %d memory functions have been recorded, that's strange.\n",
+                       $found);
+
+       mysqli_close($link);
+       @unlink($trace_file);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
index 03c709396b3491a03cd91b15152dabc48d6b2c07..94911913202ba3d05c45b9ab71090a0e0dc72f48 100644 (file)
@@ -21,6 +21,7 @@ require_once('skipifconnectfailure.inc');
                printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
 
        require('table.inc');
+
        if (!$res = mysqli_query($link, "SELECT id AS ID, label FROM test AS TEST ORDER BY id LIMIT 1")) {
                printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
        }
@@ -31,10 +32,28 @@ require_once('skipifconnectfailure.inc');
 
        mysqli_free_result($res);
 
+       // Read http://bugs.php.net/bug.php?id=42344 on defaults!
        if (NULL !== ($tmp = mysqli_fetch_field($res)))
                printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
 
+       if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+               printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!mysqli_query($link, "CREATE TABLE test(id INT NOT NULL DEFAULT 1)"))
+               printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!mysqli_query($link, "INSERT INTO test(id) VALUES (2)"))
+               printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$res = mysqli_query($link, "SELECT id as _default_test FROM test")) {
+               printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       }
+       var_dump(mysqli_fetch_assoc($res));
+       var_dump(mysqli_fetch_field($res));
+       mysqli_free_result($res);
+
        mysqli_close($link);
+
        print "done!";
 ?>
 --EXPECTF--
@@ -89,6 +108,34 @@ object(stdClass)#%d (11) {
 bool(false)
 
 Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+array(1) {
+  ["_default_test"]=>
+  string(1) "2"
+}
+object(stdClass)#%d (11) {
+  ["name"]=>
+  string(13) "_default_test"
+  ["orgname"]=>
+  string(2) "id"
+  ["table"]=>
+  string(4) "test"
+  ["orgtable"]=>
+  string(4) "test"
+  ["def"]=>
+  string(0) ""
+  ["max_length"]=>
+  int(1)
+  ["length"]=>
+  int(11)
+  ["charsetnr"]=>
+  int(63)
+  ["flags"]=>
+  int(32769)
+  ["type"]=>
+  int(3)
+  ["decimals"]=>
+  int(0)
+}
 done!
 --UEXPECTF--
 object(stdClass)#%d (11) {
@@ -142,4 +189,32 @@ object(stdClass)#%d (11) {
 bool(false)
 
 Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+array(1) {
+  [u"_default_test"]=>
+  unicode(1) "2"
+}
+object(stdClass)#%d (11) {
+  [u"name"]=>
+  unicode(13) "_default_test"
+  [u"orgname"]=>
+  unicode(2) "id"
+  [u"table"]=>
+  unicode(4) "test"
+  [u"orgtable"]=>
+  unicode(4) "test"
+  [u"def"]=>
+  unicode(0) ""
+  [u"max_length"]=>
+  int(1)
+  [u"length"]=>
+  int(11)
+  [u"charsetnr"]=>
+  int(63)
+  [u"flags"]=>
+  int(32769)
+  [u"type"]=>
+  int(3)
+  [u"decimals"]=>
+  int(0)
+}
 done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field_flags.phpt b/ext/mysqli/tests/mysqli_fetch_field_flags.phpt
new file mode 100644 (file)
index 0000000..ebaab10
--- /dev/null
@@ -0,0 +1,172 @@
+--TEST--
+mysqli_fetch_field() - flags/field->flags
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+       include "connect.inc";
+
+       $flags = array(
+               MYSQLI_NOT_NULL_FLAG => 'NOT_NULL',
+               MYSQLI_PRI_KEY_FLAG => 'PRI_KEY',
+               MYSQLI_UNIQUE_KEY_FLAG => 'UNIQUE_KEY',
+               MYSQLI_MULTIPLE_KEY_FLAG => 'MULTIPLE_KEY',
+               MYSQLI_BLOB_FLAG => 'BLOB',
+               MYSQLI_UNSIGNED_FLAG    => 'UNSIGNED',
+               MYSQLI_ZEROFILL_FLAG => 'ZEROFILL',
+               MYSQLI_AUTO_INCREMENT_FLAG => 'AUTO_INCREMENT',
+               MYSQLI_TIMESTAMP_FLAG   => 'TIMESTAMP',
+               MYSQLI_SET_FLAG => 'SET',
+               MYSQLI_NUM_FLAG => 'NUM',
+               MYSQLI_PART_KEY_FLAG => 'PART_KEY',
+               MYSQLI_GROUP_FLAG => 'MYSQLI_GROUP_FLAG'
+               // MYSQLI_NO_DEFAULT_VALUE_FLAG
+               // MYSQLI_BINARY_FLAG
+               // MYSQLI_ENUM_FLAG
+               // MYSQLI_BINCMP_FLAG
+       );
+       krsort($flags);
+
+       $columns = array(
+               'INT DEFAULT NULL' => 'NUM',
+               'INT NOT NULL' => 'NOT_NULL NO_DEFAULT_VALUE NUM',
+               'INT NOT NULL DEFAULT 1' => 'NOT_NULL NUM',
+               'INT UNSIGNED DEFAULT NULL' => 'UNSIGNED NUM',
+               'INT UNSIGNED NOT NULL' => 'NOT_NULL UNSIGNED NO_DEFAULT_VALUE NUM',
+               'INT UNSIGNED NOT NULL DEFAULT 1' => 'NOT_NULL UNSIGNED NULL',
+               'INT UNSIGNED ZEROFILL DEFAULT NULL' => 'UNSIGNED ZEROFILL NUM',
+               'INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY' => 'NOT_NULL PRI_KEY UNSIGNED AUTO_INCREMENT NUM PART_KEY',
+               'CHAR(1) DEFAULT NULL'  => '',
+               'CHAR(1) NOT NULL' => 'NOT_NULL NO_DEFAULT_VALUE',
+               'TIMESTAMP NOT NULL' => 'NOT_NULL UNSIGNED ZEROFILL BINARY TIMESTAMP',
+               'VARBINARY(127) DEFAULT NULL' => 'NOT_NULL BINARY',
+               'BLOB'  => 'BLOB BINARY',
+               'TINYBLOB'      => 'BLOB BINARY',
+               'MEDIUMBLOB'    => 'BLOB BINARY',
+               'LONGBLOB'      => 'BLOB BINARY',
+               'TEXT'  => 'BLOB',
+               'TINYTEXT'      => 'BLOB',
+               'MEDIUMTEXT'    => 'BLOB',
+               'LONGTEXT'      => 'BLOB',
+               'SET("one", "two")'     => 'SET',
+               'SET("one", "two") NOT NULL'    => 'NOT_NULL SET NO_DEFAULT_VALUE',
+               'SET("one", "two") NOT NULL DEFAULT "one"'      => 'NOT_NULL SET',
+               'ENUM("one", "two")'    => 'ENUM',
+               'ENUM("one", "two") NOT NULL' => 'NOT_NULL ENUM NO_DEFAULT_VALUE',
+               'ENUM("one", "two") NOT NULL DEFAULT "one"' => 'NOT_NULL ENUM',
+               'TINYINT UNIQUE' => 'UNIQUE_KEY NUM PART_KEY',
+               'SMALLINT UNIQUE' => 'UNIQUE_KEY NUM PART_KEY',
+               'MEDIUMINT UNIQUE DEFAULT 1' => 'UNIQUE_KEY NUM PART_KEY',
+               'BIGINT UNSIGNED UNIQUE DEFAULT 100' => 'UNIQUE_KEY UNSIGNED NUM PART_KEY',
+               'BIT' => 'UNSIGNED',
+               'VARCHAR(2) NOT NULL PRIMARY KEY' => 'NOT_NULL PRI_KEY NO_DEFAULT_VALUE PART_KEY'
+       );
+
+       function checkFlags($reported_flags, $expected_flags, $flags) {
+
+               $found_flags = $unexpected_flags = '';
+               foreach ($flags as $code => $name) {
+                       if ($code >= $reported_flags) {
+                               $reported_flags -= $code;
+                               $found_flags .= $name . ' ';
+                               if (stristr($expected_flags, $name)) {
+                                       $expected_flags = trim(str_ireplace($name, '', $expected_flags));
+                               } else {
+                                       $unexpected_flags .= $name . ' ';
+                               }
+                       }
+               }
+
+               return array($expected_flags, $unexpected_flags, $found_flags);
+       }
+
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+       foreach ($columns as $column_def => $expected_flags) {
+               if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+                       printf("[002] %s [%d] %s\n", $column_def,
+                               mysqli_errno($link), mysqli_error($link));
+                       continue;
+               }
+
+               $create = sprintf('CREATE TABLE test(id INT, col1 %s)', $column_def);
+               if (!mysqli_query($link, $create)) {
+                       // Server might not support it - skip
+                       continue;
+               }
+
+               if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+                       printf("[003] Can't select from table, %s [%d] %s\n", $column_def,
+                               mysqli_errno($link), mysqli_error($link));
+                       continue;
+               }
+
+               $field = mysqli_fetch_field_direct($res, 1);
+               if (!is_object($field)) {
+                       printf("[004] Fetching the meta data failed, %s [%d] %s\n", $column_def,
+                               mysqli_errno($link), mysqli_error($link));
+                       continue;
+               }
+               if ($field->name != 'col1') {
+                       printf("[005] Field information seems wrong, %s [%d] %s\n", $column_def,
+                               mysqli_errno($link), mysqli_error($link));
+                       continue;
+               }
+
+               list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags, $flags);
+               if ($unexpected_flags)
+                       printf("[006] Found unexpected flags '%s' for %s, found '%s'\n",
+                               $unexpected_flags, $column_def, $flags_found);
+               if ($missing_flags)
+                       printf("[007] The flags '%s' have not been reported for %s, found '%s'\n",
+                               $missing_flags, $column_def, $flags_found);
+
+               mysqli_free_result($res);
+       }
+
+       if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+               printf("[008] %s [%d] %s\n", $column_def,
+                       mysqli_errno($link), mysqli_error($link));
+               continue;
+       }
+
+       $column_def = array('col1 CHAR(1)', 'col2 CHAR(2)','INDEX idx_col1_col2(col1, col2)');
+       $expected_flags = array('col1' => 'MULTIPLE_KEY PART_KEY', 'col2' => 'PART_KEY');
+       $create = 'CREATE TABLE test(id INT, ';
+       foreach ($column_def as $k => $v) {
+               $create .= sprintf('%s, ', $v);
+       }
+       $create = sprintf('%s)', substr($create, 0, -2));
+
+       if (mysqli_query($link, $create)) {
+               if (!$res = mysqli_query($link, 'SELECT * FROM test')) {
+                       printf("[009] Cannot run SELECT, [%d] %s\n",
+                               mysqli_errno($link), mysqli_error($link));
+               }
+               // id column - skip it
+               $field = mysqli_fetch_field($res);
+               while ($field = mysqli_fetch_field($res)) {
+                       if (!isset($expected_flags[$field->name])) {
+                               printf("[010] Found unexpected field '%s'\n", $field->name);
+                               continue;
+                       }
+                       list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags[$field->name], $flags);
+                       if ($unexpected_flags)
+                               printf("[011] Found unexpected flags '%s' for %s, found '%s'\n",
+                                       $unexpected_flags, $field->name, $flags_found);
+                       if ($missing_flags)
+                               printf("[012] The flags '%s' have not been reported for %s, found '%s'\n",
+                                       $missing_flags, $field->name, $flags_found);
+               }
+       }
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_fetch_field_types.phpt b/ext/mysqli/tests/mysqli_fetch_field_types.phpt
new file mode 100644 (file)
index 0000000..84038c4
--- /dev/null
@@ -0,0 +1,119 @@
+--TEST--
+mysqli_fetch_field() - data types/field->type
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+       include "connect.inc";
+       require('table.inc');
+
+       function mysqli_field_datatypes($link, $sql_type, $php_value, $php_type, $datatypes) {
+               if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+                       printf("[001] %s, [%d] %s\n", $sql_type,
+                               mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               $sql = sprintf("CREATE TABLE test(id %s)", $sql_type);
+               if (!mysqli_query($link, $sql)) {
+                       printf("[002] %s, [%d] %s\n", $sql_type,
+                               mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               $sql = sprintf("INSERT INTO test(id) VALUES ('%s')", $php_value);
+               if (!mysqli_query($link, $sql)) {
+                       printf("[003] %s, [%d] %s\n", $sql_type,
+                               mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               if (!$res = mysqli_query($link, 'SELECT id FROM test')) {
+                       printf("[004] %s, [%d] %s\n", $sql_type,
+                               mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               if (!is_object($field = mysqli_fetch_field($res))) {
+                       printf("[004] %s, expecting object got %s, [%d] %s\n", $sql_type,
+                               gettype($field),
+                               mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               if ($field->type != $php_type) {
+                       $code_name = 'unknown';
+                       foreach ($datatypes as $k => $v) {
+                               if ($k == $field->type) {
+                                       $code_name = (is_array($v)) ? $v[0] : $v;
+                                       break;
+                               }
+                       }
+                       printf("[006] Expecting %d for %s got code %d for %s\n",
+                               $php_type, $sql_type, $field->type, $code_name);
+                       return false;
+               }
+
+               return true;
+       }
+
+       $datatypes = array(
+               MYSQLI_TYPE_TINY => array('TINYINT', 5),
+               MYSQLI_TYPE_SHORT => array('SMALLINT', 10),
+               MYSQLI_TYPE_LONG => 'MYSQLI_TYPE_LONG - TODO add testing',
+               MYSQLI_TYPE_FLOAT => array('FLOAT', '1.3'),
+               MYSQLI_TYPE_DOUBLE => array('DOUBLE', '1.4'),
+               MYSQLI_TYPE_TIMESTAMP => array('TIMESTAMP', '2007-08-20 18:34:00'),
+               MYSQLI_TYPE_LONGLONG => array('BIGINT', 100),
+               MYSQLI_TYPE_INT24       => array('MEDIUMINT', 10),
+               MYSQLI_TYPE_DATE => array('DATE', '2007-08-20'),
+               MYSQLI_TYPE_TIME => array('TIME', '18:41:38'),
+               MYSQLI_TYPE_DATETIME => array('DATETIME', '2007-08-20 18:42:01'),
+               MYSQLI_TYPE_YEAR => array('YEAR', '2007'),
+               MYSQLI_TYPE_ENUM => array('ENUM("everything", "is", "just", "wonderful")', 'is'),
+               // MYSQLI_TYPE_SET      => array('SET("I", "smash", "the")', 'I,smash,the'), - string
+               // MYSQLI_TYPE_TINY_BLOB => array("TINYBLOB", "I got a tiny blog"), - blob
+               // MYSQLI_TYPE_MEDIUM_BLOB => array("MEDIUMBLOB", "No blob for masses"), - blob
+               // MYSQLI_TYPE_LONG_BLOB => array("LONGBLOB", "Small is beautiful?"), - blob
+               MYSQLI_TYPE_BLOB => array("LONGBLOB", 'MySQL does not report proper type. Use Length to distinct BLOB types'),
+               MYSQLI_TYPE_BLOB => array("MEDIUMBLOB", 'MySQL does not report proper type. Use Length to distinct BLOB types'),
+               MYSQLI_TYPE_BLOB => array("TINYBLOB", 'MySQL does not report proper type. Use Length to distinct BLOB types'),
+               MYSQLI_TYPE_BLOB => array("BLOB", 'silly'),
+               MYSQLI_TYPE_VAR_STRING => array("VARCHAR(32768)", 'varchar'),
+               MYSQLI_TYPE_STRING => 'MYSQLI_TYPE_STRING - TODO add testing',
+               MYSQLI_TYPE_STRING => array('CHAR(1)', 'a'),
+               MYSQLI_TYPE_STRING => array('SET("I", "smash", "the")', 'Will be converted to string although it is a SET...'),
+               MYSQLI_TYPE_NULL => 'MYSQLI_TYPE_NULL - TODO add testing',
+               MYSQLI_TYPE_NEWDATE => 'MYSQLI_TYPE_NEWDATE - TODO add testing',
+               MYSQLI_TYPE_INTERVAL => 'MYSQLI_TYPE_INTERVAL - TODO add testing',
+               MYSQLI_TYPE_GEOMETRY => 'MYSQLI_TYPE_GEOMETRY - TODO add testing',
+       );
+
+       if ($IS_MYSQLND) {
+               $version = 50007 + 1;
+       } else {
+               $version = mysqli_get_client_version();
+       }
+
+       if ($version > 50002) {
+               $datatypes[MYSQLI_TYPE_NEWDECIMAL] = array('DECIMAL', '1.1');
+               $datatypes[MYSQLI_TYPE_BIT] = array('BIT', 0);
+       } else {
+               $datatypes[MYSQLI_TYPE_DECIMAL] = array('DECIMAL', '1.1');
+       }
+
+       foreach ($datatypes as $php_type => $datatype) {
+               if (is_array($datatype))
+                       mysqli_field_datatypes($link, $datatype[0], $datatype[1], $php_type, $datatypes);
+       }
+
+       mysqli_close($link);
+
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file