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

General updates -- Node as module, update depency versionsto supported ones, PHP strict_types declaration and phpunit tests #5

Open
wants to merge 8 commits into
base: zoon
Choose a base branch
from
Prev Previous commit
Next Next commit
Update tests to run on phpunit 11.3
mreiden committed Aug 16, 2024
commit 6512a56573f8b4ba852b8dc1549d2dbe5f2b0f71
29 changes: 16 additions & 13 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.5/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.3/phpunit.xsd"
bootstrap="vendor/autoload.php"
forceCoversAnnotation="true"
beStrictAboutCoversAnnotation="true"
cacheDirectory=".phpunit.cache"
executionOrder="depends,defects"
requireCoverageMetadata="false"
beStrictAboutCoverageMetadata="false"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
colors="true"
verbose="true">
failOnRisky="true"
failOnWarning="true"
colors="true">
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
<directory suffix="Test.php">tests</directory>
</testsuite>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</testsuites>
<source restrictNotices="true" restrictWarnings="true" ignoreIndirectDeprecations="true">
<include>
<directory suffix=".php">src</directory>
</include>
</source>
</phpunit>
31 changes: 13 additions & 18 deletions tests/Implementation/FsConnectionDelegate.mjs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
'use strict';
"use strict";

const fs = require('fs'),
{ConnectionDelegate} = require('../../src/node-process');
import fs from "fs";
import ConnectionDelegate from "../../src/node-process/ConnectionDelegate.mjs";

/**
* Handle the requests of a connection to control the "fs" module.
*/
class FsConnectionDelegate extends ConnectionDelegate
{
async handleInstruction(instruction, responseHandler, errorHandler)
{
export default class FsConnectionDelegate extends ConnectionDelegate {
async handleInstruction(instruction, responseHandler, errorHandler) {
instruction.setDefaultResource(this.extendFsModule(fs));

let value = null;
@@ -27,30 +25,27 @@ class FsConnectionDelegate extends ConnectionDelegate
responseHandler(value);
}

extendFsModule(fs)
{
extendFsModule(fs) {
fs.multipleStatSync = (...paths) => paths.map(fs.statSync);

fs.multipleResourcesIsFile = resources => resources.map(resource => resource.isFile());
fs.multipleResourcesIsFile = (resources) => resources.map((resource) => resource.isFile());

fs.getHeavyPayloadWithNonAsciiChars = () => {
let payload = '';
let payload = "";

for (let i = 0 ; i < 1024 ; i++) {
payload += 'a';
for (let i = 0; i < 1024; i++) {
payload += "a";
}

return `😘${payload}😘`;
};

fs.wait = ms => new Promise(resolve => setTimeout(resolve, ms));
fs.wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

fs.runCallback = cb => cb(fs);
fs.runCallback = (cb) => cb(fs);

fs.getOption = name => this.options[name];
fs.getOption = (name) => this.options[name];

return fs;
}
}

module.exports = FsConnectionDelegate;
10 changes: 7 additions & 3 deletions tests/Implementation/FsProcessDelegate.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<?php

declare(strict_types=1);

namespace Nesk\Rialto\Tests\Implementation;

use Nesk\Rialto\Traits\UsesBasicResourceAsDefault;
use Nesk\Rialto\Interfaces\ShouldHandleProcessDelegation;
use Nesk\Rialto\{
Interfaces\ShouldHandleProcessDelegation,
Traits\UsesBasicResourceAsDefault,
};

class FsProcessDelegate implements ShouldHandleProcessDelegation
{
use UsesBasicResourceAsDefault;

public function resourceFromOriginalClassName(string $className): ?string
{
$class = __NAMESPACE__."\\Resources\\$className";
$class = __NAMESPACE__ . "\\Resources\\$className";

return class_exists($class) ? $class : null;
}
7 changes: 4 additions & 3 deletions tests/Implementation/FsWithProcessDelegation.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
<?php

declare(strict_types=1);

namespace Nesk\Rialto\Tests\Implementation;

use Nesk\Rialto\ProcessSupervisor;
use Nesk\Rialto\AbstractEntryPoint;
use Nesk\Rialto\{AbstractEntryPoint, ProcessSupervisor};

class FsWithProcessDelegation extends AbstractEntryPoint
{
protected $forbiddenOptions = ['stop_timeout', 'foo'];

public function __construct(array $userOptions = [])
{
parent::__construct(__DIR__.'/FsConnectionDelegate.js', new FsProcessDelegate, [], $userOptions);
parent::__construct(__DIR__ . '/FsConnectionDelegate.mjs', new FsProcessDelegate(), [], $userOptions);
}

public function getProcessSupervisor(): ProcessSupervisor
4 changes: 3 additions & 1 deletion tests/Implementation/FsWithoutProcessDelegation.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Nesk\Rialto\Tests\Implementation;

use Nesk\Rialto\AbstractEntryPoint;
@@ -8,6 +10,6 @@ class FsWithoutProcessDelegation extends AbstractEntryPoint
{
public function __construct()
{
parent::__construct(__DIR__.'/FsConnectionDelegate.js');
parent::__construct(__DIR__ . '/FsConnectionDelegate.mjs');
}
}
2 changes: 2 additions & 0 deletions tests/Implementation/Resources/Stats.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Nesk\Rialto\Tests\Implementation\Resources;

use Nesk\Rialto\Data\BasicResource;
273 changes: 144 additions & 129 deletions tests/ImplementationTest.php

Large diffs are not rendered by default.

64 changes: 30 additions & 34 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
<?php

declare(strict_types=1);

namespace Nesk\Rialto\Tests;

use Monolog\Logger;
use PHPUnit\Framework\{Constraint\Callback, TestCase as BaseTestCase};
use PHPUnit\Framework\MockObject\Rule\InvocationOrder;
use ReflectionClass;
use Psr\Log\LogLevel;
use PHPUnit\Util\ErrorHandler;
use Psr\Log\LogLevel;
use Symfony\Component\Process\Process;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\TestCase as BaseTestCase;

use function Symfony\Component\Translation\t;

class TestCase extends BaseTestCase
{
@@ -19,10 +21,10 @@ protected function setUp(): void
{
parent::setUp();

$testMethod = new \ReflectionMethod($this, $this->getName());
$testMethod = new \ReflectionMethod($this, $this->name());
$docComment = $testMethod->getDocComment();

if (preg_match('/@dontPopulateProperties (.*)/', $docComment, $matches)) {
if (!empty($docComment) && preg_match('/@dontPopulateProperties (.*)/', $docComment, $matches)) {
$this->dontPopulateProperties = array_values(array_filter(explode(' ', $matches[1])));
}
}
@@ -32,14 +34,15 @@ public function canPopulateProperty(string $propertyName): bool
return !in_array($propertyName, $this->dontPopulateProperties);
}

public function ignoreUserDeprecation(string $messagePattern, callable $callback) {
set_error_handler(
function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) use ($messagePattern) {
if ($errorNumber !== E_USER_DEPRECATED || preg_match($messagePattern, $errorString) !== 1) {
(new ErrorHandler(true, true, true, true))($errorNumber, $errorString, $errorFile, $errorLine);
}
public function ignoreUserDeprecation(string $messagePattern, callable $callback)
{
set_error_handler(function (int $errorNumber, string $errorString, string $errorFile, int $errorLine) use (
$messagePattern,
) {
if ($errorNumber !== E_USER_DEPRECATED || preg_match($messagePattern, $errorString) !== 1) {
(new ErrorHandler(true, true, true, true))($errorNumber, $errorString, $errorFile, $errorLine);
}
);
});

$value = $callback();

@@ -48,24 +51,20 @@ function (int $errorNumber, string $errorString, string $errorFile, int $errorLi
return $value;
}

public function getPidsForProcessName(string $processName) {
public function getPidsForProcessName(string $processName)
{
$pgrep = new Process(['pgrep', $processName]);
$pgrep->run();

$pids = explode("\n", $pgrep->getOutput());

$pids = array_filter($pids, function ($pid) {
return !empty($pid);
});

$pids = array_map(function ($pid) {
return (int) $pid;
}, $pids);
$pids = array_filter($pids, fn($pid) => !empty($pid));
$pids = array_map(fn($pid) => (int) $pid, $pids);

return $pids;
}

public function loggerMock($expectations) {
public function loggerMock(InvocationOrder|array $expectations)
{
$loggerMock = $this->getMockBuilder(Logger::class)
->setConstructorArgs(['rialto'])
->onlyMethods(['log'])
@@ -74,27 +73,24 @@ public function loggerMock($expectations) {
$expectations = [func_get_args()];
}

foreach ($expectations as $expectation) {
[$matcher] = $expectation;
$with = array_slice($expectation, 1);

$loggerMock->expects($matcher)
->method('log')
->with(...$with);
foreach ($expectations as $with) {
$matcher = array_shift($with);
$loggerMock->expects($matcher)->method('log')->with(...$with);
}

return $loggerMock;
}

public function isLogLevel(): Callback {
$psrLogLevels = (new ReflectionClass(LogLevel::class))->getConstants();
$monologLevels = (new ReflectionClass(Logger::class))->getConstants();
public function isLogLevel(): Callback
{
$psrLogLevels = (new \ReflectionClass(LogLevel::class))->getConstants();
$monologLevels = (new \ReflectionClass(Logger::class))->getConstants();
$monologLevels = array_intersect_key($monologLevels, $psrLogLevels);

return $this->callback(function ($level) use ($psrLogLevels, $monologLevels) {
if (is_string($level)) {
return in_array($level, $psrLogLevels, true);
} else if (is_int($level)) {
} elseif (is_int($level)) {
return in_array($level, $monologLevels, true);
}