1--TEST--
2MySQL PDO->__construct() - Generic + DSN
3--SKIPIF--
4<?php
5require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
6require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
7MySQLPDOTest::skip();
8?>
9--FILE--
10<?php
11	require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
12
13	function tryandcatch($offset, $code) {
14
15		try {
16			eval($code);
17			assert(sprintf("[%03d] Should have failed\n", $offset) != '');
18		} catch (PDOException $e) {
19			return sprintf("[%03d] %s, [%s] %s\n",
20				$offset,
21				$e->getMessage(),
22				(isset($db) && is_object($db)) ? $db->errorCode() : 'n/a',
23				(isset($db) && is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a');
24		}
25
26		return '';
27	}
28
29	try {
30
31		if (NULL !== ($db = @new PDO()))
32			printf("[001] Too few parameters\n");
33
34		print tryandcatch(2, '$db = new PDO(chr(0));');
35		print tryandcatch(3, '$db = new PDO("a" . chr(0) . "b");');
36		print tryandcatch(4, '$db = new PDO("MYSQL");');
37		print tryandcatch(5, '$db = new PDO("mysql");');
38		print tryandcatch(6, '$db = new PDO("mysql ");');
39		print tryandcatch(7, '$db = new PDO("fantasyandfriends :");');
40
41		$dsn = PDO_MYSQL_TEST_DSN;
42		// MySQL Server might accept anonymous connections, don't
43		// print anything
44		tryandcatch(8, '$db = new PDO("' . $dsn . '");');
45
46		$user = 'dontcreatesuchauser';
47		$pass = 'withthispassword';
48		print tryandcatch(9, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");');
49
50		// should fail
51		$dsn = 'mysql:';
52		print tryandcatch(10, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");');
53
54		$dsn = PDO_MYSQL_TEST_DSN;
55		$user = PDO_MYSQL_TEST_USER;
56		$pass	= PDO_MYSQL_TEST_PASS;
57		// should work...
58		$db = new PDO($dsn, $user, $pass);
59
60		$dsn = 'mysql:invalid=foo';
61		print tryandcatch(11, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");');
62
63		$dsn = 'mysql:' . str_repeat('howmuch=canpdoeat;', 1000);
64		print tryandcatch(12, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");');
65
66		$dsn = 'mysql:' . str_repeat('abcdefghij', 1024 * 10) . '=somevalue';
67		print tryandcatch(13, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");');
68
69		if (PDO_MYSQL_TEST_HOST) {
70			$host = PDO_MYSQL_TEST_HOST;
71			$invalid_host = $host . 'invalid';
72
73			// last host specification should be the one used
74			$dsn = MySQLPDOTest::getDSN(array('host' => $host), 'host=' . $invalid_host);
75			try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
76				$tmp = $e->getMessage();
77				if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005') && !stristr($tmp, '2002'))
78					printf("[014] Cannot find proper error codes: %s\n", $tmp);
79			}
80
81			$dsn = MySQLPDOTest::getDSN(array('host' => $invalid_host), 'host=' . $host);
82			try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) {
83				printf("[015] DSN=%s, %s\n", $dsn, $e->getMessage());
84			}
85
86			$invalid_host = '-' . chr(0);
87
88			$dsn = MySQLPDOTest::getDSN(array('host' => $invalid_host));
89			try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
90				$tmp = $e->getMessage();
91				if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005') && !stristr($tmp, '2002'))
92					printf("[016] Cannot find proper error codes: %s\n", $tmp);
93			}
94
95			// parsing should not get confused by chr(0)
96			$dsn = MySQLPDOTest::getDSN(array('host' => $invalid_host), 'host=' . $host);
97			try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) {
98				printf("[017] DSN=%s, %s\n", $dsn, $e->getMessage());
99			}
100
101		}
102
103		// what about long values for a valid option ...
104		// hostnames > 1024 chars break on some NIS-enabled FreeBSD...
105		$dsn = MySQLPDOTest::getDSN(array('host' => str_repeat('0123456789', 100)));
106		try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
107			$tmp = $e->getMessage();
108			if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005') && !stristr($tmp, '2002'))
109				printf("[018] Cannot find proper error codes: %s\n", $tmp);
110		}
111
112		if (PDO_MYSQL_TEST_PORT && (PDO_MYSQL_TEST_SOCKET == '')) {
113			// Playing with the port makes only sense if no socket gets used
114
115			$port = PDO_MYSQL_TEST_PORT;
116			// let's hope we don't hit a MySQL running on that port...
117			$invalid_port = $port * 2;
118
119			$dsn = MySQLPDOTest::getDSN(array('port' => $port), 'port=' . $invalid_port);
120			try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
121				$tmp = $e->getMessage();
122				if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005'))
123					printf("[019] Cannot find proper error codes: %s\n", $tmp);
124			}
125
126			$dsn = MySQLPDOTest::getDSN(array('port' => $invalid_port), 'port=' . $port);
127			try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) {
128				printf("[020] DSN=%s, %s\n", $dsn, $e->getMessage());
129			}
130
131			$invalid_port = 'abc';
132			$dsn = MySQLPDOTest::getDSN(array('port' => $port), 'port=' . $invalid_port);
133			try {
134				$db = @new PDO($dsn, $user, $pass);
135				// atoi('abc') = 0, 0 -> fallback to default 3306 -> may or may not fail!
136			} catch (PDOException $e) {
137			}
138
139		}
140
141		if (PDO_MYSQL_TEST_DB) {
142			$db = PDO_MYSQL_TEST_DB;
143			$invalid_db = 'letshopeitdoesnotexist';
144
145			$dsn = MySQLPDOTest::getDSN(array('dbname' => $db), 'dbname=' . $invalid_db);
146			try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
147				$tmp = $e->getMessage();
148				if (!stristr($tmp, '42000') && !stristr($tmp, '1049'))
149					printf("[022] Cannot find proper error codes: %s\n", $tmp);
150			}
151
152			$dsn = MySQLPDOTest::getDSN(array('dbname' => $invalid_db), 'dbname=' . $db);
153			try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) {
154				printf("[023] DSN=%s, %s\n", $dsn, $e->getMessage());
155			}
156
157		}
158
159		if (PDO_MYSQL_TEST_SOCKET && (stristr(PDO_MYSQL_TEST_DSN, PDO_MYSQL_TEST_SOCKET) !== false)) {
160			$socket = PDO_MYSQL_TEST_SOCKET;
161			$invalid_socket = '/lets/hope/it/does/not/exist';
162
163			$dsn = MySQLPDOTest::getDSN(array('unix_socket' => $socket), 'unix_socket=' . $invalid_socket);
164			try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
165				$tmp = $e->getMessage();
166				if (!stristr($tmp, 'HY000') && !stristr($tmp, '2002'))
167					printf("[024] Cannot find proper error codes: %s\n", $tmp);
168			}
169
170			$dsn = MySQLPDOTest::getDSN(array('unix_socket' => $invalid_socket), 'unix_socket=' . $socket);
171			try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) {
172				printf("[025] DSN=%s, %s\n", $dsn, $e->getMessage());
173			}
174
175		}
176
177		$have_charset_support = false;
178		$dsn = MySQLPDOTest::getDSN();
179		try {
180			$db = new PDO($dsn, $user, $pass);
181			$stmt = $db->query('SELECT VERSION() as _version');
182			$version = $stmt->fetch(PDO::FETCH_ASSOC);
183
184			$tmp = explode('.', $version['_version']);
185			if ((count($tmp) == 3) &&
186					(($tmp[0] >= 4 && $tmp[1] >= 1) || ($tmp[0] >= 5))) {
187				// MySQL Server 4.1 - charset support available
188				$have_charset_support = true;
189			}
190
191		} catch (PDOException $e) {
192			printf("[026] DSN=%s, %s\n", $dsn, $e->getMessage());
193		}
194
195		if (PDO_MYSQL_TEST_CHARSET) {
196			$charset = PDO_MYSQL_TEST_CHARSET;
197			$invalid_charset = 'invalid';
198
199			if ($have_charset_support) {
200				$dsn = MySQLPDOTest::getDSN();
201				$db = new PDO($dsn, $user, $pass);
202				$stmt = $db->query(sprintf('SHOW CHARACTER SET LIKE "%s"', $charset));
203				$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
204				$have_charset = (empty($tmp)) ? false : true;
205
206				if ($have_charset) {
207					$dsn = MySQLPDOTest::getDSN(array('charset' => $charset), 'charset=' . $invalid_charset);
208					try {
209						$db = @new PDO($dsn, $user, $pass);
210						/* NOTE: MySQL does a fallback to the charset suggested during the handshake - no error - no bug! */
211					} catch (PDOException $e) {
212						$tmp = $e->getMessage();
213						/* TODO: add proper codes */
214						if (!stristr($tmp, 'sqlstatecode') || !stristr($tmp, 'mysqlinternalerrcode'))
215							printf("[027] TODO - Cannot find proper error codes: %s\n", $tmp);
216					}
217
218					$dsn = MySQLPDOTest::getDSN(array('charset' => $invalid_charset), 'charset=' . $charset);
219					try {
220						$db = @new PDO($dsn, $user, $pass);
221						/* Strictly speaking we should test more: character_set_client, character_set_results, and character_set_connection */
222						$stmt = $db->query('SELECT @@character_set_connection AS _charset');
223						$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
224						if ($tmp['_charset'] != $charset)
225							printf("[028] Character sets has not been set, @@character_set_connection reports '%s', expecting '%s'",
226								$tmp['_charset'], $charset);
227					} catch (PDOException $e) {
228						printf("[029] DSN=%s, %s\n", $dsn, $e->getMessage());
229					}
230				} else {
231					printf("[030] You're trying to run the tests with charset '%s' which seems not supported by the server!", $charset);
232				}
233
234			}
235
236		}
237
238		if ($have_charset_support) {
239			// In case the PDO_MYSQL_TEST_CHARSET interferes with any defaults
240			// we do another test to verify that the charset has been set.
241			$dsn = MySQLPDOTest::getDSN();
242			$db = new PDO($dsn, $user, $pass);
243			$stmt = $db->query('SHOW CHARACTER SET LIKE "latin1"');
244			$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
245			$have_latin1 =(empty($tmp)) ? false : true;
246			$stmt = $db->query('SHOW CHARACTER SET LIKE "latin2"');
247			$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
248			$have_latin2 =(empty($tmp)) ? false : true;
249
250			if ($have_latin1 && $have_latin2) {
251				// very likely we do have both of them...
252				try {
253					$dsn = MySQLPDOTest::getDSN(array('charset' => 'latin1'));
254					$db = new PDO($dsn, $user, $pass);
255					$stmt = $db->query('SELECT @@character_set_connection AS _charset');
256					$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
257					if ($tmp['_charset'] != 'latin1')
258						printf("[031] DSN = %s, Character sets has not been set, @@character_set_connection reports '%s', expecting '%s'",
259							$dsn, $tmp['_charset'], 'latin1');
260
261				} catch (PDOException $e) {
262					printf("[032] %s\n", $e->getMessage());
263				}
264
265				try {
266					$dsn = MySQLPDOTest::getDSN(array('charset' => 'latin2'));
267					$db = new PDO($dsn, $user, $pass);
268					$stmt = $db->query('SELECT @@character_set_connection AS _charset');
269					$tmp = $stmt->fetch(PDO::FETCH_ASSOC);
270					if ($tmp['_charset'] != 'latin2')
271						printf("[033] DSN = %s, character sets has not been set, @@character_set_connection reports '%s', expecting '%s'",
272							$dsn, $tmp['_charset'], 'latin2');
273
274				} catch (PDOException $e) {
275					printf("[034] %s\n", $e->getMessage());
276				}
277
278			}
279		}
280
281	} catch (PDOException $e) {
282		printf("[001] %s, [%s] %s\n",
283			$e->getMessage(),
284			(is_object($db)) ? $db->errorCode() : 'n/a',
285			(is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a');
286	}
287
288	print "done!";
289?>
290--EXPECTF--
291[002] invalid data source name, [n/a] n/a
292[003] invalid data source name, [n/a] n/a
293[004] invalid data source name, [n/a] n/a
294[005] invalid data source name, [n/a] n/a
295[006] invalid data source name, [n/a] n/a
296[007] could not find driver, [n/a] n/a
297[009] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a
298[010] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a
299[017] DSN=%s, SQLSTATE[%s] [%d] %s
300[033] DSN = mysql:%s, character sets has not been set, @@character_set_connection reports 'latin1', expecting 'latin2'done!
301