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