1--TEST--
2Test binary operands exposing the same behavior at compile as at run time
3--INI--
4memory_limit=256M
5--SKIPIF--
6<?php
7if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
8?>
9--FILE--
10<?php
11
12$binaryOperators = [
13    "==",
14    "!=",
15    "===",
16    "!==",
17    "<",
18    "<=",
19    ">",
20    ">=",
21    "<=>",
22    "+",
23    "-",
24    "*",
25    "/",
26    "%",
27    "**",
28    ".",
29    "|",
30    "&",
31    "^",
32    "or",
33    "and",
34    "xor",
35    "||",
36    "&&",
37];
38$unaryOperators = [
39    "~",
40    "-",
41    "+",
42    "!",
43];
44
45$input = [
46    0,
47    1,
48    2,
49    -1,
50    2.0,
51    2.1,
52    -2.0,
53    -2.1,
54    PHP_INT_MAX,
55    PHP_INT_MIN,
56    PHP_INT_MAX * 2,
57    PHP_INT_MIN * 2,
58    INF,
59    NAN,
60    [],
61    [1, 2],
62    [1, 2, 3],
63    [1 => 2, 0 => 1],
64    [1, 'a' => 2],
65    [1, 4],
66    [1, 'a'],
67    [1, 2 => 2],
68    [1, [ 2 ]],
69    null,
70    false,
71    true,
72    "",
73    " ",
74    "banana",
75    "Banana",
76    "banan",
77    "0",
78    "200",
79    "20",
80    "20a",
81    " \t\n\r\v\f20",
82    "20  ",
83    "2e1",
84    "2e150",
85    "9179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368",
86    "-9179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368",
87    "0.1",
88    "-0.1",
89    "1e-1",
90    "-20",
91    "-20.0",
92    "0x14",
93    (string) PHP_INT_MAX * 2,
94    (string) PHP_INT_MIN * 2,
95];
96
97function makeParam($param) {
98    if ($param === PHP_INT_MIN) {
99        return "PHP_INT_MIN";
100    }
101    if ($param === PHP_INT_MAX) {
102        return "PHP_INT_MAX";
103    }
104    if (is_string($param)) {
105        return '"' . strtr($param, ["\t" => '\t', "\n" => '\n', "\r" => '\r', "\v" => '\v', "\f" => '\f', '$' => '\$', '"' => '\"']) . '"';
106    }
107    return "(" . str_replace("\n", "", var_export($param, true)) . ")";
108}
109
110$c = 0;
111$f = 0;
112
113function prepareBinaryLine($op1, $op2, $cmp, $operator) {
114    $op1_p = makeParam($op1);
115    $op2_p = makeParam($op2);
116
117    $error = "echo '" . addcslashes("$op1_p $operator $op2_p", "\\'") . '\', "\n"; $f++;';
118
119    $compare = "@($op1_p $operator $op2_p)";
120    $line = "\$c++; ";
121    try {
122        $result = makeParam($cmp());
123        $line .= "if (" . ($result === "(NAN)" ? "!is_nan($compare)" : "$compare !== $result") . ") { $error }";
124    } catch (Error $e) {
125        $msg = makeParam($e->getMessage());
126        $line .= "try { $compare; $error } catch (Error \$e) { if (\$e->getMessage() !== $msg) { $error } }";
127    }
128    return $line;
129}
130function prepareUnaryLine($op, $cmp, $operator) {
131    $op_p = makeParam($op);
132
133    $error = "echo '" . addcslashes("$operator $op_p", "\\'") . '\', "\n"; $f++;';
134
135    $compare = "@($operator $op_p)";
136    $line = "\$c++; ";
137    try {
138        $result = makeParam($cmp());
139        $line .= "if (" . ($result === "(NAN)" ? "!is_nan($compare)" : "$compare !== $result") . ") { $error }";
140    } catch (Error $e) {
141        $msg = makeParam($e->getMessage());
142        $line .= "try { $compare; $error } catch (Error \$e) { if (\$e->getMessage() !== $msg) { $error } }";
143    }
144    return $line;
145}
146
147$filename = __DIR__ . DIRECTORY_SEPARATOR . 'compare_binary_operands_temp.php';
148$file = fopen($filename, "w");
149
150fwrite($file, "<?php\n");
151
152foreach ($input as $left) {
153    foreach ($input as $right) {
154        foreach ($binaryOperators as $operator) {
155            $line = prepareBinaryLine($left, $right, function() use ($left, $right, $operator) {
156                return eval("return @(\$left $operator \$right);");
157            }, $operator);
158            fwrite($file, $line . "\n");
159        }
160    }
161}
162foreach ($input as $right) {
163    foreach ($unaryOperators as $operator) {
164        $line = prepareUnaryLine($right, function() use ($right, $operator) {
165            return eval("return @($operator \$right);");
166        }, $operator);
167        fwrite($file, $line . "\n");
168    }
169}
170
171fclose($file);
172
173include $filename;
174
175if($c === 0) {
176    echo "Completely failed\n";
177} else {
178    echo "Failed: $f\n";
179}
180?>
181--CLEAN--
182<?php
183$fl = __DIR__ . DIRECTORY_SEPARATOR . 'compare_binary_operands_temp.php';
184@unlink($fl);
185?>
186--EXPECT--
187Failed: 0
188