diff --git a/tests/aot/basic/preprocessor-condition-stack.phpt b/tests/aot/basic/preprocessor-condition-stack.phpt new file mode 100644 index 00000000..a7224dbf --- /dev/null +++ b/tests/aot/basic/preprocessor-condition-stack.phpt @@ -0,0 +1,50 @@ +--TEST-- +preprocessor comment condition stack +--FILE-- += 80400'])); + var_dump(handle_preprocessor_conditions($conds, ['#else'])); + var_dump(handle_preprocessor_conditions($conds, ['#endif', '#endif'])); + var_dump(handle_preprocessor_conditions($conds, ['#else'])); + var_dump(handle_preprocessor_conditions($conds, ['#pragma once'])); +} +?> +--EXPECT-- +string(45) "defined(PHP_WIN32) && PHP_VERSION_ID >= 80400" +string(48) "defined(PHP_WIN32) && !(PHP_VERSION_ID >= 80400)" +NULL +string(10) "else-error" +string(20) "unknown:#pragma once" diff --git a/tests/aot/basic/short-option-preprocess.phpt b/tests/aot/basic/short-option-preprocess.phpt new file mode 100644 index 00000000..9f4b8ec2 --- /dev/null +++ b/tests/aot/basic/short-option-preprocess.phpt @@ -0,0 +1,51 @@ +--TEST-- +short option preprocessing splits compact short flag values +--FILE-- + +--EXPECT-- +array(7) { + [0]=> + string(12) "compiler.php" + [1]=> + string(2) "-I" + [2]=> + string(7) "include" + [3]=> + string(2) "-a" + [4]=> + string(2) "bc" + [5]=> + string(7) "--debug" + [6]=> + string(11) "project.yml" +} diff --git a/tests/aot/basic/target-name-normalize.phpt b/tests/aot/basic/target-name-normalize.phpt new file mode 100644 index 00000000..1f0eb46f --- /dev/null +++ b/tests/aot/basic/target-name-normalize.phpt @@ -0,0 +1,51 @@ +--TEST-- +target name normalization with path separators and identifier validation +--FILE-- + +--EXPECT-- +array(3) { + [0]=> + string(5) "build" + [1]=> + string(6) "my_app" + [2]=> + bool(true) +} +array(3) { + [0]=> + string(1) "." + [1]=> + string(13) "C:\tmp\my_app" + [2]=> + bool(false) +} +array(3) { + [0]=> + string(0) "" + [1]=> + string(8) "bad.name" + [2]=> + bool(false) +} diff --git a/tests/aot/functions/compiler-name-normalize.phpt b/tests/aot/functions/compiler-name-normalize.phpt new file mode 100644 index 00000000..7cd5da6b --- /dev/null +++ b/tests/aot/functions/compiler-name-normalize.phpt @@ -0,0 +1,29 @@ +--TEST-- +compiler command name normalization from command string +--FILE-- + +--EXPECT-- +string(7) "clang++" +string(3) "g++" +string(0) "" diff --git a/tests/aot/functions/cpp-signature-param-parser.phpt b/tests/aot/functions/cpp-signature-param-parser.phpt new file mode 100644 index 00000000..2dedfa9e --- /dev/null +++ b/tests/aot/functions/cpp-signature-param-parser.phpt @@ -0,0 +1,102 @@ +--TEST-- +C++ signature parameter splitter with nested templates and defaults +--FILE-- +' || $char === ')' || $char === ']') { + $depth--; + $current .= $char; + } elseif ($char === ',' && $depth === 0) { + $params[] = $current; + $current = ''; + } else { + $current .= $char; + } + } + + if (!empty($current)) { + $params[] = $current; + } + + return $params; +} + +function parse_cpp_parameter(string $param): array +{ + $param = trim($param); + $param = preg_replace('/\s*=\s*.*$/', '', $param); + + if (preg_match('/^(.+?)\s+(\w+)\s*$/', $param, $matches)) { + return [ + 'type' => trim($matches[1]), + 'name' => trim($matches[2]), + ]; + } + + return [ + 'type' => $param, + 'name' => '', + ]; +} + +function parse_cpp_parameters(string $signature, string $funcName): array +{ + $pattern = '/' . preg_quote($funcName, '/') . '\s*\((.*?)\)/s'; + if (!preg_match($pattern, $signature, $matches)) { + return []; + } + + $paramsStr = trim($matches[1]); + if (empty($paramsStr) || $paramsStr === 'void') { + return []; + } + + return array_map('parse_cpp_parameter', split_cpp_parameters($paramsStr)); +} + +function main(): void +{ + $signature = 'static std::vector> build(std::map values, const char* name = "x", Callback cb)'; + var_dump(parse_cpp_parameters($signature, 'build')); + var_dump(parse_cpp_parameters('void reset(void)', 'reset')); +} +?> +--EXPECT-- +array(3) { + [0]=> + array(2) { + ["type"]=> + string(26) "std::map" + ["name"]=> + string(6) "values" + } + [1]=> + array(2) { + ["type"]=> + string(11) "const char*" + ["name"]=> + string(4) "name" + } + [2]=> + array(2) { + ["type"]=> + string(20) "Callback" + ["name"]=> + string(2) "cb" + } +} +array(0) { +} diff --git a/tests/aot/functions/doc-comment-tags.phpt b/tests/aot/functions/doc-comment-tags.phpt new file mode 100644 index 00000000..fa3b75bb --- /dev/null +++ b/tests/aot/functions/doc-comment-tags.phpt @@ -0,0 +1,48 @@ +--TEST-- +doc comment tag extraction with preg_match_all set order +--FILE-- + +--EXPECT-- +array(2) { + ["param"]=> + array(2) { + [0]=> + string(7) "int $id" + [1]=> + string(22) "string $name user name" + } + ["return"]=> + array(1) { + [0]=> + string(4) "bool" + } +} diff --git a/tests/aot/functions/docblock-param-regex.phpt b/tests/aot/functions/docblock-param-regex.phpt new file mode 100644 index 00000000..9b8e8fba --- /dev/null +++ b/tests/aot/functions/docblock-param-regex.phpt @@ -0,0 +1,42 @@ +--TEST-- +docblock param regex with recursive named groups +--FILE-- +[\w\|\\\\]+(?\((?(?:(?&parens)|[^(){}[\]<>]*+))++\)|\{(?&inparens)\}|\[(?&inparens)\]|<(?&inparens)>)*+(?::(?&type))?)\s*(\.\.\.)?\$(?\w+).*$/', $value, $matches); + + return [ + $matches['type'] ?? '', + $matches['name'] ?? '', + ]; +} + +function main(): void +{ + var_dump(parse_doc_param_name('callable(array):mixed $handler callback')); + var_dump(parse_doc_param_name('int ...$items')); + var_dump(parse_doc_param_name('$missingType')); +} +?> +--EXPECT-- +array(2) { + [0]=> + string(34) "callable(array):mixed" + [1]=> + string(7) "handler" +} +array(2) { + [0]=> + string(3) "int" + [1]=> + string(5) "items" +} +array(2) { + [0]=> + string(0) "" + [1]=> + string(0) "" +} diff --git a/tests/aot/functions/file-extension-classifier.phpt b/tests/aot/functions/file-extension-classifier.phpt new file mode 100644 index 00000000..b442147e --- /dev/null +++ b/tests/aot/functions/file-extension-classifier.phpt @@ -0,0 +1,43 @@ +--TEST-- +file extension classifier with pathinfo and in_array +--FILE-- + +--EXPECT-- +string(8) "php:main" +string(12) "cpp:compiler" +string(10) "native:aot" +string(6) "other:" diff --git a/tests/aot/functions/resource-version-normalize.phpt b/tests/aot/functions/resource-version-normalize.phpt new file mode 100644 index 00000000..ba1c0e6f --- /dev/null +++ b/tests/aot/functions/resource-version-normalize.phpt @@ -0,0 +1,36 @@ +--TEST-- +resource version normalization with ltrim explode preg_replace and slice +--FILE-- + $part) { + $parts[$i] = preg_replace('/[^0-9]/', '', $part) ?: '0'; + } + + while (count($parts) < 4) { + $parts[] = '0'; + } + + return implode(',', array_slice($parts, 0, 4)); +} + +function main(): void +{ + var_dump(normalize_resource_version('v1.2.3')); + var_dump(normalize_resource_version('V10.beta.5-rc1.7.9')); + var_dump(normalize_resource_version('1,2,3,4')); +} +?> +--EXPECT-- +string(7) "1,2,3,0" +string(9) "10,0,51,7" +string(7) "1,2,3,4" diff --git a/tests/aot/functions/unix-link-lib-flags.phpt b/tests/aot/functions/unix-link-lib-flags.phpt new file mode 100644 index 00000000..cb1b3976 --- /dev/null +++ b/tests/aot/functions/unix-link-lib-flags.phpt @@ -0,0 +1,30 @@ +--TEST-- +unix library paths normalized into linker flags +--FILE-- + +--EXPECT-- +string(18) "-lssl -lcrypto -lz" +string(20) "-lcustom -lplain.txt" diff --git a/tests/aot/string_method/camel-to-snake-regex.phpt b/tests/aot/string_method/camel-to-snake-regex.phpt new file mode 100644 index 00000000..650a2c49 --- /dev/null +++ b/tests/aot/string_method/camel-to-snake-regex.phpt @@ -0,0 +1,21 @@ +--TEST-- +camel case to snake case with regex replacement +--FILE-- + +--EXPECT-- +string(18) "to_std_ordered_map" +string(16) "htmlparser_value" +string(6) "simple" diff --git a/tests/aot/string_method/negative-string-offset.phpt b/tests/aot/string_method/negative-string-offset.phpt new file mode 100644 index 00000000..5aebdef1 --- /dev/null +++ b/tests/aot/string_method/negative-string-offset.phpt @@ -0,0 +1,26 @@ +--TEST-- +negative string offset read +--FILE-- + +--EXPECT-- +string(7) "float:3" +string(13) "date:%Y-%m-%d" +string(7) "other:c" diff --git a/tests/aot/type_decl/numeric-literal-classifier.phpt b/tests/aot/type_decl/numeric-literal-classifier.phpt new file mode 100644 index 00000000..2c7fd0c2 --- /dev/null +++ b/tests/aot/type_decl/numeric-literal-classifier.phpt @@ -0,0 +1,42 @@ +--TEST-- +numeric literal classifier style regex and digit extraction +--FILE-- += 19; +} + +function is_decimal_literal_string(string $rawValue): bool +{ + $clean = strip_numeric_underscores($rawValue); + if (!preg_match('/[\.eE]/', $clean)) { + return false; + } + $digits = preg_replace('/[^0-9]/', '', $clean); + return strlen(ltrim($digits, '0')) >= 16; +} + +function main(): void +{ + var_dump(is_big_int_literal_string('9_223_372_036_854_775_808')); + var_dump(is_big_int_literal_string('0x10000000000000000')); + var_dump(is_decimal_literal_string('123_456_789_012_345.6')); + var_dump(is_decimal_literal_string('123.45')); +} +?> +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(false)