95 lines
3.1 KiB
PHP
95 lines
3.1 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace HyperfTest\Cases\Integration\Materialization;
|
||
|
|
|
||
|
|
use Hyperf\DbConnection\Db;
|
||
|
|
use PHPUnit\Framework\TestCase;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* P22.3 物化对象集成测试:跨两类物化对象 + 跨命名空间索引的存在性断言。
|
||
|
|
*
|
||
|
|
* 与 P22.2 烟雾测试 `System/MaterializedViewSmokeTest` 各自关注点不同:
|
||
|
|
* - 烟雾测试:单点测试,专测 by_paid 视图与索引
|
||
|
|
* - 本测试:跨两类对象(连续聚合 + PG 物化视图)+ 跨命名空间索引(pg_indexes 不区分视图类型)
|
||
|
|
*
|
||
|
|
* @internal
|
||
|
|
* @coversNothing
|
||
|
|
*/
|
||
|
|
class MaterializationObjectsTest extends TestCase
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* @template T
|
||
|
|
* @param callable(): T $callback
|
||
|
|
* @return T
|
||
|
|
*/
|
||
|
|
protected function runInCoroutine(callable $callback): mixed
|
||
|
|
{
|
||
|
|
if (\Swoole\Coroutine::getCid() > 0) {
|
||
|
|
return $callback();
|
||
|
|
}
|
||
|
|
|
||
|
|
$result = null;
|
||
|
|
$exception = null;
|
||
|
|
\Swoole\Coroutine\run(static function () use ($callback, &$result, &$exception): void {
|
||
|
|
try {
|
||
|
|
$result = $callback();
|
||
|
|
} catch (\Throwable $e) {
|
||
|
|
$exception = $e;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
if ($exception !== null) {
|
||
|
|
throw $exception;
|
||
|
|
}
|
||
|
|
return $result;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_continuous_aggregate_exists(): void
|
||
|
|
{
|
||
|
|
$rows = $this->runInCoroutine(static fn () => Db::select(
|
||
|
|
"SELECT view_name FROM timescaledb_information.continuous_aggregates
|
||
|
|
WHERE view_name = 'orders_daily_by_created'"
|
||
|
|
));
|
||
|
|
$this->assertCount(1, $rows);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_pg_materialized_view_exists(): void
|
||
|
|
{
|
||
|
|
$rows = $this->runInCoroutine(static fn () => Db::select(
|
||
|
|
"SELECT matviewname FROM pg_matviews
|
||
|
|
WHERE matviewname = 'orders_daily_by_paid'"
|
||
|
|
));
|
||
|
|
$this->assertCount(1, $rows);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_refresh_policy_registered(): void
|
||
|
|
{
|
||
|
|
// 显式过滤 hypertable_name,避免未来追加其他连续聚合策略时此断言无关地失败。
|
||
|
|
$rows = $this->runInCoroutine(static fn () => Db::select(
|
||
|
|
"SELECT hypertable_name FROM timescaledb_information.jobs
|
||
|
|
WHERE proc_name = 'policy_refresh_continuous_aggregate'
|
||
|
|
AND hypertable_name = 'orders_daily_by_created'"
|
||
|
|
));
|
||
|
|
$this->assertCount(1, $rows);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_by_created_indexes_present(): void
|
||
|
|
{
|
||
|
|
// P22.1 创建 5 复合索引;chunk 索引名是 `_hyper_*` 不会被 LIKE 'idx_*' 匹配。
|
||
|
|
$rows = $this->runInCoroutine(static fn () => Db::select(
|
||
|
|
"SELECT indexname FROM pg_indexes WHERE indexname LIKE 'idx_orders_daily_by_created%'"
|
||
|
|
));
|
||
|
|
$this->assertCount(5, $rows);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_by_paid_indexes_present(): void
|
||
|
|
{
|
||
|
|
// P22.2 创建 1 UNIQUE + 5 复合 = 6 索引。
|
||
|
|
$rows = $this->runInCoroutine(static fn () => Db::select(
|
||
|
|
"SELECT indexname FROM pg_indexes WHERE indexname LIKE 'idx_orders_daily_by_paid%'"
|
||
|
|
));
|
||
|
|
$this->assertCount(6, $rows);
|
||
|
|
}
|
||
|
|
}
|