1--TEST--
2MySQL PDO->__construct() - Generic + DSN
3--SKIPIF--
4<?php
5require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
6require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
7MySQLPDOTest::skip();
8?>
9--FILE--
10<?php
11    require_once(__DIR__ . 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                // 1044 may occur here if running tests using a custom user that does not have access to all databases
154                if (!stristr($tmp, '42000') && !stristr($tmp, '1049') && !stristr($tmp, '1044'))
155                    printf("[022] Cannot find proper error codes: %s\n", $tmp);
156            }
157
158            $dsn = MySQLPDOTest::getDSN(array('dbname' => $invalid_db), 'dbname=' . $db);
159            try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) {
160                printf("[023] DSN=%s, %s\n", $dsn, $e->getMessage());
161            }
162
163        }
164
165        if (PDO_MYSQL_TEST_SOCKET && (stristr(PDO_MYSQL_TEST_DSN, PDO_MYSQL_TEST_SOCKET) !== false)) {
166            $socket = PDO_MYSQL_TEST_SOCKET;
167            $invalid_socket = '/lets/hope/it/does/not/exist';
168
169            $dsn = MySQLPDOTest::getDSN(array('unix_socket' => $socket), 'unix_socket=' . $invalid_socket);
170            try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) {
171                $tmp = $e->getMessage();
172                if (!stristr($tmp, 'HY000') && !stristr($tmp, '2002'))
173                    printf("[024] Cannot find proper error codes: %s\n", $tmp);
174            }
175
176            $dsn = MySQLPDOTest::getDSN(array('unix_socket' => $invalid_socket), 'unix_socket=' . $socket);
177            try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) {
178                printf("[025] DSN=%s, %s\n", $dsn, $e->getMessage());
179            }
180
181        }
182
183        $have_charset_support = false;
184        $dsn = MySQLPDOTest::getDSN();
185        try {
186            $db = new PDO($dsn, $user, $pass);
187            $stmt = $db->query('SELECT VERSION() as _version');
188            $version = $stmt->fetch(PDO::FETCH_ASSOC);
189
190            $tmp = explode('.', $version['_version']);
191            if ((count($tmp) == 3) &&
192                    (($tmp[0] >= 4 && $tmp[1] >= 1) || ($tmp[0] >= 5))) {
193                // MySQL Server 4.1 - charset support available
194                $have_charset_support = true;
195            }
196
197        } catch (PDOException $e) {
198            printf("[026] DSN=%s, %s\n", $dsn, $e->getMessage());
199        }
200
201        if (PDO_MYSQL_TEST_CHARSET) {
202            $charset = PDO_MYSQL_TEST_CHARSET;
203            $invalid_charset = 'invalid';
204
205            if ($have_charset_support) {
206                $dsn = MySQLPDOTest::getDSN();
207                $db = new PDO($dsn, $user, $pass);
208                $stmt = $db->query(sprintf('SHOW CHARACTER SET LIKE "%s"', $charset));
209                $tmp = $stmt->fetch(PDO::FETCH_ASSOC);
210                $have_charset = (empty($tmp)) ? false : true;
211
212                if ($have_charset) {
213                    $dsn = MySQLPDOTest::getDSN(array('charset' => $charset), 'charset=' . $invalid_charset);
214                    try {
215                        $db = @new PDO($dsn, $user, $pass);
216                        /* NOTE: MySQL does a fallback to the charset suggested during the handshake - no error - no bug! */
217                    } catch (PDOException $e) {
218                        $tmp = $e->getMessage();
219                        /* TODO: add proper codes */
220                        if (!stristr($tmp, 'sqlstatecode') || !stristr($tmp, 'mysqlinternalerrcode'))
221                            printf("[027] TODO - Cannot find proper error codes: %s\n", $tmp);
222                    }
223
224                    $dsn = MySQLPDOTest::getDSN(array('charset' => $invalid_charset), 'charset=' . $charset);
225                    try {
226                        $db = @new PDO($dsn, $user, $pass);
227                        /* Strictly speaking we should test more: character_set_client, character_set_results, and character_set_connection */
228                        $stmt = $db->query('SELECT @@character_set_connection AS _charset');
229                        $tmp = $stmt->fetch(PDO::FETCH_ASSOC);
230                        if ($tmp['_charset'] != $charset)
231                            printf("[028] Character sets has not been set, @@character_set_connection reports '%s', expecting '%s'",
232                                $tmp['_charset'], $charset);
233                    } catch (PDOException $e) {
234                        printf("[029] DSN=%s, %s\n", $dsn, $e->getMessage());
235                    }
236                } else {
237                    printf("[030] You're trying to run the tests with charset '%s' which seems not supported by the server!", $charset);
238                }
239
240            }
241
242        }
243
244        if ($have_charset_support) {
245            // In case the PDO_MYSQL_TEST_CHARSET interferes with any defaults
246            // we do another test to verify that the charset has been set.
247            $dsn = MySQLPDOTest::getDSN();
248            $db = new PDO($dsn, $user, $pass);
249            $stmt = $db->query('SHOW CHARACTER SET LIKE "latin1"');
250            $tmp = $stmt->fetch(PDO::FETCH_ASSOC);
251            $have_latin1 =(empty($tmp)) ? false : true;
252            $stmt = $db->query('SHOW CHARACTER SET LIKE "latin2"');
253            $tmp = $stmt->fetch(PDO::FETCH_ASSOC);
254            $have_latin2 =(empty($tmp)) ? false : true;
255
256            if ($have_latin1 && $have_latin2) {
257                // very likely we do have both of them...
258                try {
259                    $dsn = MySQLPDOTest::getDSN(array('charset' => 'latin1'));
260                    $db = new PDO($dsn, $user, $pass);
261                    $stmt = $db->query('SELECT @@character_set_connection AS _charset');
262                    $tmp = $stmt->fetch(PDO::FETCH_ASSOC);
263                    if ($tmp['_charset'] != 'latin1')
264                        printf("[031] DSN = %s, Character sets has not been set, @@character_set_connection reports '%s', expecting '%s'",
265                            $dsn, $tmp['_charset'], 'latin1');
266
267                } catch (PDOException $e) {
268                    printf("[032] %s\n", $e->getMessage());
269                }
270
271                try {
272                    $dsn = MySQLPDOTest::getDSN(array('charset' => 'latin2'));
273                    $db = new PDO($dsn, $user, $pass);
274                    $stmt = $db->query('SELECT @@character_set_connection AS _charset');
275                    $tmp = $stmt->fetch(PDO::FETCH_ASSOC);
276                    if ($tmp['_charset'] != 'latin2')
277                        printf("[033] DSN = %s, character sets has not been set, @@character_set_connection reports '%s', expecting '%s'",
278                            $dsn, $tmp['_charset'], 'latin2');
279
280                } catch (PDOException $e) {
281                    printf("[034] %s\n", $e->getMessage());
282                }
283
284            }
285        }
286
287    } catch (PDOException $e) {
288        printf("[001] %s, [%s] %s\n",
289            $e->getMessage(),
290            (is_object($db)) ? $db->errorCode() : 'n/a',
291            (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a');
292    }
293
294    print "done!";
295?>
296--EXPECTF--
297[002] PDO::__construct(): Argument #1 ($dsn) must be a valid data source name, [n/a] n/a
298[003] PDO::__construct(): Argument #1 ($dsn) must be a valid data source name, [n/a] n/a
299[004] PDO::__construct(): Argument #1 ($dsn) must be a valid data source name, [n/a] n/a
300[005] PDO::__construct(): Argument #1 ($dsn) must be a valid data source name, [n/a] n/a
301[006] PDO::__construct(): Argument #1 ($dsn) must be a valid data source name, [n/a] n/a
302[007] could not find driver, [n/a] n/a
303[009] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a
304[017] DSN=%s, SQLSTATE[%s] [%d] %s
305done!
306