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