1--TEST--
2mysqli_poll() & references
3--SKIPIF--
4<?php
5require_once('skipif.inc');
6require_once('connect.inc');
7require_once('skipifconnectfailure.inc');
8
9if (!$IS_MYSQLND)
10    die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
11
12if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
13    die("skip cannot connect");
14
15if (mysqli_get_server_version($link) < 50012)
16    die("skip Test needs SQL function SLEEP() available as of MySQL 5.0.12");
17
18?>
19--FILE--
20<?php
21    require_once('connect.inc');
22
23    function get_connection() {
24        global $host, $user, $passwd, $db, $port, $socket;
25
26        if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
27            printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
28        return $link;
29    }
30
31
32    $mysqli1 = get_connection();
33    $mysqli2 = get_connection();
34
35    var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
36    var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
37
38    $processed = $loops = 0;
39    do {
40        $loops++;
41        if ($loops > 10) {
42            printf("[002] The queries should have finished already\n");
43            break;
44        }
45        // WARNING: All arrays point to the same object - this will give bogus results!
46        // The behaviour is in line with stream_select(). Be warned, be careful.
47        $links = $errors = $reject = array($mysqli1, $mysqli2);
48        if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
49            continue;
50        }
51
52        foreach ($links as $link) {
53            if ($res = mysqli_reap_async_query($link)) {
54                mysqli_free_result($res);
55            }
56            $processed++;
57        }
58    } while ($processed < 2);
59
60    mysqli_close($mysqli1);
61    mysqli_close($mysqli2);
62
63    $mysqli1 = get_connection();
64    $mysqli2 = get_connection();
65
66    var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
67    var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
68
69    $processed = $loops = 0;
70    do {
71        $loops++;
72        if ($loops > 10) {
73            printf("[003] The queries should have finished already\n");
74            break;
75        }
76        // WARNING: All arrays point to the same object - this will give bogus results!
77        $links = $errors = array($mysqli1, $mysqli2);
78        $reject = array($mysqli1, $mysqli2);
79        if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
80            continue;
81        }
82        foreach ($links as $link) {
83            if ($res = mysqli_reap_async_query($link)) {
84                mysqli_free_result($res);
85            }
86            $processed++;
87        }
88    } while ($processed < 2);
89
90    mysqli_close($mysqli1);
91    mysqli_close($mysqli2);
92
93    $mysqli1 = get_connection();
94    $mysqli2 = get_connection();
95
96    var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
97    var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
98
99    $processed = $loops = 0;
100    do {
101        $loops++;
102        if ($loops > 10) {
103            printf("[004] The queries should have finished already\n");
104            break;
105        }
106        // WARNING: All arrays point to the same object - this will give bogus results!
107        $links = array($mysqli1, $mysqli2);
108        $errors = $reject = array($mysqli1, $mysqli2);
109        if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
110            continue;
111        }
112        foreach ($links as $link) {
113            if ($res = mysqli_reap_async_query($link)) {
114                mysqli_free_result($res);
115            }
116            $processed++;
117        }
118    } while ($processed < 2);
119
120    mysqli_close($mysqli1);
121    mysqli_close($mysqli2);
122
123    // This is bogus code and bogus usage - OK to throw no errors!
124    $mysqli1 = get_connection();
125    $mysqli2 = get_connection();
126
127    var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
128    $thread_id = mysqli_thread_id($mysqli2);
129    printf("Connection %d should be rejected...\n", $thread_id);
130
131    $processed = $loops = 0;
132    do {
133        $loops++;
134        if ($loops > 10) {
135            printf("[005] The queries should have finished already\n");
136            break;
137        }
138        $links = $errors = $reject = array($mysqli1, $mysqli2);
139        if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
140            continue;
141        }
142        // WARNING: Due to the reference issue none of these should ever fire!
143        foreach ($reject as $link) {
144            printf("Connection %d was rejected...\n", mysqli_thread_id($link));
145            if (mysqli_thread_id($link) != $thread_id) {
146                printf("[006] Connector %d should have been rejected. But also %d has been rejected.",
147                  $thread_id, mysqli_thread_id($link));
148            }
149            $processed++;
150        }
151        foreach ($errors as $link) {
152            printf("Connection %d has an error...\n", mysqli_thread_id($link));
153            $processed++;
154        }
155        foreach ($links as $link) {
156            if ($res = mysqli_reap_async_query($link)) {
157                mysqli_free_result($res);
158                $processed++;
159            }
160        }
161    } while ($processed < 2);
162
163    mysqli_close($mysqli1);
164    mysqli_close($mysqli2);
165
166    $mysqli1 = get_connection();
167    $mysqli2 = get_connection();
168
169    var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
170    var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT));
171
172    $processed = $loops = 0;
173    $all = array($mysqli1, $mysqli2);
174    do {
175        $loops++;
176        if ($loops > 10) {
177            printf("[006] The queries should have finished already\n");
178            break;
179        }
180        $links = $errors = $reject = $all;
181        ob_start();
182        if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) {
183            $tmp = ob_get_contents();
184            ob_end_clean();
185            if ($tmp != '') {
186                printf("Expected error:\n%s\n", $tmp);
187                break;
188            }
189            continue;
190        }
191        foreach ($links as $link) {
192            if ($res = mysqli_reap_async_query($link)) {
193                mysqli_free_result($res);
194            }
195            $processed++;
196        }
197    } while ($processed < 2);
198
199    $ready = mysqli_poll($links, $errors, $reject, 0, 50000);
200    mysqli_close($mysqli1);
201    mysqli_close($mysqli2);
202
203    print "done!";
204?>
205--EXPECTF--
206bool(true)
207bool(true)
208bool(true)
209bool(true)
210bool(true)
211bool(true)
212bool(true)
213Connection %d should be rejected...
214Connection %d was rejected...
215bool(true)
216bool(true)
217
218Warning: mysqli_poll(): All arrays passed are clear in %s on line %d
219done!
220