Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test mutiple target PHP versions via docker and fixes some bugs #424

Merged
merged 10 commits into from
Feb 7, 2024
5 changes: 4 additions & 1 deletion .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ jobs:
- name: Run test suite
run: |
mkdir -p build/logs
./vendor/bin/phpunit --coverage-clover build/logs/clover.xml
composer test-for-ci

- name: Fix absolute paths in the coverage report
run: sed -i "s|<file name=\"/app/|<file name=\"`pwd`/|g" build/logs/clover.xml

- name: Send to coveralls
env:
Expand Down
31 changes: 31 additions & 0 deletions Dockerfile-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
FROM php:8.1-cli

RUN apt-get update && apt-get install -y \
libffi-dev \
libzip-dev \
&& docker-php-ext-install ffi \
&& docker-php-ext-install pcntl \
&& docker-php-ext-install zip \
&& pecl install pcov \
&& docker-php-ext-enable pcov \
&& rm -rf /var/lib/apt/lists/*

RUN apt-get update -y \
&& apt-get install -y ca-certificates curl gnupg \
&& install -m 0755 -d /etc/apt/keyrings \
&& curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
&& chmod a+r /etc/apt/keyrings/docker.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| tee /etc/apt/sources.list.d/docker.list > /dev/null \
&& apt-get update -y \
&& apt-get install -y docker-ce-cli \
&& rm -rf /var/lib/apt/lists/*

COPY --from=composer /usr/bin/composer /usr/bin/composer

WORKDIR /app
COPY . .

RUN composer install

CMD ["php", "vendor/bin/phpunit", "--colors=always", "--testdox", "--coverage-text", "--coverage-clover=coverage.xml", "--coverage-html=coverage"]
11 changes: 9 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,22 @@
},
"autoload-dev": {
"psr-4": {
"Reli\\": "tests"
"Reli\\": "tests",
"Reli\\Command\\": "tests/Command/CommandEnumeratorTestData"
}
},
"bin": [
"reli"
],
"scripts": {
"test": [
"phpunit"
"docker-compose run reli-test"
],
"test-with-coverage": [
"docker-compose run reli-test-with-coverage"
],
"test-for-ci": [
"docker-compose run reli-test-for-ci"
],
"psalm": [
"psalm.phar"
Expand Down
49 changes: 49 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
version: '3.9'
services:
reli-test:
build:
context: .
dockerfile: Dockerfile-dev
pid: "host"
cap_add:
- SYS_PTRACE
security_opt:
- seccomp:unconfined
volumes:
- .:/app
- /var/run/docker.sock:/var/run/docker.sock
- /tmp/reli-test:/tmp/reli-test
container_name: reli-test
command: ["vendor/bin/phpunit" , "--colors=always", "--testdox"]
reli-test-with-coverage:
build:
context: .
dockerfile: Dockerfile-dev
pid: "host"
cap_add:
- SYS_PTRACE
security_opt:
- seccomp:unconfined
volumes:
- .:/app
- /var/run/docker.sock:/var/run/docker.sock
- /tmp/reli-test:/tmp/reli-test
- ./build:/app/build
container_name: reli-test
command: ["vendor/bin/phpunit" , "--colors=always", "--testdox", "--coverage-clover", "build/logs/clover.xml"]
reli-test-for-ci:
build:
context: .
dockerfile: Dockerfile-dev
pid: "host"
cap_add:
- SYS_PTRACE
security_opt:
- seccomp:unconfined
volumes:
- .:/app
- /var/run/docker.sock:/var/run/docker.sock
- /tmp/reli-test:/tmp/reli-test
- ./build:/app/build
container_name: reli-test
command: ["vendor/bin/phpunit" , "--coverage-clover", "build/logs/clover.xml"]
11 changes: 11 additions & 0 deletions src/Lib/PhpInternals/Headers/v70.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ struct _zend_resource {
void *ptr;
};

// zend_compile.h
typedef struct _zend_property_info {
uint32_t offset; /* property offset for object properties or
property index for static properties */
uint32_t flags;
zend_string *name;
zend_string *doc_comment;
zend_class_entry *ce;
} zend_property_info;

// zend_types.h
struct _zend_reference {
zend_refcounted_h gc;
zval val;
Expand Down
11 changes: 11 additions & 0 deletions src/Lib/PhpInternals/Headers/v71.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,17 @@ struct _zend_resource {
void *ptr;
};

// zend_compile.h
typedef struct _zend_property_info {
uint32_t offset; /* property offset for object properties or
property index for static properties */
uint32_t flags;
zend_string *name;
zend_string *doc_comment;
zend_class_entry *ce;
} zend_property_info;

// zend_types.h
struct _zend_reference {
zend_refcounted_h gc;
zval val;
Expand Down
11 changes: 11 additions & 0 deletions src/Lib/PhpInternals/Headers/v72.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ struct _zend_resource {

typedef uintptr_t zend_type;

// zend_compile.h
typedef struct _zend_property_info {
uint32_t offset; /* property offset for object properties or
property index for static properties */
uint32_t flags;
zend_string *name;
zend_string *doc_comment;
zend_class_entry *ce;
} zend_property_info;

// zend_types.h
struct _zend_reference {
zend_refcounted_h gc;
zval val;
Expand Down
11 changes: 11 additions & 0 deletions src/Lib/PhpInternals/Headers/v73.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,17 @@ struct _zend_resource {

typedef uintptr_t zend_type;

// zend_compile.h
typedef struct _zend_property_info {
uint32_t offset; /* property offset for object properties or
property index for static properties */
uint32_t flags;
zend_string *name;
zend_string *doc_comment;
zend_class_entry *ce;
} zend_property_info;

// zend_types.h
struct _zend_reference {
zend_refcounted_h gc;
zval val;
Expand Down
31 changes: 31 additions & 0 deletions src/Lib/PhpInternals/Types/Zend/V74/ZendArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,37 @@ public function __get(string $field_name): mixed
};
}

public function dumpFlags(): string
{
$flags = $this->flags;
$flag_names = [];
if ($flags & ((1 << 0) | (1 << 1))) {
$flag_names[] = 'HASH_FLAG_CONSISTENCY';
}
if ($flags & (1 << 2)) {
$flag_names[] = 'HASH_FLAG_PACKED';
}
if ($flags & (1 << 3)) {
$flag_names[] = 'HASH_FLAG_UNINITIALIZED';
}
if ($flags & (1 << 4)) {
$flag_names[] = 'HASH_FLAG_STATIC_KEYS';
}
if ($flags & (1 << 5)) {
$flag_names[] = 'HASH_FLAG_HAS_EMPTY_IND';
}
if ($flags & (1 << 6)) {
$flag_names[] = 'HASH_FLAG_ALLOW_COW_VIOLATION';
}

return implode(' | ', $flag_names);
}

public function isUninitialized(): bool
{
return (bool)($this->flags & (1 << 3));
}

public function getDataSize(): int
{
return $this->nTableSize * self::BUCKET_SIZE_IN_BYTES;
Expand Down
1 change: 1 addition & 0 deletions src/Lib/PhpInternals/Types/Zend/ZendArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ public static function fromCastedCData(CastedCData $casted_cdata, Pointer $point
return new static($casted_cdata, $pointer);
}

/** @return Pointer<ZendArray> */
public function getPointer(): Pointer
{
return $this->pointer;
Expand Down
3 changes: 2 additions & 1 deletion src/Lib/PhpInternals/Types/Zend/ZendClassEntry.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ public function iteratePropertyInfo(
Dereferencer $dereferencer,
ZendTypeReader $type_reader,
): iterable {
foreach ($this->properties_info->getItemIterator($dereferencer) as $name => $item) {
$property_info = $dereferencer->deref($this->properties_info->getPointer());
foreach ($property_info->getItemIterator($dereferencer) as $name => $item) {
$property_info_pointer = $item->value->getAsPointer(
ZendPropertyInfo::class,
$type_reader->sizeOf(ZendPropertyInfo::getCTypeName()),
Expand Down
4 changes: 3 additions & 1 deletion src/Lib/PhpInternals/Types/Zend/ZendExecuteData.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ public function getRootFrame(

public function getVariableTableAddress(): int
{
return $this->pointer->indexedAt(1)->address;
return (int)($this->pointer->address
+ (int)((($this->pointer->size) + 16 - 1) / 16) * 16
);
}

public function getTotalVariablesNum(Dereferencer $dereferencer): int
Expand Down
47 changes: 44 additions & 3 deletions src/Lib/PhpProcessReader/CallTraceReader/CallTraceReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@

use Reli\Lib\PhpInternals\Opcodes\OpcodeFactory;
use Reli\Lib\PhpInternals\Types\C\RawDouble;
use Reli\Lib\PhpInternals\Types\Zend\Bucket;
use Reli\Lib\PhpInternals\Types\Zend\Opline;
use Reli\Lib\PhpInternals\Types\Zend\ZendArray;
use Reli\Lib\PhpInternals\Types\Zend\ZendCastedTypeProvider;
use Reli\Lib\PhpInternals\Types\Zend\ZendExecuteData;
use Reli\Lib\PhpInternals\Types\Zend\ZendExecutorGlobals;
use Reli\Lib\PhpInternals\Types\Zend\ZendFunction;
use Reli\Lib\PhpInternals\Types\Zend\ZendOp;
use Reli\Lib\PhpInternals\Types\Zend\Zval;
use Reli\Lib\PhpInternals\ZendTypeReader;
use Reli\Lib\PhpInternals\ZendTypeReaderCreator;
use Reli\Lib\Process\MemoryReader\MemoryReaderInterface;
use Reli\Lib\Process\MemoryReader\MemoryReaderException;
use Reli\Lib\Process\Pointer\Dereferencer;
use Reli\Lib\Process\Pointer\PointedTypeResolver;
use Reli\Lib\Process\Pointer\Pointer;
use Reli\Lib\Process\Pointer\RemoteProcessDereferencer;
use Reli\Lib\Process\ProcessSpecifier;
Expand Down Expand Up @@ -62,7 +64,46 @@ private function getDereferencer(int $pid, string $php_version): Dereferencer
new ProcessSpecifier($pid),
new ZendCastedTypeProvider(
$this->getTypeReader($php_version),
)
),
new class ($php_version) implements PointedTypeResolver {
public function __construct(
private string $php_version,
) {
}

public function resolve(string $type_name): string
{
return match ($this->php_version) {
ZendTypeReader::V70,
ZendTypeReader::V71,
ZendTypeReader::V72 => match ($type_name) {
Bucket::class => \Reli\Lib\PhpInternals\Types\Zend\V70\Bucket::class,
ZendArray::class => \Reli\Lib\PhpInternals\Types\Zend\V70\ZendArray::class,
Zval::class => \Reli\Lib\PhpInternals\Types\Zend\V70\Zval::class,
default => $type_name,
},
ZendTypeReader::V73 => match ($type_name) {
Bucket::class => \Reli\Lib\PhpInternals\Types\Zend\V73\Bucket::class,
ZendArray::class => \Reli\Lib\PhpInternals\Types\Zend\V73\ZendArray::class,
Zval::class => \Reli\Lib\PhpInternals\Types\Zend\V73\Zval::class,
default => $type_name,
},
ZendTypeReader::V74 => match ($type_name) {
Bucket::class => \Reli\Lib\PhpInternals\Types\Zend\V74\Bucket::class,
ZendArray::class => \Reli\Lib\PhpInternals\Types\Zend\V74\ZendArray::class,
Zval::class => \Reli\Lib\PhpInternals\Types\Zend\V74\Zval::class,
default => $type_name,
},
ZendTypeReader::V80,
ZendTypeReader::V81 => match ($type_name) {
ZendArray::class => \Reli\Lib\PhpInternals\Types\Zend\V80\ZendArray::class,
default => $type_name,
},
ZendTypeReader::V82,
ZendTypeReader::V83 => $type_name,
};
}
}
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ public static function fromZendObject(
$class_name = $ce->getClassName($dereferencer);
if ($class_name === \Fiber::class) {
$size = $zend_type_reader->sizeOf('zend_fiber');
} elseif ($class_name === \Closure::class) {
} elseif (
$class_name === \Closure::class
and !$zend_type_reader->isPhpVersionLowerThan(ZendTypeReader::V71)
) {
$size = $zend_type_reader->sizeOf('zend_closure');
} else {
$size = $zend_object->getMemorySize($dereferencer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1055,7 +1055,10 @@ public function collectZendObject(

assert(!is_null($object->ce));
$class_entry = $dereferencer->deref($object->ce);
if ($class_entry->getClassName($dereferencer) === 'Closure') {
if (
$class_entry->getClassName($dereferencer) === 'Closure'
and !$zend_type_reader->isPhpVersionLowerThan(ZendTypeReader::V71)
) {
$closure_context = $this->collectClosure(
$dereferencer->deref(
ZendClosure::getPointerFromZendObjectPointer(
Expand Down Expand Up @@ -1636,7 +1639,7 @@ private function collectClassDefinition(
}

$methods_context = $this->collectFunctionTable(
$class_entry->function_table,
$dereferencer->deref($class_entry->function_table->getPointer()),
$map_ptr_base,
$dereferencer,
$zend_type_reader,
Expand All @@ -1647,7 +1650,7 @@ private function collectClassDefinition(
$class_definition_context->add('methods', $methods_context);

$class_constants_context = $this->collectClassConstantsTable(
$class_entry->constants_table,
$dereferencer->deref($class_entry->constants_table->getPointer()),
$map_ptr_base,
$dereferencer,
$zend_type_reader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

declare(strict_types=1);

namespace Reli\Command\CommandEnumeratorTestData\Test1Directory;
namespace Reli\Command\Test1Directory;

final class Test1Command
use Symfony\Component\Console\Command\Command;

final class Test1Command extends Command
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@

declare(strict_types=1);

namespace Reli\Command\CommandEnumeratorTestData\Test1Directory;
namespace Reli\Command\Test1Directory;

final class Test2Command
use Symfony\Component\Console\Command\Command;

final class Test2Command extends Command
{
}
Loading
Loading