parent
0c2a25ea52
commit
d73d077a7a
13 changed files with 1185 additions and 0 deletions
@ -0,0 +1,114 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\ArgInfo; |
||||||
|
|
||||||
|
class ArgInfoTest extends TestCase |
||||||
|
{ |
||||||
|
public function testDefaultBooleanProperties(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
// Set required string properties first (they have no defaults) |
||||||
|
$arg->name = ''; |
||||||
|
$arg->type = ''; |
||||||
|
|
||||||
|
// default values for implicitly-initialized fields |
||||||
|
$this->assertEquals('', $arg->default); |
||||||
|
$this->assertNull($arg->defaultValue); |
||||||
|
$this->assertEquals('', $arg->class); |
||||||
|
$this->assertFalse($arg->byRef); |
||||||
|
$this->assertFalse($arg->variadic); |
||||||
|
$this->assertFalse($arg->nullable); |
||||||
|
$this->assertFalse($arg->property); |
||||||
|
$this->assertFalse($arg->unsafePtr); |
||||||
|
} |
||||||
|
|
||||||
|
public function testNameAndType(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$arg->name = 'value'; |
||||||
|
$arg->type = 'php::Int'; |
||||||
|
|
||||||
|
$this->assertEquals('value', $arg->name); |
||||||
|
$this->assertEquals('php::Int', $arg->type); |
||||||
|
} |
||||||
|
|
||||||
|
public function testDefaultValues(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$arg->default = '0'; |
||||||
|
|
||||||
|
$this->assertEquals('0', $arg->default); |
||||||
|
} |
||||||
|
|
||||||
|
public function testClass(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$arg->class = 'DateTime'; |
||||||
|
|
||||||
|
$this->assertEquals('DateTime', $arg->class); |
||||||
|
} |
||||||
|
|
||||||
|
public function testByRef(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$this->assertFalse($arg->byRef); |
||||||
|
|
||||||
|
$arg->byRef = true; |
||||||
|
$this->assertTrue($arg->byRef); |
||||||
|
} |
||||||
|
|
||||||
|
public function testVariadic(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$this->assertFalse($arg->variadic); |
||||||
|
|
||||||
|
$arg->variadic = true; |
||||||
|
$this->assertTrue($arg->variadic); |
||||||
|
} |
||||||
|
|
||||||
|
public function testNullable(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$this->assertFalse($arg->nullable); |
||||||
|
|
||||||
|
$arg->nullable = true; |
||||||
|
$this->assertTrue($arg->nullable); |
||||||
|
} |
||||||
|
|
||||||
|
public function testProperty(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$this->assertFalse($arg->property); |
||||||
|
|
||||||
|
$arg->property = true; |
||||||
|
$this->assertTrue($arg->property); |
||||||
|
} |
||||||
|
|
||||||
|
public function testUnsafePtr(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$this->assertFalse($arg->unsafePtr); |
||||||
|
|
||||||
|
$arg->unsafePtr = true; |
||||||
|
$this->assertTrue($arg->unsafePtr); |
||||||
|
} |
||||||
|
|
||||||
|
public function testAllFlagsCombined(): void |
||||||
|
{ |
||||||
|
$arg = new ArgInfo(); |
||||||
|
$arg->name = 'args'; |
||||||
|
$arg->type = 'php::Var'; |
||||||
|
$arg->variadic = true; |
||||||
|
$arg->byRef = true; |
||||||
|
$arg->nullable = true; |
||||||
|
|
||||||
|
$this->assertEquals('args', $arg->name); |
||||||
|
$this->assertEquals('php::Var', $arg->type); |
||||||
|
$this->assertTrue($arg->variadic); |
||||||
|
$this->assertTrue($arg->byRef); |
||||||
|
$this->assertTrue($arg->nullable); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,113 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Context; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Context\FunctionContext; |
||||||
|
use PhpAot\Php\Context\ScopeContext; |
||||||
|
|
||||||
|
class FunctionContextTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstructInitializesAllProperties(): void |
||||||
|
{ |
||||||
|
$ctx = new FunctionContext(); |
||||||
|
|
||||||
|
$this->assertEmpty($ctx->objects); |
||||||
|
$this->assertEmpty($ctx->stdArrays); |
||||||
|
$this->assertEmpty($ctx->stdContainers); |
||||||
|
$this->assertEmpty($ctx->localVars); |
||||||
|
$this->assertEmpty($ctx->staticVars); |
||||||
|
$this->assertEmpty($ctx->globalVars); |
||||||
|
$this->assertEmpty($ctx->ceWrappers); |
||||||
|
$this->assertEmpty($ctx->arguments); |
||||||
|
$this->assertEmpty($ctx->beforeStmtLines); |
||||||
|
$this->assertEmpty($ctx->afterStmtLines); |
||||||
|
$this->assertEmpty($ctx->objectProps); |
||||||
|
$this->assertEmpty($ctx->scopeLayouts); |
||||||
|
|
||||||
|
$this->assertSame(0, $ctx->tmpVarIndex); |
||||||
|
$this->assertSame(0, $ctx->scopeLevel); |
||||||
|
$this->assertFalse($ctx->inLoop); |
||||||
|
$this->assertFalse($ctx->inClosure); |
||||||
|
$this->assertFalse($ctx->inAssignExpr); |
||||||
|
} |
||||||
|
|
||||||
|
public function testEnterScopeIncrementsLevel(): void |
||||||
|
{ |
||||||
|
$ctx = new FunctionContext(); |
||||||
|
$this->assertSame(0, $ctx->scopeLevel); |
||||||
|
|
||||||
|
$ctx->enterScope(); |
||||||
|
$this->assertSame(1, $ctx->scopeLevel); |
||||||
|
$this->assertArrayHasKey(0, $ctx->scopeLayouts); |
||||||
|
$this->assertInstanceOf(ScopeContext::class, $ctx->scopeLayouts[0]); |
||||||
|
|
||||||
|
$ctx->enterScope(); |
||||||
|
$this->assertSame(2, $ctx->scopeLevel); |
||||||
|
$this->assertArrayHasKey(0, $ctx->scopeLayouts); |
||||||
|
$this->assertArrayHasKey(1, $ctx->scopeLayouts); |
||||||
|
} |
||||||
|
|
||||||
|
public function testLeaveScopeDecrementsLevel(): void |
||||||
|
{ |
||||||
|
$ctx = new FunctionContext(); |
||||||
|
$ctx->enterScope(); |
||||||
|
$ctx->enterScope(); |
||||||
|
$this->assertSame(2, $ctx->scopeLevel); |
||||||
|
|
||||||
|
$ctx->leaveScope(); |
||||||
|
$this->assertSame(1, $ctx->scopeLevel); |
||||||
|
|
||||||
|
$ctx->leaveScope(); |
||||||
|
$this->assertSame(0, $ctx->scopeLevel); |
||||||
|
} |
||||||
|
|
||||||
|
public function testMutableProperties(): void |
||||||
|
{ |
||||||
|
$ctx = new FunctionContext(); |
||||||
|
|
||||||
|
$ctx->inLoop = true; |
||||||
|
$this->assertTrue($ctx->inLoop); |
||||||
|
|
||||||
|
$ctx->inClosure = true; |
||||||
|
$this->assertTrue($ctx->inClosure); |
||||||
|
|
||||||
|
$ctx->inAssignExpr = true; |
||||||
|
$this->assertTrue($ctx->inAssignExpr); |
||||||
|
|
||||||
|
$ctx->tmpVarIndex = 5; |
||||||
|
$this->assertSame(5, $ctx->tmpVarIndex); |
||||||
|
} |
||||||
|
|
||||||
|
public function testLocalVarsManipulation(): void |
||||||
|
{ |
||||||
|
$ctx = new FunctionContext(); |
||||||
|
$ctx->localVars['x'] = 'php::Int'; |
||||||
|
$ctx->localVars['name'] = 'php::Str'; |
||||||
|
|
||||||
|
$this->assertArrayHasKey('x', $ctx->localVars); |
||||||
|
$this->assertArrayHasKey('name', $ctx->localVars); |
||||||
|
$this->assertEquals('php::Int', $ctx->localVars['x']); |
||||||
|
$this->assertEquals('php::Str', $ctx->localVars['name']); |
||||||
|
} |
||||||
|
|
||||||
|
public function testObjectsMap(): void |
||||||
|
{ |
||||||
|
$ctx = new FunctionContext(); |
||||||
|
$ctx->objects['obj1'] = 'stdClass'; |
||||||
|
$ctx->objects['obj2'] = 'DateTime'; |
||||||
|
|
||||||
|
$this->assertCount(2, $ctx->objects); |
||||||
|
$this->assertEquals('stdClass', $ctx->objects['obj1']); |
||||||
|
} |
||||||
|
|
||||||
|
public function testBeforeAfterStmtLines(): void |
||||||
|
{ |
||||||
|
$ctx = new FunctionContext(); |
||||||
|
$ctx->beforeStmtLines[] = 'int x = 1;'; |
||||||
|
$ctx->afterStmtLines[] = 'x = 0;'; |
||||||
|
|
||||||
|
$this->assertCount(1, $ctx->beforeStmtLines); |
||||||
|
$this->assertCount(1, $ctx->afterStmtLines); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,15 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Context; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Context\ScopeContext; |
||||||
|
|
||||||
|
class ScopeContextTest extends TestCase |
||||||
|
{ |
||||||
|
public function testCanInstantiate(): void |
||||||
|
{ |
||||||
|
$scope = new ScopeContext(); |
||||||
|
$this->assertInstanceOf(ScopeContext::class, $scope); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,133 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Entity; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Entity\ClassDef; |
||||||
|
use PhpAot\Php\Entity\MethodDef; |
||||||
|
use PhpAot\Php\Entity\PropertyDef; |
||||||
|
use PhpAot\Php\Entity\ConstantDef; |
||||||
|
use PhpAot\Php\Entity\FunctionDef; |
||||||
|
use PhpParser\Modifiers; |
||||||
|
|
||||||
|
class ClassDefTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstructDefaults(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$this->assertEquals('Foo', $class->name); |
||||||
|
$this->assertEquals('', $class->namespace); |
||||||
|
$this->assertSame(Modifiers::PUBLIC, $class->flags); |
||||||
|
$this->assertEquals('', $class->extends); |
||||||
|
$this->assertEmpty($class->implements); |
||||||
|
$this->assertEmpty($class->methods); |
||||||
|
$this->assertEmpty($class->properties); |
||||||
|
$this->assertEmpty($class->constants); |
||||||
|
$this->assertFalse($class->enum); |
||||||
|
$this->assertFalse($class->requireCtor); |
||||||
|
$this->assertFalse($class->inheritedFromInternalClass); |
||||||
|
$this->assertNull($class->trait); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructWithNamespace(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Bar', Modifiers::PUBLIC, 'App\\Lib'); |
||||||
|
$this->assertEquals('Bar', $class->name); |
||||||
|
$this->assertEquals('App\\Lib', $class->namespace); |
||||||
|
} |
||||||
|
|
||||||
|
public function testPropertyContextIsInitialized(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$this->assertNotNull($class->propertyContext); |
||||||
|
$this->assertInstanceOf(\PhpAot\Php\Context\FunctionContext::class, $class->propertyContext); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetNamespacedNameInheritedFromClassLikeDef(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC, 'A\\B'); |
||||||
|
$this->assertEquals('A_B_Foo', $class->getNamespacedName(true)); |
||||||
|
$this->assertEquals('A\\B\\Foo', $class->getNamespacedName(false)); |
||||||
|
} |
||||||
|
|
||||||
|
public function testAddAndHasMethod(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$method = new MethodDef(Modifiers::PUBLIC, 'bar'); |
||||||
|
|
||||||
|
$this->assertFalse($class->hasMethod('bar')); |
||||||
|
|
||||||
|
$class->addMethod($method); |
||||||
|
$this->assertTrue($class->hasMethod('bar')); |
||||||
|
$this->assertTrue($class->hasMethod('BAR')); // case-insensitive |
||||||
|
$this->assertSame($method, $class->getMethod('bar')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetMethodCaseInsensitive(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$method = new MethodDef(Modifiers::PUBLIC, 'MyMethod'); |
||||||
|
|
||||||
|
$class->addMethod($method); |
||||||
|
$this->assertSame($method, $class->getMethod('mymethod')); |
||||||
|
$this->assertSame($method, $class->getMethod('MYMETHOD')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testHasMethodNotFound(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$this->assertFalse($class->hasMethod('nonexistent')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testHasProperty(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$prop = new PropertyDef('name', Modifiers::PUBLIC, 'php::Str'); |
||||||
|
$class->properties['name'] = $prop; |
||||||
|
|
||||||
|
$this->assertTrue($class->hasProperty('name')); |
||||||
|
$this->assertFalse($class->hasProperty('missing')); |
||||||
|
$this->assertSame($prop, $class->getProperty('name')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testHasConstant(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$const = new ConstantDef('VERSION', Modifiers::PUBLIC, 'php::Str', '"1.0"'); |
||||||
|
$class->constants['VERSION'] = $const; |
||||||
|
|
||||||
|
$this->assertTrue($class->hasConstant('VERSION')); |
||||||
|
$this->assertFalse($class->hasConstant('MISSING')); |
||||||
|
$this->assertSame($const, $class->getConstant('VERSION')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testIsAbstract(): void |
||||||
|
{ |
||||||
|
$abstractClass = new ClassDef('AbstractFoo', Modifiers::ABSTRACT); |
||||||
|
$this->assertTrue($abstractClass->isAbstract()); |
||||||
|
|
||||||
|
$concreteClass = new ClassDef('ConcreteFoo', Modifiers::PUBLIC); |
||||||
|
$this->assertFalse($concreteClass->isAbstract()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testRequireCtorAndEnumDefaults(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$this->assertFalse($class->requireCtor); |
||||||
|
$this->assertFalse($class->enum); |
||||||
|
} |
||||||
|
|
||||||
|
public function testTraitAliasesAndIgnoredDefaults(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$this->assertEmpty($class->traitAliases); |
||||||
|
$this->assertEmpty($class->traitIgnored); |
||||||
|
} |
||||||
|
|
||||||
|
public function testImplementsAndExtendsDefaults(): void |
||||||
|
{ |
||||||
|
$class = new ClassDef('Foo', Modifiers::PUBLIC); |
||||||
|
$this->assertEmpty($class->implements); |
||||||
|
$this->assertEquals('', $class->extends); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,47 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Entity; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Entity\ClassLikeDef; |
||||||
|
use PhpAot\Php\Entity\ClassDef; |
||||||
|
use PhpAot\Php\Entity\InterfaceDef; |
||||||
|
use PhpParser\Modifiers; |
||||||
|
|
||||||
|
class ClassLikeDefTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstructWithoutNamespace(): void |
||||||
|
{ |
||||||
|
$def = new ClassLikeDef('Foo'); |
||||||
|
$this->assertEquals('Foo', $def->name); |
||||||
|
$this->assertEquals('', $def->namespace); |
||||||
|
$this->assertEquals('', $def->extends); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructWithNamespace(): void |
||||||
|
{ |
||||||
|
$def = new ClassLikeDef('Foo', 'App\\Bar'); |
||||||
|
$this->assertEquals('Foo', $def->name); |
||||||
|
$this->assertEquals('App\\Bar', $def->namespace); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetNamespacedNameWithoutNamespace(): void |
||||||
|
{ |
||||||
|
$def = new ClassLikeDef('Foo'); |
||||||
|
$this->assertEquals('Foo', $def->getNamespacedName()); |
||||||
|
$this->assertEquals('Foo', $def->getNamespacedName(false)); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetNamespacedNameSymbolic(): void |
||||||
|
{ |
||||||
|
$def = new ClassLikeDef('Foo', 'App\\Bar'); |
||||||
|
// symbolic: backslashes → underscores → App_Bar_Foo |
||||||
|
$this->assertEquals('App_Bar_Foo', $def->getNamespacedName(true)); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetNamespacedNameNonSymbolic(): void |
||||||
|
{ |
||||||
|
$def = new ClassLikeDef('Foo', 'App\\Bar'); |
||||||
|
$this->assertEquals('App\\Bar\\Foo', $def->getNamespacedName(false)); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Entity; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Entity\ConstantDef; |
||||||
|
use PhpParser\Modifiers; |
||||||
|
|
||||||
|
class ConstantDefTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstruct(): void |
||||||
|
{ |
||||||
|
$const = new ConstantDef('MAX_SIZE', Modifiers::PUBLIC, 'php::Int', '1024L'); |
||||||
|
|
||||||
|
$this->assertEquals('MAX_SIZE', $const->name); |
||||||
|
$this->assertSame(Modifiers::PUBLIC, $const->flags); |
||||||
|
$this->assertEquals('php::Int', $const->type); |
||||||
|
$this->assertEquals('1024L', $const->value); |
||||||
|
$this->assertEquals('', $const->arrayExpr); |
||||||
|
$this->assertEquals('', $const->class); |
||||||
|
$this->assertNull($const->valueExpr); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructWithStringValue(): void |
||||||
|
{ |
||||||
|
$const = new ConstantDef('APP_NAME', Modifiers::PUBLIC, 'php::Str', 'php::Str{"MyApp"}'); |
||||||
|
|
||||||
|
$this->assertEquals('APP_NAME', $const->name); |
||||||
|
$this->assertEquals('php::Str', $const->type); |
||||||
|
$this->assertEquals('php::Str{"MyApp"}', $const->value); |
||||||
|
} |
||||||
|
|
||||||
|
public function testClassProperty(): void |
||||||
|
{ |
||||||
|
$const = new ConstantDef('PI', Modifiers::PUBLIC, 'php::Float', '3.14'); |
||||||
|
$this->assertEquals('', $const->class); |
||||||
|
|
||||||
|
$const->class = 'Math'; |
||||||
|
$this->assertEquals('Math', $const->class); |
||||||
|
} |
||||||
|
|
||||||
|
public function testArrayExprProperty(): void |
||||||
|
{ |
||||||
|
$const = new ConstantDef('ITEMS', Modifiers::PUBLIC, 'php::Array', '[]'); |
||||||
|
$this->assertEquals('', $const->arrayExpr); |
||||||
|
|
||||||
|
$const->arrayExpr = 'zval arr; array_init(&arr);'; |
||||||
|
$this->assertEquals('zval arr; array_init(&arr);', $const->arrayExpr); |
||||||
|
} |
||||||
|
|
||||||
|
public function testValueExprProperty(): void |
||||||
|
{ |
||||||
|
$const = new ConstantDef('VALUE', Modifiers::PUBLIC, 'php::Int', '1L'); |
||||||
|
$this->assertNull($const->valueExpr); |
||||||
|
} |
||||||
|
|
||||||
|
public function testDifferentVisibilityFlags(): void |
||||||
|
{ |
||||||
|
$publicConst = new ConstantDef('A', Modifiers::PUBLIC, 'php::Int', '1'); |
||||||
|
$this->assertSame(Modifiers::PUBLIC, $publicConst->flags); |
||||||
|
|
||||||
|
$protectedConst = new ConstantDef('B', Modifiers::PROTECTED, 'php::Int', '2'); |
||||||
|
$this->assertSame(Modifiers::PROTECTED, $protectedConst->flags); |
||||||
|
|
||||||
|
$privateConst = new ConstantDef('C', Modifiers::PRIVATE, 'php::Int', '3'); |
||||||
|
$this->assertSame(Modifiers::PRIVATE, $privateConst->flags); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,115 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Entity; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Entity\FunctionDef; |
||||||
|
use PhpAot\Php\ArgInfo; |
||||||
|
|
||||||
|
class FunctionDefTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstruct(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('test', 'void', ''); |
||||||
|
|
||||||
|
$this->assertEquals('test', $fn->name); |
||||||
|
$this->assertEquals('void', $fn->returnType); |
||||||
|
$this->assertEquals('', $fn->namespace); |
||||||
|
$this->assertFalse($fn->method); |
||||||
|
$this->assertFalse($fn->stub); |
||||||
|
$this->assertEmpty($fn->argInfoList); |
||||||
|
$this->assertEquals(0, $fn->argCountRequired); |
||||||
|
$this->assertEquals('', $fn->params); |
||||||
|
$this->assertEquals('', $fn->returnClass); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructWithNamespace(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('run', 'php::Int', 'App\\Lib'); |
||||||
|
|
||||||
|
$this->assertEquals('run', $fn->name); |
||||||
|
$this->assertEquals('php::Int', $fn->returnType); |
||||||
|
$this->assertEquals('App\\Lib', $fn->namespace); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetNamespacedNameWithoutNamespace(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('main', 'void', ''); |
||||||
|
$this->assertEquals('main', $fn->getNamespacedName()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetNamespacedNameWithNamespace(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('run', 'void', 'App\\Lib'); |
||||||
|
$this->assertEquals('App\\Lib\\run', $fn->getNamespacedName()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testHasVariadicArgEmptyList(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('test', 'void', ''); |
||||||
|
$this->assertFalse($fn->hasVariadicArg()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testHasVariadicArgFalse(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('test', 'void', ''); |
||||||
|
|
||||||
|
$arg1 = new ArgInfo(); |
||||||
|
$arg1->name = 'x'; |
||||||
|
$arg1->type = 'php::Int'; |
||||||
|
$arg1->variadic = false; |
||||||
|
|
||||||
|
$fn->argInfoList = [$arg1]; |
||||||
|
$this->assertFalse($fn->hasVariadicArg()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testHasVariadicArgTrue(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('test', 'void', ''); |
||||||
|
|
||||||
|
$arg1 = new ArgInfo(); |
||||||
|
$arg1->name = 'args'; |
||||||
|
$arg1->type = 'php::Var'; |
||||||
|
$arg1->variadic = true; |
||||||
|
|
||||||
|
$fn->argInfoList = [$arg1]; |
||||||
|
$this->assertTrue($fn->hasVariadicArg()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testHasVariadicArgLastOnly(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('test', 'void', ''); |
||||||
|
|
||||||
|
$arg1 = new ArgInfo(); |
||||||
|
$arg1->name = 'x'; |
||||||
|
$arg1->type = 'php::Int'; |
||||||
|
$arg1->variadic = false; |
||||||
|
|
||||||
|
$arg2 = new ArgInfo(); |
||||||
|
$arg2->name = 'rest'; |
||||||
|
$arg2->type = 'php::Var'; |
||||||
|
$arg2->variadic = true; |
||||||
|
|
||||||
|
$fn->argInfoList = [$arg1, $arg2]; |
||||||
|
$this->assertTrue($fn->hasVariadicArg()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testMethodFlag(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('handle', 'void', ''); |
||||||
|
$this->assertFalse($fn->method); |
||||||
|
|
||||||
|
$fn->method = true; |
||||||
|
$this->assertTrue($fn->method); |
||||||
|
} |
||||||
|
|
||||||
|
public function testParamsAndReturnClassSettable(): void |
||||||
|
{ |
||||||
|
$fn = new FunctionDef('test', 'php::Object', ''); |
||||||
|
$fn->params = 'php::Int x, php::Str y'; |
||||||
|
$fn->returnClass = 'DateTime'; |
||||||
|
|
||||||
|
$this->assertEquals('php::Int x, php::Str y', $fn->params); |
||||||
|
$this->assertEquals('DateTime', $fn->returnClass); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Entity; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Entity\InterfaceDef; |
||||||
|
|
||||||
|
class InterfaceDefTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstructWithoutNamespace(): void |
||||||
|
{ |
||||||
|
$iface = new InterfaceDef('JsonSerializable'); |
||||||
|
|
||||||
|
$this->assertEquals('JsonSerializable', $iface->name); |
||||||
|
$this->assertEquals('', $iface->namespace); |
||||||
|
$this->assertEquals('', $iface->extends); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructWithNamespace(): void |
||||||
|
{ |
||||||
|
$iface = new InterfaceDef('Renderable', 'App\\Contracts'); |
||||||
|
|
||||||
|
$this->assertEquals('Renderable', $iface->name); |
||||||
|
$this->assertEquals('App\\Contracts', $iface->namespace); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetNamespacedName(): void |
||||||
|
{ |
||||||
|
$iface = new InterfaceDef('Logger', 'App\\Contracts'); |
||||||
|
|
||||||
|
$this->assertEquals('App_Contracts_Logger', $iface->getNamespacedName(true)); |
||||||
|
$this->assertEquals('App\\Contracts\\Logger', $iface->getNamespacedName(false)); |
||||||
|
} |
||||||
|
|
||||||
|
public function testExtendsCanBeSet(): void |
||||||
|
{ |
||||||
|
$iface = new InterfaceDef('Child'); |
||||||
|
$iface->extends = 'Parent'; |
||||||
|
|
||||||
|
$this->assertEquals('Parent', $iface->extends); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Entity; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Entity\MethodDef; |
||||||
|
use PhpAot\Php\Entity\FunctionDef; |
||||||
|
use PhpParser\Modifiers; |
||||||
|
|
||||||
|
class MethodDefTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstruct(): void |
||||||
|
{ |
||||||
|
$method = new MethodDef(Modifiers::PUBLIC, 'handle'); |
||||||
|
|
||||||
|
$this->assertEquals('handle', $method->name); |
||||||
|
$this->assertSame(Modifiers::PUBLIC, $method->flags); |
||||||
|
$this->assertNull($method->functionDef); |
||||||
|
$this->assertFalse($method->hasDynamicCall); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetReturnType(): void |
||||||
|
{ |
||||||
|
$method = new MethodDef(Modifiers::PUBLIC, 'getValue'); |
||||||
|
$fn = new FunctionDef('getValue', 'php::Int', ''); |
||||||
|
$method->functionDef = $fn; |
||||||
|
|
||||||
|
$this->assertEquals('php::Int', $method->getReturnType()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetReturnTypeVoid(): void |
||||||
|
{ |
||||||
|
$method = new MethodDef(Modifiers::PROTECTED, 'execute'); |
||||||
|
$fn = new FunctionDef('execute', 'void', ''); |
||||||
|
$method->functionDef = $fn; |
||||||
|
|
||||||
|
$this->assertEquals('void', $method->getReturnType()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testFlags(): void |
||||||
|
{ |
||||||
|
$publicMethod = new MethodDef(Modifiers::PUBLIC, 'pub'); |
||||||
|
$this->assertSame(Modifiers::PUBLIC, $publicMethod->flags); |
||||||
|
|
||||||
|
$protectedMethod = new MethodDef(Modifiers::PROTECTED, 'prot'); |
||||||
|
$this->assertSame(Modifiers::PROTECTED, $protectedMethod->flags); |
||||||
|
|
||||||
|
$privateMethod = new MethodDef(Modifiers::PRIVATE, 'priv'); |
||||||
|
$this->assertSame(Modifiers::PRIVATE, $privateMethod->flags); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests\Entity; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Entity\PropertyDef; |
||||||
|
use PhpParser\Modifiers; |
||||||
|
|
||||||
|
class PropertyDefTest extends TestCase |
||||||
|
{ |
||||||
|
public function testConstructWithDefaults(): void |
||||||
|
{ |
||||||
|
$prop = new PropertyDef('count', Modifiers::PUBLIC, 'php::Int'); |
||||||
|
|
||||||
|
$this->assertEquals('count', $prop->name); |
||||||
|
$this->assertSame(Modifiers::PUBLIC, $prop->flags); |
||||||
|
$this->assertEquals('php::Int', $prop->type); |
||||||
|
$this->assertNull($prop->default); |
||||||
|
$this->assertFalse($prop->nullable); |
||||||
|
$this->assertEquals('', $prop->class); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructWithDefaultValue(): void |
||||||
|
{ |
||||||
|
$prop = new PropertyDef('count', Modifiers::PUBLIC, 'php::Int', '0'); |
||||||
|
|
||||||
|
$this->assertEquals('0', $prop->default); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructWithNullable(): void |
||||||
|
{ |
||||||
|
$prop = new PropertyDef('name', Modifiers::PUBLIC, 'php::Str', null, true); |
||||||
|
|
||||||
|
$this->assertTrue($prop->nullable); |
||||||
|
} |
||||||
|
|
||||||
|
public function testIsPrivate(): void |
||||||
|
{ |
||||||
|
$privateProp = new PropertyDef('secret', Modifiers::PRIVATE, 'php::Str'); |
||||||
|
$this->assertTrue($privateProp->isPrivate()); |
||||||
|
$this->assertFalse($privateProp->isProtected()); |
||||||
|
$this->assertFalse($privateProp->isPublic()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testIsProtected(): void |
||||||
|
{ |
||||||
|
$protectedProp = new PropertyDef('value', Modifiers::PROTECTED, 'php::Int'); |
||||||
|
$this->assertFalse($protectedProp->isPrivate()); |
||||||
|
$this->assertTrue($protectedProp->isProtected()); |
||||||
|
$this->assertFalse($protectedProp->isPublic()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testIsPublic(): void |
||||||
|
{ |
||||||
|
$publicProp = new PropertyDef('name', Modifiers::PUBLIC, 'php::Str'); |
||||||
|
$this->assertFalse($publicProp->isPrivate()); |
||||||
|
$this->assertFalse($publicProp->isProtected()); |
||||||
|
$this->assertTrue($publicProp->isPublic()); |
||||||
|
|
||||||
|
// PUBLIC flag is 0, so no-flag properties are also public |
||||||
|
$impliedPublic = new PropertyDef('name', 0, 'php::Str'); |
||||||
|
$this->assertTrue($impliedPublic->isPublic()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testIsStatic(): void |
||||||
|
{ |
||||||
|
$staticProp = new PropertyDef('counter', Modifiers::PUBLIC | Modifiers::STATIC, 'php::Int'); |
||||||
|
$this->assertTrue($staticProp->isStatic()); |
||||||
|
|
||||||
|
$instanceProp = new PropertyDef('counter', Modifiers::PUBLIC, 'php::Int'); |
||||||
|
$this->assertFalse($instanceProp->isStatic()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testClassProperty(): void |
||||||
|
{ |
||||||
|
$prop = new PropertyDef('data', Modifiers::PUBLIC, 'php::Var'); |
||||||
|
$this->assertEquals('', $prop->class); |
||||||
|
|
||||||
|
$prop->class = 'App\\Entity\\User'; |
||||||
|
$this->assertEquals('App\\Entity\\User', $prop->class); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,151 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Exception\DynamicCall; |
||||||
|
use PhpAot\Php\Exception\PlaceHolder; |
||||||
|
use PhpAot\Php\Exception\Redo; |
||||||
|
use PhpAot\Php\Exception\Skip; |
||||||
|
use PhpAot\Php\Exception\SyntaxError; |
||||||
|
use PhpAot\Php\Exception\TestError; |
||||||
|
use PhpAot\Php\Exception\Unsupported; |
||||||
|
use PhpAot\Php\Constants; |
||||||
|
|
||||||
|
class ExceptionTest extends TestCase |
||||||
|
{ |
||||||
|
public function testDynamicCall(): void |
||||||
|
{ |
||||||
|
$e = new DynamicCall('Dynamic call error'); |
||||||
|
$this->assertInstanceOf(\RuntimeException::class, $e); |
||||||
|
$this->assertEquals('Dynamic call error', $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testPlaceHolder(): void |
||||||
|
{ |
||||||
|
$e = new PlaceHolder('Placeholder error'); |
||||||
|
$this->assertInstanceOf(\RuntimeException::class, $e); |
||||||
|
$this->assertEquals('Placeholder error', $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testRedo(): void |
||||||
|
{ |
||||||
|
$e = new Redo('Redo compilation'); |
||||||
|
$this->assertInstanceOf(\RuntimeException::class, $e); |
||||||
|
$this->assertStringContainsString('Redo', $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testSkip(): void |
||||||
|
{ |
||||||
|
$e = new Skip('Skip this file'); |
||||||
|
$this->assertInstanceOf(\RuntimeException::class, $e); |
||||||
|
$this->assertStringContainsString('Skip', $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testSyntaxError(): void |
||||||
|
{ |
||||||
|
$e = new SyntaxError('Unexpected token'); |
||||||
|
$this->assertInstanceOf(\RuntimeException::class, $e); |
||||||
|
$this->assertStringContainsString('Unexpected', $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testTestError(): void |
||||||
|
{ |
||||||
|
$e = new TestError('Test assertion failed'); |
||||||
|
$this->assertInstanceOf(\RuntimeException::class, $e); |
||||||
|
$this->assertStringContainsString('Test assertion', $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testUnsupported(): void |
||||||
|
{ |
||||||
|
$e = new Unsupported('Unsupported syntax'); |
||||||
|
$this->assertInstanceOf(\RuntimeException::class, $e); |
||||||
|
$this->assertStringContainsString('Unsupported', $e->getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testCustomErrorCodes(): void |
||||||
|
{ |
||||||
|
$e = new TestError('Error 42', 42); |
||||||
|
$this->assertEquals(42, $e->getCode()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testCatchByBaseRuntimeException(): void |
||||||
|
{ |
||||||
|
// All exceptions can be caught by their parent RuntimeException |
||||||
|
$errors = [ |
||||||
|
new DynamicCall('test'), |
||||||
|
new PlaceHolder('test'), |
||||||
|
new Redo('test'), |
||||||
|
new Skip('test'), |
||||||
|
new SyntaxError('test'), |
||||||
|
new TestError('test'), |
||||||
|
new Unsupported('test'), |
||||||
|
]; |
||||||
|
|
||||||
|
foreach ($errors as $e) { |
||||||
|
try { |
||||||
|
throw $e; |
||||||
|
} catch (\RuntimeException $caught) { |
||||||
|
$this->assertSame($e, $caught); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstantsReservedNames(): void |
||||||
|
{ |
||||||
|
$this->assertIsArray(Constants::CPP_RESERVED_NAMES); |
||||||
|
$this->assertContains('class', Constants::CPP_RESERVED_NAMES); |
||||||
|
$this->assertContains('namespace', Constants::CPP_RESERVED_NAMES); |
||||||
|
$this->assertContains('int', Constants::CPP_RESERVED_NAMES); |
||||||
|
$this->assertContains('void', Constants::CPP_RESERVED_NAMES); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstantsUnsupportedFunctions(): void |
||||||
|
{ |
||||||
|
$this->assertIsArray(Constants::UNSUPPORTED_FUNCTIONS); |
||||||
|
$this->assertContains('extract', Constants::UNSUPPORTED_FUNCTIONS); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstantsCompilerOptions(): void |
||||||
|
{ |
||||||
|
$options = Constants::COMPILER_OPTIONS; |
||||||
|
$this->assertIsArray($options); |
||||||
|
$this->assertArrayHasKey('optimize', $options); |
||||||
|
$this->assertArrayHasKey('output', $options); |
||||||
|
$this->assertArrayHasKey('help', $options); |
||||||
|
$this->assertArrayHasKey('debug', $options); |
||||||
|
$this->assertArrayHasKey('job', $options); |
||||||
|
$this->assertArrayHasKey('mode', $options); |
||||||
|
} |
||||||
|
|
||||||
|
public function testCompilerOptionOptimizeDefaults(): void |
||||||
|
{ |
||||||
|
$opt = Constants::COMPILER_OPTIONS['optimize']; |
||||||
|
$this->assertEquals('O', $opt['prefix']); |
||||||
|
$this->assertIsInt($opt['defaultValue']); |
||||||
|
$this->assertEquals(0, $opt['defaultValue']); |
||||||
|
} |
||||||
|
|
||||||
|
public function testCompilerOptionModeDefaults(): void |
||||||
|
{ |
||||||
|
$opt = Constants::COMPILER_OPTIONS['mode']; |
||||||
|
$this->assertEquals('bin', $opt['defaultValue']); |
||||||
|
} |
||||||
|
|
||||||
|
public function testCompilerOptionNoValueFlags(): void |
||||||
|
{ |
||||||
|
$noValueFlags = ['help', 'version', 'no-literal-strings', 'force', 'debug', 'no-console']; |
||||||
|
foreach ($noValueFlags as $flag) { |
||||||
|
$this->assertArrayHasKey($flag, Constants::COMPILER_OPTIONS); |
||||||
|
$this->assertTrue(Constants::COMPILER_OPTIONS[$flag]['noValue'] ?? false); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public function testMsvcSuppressedWarnings(): void |
||||||
|
{ |
||||||
|
$warnings = Constants::MSVC_SUPPRESSED_WARNINGS; |
||||||
|
$this->assertIsArray($warnings); |
||||||
|
$this->assertArrayHasKey('4244', $warnings); |
||||||
|
$this->assertArrayHasKey('4127', $warnings); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,183 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\FileScanner; |
||||||
|
|
||||||
|
class FileScannerTest extends TestCase |
||||||
|
{ |
||||||
|
// ======================================================================== |
||||||
|
// Extension type detection |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
public function testIsPhpFile(): void |
||||||
|
{ |
||||||
|
$this->assertTrue(FileScanner::isPhpFile('/path/to/file.php')); |
||||||
|
$this->assertFalse(FileScanner::isPhpFile('/path/to/file.cc')); |
||||||
|
$this->assertFalse(FileScanner::isPhpFile('/path/to/file.c')); |
||||||
|
$this->assertFalse(FileScanner::isPhpFile('/path/to/file.py')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testIsCppFile(): void |
||||||
|
{ |
||||||
|
$this->assertTrue(FileScanner::isCppFile('/path/to/file.cc')); |
||||||
|
$this->assertTrue(FileScanner::isCppFile('/path/to/file.cpp')); |
||||||
|
$this->assertTrue(FileScanner::isCppFile('/path/to/file.cxx')); |
||||||
|
$this->assertFalse(FileScanner::isCppFile('/path/to/file.c')); |
||||||
|
$this->assertFalse(FileScanner::isCppFile('/path/to/file.php')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testIsNativeSourceFile(): void |
||||||
|
{ |
||||||
|
// C++ files |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.cc')); |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.cpp')); |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.cxx')); |
||||||
|
// C files |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.c')); |
||||||
|
// Assembly files |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.s')); |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.S')); |
||||||
|
// Objective-C files |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.m')); |
||||||
|
$this->assertTrue(FileScanner::isNativeSourceFile('/path/to/file.mm')); |
||||||
|
// Not native source |
||||||
|
$this->assertFalse(FileScanner::isNativeSourceFile('/path/to/file.php')); |
||||||
|
$this->assertFalse(FileScanner::isNativeSourceFile('/path/to/file.py')); |
||||||
|
$this->assertFalse(FileScanner::isNativeSourceFile('/path/to/file.h')); |
||||||
|
$this->assertFalse(FileScanner::isNativeSourceFile('/path/to/file.hpp')); |
||||||
|
} |
||||||
|
|
||||||
|
// ======================================================================== |
||||||
|
// getFileName / getFileExt |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
public function testGetFileName(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('hello', FileScanner::getFileName('/path/to/hello.php')); |
||||||
|
$this->assertEquals('helper', FileScanner::getFileName('/path/to/helper.c')); |
||||||
|
$this->assertEquals('main', FileScanner::getFileName('/path/to/main.cc')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetFileNameWithMultipleDots(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('my.test', FileScanner::getFileName('/path/to/my.test.php')); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetFileExt(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php', FileScanner::getFileExt('/path/to/file.php')); |
||||||
|
$this->assertEquals('c', FileScanner::getFileExt('/path/to/file.c')); |
||||||
|
$this->assertEquals('cc', FileScanner::getFileExt('/path/to/file.cc')); |
||||||
|
$this->assertEquals('S', FileScanner::getFileExt('/path/to/file.S')); |
||||||
|
} |
||||||
|
|
||||||
|
// ======================================================================== |
||||||
|
// Constants |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
public function testPhpExtConstant(): void |
||||||
|
{ |
||||||
|
$this->assertEquals(['php'], FileScanner::PHP_EXT); |
||||||
|
} |
||||||
|
|
||||||
|
public function testCppExtConstant(): void |
||||||
|
{ |
||||||
|
$this->assertContains('cc', FileScanner::CPP_EXT); |
||||||
|
$this->assertContains('cpp', FileScanner::CPP_EXT); |
||||||
|
$this->assertContains('cxx', FileScanner::CPP_EXT); |
||||||
|
} |
||||||
|
|
||||||
|
public function testCextConstant(): void |
||||||
|
{ |
||||||
|
$this->assertEquals(['c'], FileScanner::C_EXT); |
||||||
|
} |
||||||
|
|
||||||
|
public function testAsmExtConstant(): void |
||||||
|
{ |
||||||
|
$this->assertContains('s', FileScanner::ASM_EXT); |
||||||
|
$this->assertContains('S', FileScanner::ASM_EXT); |
||||||
|
} |
||||||
|
|
||||||
|
public function testObjcExtConstant(): void |
||||||
|
{ |
||||||
|
$this->assertEquals(['m'], FileScanner::OBJC_EXT); |
||||||
|
} |
||||||
|
|
||||||
|
public function testObjcxxExtConstant(): void |
||||||
|
{ |
||||||
|
$this->assertEquals(['mm'], FileScanner::OBJCXX_EXT); |
||||||
|
} |
||||||
|
|
||||||
|
public function testNativeSrcExtConstant(): void |
||||||
|
{ |
||||||
|
$expected = ['cpp', 'cxx', 'cc', 'c', 's', 'S', 'm', 'mm']; |
||||||
|
sort($expected); |
||||||
|
$actual = FileScanner::NATIVE_SRC_EXT; |
||||||
|
sort($actual); |
||||||
|
$this->assertEquals($expected, $actual); |
||||||
|
} |
||||||
|
|
||||||
|
// ======================================================================== |
||||||
|
// Scan method |
||||||
|
// ======================================================================== |
||||||
|
|
||||||
|
public function testScanDirectory(): void |
||||||
|
{ |
||||||
|
$tmpDir = sys_get_temp_dir() . '/file_scanner_test_' . uniqid(); |
||||||
|
mkdir($tmpDir, 0777, true); |
||||||
|
mkdir($tmpDir . '/sub', 0777, true); |
||||||
|
|
||||||
|
touch($tmpDir . '/main.php'); |
||||||
|
touch($tmpDir . '/helper.c'); |
||||||
|
touch($tmpDir . '/math.S'); |
||||||
|
touch($tmpDir . '/module.cc'); |
||||||
|
touch($tmpDir . '/lib.m'); |
||||||
|
touch($tmpDir . '/ignored.py'); |
||||||
|
touch($tmpDir . '/README.md'); |
||||||
|
touch($tmpDir . '/sub/nested.cpp'); |
||||||
|
|
||||||
|
$scanner = new FileScanner($tmpDir); |
||||||
|
$files = $scanner->scan(); |
||||||
|
|
||||||
|
// Python and Markdown should not be included |
||||||
|
$this->assertContains($tmpDir . '/main.php', $files); |
||||||
|
$this->assertContains($tmpDir . '/helper.c', $files); |
||||||
|
$this->assertContains($tmpDir . '/math.S', $files); |
||||||
|
$this->assertContains($tmpDir . '/module.cc', $files); |
||||||
|
$this->assertContains($tmpDir . '/lib.m', $files); |
||||||
|
$this->assertContains($tmpDir . '/sub/nested.cpp', $files); |
||||||
|
$this->assertNotContains($tmpDir . '/ignored.py', $files); |
||||||
|
$this->assertNotContains($tmpDir . '/README.md', $files); |
||||||
|
|
||||||
|
// Clean up |
||||||
|
unlink($tmpDir . '/main.php'); |
||||||
|
unlink($tmpDir . '/helper.c'); |
||||||
|
unlink($tmpDir . '/math.S'); |
||||||
|
unlink($tmpDir . '/module.cc'); |
||||||
|
unlink($tmpDir . '/lib.m'); |
||||||
|
unlink($tmpDir . '/ignored.py'); |
||||||
|
unlink($tmpDir . '/README.md'); |
||||||
|
unlink($tmpDir . '/sub/nested.cpp'); |
||||||
|
rmdir($tmpDir . '/sub'); |
||||||
|
rmdir($tmpDir); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstructorRejectsNonexistentDir(): void |
||||||
|
{ |
||||||
|
$this->expectException(\InvalidArgumentException::class); |
||||||
|
new FileScanner('/nonexistent/path'); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetDirectory(): void |
||||||
|
{ |
||||||
|
$tmpDir = sys_get_temp_dir() . '/file_scanner_getdir_' . uniqid(); |
||||||
|
mkdir($tmpDir, 0777, true); |
||||||
|
|
||||||
|
$scanner = new FileScanner($tmpDir); |
||||||
|
$this->assertEquals($tmpDir, $scanner->getDirectory()); |
||||||
|
|
||||||
|
rmdir($tmpDir); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,71 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
namespace PhpAot\Tests; |
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase; |
||||||
|
use PhpAot\Php\Symbol; |
||||||
|
use PhpAot\Php\CompilerBase; |
||||||
|
|
||||||
|
class SymbolTest extends TestCase |
||||||
|
{ |
||||||
|
public function testGetStaticProperty(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php::getStaticProperty', Symbol::getStaticProperty()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testSetStaticProperty(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php::setStaticProperty', Symbol::setStaticProperty()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testInstanceOf(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php::instanceOf', Symbol::instanceOf()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConcat(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php::concat', Symbol::concat()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testConstant(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php::constant', Symbol::constant()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetClassEntrySafe(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php::getClassEntrySafe', Symbol::getClassEntrySafe()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testArgList(): void |
||||||
|
{ |
||||||
|
$this->assertEquals('php::ArgList', Symbol::argList()); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetCalledCe(): void |
||||||
|
{ |
||||||
|
$result = Symbol::getCalledCe(); |
||||||
|
$this->assertStringContainsString(CompilerBase::PREFIX, $result); |
||||||
|
$this->assertStringContainsString('get_called_ce', $result); |
||||||
|
} |
||||||
|
|
||||||
|
public function testGetCalledClass(): void |
||||||
|
{ |
||||||
|
$result = Symbol::getCalledClass(); |
||||||
|
$this->assertStringContainsString(CompilerBase::PREFIX, $result); |
||||||
|
$this->assertStringContainsString('get_called_class', $result); |
||||||
|
} |
||||||
|
|
||||||
|
public function testSafeIndex(): void |
||||||
|
{ |
||||||
|
$result = Symbol::safeIndex('0', '10'); |
||||||
|
$this->assertEquals('php::safeIndex(0, 10)', $result); |
||||||
|
} |
||||||
|
|
||||||
|
public function testSafeIndexWithVariables(): void |
||||||
|
{ |
||||||
|
$result = Symbol::safeIndex('i', 'count'); |
||||||
|
$this->assertEquals('php::safeIndex(i, count)', $result); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue