diff --git a/tests/compiler/dynamic_call/return-base-class-001.phpt b/tests/compiler/dynamic_call/return-base-class-001.phpt index 81e81fad..1182fa9c 100644 --- a/tests/compiler/dynamic_call/return-base-class-001.phpt +++ b/tests/compiler/dynamic_call/return-base-class-001.phpt @@ -1,7 +1,6 @@ --TEST-- return abstract class --SKIPIF-- - --FILE-- --EXPECT-- -string(3) "foo" \ No newline at end of file +string(4) "user" \ No newline at end of file diff --git a/tests/compiler/dynamic_call/return-base-class-002.phpt b/tests/compiler/dynamic_call/return-base-class-002.phpt index 4d6a60d1..30b50d4f 100644 --- a/tests/compiler/dynamic_call/return-base-class-002.phpt +++ b/tests/compiler/dynamic_call/return-base-class-002.phpt @@ -1,7 +1,6 @@ --TEST-- return abstract class --SKIPIF-- - --FILE-- --EXPECT-- -string(3) "foo" \ No newline at end of file +string(4) "user" \ No newline at end of file diff --git a/tests/compiler/object_property/prop-001.phpt b/tests/compiler/object_property/prop-001.phpt index f3dc4c7d..954a4b29 100644 --- a/tests/compiler/object_property/prop-001.phpt +++ b/tests/compiler/object_property/prop-001.phpt @@ -1,255 +1,43 @@ --TEST-- -Property ---SKIPIF-- -context 存在性检查 - !isset($worker->$prop) && !isset($worker->context->$prop) && $worker->context->$prop = 'NNNN'; +function originalLogic($worker, $prop) +{ + !isset($worker->$prop) + && !isset($worker->context->$prop) + && $worker->context->$prop = 'NNNN'; } -/** - * 改进后的安全写法 - */ -function safeLogic($worker, $prop) { - // ✅ 安全写法:先确保 context 存在,再使用空合并赋值 - if (!isset($worker->context)) { - $worker->context = new stdClass(); - } - $worker->context->$prop ??= 'NNNN'; -} - -/** - * 测试工具函数 - */ -function dumpState($label, $worker, $prop) { - echo "\n[$label]\n"; - echo " worker->$prop: " . (isset($worker->$prop) ? "'" . $worker->$prop . "'" : 'UNSET') . "\n"; - echo " context->$prop: " . ( - isset($worker->context) && isset($worker->context->$prop) - ? "'" . $worker->context->$prop . "'" - : (isset($worker->context) ? 'UNSET' : 'CONTEXT_NULL') - ) . "\n"; -} - -function main() { - echo "=".str_repeat("=", 70) . "\n"; - echo "TEST SUITE: isset + assignment short-circuit logic\n"; - echo "=".str_repeat("=", 70) . "\n"; - +function main() +{ $prop = 'name'; + ini_set('error_reporting', E_ERROR | E_WARNING); - // ======================================================================== - // 测试 1: 两个属性都不存在 → 应触发赋值 - // ======================================================================== - echo "\n【TEST 1】两个属性都不存在 → 应触发赋值 'NNNN'\n"; $worker = new Worker(); $worker->context = new stdClass(); - - dumpState('BEFORE', $worker, $prop); originalLogic($worker, $prop); - dumpState('AFTER (original)', $worker, $prop); + var_dump($worker->context->name); - // 验证 - assert(isset($worker->context->name), "TEST 1 FAILED: context->name should be set"); - assert($worker->context->name === 'NNNN', "TEST 1 FAILED: value should be 'NNNN'"); - echo "✅ TEST 1 PASSED\n"; - - // ======================================================================== - // 测试 2: $worker->$prop 存在 → 不应触发赋值 - // ======================================================================== - echo "\n【TEST 2】\$worker->\$prop 存在 → 不应触发赋值\n"; $worker = new Worker(); $worker->context = new stdClass(); - $worker->name = 'Alice'; // worker 有值 - - dumpState('BEFORE', $worker, $prop); + $worker->name = 'Alice'; originalLogic($worker, $prop); - dumpState('AFTER (original)', $worker, $prop); + var_dump(isset($worker->context->name)); - // 验证:context->name 应该仍不存在 - assert(!isset($worker->context->name), "TEST 2 FAILED: context->name should NOT be set"); - echo "✅ TEST 2 PASSED\n"; - - // ======================================================================== - // 测试 3: $worker->context->$prop 存在 → 不应触发赋值 - // ======================================================================== - echo "\n【TEST 3】\$worker->context->\$prop 存在 → 不应触发赋值\n"; $worker = new Worker(); $worker->context = new stdClass(); - $worker->context->name = 'Bob'; // context 有值 - - dumpState('BEFORE', $worker, $prop); + $worker->context->name = 'Bob'; originalLogic($worker, $prop); - dumpState('AFTER (original)', $worker, $prop); - - // 验证:context->name 应保持原值 - assert($worker->context->name === 'Bob', "TEST 3 FAILED: value should remain 'Bob'"); - echo "✅ TEST 3 PASSED\n"; - - // ======================================================================== - // 测试 4: 两个属性都存在 → 不应触发赋值 - // ======================================================================== - echo "\n【TEST 4】两个属性都存在 → 不应触发赋值\n"; - $worker = new Worker(); - $worker->context = new stdClass(); - $worker->name = 'Charlie'; - $worker->context->name = 'David'; - - dumpState('BEFORE', $worker, $prop); - originalLogic($worker, $prop); - dumpState('AFTER (original)', $worker, $prop); - - // 验证:context->name 应保持原值 - assert($worker->context->name === 'David', "TEST 4 FAILED: value should remain 'David'"); - echo "✅ TEST 4 PASSED\n"; - - // ======================================================================== - // 测试 5: $worker->context 为 null → 原始代码会触发错误! - // ======================================================================== - echo "\n【TEST 5】\$worker->context 为 null → 原始代码会触发 FATAL ERROR\n"; - $worker = new Worker(); - $worker->context = null; // context 为 null - - dumpState('BEFORE', $worker, $prop); - - try { - originalLogic($worker, $prop); - echo "❌ TEST 5 FAILED: Should have thrown error!\n"; - } catch (Error $e) { - echo "✅ TEST 5 PASSED: Caught expected error: " . $e->getMessage() . "\n"; - } - - // 安全写法测试 - $worker2 = new Worker(); - $worker2->context = null; - safeLogic($worker2, $prop); - dumpState('AFTER (safe)', $worker2, $prop); - assert(isset($worker2->context->name), "TEST 5 SAFE FAILED: context should be created"); - echo "✅ TEST 5 SAFE PASSED: Safe logic handled null context\n"; - - // ======================================================================== - // 测试 6: $worker->context 完全不存在(未定义)→ 原始代码会触发错误! - // ======================================================================== - echo "\n【TEST 6】\$worker->context 未定义 → 原始代码会触发 NOTICE\n"; - $worker = new Worker(); - unset($worker->context); // 完全移除 context 属性 - - dumpState('BEFORE', $worker, $prop); - - // PHP 8.0+ 会抛出 Error,PHP 7.x 会触发 Notice - try { - originalLogic($worker, $prop); - echo "❌ TEST 6 FAILED: Should have thrown error!\n"; - } catch (Error $e) { - echo "✅ TEST 6 PASSED: Caught expected error: " . $e->getMessage() . "\n"; - } catch (Exception $e) { - echo "⚠️ TEST 6: Notice triggered (PHP 7.x behavior)\n"; - } - - // 安全写法测试 - $worker2 = new Worker(); - unset($worker2->context); - safeLogic($worker2, $prop); - dumpState('AFTER (safe)', $worker2, $prop); - assert(isset($worker2->context->name), "TEST 6 SAFE FAILED: context should be created"); - echo "✅ TEST 6 SAFE PASSED: Safe logic handled undefined context\n"; - - // ======================================================================== - // 测试 7: 属性值为 null(isset 返回 false) - // ======================================================================== - echo "\n【TEST 7】属性值为 null → isset 返回 false,应触发赋值\n"; - $worker = new Worker(); - $worker->context = new stdClass(); - $worker->name = null; // null 值 - $worker->context->name = null; // null 值 - - dumpState('BEFORE', $worker, $prop); - originalLogic($worker, $prop); - dumpState('AFTER (original)', $worker, $prop); - - // 验证:null 被视为"不存在",应触发赋值 - assert($worker->context->name === 'NNNN', "TEST 7 FAILED: null should trigger assignment"); - echo "✅ TEST 7 PASSED\n"; - - // ======================================================================== - // 测试 8: 属性值为假值(0, '', false)→ isset 返回 true,不应触发赋值 - // ======================================================================== - echo "\n【TEST 8】属性值为假值(0, '', false)→ isset 返回 true\n"; - - // 子测试 8a: 空字符串 - $worker = new Worker(); - $worker->context = new stdClass(); - $worker->context->name = ''; - originalLogic($worker, $prop); - assert($worker->context->name === '', "TEST 8a FAILED: empty string should NOT trigger assignment"); - echo "✅ TEST 8a PASSED: empty string preserved\n"; - - // 子测试 8b: 数字 0 - $worker = new Worker(); - $worker->context = new stdClass(); - $worker->context->name = 0; - originalLogic($worker, $prop); - assert($worker->context->name === 0, "TEST 8b FAILED: zero should NOT trigger assignment"); - echo "✅ TEST 8b PASSED: zero preserved\n"; - - // 子测试 8c: false - $worker = new Worker(); - $worker->context = new stdClass(); - $worker->context->name = false; - originalLogic($worker, $prop); - assert($worker->context->name === false, "TEST 8c FAILED: false should NOT trigger assignment"); - echo "✅ TEST 8c PASSED: false preserved\n"; - - // ======================================================================== - // 测试 9: 动态属性名(变量) - // ======================================================================== - echo "\n【TEST 9】动态属性名(变量)\n"; - $worker = new Worker(); - $worker->context = new stdClass(); - $dynamicProp = 'email'; - - originalLogic($worker, $dynamicProp); - assert(isset($worker->context->email), "TEST 9 FAILED: dynamic property should be set"); - assert($worker->context->email === 'NNNN', "TEST 9 FAILED: value should be 'NNNN'"); - echo "✅ TEST 9 PASSED\n"; - - // ======================================================================== - // 测试 10: 多次调用(幂等性) - // ======================================================================== - echo "\n【TEST 10】多次调用(幂等性)\n"; - $worker = new Worker(); - $worker->context = new stdClass(); - - originalLogic($worker, $prop); // 第一次:赋值 - $firstValue = $worker->context->name; - - originalLogic($worker, $prop); // 第二次:不应覆盖 - $secondValue = $worker->context->name; - - assert($firstValue === 'NNNN', "TEST 10 FAILED: first call should set value"); - assert($secondValue === 'NNNN', "TEST 10 FAILED: second call should not change value"); - assert($firstValue === $secondValue, "TEST 10 FAILED: value should be idempotent"); - echo "✅ TEST 10 PASSED: Idempotent behavior confirmed\n"; - - // ======================================================================== - // 总结 - // ======================================================================== - echo "\n".str_repeat("=", 70); - echo "\n✅ ALL TESTS COMPLETED SUCCESSFULLY\n"; - echo "=".str_repeat("=", 70) . "\n"; + var_dump($worker->context->name); } ?> --EXPECT-- -string(10) "Processing" -string(7) "unknown" -string(2) "OK" -string(2) "OK" \ No newline at end of file +string(4) "NNNN" +bool(false) +string(3) "Bob"