Skip to content

Commit

Permalink
feat: Pool修复及测试
Browse files Browse the repository at this point in the history
  • Loading branch information
chaz6chez committed Oct 10, 2024
1 parent 135d0b6 commit ae0a77e
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 21 deletions.
57 changes: 36 additions & 21 deletions src/Utils/Pool/Pool.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ class Pool
/**
* 元素
*
* @var object|array|null
* @var object|array|null|mixed
*/
protected object|array|null $_element;
protected mixed $_element;

/**
* 是否空闲
Expand Down Expand Up @@ -83,26 +83,18 @@ public static function create(string $name, int $count, mixed $element): array
public static function destroy(string $name, ?int $index, bool $force = false): void
{
$pools = static::get($name, $index);
if ($pools) {
foreach ($pools as $in => $pool) {
// Pool
if ($pool instanceof Pool) {
$pool->setForce($force);
unset(self::$pools[$name][$in]);
continue;
}
/**
* 非Pool则为数组
* @var int $i
* @var Pool $p
*/
foreach ($pool as $i => $p) {
$p->setForce($force);
unset(self::$pools[$name][$i]);
}
if ($pools instanceof Pool) {
$pools->setForce($force);
unset(self::$pools[$name][$index]);
return;
}
if (is_array($pools)) {
foreach ($pools as $i => $p) {
$p->setForce($force);
unset(self::$pools[$name][$i]);
return;
}
}

}

/**
Expand Down Expand Up @@ -154,6 +146,27 @@ public static function waitForIdle(string $name, \Closure $closure, int $timeout
return call_user_func($closure, $pool);
}

/**
* 数组的深拷贝
*
* @param array $array
* @return array
*/
protected static function _deepCopyArray(array $array): array
{
$copy = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$copy[$key] = self::_deepCopyArray($value);
} elseif (is_object($value)) {
$copy[$key] = clone $value;
} else {
$copy[$key] = $value;
}
}
return $copy;
}

/**
* 构造
*
Expand All @@ -171,7 +184,8 @@ public function __construct(string $name, int $index, mixed $element)
$this->setForce(false);
$this->setIdle(true);
$this->_element = match (true) {
is_object($element), is_array($element) => clone $element,
is_object($element) => clone $element,
is_array($element) => self::_deepCopyArray($element),
is_callable($element) => call_user_func($element),
default => $element,
};
Expand Down Expand Up @@ -274,4 +288,5 @@ public function wait(?\Closure $closure = null): void
call_user_func($closure, $this);
}
}

}
147 changes: 147 additions & 0 deletions tests/UtilsCase/Pool/PoolTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?php

declare(strict_types=1);

namespace Workbunny\Tests\UtilsCase\Pool;

use Mockery;
use PHPUnit\Framework\TestCase;
use \stdClass;
use Workbunny\WebmanCoroutine\Utils\Pool\Pool;
use Workbunny\WebmanCoroutine\Exceptions\PoolException;

class PoolTest extends TestCase
{
public function tearDown(): void
{
Mockery::close();
}

public function testCreatePoolWithStdClass()
{
$element = new stdClass();
$element->property = 'value';
$pools = Pool::create(__METHOD__, 2, $element);

$this->assertCount(2, $pools);
$this->assertInstanceOf(Pool::class, $pools[1]);
$this->assertInstanceOf(Pool::class, $pools[2]);

// 验证克隆是否生效
$this->assertNotSame($element, $pools[1]->getElement());
$this->assertEquals('value', $pools[1]->getElement()->property);
}

public function testCreatePoolWithArray()
{
$element = ['key' => 'value'];
$pools = Pool::create(__METHOD__, 2, $element);

$this->assertCount(2, $pools);
$this->assertInstanceOf(Pool::class, $pools[1]);
$this->assertInstanceOf(Pool::class, $pools[2]);

$element['key'] = 1;
// 验证数组是否正确克隆
$this->assertTrue($this->_arraysAreDifferent($element, $pools[1]->getElement()));
$this->assertEquals('value', $pools[1]->getElement()['key']);
}

/**
* 递归比较数组
*
* @param array $array1
* @param array $array2
* @return bool
*/
protected function _arraysAreDifferent(array $array1, array $array2): bool
{
if (count($array1) !== count($array2)) {
return true;
}
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (!is_array($array2[$key]) || $this->_arraysAreDifferent($value, $array2[$key])) {
return true;
}
} elseif (is_object($value)) {
if (!is_object($array2[$key]) || spl_object_id($value) === spl_object_id($array2[$key])) {
return true;
}
} else {
if ($value !== $array2[$key]) {
return true;
}
}
}
return false;
}

public function testCreatePoolWithResource()
{
$element = fopen('php://memory', 'r');
$pools = Pool::create(__METHOD__, 2, $element);

$this->assertCount(2, $pools);
$this->assertInstanceOf(Pool::class, $pools[1]);
$this->assertInstanceOf(Pool::class, $pools[2]);

// 验证资源类型
$this->assertIsResource($pools[1]->getElement());
fclose($element);
}

public function testCreatePoolThrowsException()
{
$this->expectException(PoolException::class);
$name = __METHOD__;
$this->expectExceptionMessage("Pools $name already exists.");

$element = new stdClass();
Pool::create(__METHOD__, 2, $element);
Pool::create(__METHOD__, 2, $element);
}

public function testGetPool()
{
$element = new stdClass();
Pool::create(__METHOD__, 2, $element);

$pool = Pool::get(__METHOD__, 1);
$this->assertInstanceOf(Pool::class, $pool);
$this->assertEquals(__METHOD__, $pool->getName());
$this->assertEquals(1, $pool->getIndex());
}

public function testIdlePool()
{
$element = new stdClass();
Pool::create(__METHOD__, 2, $element);

$pool = Pool::idle(__METHOD__);
$this->assertInstanceOf(Pool::class, $pool);
$this->assertTrue($pool->isIdle());
}

public function testWaitForIdle()
{
$element = new stdClass();
Pool::create(__METHOD__, 2, $element);

$result = Pool::waitForIdle(__METHOD__, function ($pool) {
return $pool->getName();
});

$this->assertEquals(__METHOD__, $result);
}

public function testDestroyPool()
{
$element = new stdClass();
Pool::create(__METHOD__, 2, $element);

Pool::destroy(__METHOD__, 1);
$this->assertNull(Pool::get(__METHOD__, 1));
}
}

0 comments on commit ae0a77e

Please sign in to comment.