- 添加浮点数边界情况测试,包括NAN、INF、-INF的处理 - 添加带接口的枚举功能测试,验证枚举实现接口和使用trait的场景 - 添加try/finally无catch块的异常处理测试 - 添加魔术方法__invoke和__toString的表达式调用测试 - 添加parent::method()父类方法调用测试 - 添加严格类型声明strict_types=1的功能测试pull/1/head
parent
2da2bc094f
commit
e5e94b034c
6 changed files with 254 additions and 0 deletions
@ -0,0 +1,52 @@ |
|||||||
|
--TEST-- |
||||||
|
Backed enum with interface and trait |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
interface Labeled { |
||||||
|
public function label(): string; |
||||||
|
} |
||||||
|
|
||||||
|
trait Description { |
||||||
|
public function describe(): string { |
||||||
|
return "Status: " . $this->value . " - " . $this->label(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
enum Status: int implements Labeled { |
||||||
|
use Description; |
||||||
|
|
||||||
|
case Active = 1; |
||||||
|
case Inactive = 0; |
||||||
|
case Pending = 2; |
||||||
|
|
||||||
|
public function label(): string { |
||||||
|
return match ($this) { |
||||||
|
self::Active => 'Active', |
||||||
|
self::Inactive => 'Inactive', |
||||||
|
self::Pending => 'Pending', |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public function isActive(): bool { |
||||||
|
return $this === self::Active; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void { |
||||||
|
var_dump(Status::Active->value); |
||||||
|
var_dump(Status::Active->label()); |
||||||
|
var_dump(Status::Active->describe()); |
||||||
|
var_dump(Status::Active->isActive()); |
||||||
|
var_dump(Status::Inactive->isActive()); |
||||||
|
var_dump(Status::from(2)); |
||||||
|
var_dump(Status::tryFrom(99)); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
int(1) |
||||||
|
string(6) "Active" |
||||||
|
string(18) "Status: 1 - Active" |
||||||
|
bool(true) |
||||||
|
bool(false) |
||||||
|
enum(Status::Pending) |
||||||
|
NULL |
||||||
@ -0,0 +1,35 @@ |
|||||||
|
--TEST-- |
||||||
|
try/finally without catch |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
function testFinally(int $x): string { |
||||||
|
$result = ""; |
||||||
|
try { |
||||||
|
$result .= "try-{$x}"; |
||||||
|
if ($x <= 0) { |
||||||
|
return $result . " early-return"; |
||||||
|
} |
||||||
|
if ($x >= 10) { |
||||||
|
throw new Exception("too large"); |
||||||
|
} |
||||||
|
$result .= " normal"; |
||||||
|
} finally { |
||||||
|
$result .= " finally"; |
||||||
|
} |
||||||
|
return $result; |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void { |
||||||
|
echo testFinally(5) . "\n"; |
||||||
|
echo testFinally(0) . "\n"; |
||||||
|
try { |
||||||
|
echo testFinally(20) . "\n"; |
||||||
|
} catch (Exception $e) { |
||||||
|
echo "Caught: " . $e->getMessage() . "\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
try-5 normal finally |
||||||
|
try-0 early-return |
||||||
|
Caught: too large |
||||||
@ -0,0 +1,40 @@ |
|||||||
|
--TEST-- |
||||||
|
Float edge cases: NAN, INF, -INF |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
function main(): void { |
||||||
|
var_dump(NAN); |
||||||
|
var_dump(INF); |
||||||
|
var_dump(-INF); |
||||||
|
var_dump(is_nan(NAN)); |
||||||
|
var_dump(is_nan(0.0)); |
||||||
|
var_dump(is_infinite(INF)); |
||||||
|
var_dump(is_infinite(-INF)); |
||||||
|
var_dump(is_infinite(1.5)); |
||||||
|
var_dump(is_finite(INF)); |
||||||
|
var_dump(is_finite(1.5)); |
||||||
|
echo NAN . "\n"; |
||||||
|
echo INF . "\n"; |
||||||
|
echo -INF . "\n"; |
||||||
|
var_dump(INF + INF); |
||||||
|
var_dump(INF / INF); |
||||||
|
var_dump(0.0 / 0.0); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
float(NAN) |
||||||
|
float(INF) |
||||||
|
float(-INF) |
||||||
|
bool(true) |
||||||
|
bool(false) |
||||||
|
bool(true) |
||||||
|
bool(true) |
||||||
|
bool(false) |
||||||
|
bool(false) |
||||||
|
bool(true) |
||||||
|
NAN |
||||||
|
INF |
||||||
|
-INF |
||||||
|
float(INF) |
||||||
|
float(NAN) |
||||||
|
float(NAN) |
||||||
@ -0,0 +1,54 @@ |
|||||||
|
--TEST-- |
||||||
|
__invoke closure-style call and __toString in expressions |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
class CallableClass { |
||||||
|
private int $multiplier; |
||||||
|
|
||||||
|
public function __construct(int $m) { |
||||||
|
$this->multiplier = $m; |
||||||
|
} |
||||||
|
|
||||||
|
public function __invoke(int $x): int { |
||||||
|
return $x * $this->multiplier; |
||||||
|
} |
||||||
|
|
||||||
|
public function __toString(): string { |
||||||
|
return "CallableClass(multiplier={$this->multiplier})"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Greeter { |
||||||
|
public function __invoke(string $name): string { |
||||||
|
return "Hello, {$name}!"; |
||||||
|
} |
||||||
|
|
||||||
|
public function __toString(): string { |
||||||
|
return "Greeter"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void { |
||||||
|
$double = new CallableClass(2); |
||||||
|
$triple = new CallableClass(3); |
||||||
|
|
||||||
|
echo $double(5) . "\n"; |
||||||
|
echo $triple(5) . "\n"; |
||||||
|
echo $double . "\n"; |
||||||
|
echo $triple . "\n"; |
||||||
|
|
||||||
|
$greet = new Greeter(); |
||||||
|
echo $greet("World") . "\n"; |
||||||
|
echo $greet . "\n"; |
||||||
|
|
||||||
|
echo strlen($double) . "\n"; |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
10 |
||||||
|
15 |
||||||
|
CallableClass(multiplier=2) |
||||||
|
CallableClass(multiplier=3) |
||||||
|
Hello, World! |
||||||
|
Greeter |
||||||
|
27 |
||||||
@ -0,0 +1,49 @@ |
|||||||
|
--TEST-- |
||||||
|
parent::method() call |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
class Base { |
||||||
|
public function greet(): string { |
||||||
|
return "Hello from Base"; |
||||||
|
} |
||||||
|
|
||||||
|
public function value(): int { |
||||||
|
return 10; |
||||||
|
} |
||||||
|
|
||||||
|
public static function staticValue(): int { |
||||||
|
return 100; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class Child extends Base { |
||||||
|
public function greet(): string { |
||||||
|
return parent::greet() . " and Child"; |
||||||
|
} |
||||||
|
|
||||||
|
public function value(): int { |
||||||
|
return parent::value() + 5; |
||||||
|
} |
||||||
|
|
||||||
|
public function getParentGreet(): string { |
||||||
|
return parent::greet(); |
||||||
|
} |
||||||
|
|
||||||
|
public static function staticValue(): int { |
||||||
|
return parent::staticValue() + 50; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void { |
||||||
|
$child = new Child(); |
||||||
|
echo $child->greet() . "\n"; |
||||||
|
echo $child->value() . "\n"; |
||||||
|
echo $child->getParentGreet() . "\n"; |
||||||
|
echo Child::staticValue() . "\n"; |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
Hello from Base and Child |
||||||
|
15 |
||||||
|
Hello from Base |
||||||
|
150 |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
--TEST-- |
||||||
|
strict_types=1 with typed functions |
||||||
|
--FILE-- |
||||||
|
<?php |
||||||
|
declare(strict_types=1); |
||||||
|
|
||||||
|
function add(int $a, int $b): int { |
||||||
|
return $a + $b; |
||||||
|
} |
||||||
|
|
||||||
|
function greet(string $name): string { |
||||||
|
return "Hello, " . $name; |
||||||
|
} |
||||||
|
|
||||||
|
function main(): void { |
||||||
|
var_dump(add(10, 20)); |
||||||
|
var_dump(add(-5, 15)); |
||||||
|
var_dump(greet("World")); |
||||||
|
} |
||||||
|
?> |
||||||
|
--EXPECT-- |
||||||
|
int(30) |
||||||
|
int(10) |
||||||
|
string(12) "Hello, World" |
||||||
Loading…
Reference in new issue