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