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