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