1--TEST--
2Scalar type basics
3--FILE--
4<?php
5
6$errnames = [
7    E_NOTICE => 'E_NOTICE',
8    E_WARNING => 'E_WARNING',
9];
10set_error_handler(function (int $errno, string $errmsg, string $file, int $line) use ($errnames) {
11    echo "$errnames[$errno]: $errmsg on line $line\n";
12    return true;
13});
14
15$functions = [
16    'int' => function (int $i) { return $i; },
17    'float' => function (float $f) { return $f; },
18    'string' => function (string $s) { return $s; },
19    'bool' => function (bool $b) { return $b; }
20];
21
22class StringCapable implements Stringable {
23    public function __toString() {
24        return "foobar";
25    }
26}
27
28$values = [
29    1,
30    "1",
31    1.0,
32    1.5,
33    "1a",
34    "a",
35    "",
36    PHP_INT_MAX,
37    NAN,
38    TRUE,
39    FALSE,
40    NULL,
41    [],
42    new StdClass,
43    new StringCapable,
44    fopen("data:text/plain,foobar", "r")
45];
46
47foreach ($functions as $type => $function) {
48    echo PHP_EOL, "Testing '$type' type:", PHP_EOL;
49    foreach ($values as $value) {
50        echo PHP_EOL . "*** Trying ";
51        var_dump($value);
52        try {
53            var_dump($function($value));
54        } catch (\TypeError $e) {
55            echo "*** Caught " . $e->getMessage() . PHP_EOL;
56        }
57    }
58}
59echo PHP_EOL . "Done";
60?>
61--EXPECTF--
62Testing 'int' type:
63
64*** Trying int(1)
65int(1)
66
67*** Trying string(1) "1"
68int(1)
69
70*** Trying float(1)
71int(1)
72
73*** Trying float(1.5)
74int(1)
75
76*** Trying string(2) "1a"
77*** Caught {closure}(): Argument #1 ($i) must be of type int, string given, called in %s on line %d
78
79*** Trying string(1) "a"
80*** Caught {closure}(): Argument #1 ($i) must be of type int, string given, called in %s on line %d
81
82*** Trying string(0) ""
83*** Caught {closure}(): Argument #1 ($i) must be of type int, string given, called in %s on line %d
84
85*** Trying int(%d)
86int(%d)
87
88*** Trying float(NAN)
89*** Caught {closure}(): Argument #1 ($i) must be of type int, float given, called in %s on line %d
90
91*** Trying bool(true)
92int(1)
93
94*** Trying bool(false)
95int(0)
96
97*** Trying NULL
98*** Caught {closure}(): Argument #1 ($i) must be of type int, null given, called in %s on line %d
99
100*** Trying array(0) {
101}
102*** Caught {closure}(): Argument #1 ($i) must be of type int, array given, called in %s on line %d
103
104*** Trying object(stdClass)#%s (0) {
105}
106*** Caught {closure}(): Argument #1 ($i) must be of type int, stdClass given, called in %s on line %d
107
108*** Trying object(StringCapable)#%s (0) {
109}
110*** Caught {closure}(): Argument #1 ($i) must be of type int, StringCapable given, called in %s on line %d
111
112*** Trying resource(%d) of type (stream)
113*** Caught {closure}(): Argument #1 ($i) must be of type int, resource given, called in %s on line %d
114
115Testing 'float' type:
116
117*** Trying int(1)
118float(1)
119
120*** Trying string(1) "1"
121float(1)
122
123*** Trying float(1)
124float(1)
125
126*** Trying float(1.5)
127float(1.5)
128
129*** Trying string(2) "1a"
130*** Caught {closure}(): Argument #1 ($f) must be of type float, string given, called in %s on line %d
131
132*** Trying string(1) "a"
133*** Caught {closure}(): Argument #1 ($f) must be of type float, string given, called in %s on line %d
134
135*** Trying string(0) ""
136*** Caught {closure}(): Argument #1 ($f) must be of type float, string given, called in %s on line %d
137
138*** Trying int(%d)
139float(%s)
140
141*** Trying float(NAN)
142float(NAN)
143
144*** Trying bool(true)
145float(1)
146
147*** Trying bool(false)
148float(0)
149
150*** Trying NULL
151*** Caught {closure}(): Argument #1 ($f) must be of type float, null given, called in %s on line %d
152
153*** Trying array(0) {
154}
155*** Caught {closure}(): Argument #1 ($f) must be of type float, array given, called in %s on line %d
156
157*** Trying object(stdClass)#%s (0) {
158}
159*** Caught {closure}(): Argument #1 ($f) must be of type float, stdClass given, called in %s on line %d
160
161*** Trying object(StringCapable)#%s (0) {
162}
163*** Caught {closure}(): Argument #1 ($f) must be of type float, StringCapable given, called in %s on line %d
164
165*** Trying resource(%d) of type (stream)
166*** Caught {closure}(): Argument #1 ($f) must be of type float, resource given, called in %s on line %d
167
168Testing 'string' type:
169
170*** Trying int(1)
171string(1) "1"
172
173*** Trying string(1) "1"
174string(1) "1"
175
176*** Trying float(1)
177string(1) "1"
178
179*** Trying float(1.5)
180string(3) "1.5"
181
182*** Trying string(2) "1a"
183string(2) "1a"
184
185*** Trying string(1) "a"
186string(1) "a"
187
188*** Trying string(0) ""
189string(0) ""
190
191*** Trying int(%d)
192string(%d) "%d"
193
194*** Trying float(NAN)
195string(3) "NAN"
196
197*** Trying bool(true)
198string(1) "1"
199
200*** Trying bool(false)
201string(0) ""
202
203*** Trying NULL
204*** Caught {closure}(): Argument #1 ($s) must be of type string, null given, called in %s on line %d
205
206*** Trying array(0) {
207}
208*** Caught {closure}(): Argument #1 ($s) must be of type string, array given, called in %s on line %d
209
210*** Trying object(stdClass)#%s (0) {
211}
212*** Caught {closure}(): Argument #1 ($s) must be of type string, stdClass given, called in %s on line %d
213
214*** Trying object(StringCapable)#%s (0) {
215}
216string(6) "foobar"
217
218*** Trying resource(%d) of type (stream)
219*** Caught {closure}(): Argument #1 ($s) must be of type string, resource given, called in %s on line %d
220
221Testing 'bool' type:
222
223*** Trying int(1)
224bool(true)
225
226*** Trying string(1) "1"
227bool(true)
228
229*** Trying float(1)
230bool(true)
231
232*** Trying float(1.5)
233bool(true)
234
235*** Trying string(2) "1a"
236bool(true)
237
238*** Trying string(1) "a"
239bool(true)
240
241*** Trying string(0) ""
242bool(false)
243
244*** Trying int(%d)
245bool(true)
246
247*** Trying float(NAN)
248bool(true)
249
250*** Trying bool(true)
251bool(true)
252
253*** Trying bool(false)
254bool(false)
255
256*** Trying NULL
257*** Caught {closure}(): Argument #1 ($b) must be of type bool, null given, called in %s on line %d
258
259*** Trying array(0) {
260}
261*** Caught {closure}(): Argument #1 ($b) must be of type bool, array given, called in %s on line %d
262
263*** Trying object(stdClass)#%s (0) {
264}
265*** Caught {closure}(): Argument #1 ($b) must be of type bool, stdClass given, called in %s on line %d
266
267*** Trying object(StringCapable)#%s (0) {
268}
269*** Caught {closure}(): Argument #1 ($b) must be of type bool, StringCapable given, called in %s on line %d
270
271*** Trying resource(%d) of type (stream)
272*** Caught {closure}(): Argument #1 ($b) must be of type bool, resource given, called in %s on line %d
273
274Done
275