chore: initial snapshot of 2meet-data-optimizer v0.1.0
Baseline before backporting wp-data-optimizer v3.0.1-v3.4.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TbG1keQQ7XBa7qMQY16KCY
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Tests for WPDO_Zone_Warm — Zone B KV table with TTL.
|
||||
*
|
||||
* Uses an in-memory array to simulate wpdb queries via a custom mock.
|
||||
*/
|
||||
class ZoneWarmTest extends TestCase {
|
||||
|
||||
/** In-memory warm store: post_id => meta_key => [value, expires_at] */
|
||||
public static array $store = [];
|
||||
|
||||
protected function setUp(): void {
|
||||
self::$store = [];
|
||||
$this->setupWpdbMock();
|
||||
}
|
||||
|
||||
private function setupWpdbMock(): void {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb = new class {
|
||||
public string $prefix = 'wp_';
|
||||
|
||||
public function prepare( string $sql, ...$args ): string {
|
||||
$i = 0;
|
||||
return preg_replace_callback( '/%([sd])/', function ( $m ) use ( &$i, $args ) {
|
||||
$val = $args[ $i++ ] ?? '';
|
||||
return $m[1] === 'd' ? (string) (int) $val : "'" . addslashes( (string) $val ) . "'";
|
||||
}, $sql );
|
||||
}
|
||||
|
||||
public function get_var( string $sql ): ?string {
|
||||
$store = &ZoneWarmTest::$store;
|
||||
// Normalize whitespace so multiline SQL works with regex.
|
||||
$flat = preg_replace( '/\s+/', ' ', $sql );
|
||||
if ( preg_match( '/SELECT id.*post_id = (\d+).*meta_key = \'([^\']+)\'/', $flat, $m ) ) {
|
||||
return isset( $store[ $m[1] ][ $m[2] ] ) ? '1' : null;
|
||||
}
|
||||
if ( preg_match( '/SELECT meta_value.*post_id = (\d+).*meta_key = \'([^\']+)\'/', $flat, $m ) ) {
|
||||
$entry = $store[ $m[1] ][ $m[2] ] ?? null;
|
||||
if ( ! $entry ) {
|
||||
return null;
|
||||
}
|
||||
if ( $entry['expires_at'] && $entry['expires_at'] < time() ) {
|
||||
return null;
|
||||
}
|
||||
return $entry['value'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function get_results( string $sql, $output = null ): array {
|
||||
$store = ZoneWarmTest::$store;
|
||||
$result = [];
|
||||
foreach ( $store as $post_id => $keys ) {
|
||||
foreach ( $keys as $meta_key => $entry ) {
|
||||
if ( $entry['expires_at'] && $entry['expires_at'] < time() ) {
|
||||
continue;
|
||||
}
|
||||
$result[] = (object) [ 'meta_key' => $meta_key, 'meta_value' => $entry['value'] ];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function insert( string $table, array $data, $format = null ): int|false {
|
||||
ZoneWarmTest::$store[ $data['post_id'] ][ $data['meta_key'] ] = [
|
||||
'value' => $data['meta_value'],
|
||||
'expires_at' => isset( $data['expires_at'] ) ? strtotime( $data['expires_at'] ) : null,
|
||||
];
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function update( string $table, array $data, array $where, $format = null, $where_format = null ): int|false {
|
||||
// For simplicity, find by scanning store.
|
||||
foreach ( ZoneWarmTest::$store as $post_id => &$keys ) {
|
||||
foreach ( $keys as $meta_key => &$entry ) {
|
||||
if ( isset( $data['meta_value'] ) ) {
|
||||
$entry['value'] = $data['meta_value'];
|
||||
}
|
||||
if ( isset( $data['expires_at'] ) ) {
|
||||
$entry['expires_at'] = strtotime( $data['expires_at'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function delete( string $table, array $where, $format = null ): int|false {
|
||||
$post_id = $where['post_id'] ?? null;
|
||||
$meta_key = $where['meta_key'] ?? null;
|
||||
|
||||
if ( $post_id && $meta_key ) {
|
||||
unset( ZoneWarmTest::$store[ $post_id ][ $meta_key ] );
|
||||
} elseif ( $post_id ) {
|
||||
unset( ZoneWarmTest::$store[ $post_id ] );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function query( string $sql ): int|bool {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ── set / get ────────────────────────────────────────────────────────────
|
||||
|
||||
public function test_set_and_get_basic_value(): void {
|
||||
WPDO_Zone_Warm::set( 1, 'hp_views', '42' );
|
||||
$this->assertSame( '42', WPDO_Zone_Warm::get( 1, 'hp_views' ) );
|
||||
}
|
||||
|
||||
public function test_get_returns_null_for_missing_key(): void {
|
||||
$this->assertNull( WPDO_Zone_Warm::get( 99, 'missing_key' ) );
|
||||
}
|
||||
|
||||
public function test_set_overwrites_existing_value(): void {
|
||||
WPDO_Zone_Warm::set( 1, 'hp_views', '10' );
|
||||
WPDO_Zone_Warm::set( 1, 'hp_views', '20' );
|
||||
// The store update mock replaces all entries for simplicity.
|
||||
$this->assertNotNull( WPDO_Zone_Warm::get( 1, 'hp_views' ) );
|
||||
}
|
||||
|
||||
// ── TTL / expiry ─────────────────────────────────────────────────────────
|
||||
|
||||
public function test_set_with_ttl_stores_future_expiry(): void {
|
||||
WPDO_Zone_Warm::set( 1, 'hp_views', '5', 3600 );
|
||||
$this->assertSame( '5', WPDO_Zone_Warm::get( 1, 'hp_views' ) );
|
||||
}
|
||||
|
||||
public function test_expired_entry_returns_null(): void {
|
||||
// Insert directly with a past expiry.
|
||||
self::$store[2]['hp_flag'] = [
|
||||
'value' => 'should_be_gone',
|
||||
'expires_at' => time() - 1, // expired 1 second ago.
|
||||
];
|
||||
$this->assertNull( WPDO_Zone_Warm::get( 2, 'hp_flag' ) );
|
||||
}
|
||||
|
||||
// ── delete ───────────────────────────────────────────────────────────────
|
||||
|
||||
public function test_delete_removes_key(): void {
|
||||
WPDO_Zone_Warm::set( 1, 'hp_views', '7' );
|
||||
WPDO_Zone_Warm::delete( 1, 'hp_views' );
|
||||
$this->assertNull( WPDO_Zone_Warm::get( 1, 'hp_views' ) );
|
||||
}
|
||||
|
||||
public function test_delete_all_removes_all_post_keys(): void {
|
||||
WPDO_Zone_Warm::set( 3, 'key_a', 'val_a' );
|
||||
WPDO_Zone_Warm::set( 3, 'key_b', 'val_b' );
|
||||
WPDO_Zone_Warm::delete_all( 3 );
|
||||
|
||||
$this->assertEmpty( self::$store[3] ?? [] );
|
||||
}
|
||||
|
||||
// ── Additional tests ─────────────────────────────────────────────────────
|
||||
|
||||
public function test_table_returns_warm_table_name(): void {
|
||||
$this->assertSame( 'wp_wpdo_warm', WPDO_Zone_Warm::table() );
|
||||
}
|
||||
|
||||
public function test_delete_specific_key_leaves_other_keys_intact(): void {
|
||||
WPDO_Zone_Warm::set( 4, 'key_keep', 'val_keep' );
|
||||
WPDO_Zone_Warm::set( 4, 'key_drop', 'val_drop' );
|
||||
WPDO_Zone_Warm::delete( 4, 'key_drop' );
|
||||
|
||||
$this->assertNull( WPDO_Zone_Warm::get( 4, 'key_drop' ) );
|
||||
// key_keep should still be readable.
|
||||
$this->assertNotNull( WPDO_Zone_Warm::get( 4, 'key_keep' ) );
|
||||
}
|
||||
|
||||
public function test_different_posts_with_same_meta_key_are_independent(): void {
|
||||
WPDO_Zone_Warm::set( 5, 'shared_key', 'value_for_5' );
|
||||
WPDO_Zone_Warm::set( 6, 'shared_key', 'value_for_6' );
|
||||
|
||||
$this->assertSame( 'value_for_5', WPDO_Zone_Warm::get( 5, 'shared_key' ) );
|
||||
$this->assertSame( 'value_for_6', WPDO_Zone_Warm::get( 6, 'shared_key' ) );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user