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