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,269 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Integration tests — Warm Zone (Zone B) + Archive Zone (Zone D) lifecycle.
|
||||
*
|
||||
* Covers:
|
||||
* - Warm zone: set/get/TTL/purge_expired/flush_views
|
||||
* - Archive zone: archive_batch/get/stats/restore/gzip roundtrip
|
||||
* - WPDO_Listing_Stats: increment + flush + REST view count
|
||||
*
|
||||
* Uses dedicated test tables (wp_itest_ prefix) to avoid collisions.
|
||||
*/
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class WarmArchiveIntegrationTest extends TestCase {
|
||||
|
||||
private static string $warm_table;
|
||||
private static string $archive_table;
|
||||
private static string $errors_table;
|
||||
private static string $postmeta_table;
|
||||
|
||||
public static function setUpBeforeClass(): void {
|
||||
global $wpdb;
|
||||
|
||||
self::$warm_table = $wpdb->prefix . 'wpdo_warm';
|
||||
self::$archive_table = $wpdb->prefix . 'wpdo_archive';
|
||||
self::$errors_table = $wpdb->prefix . 'wpdo_errors';
|
||||
self::$postmeta_table = $wpdb->postmeta;
|
||||
|
||||
// DROP + CREATE ensures clean schema even after interrupted prior runs.
|
||||
$wpdb->query( "DROP TABLE IF EXISTS `" . self::$warm_table . "`" );
|
||||
$wpdb->query(
|
||||
"CREATE TABLE `" . self::$warm_table . "` (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
post_id BIGINT UNSIGNED NOT NULL,
|
||||
meta_key VARCHAR(255) NOT NULL,
|
||||
meta_value LONGTEXT,
|
||||
expires_at DATETIME DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY post_meta (post_id, meta_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
|
||||
);
|
||||
|
||||
// Create archive table (matches WPDO_Installer::install_system_tables DDL).
|
||||
$wpdb->query( "DROP TABLE IF EXISTS `" . self::$archive_table . "`" );
|
||||
$wpdb->query(
|
||||
"CREATE TABLE `" . self::$archive_table . "` (
|
||||
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
post_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
post_type VARCHAR(20) NOT NULL DEFAULT '',
|
||||
meta_key VARCHAR(255) NOT NULL DEFAULT '',
|
||||
meta_value LONGTEXT,
|
||||
compressed TINYINT(1) NOT NULL DEFAULT 0,
|
||||
archived_at DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
original_meta_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_post_id (post_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
|
||||
);
|
||||
|
||||
// Create errors table (needed by WPDO_Logger).
|
||||
$wpdb->query( "DROP TABLE IF EXISTS `" . self::$errors_table . "`" );
|
||||
$wpdb->query(
|
||||
"CREATE TABLE `" . self::$errors_table . "` (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
severity VARCHAR(20) NOT NULL DEFAULT 'error',
|
||||
module VARCHAR(100) NOT NULL DEFAULT '',
|
||||
zone VARCHAR(50) DEFAULT NULL,
|
||||
hook VARCHAR(100) NOT NULL DEFAULT '',
|
||||
message TEXT NOT NULL,
|
||||
context LONGTEXT DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
|
||||
);
|
||||
|
||||
// Create postmeta table (needed by flush_views_to_postmeta batch query).
|
||||
// Only create if it does not already exist — shared with other test classes.
|
||||
$wpdb->query(
|
||||
"CREATE TABLE IF NOT EXISTS `" . self::$postmeta_table . "` (
|
||||
meta_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
post_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
meta_key VARCHAR(255) DEFAULT NULL,
|
||||
meta_value LONGTEXT,
|
||||
PRIMARY KEY (meta_id),
|
||||
KEY post_id (post_id),
|
||||
KEY meta_key (meta_key(191))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"
|
||||
);
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass(): void {
|
||||
global $wpdb;
|
||||
$wpdb->query( "DROP TABLE IF EXISTS `" . self::$warm_table . "`" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS `" . self::$archive_table . "`" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS `" . self::$errors_table . "`" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS `" . self::$postmeta_table . "`" );
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
global $wpdb;
|
||||
$wpdb->query( "TRUNCATE TABLE `" . self::$warm_table . "`" );
|
||||
$wpdb->query( "TRUNCATE TABLE `" . self::$archive_table . "`" );
|
||||
$GLOBALS['_wp_cache'] = [];
|
||||
$GLOBALS['_wp_postmeta'] = [];
|
||||
$GLOBALS['_wp_options'] = [];
|
||||
}
|
||||
|
||||
// ── Zone B (Warm) ─────────────────────────────────────────────────────────
|
||||
|
||||
public function test_warm_set_and_get(): void {
|
||||
WPDO_Zone_Warm::set( 100, 'wp_key', 'hello', null );
|
||||
$val = WPDO_Zone_Warm::get( 100, 'wp_key' );
|
||||
$this->assertSame( 'hello', $val );
|
||||
}
|
||||
|
||||
public function test_warm_expired_returns_null(): void {
|
||||
global $wpdb;
|
||||
// Insert already-expired entry.
|
||||
$wpdb->query(
|
||||
"INSERT INTO `" . self::$warm_table . "` (post_id, meta_key, meta_value, expires_at)
|
||||
VALUES (101, 'stale_key', 'old', '2000-01-01 00:00:00')"
|
||||
);
|
||||
|
||||
$val = WPDO_Zone_Warm::get( 101, 'stale_key' );
|
||||
$this->assertNull( $val );
|
||||
}
|
||||
|
||||
public function test_warm_purge_expired(): void {
|
||||
global $wpdb;
|
||||
$wpdb->query(
|
||||
"INSERT INTO `" . self::$warm_table . "` (post_id, meta_key, meta_value, expires_at)
|
||||
VALUES (102, 'k1', 'v1', '2000-01-01 00:00:00'),
|
||||
(103, 'k2', 'v2', DATE_ADD(NOW(), INTERVAL 1 HOUR))"
|
||||
);
|
||||
|
||||
$deleted = WPDO_Zone_Warm::purge_expired();
|
||||
$this->assertGreaterThanOrEqual( 1, $deleted );
|
||||
|
||||
// k2 (future TTL) should still exist.
|
||||
$this->assertNotNull( WPDO_Zone_Warm::get( 103, 'k2' ) );
|
||||
}
|
||||
|
||||
public function test_warm_delete_all_for_post(): void {
|
||||
WPDO_Zone_Warm::set( 200, 'a', 'va', null );
|
||||
WPDO_Zone_Warm::set( 200, 'b', 'vb', null );
|
||||
WPDO_Zone_Warm::set( 201, 'a', 'other', null );
|
||||
|
||||
WPDO_Zone_Warm::delete_all( 200 );
|
||||
|
||||
$this->assertNull( WPDO_Zone_Warm::get( 200, 'a' ) );
|
||||
$this->assertNull( WPDO_Zone_Warm::get( 200, 'b' ) );
|
||||
$this->assertSame( 'other', WPDO_Zone_Warm::get( 201, 'a' ) );
|
||||
}
|
||||
|
||||
// ── Zone D (Archive) ──────────────────────────────────────────────────────
|
||||
|
||||
/** Helper: build a row for archive_batch with required post_type. */
|
||||
private function archive_rows( int $post_id, array $metas ): array {
|
||||
return array_map( fn( $m ) => array_merge(
|
||||
[ 'post_id' => $post_id, 'post_type' => 'hp_listing', 'meta_id' => 0 ],
|
||||
$m
|
||||
), $metas );
|
||||
}
|
||||
|
||||
public function test_archive_batch_stores_compressed(): void {
|
||||
global $wpdb;
|
||||
$rows = $this->archive_rows( 400, [
|
||||
[ 'meta_key' => 'hp_price', 'meta_value' => '999' ],
|
||||
[ 'meta_key' => 'hp_featured', 'meta_value' => '1' ],
|
||||
] );
|
||||
|
||||
WPDO_Zone_Archive::archive_batch( $rows, true );
|
||||
|
||||
$count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `" . self::$archive_table . "` WHERE post_id = 400" );
|
||||
$this->assertSame( 2, $count );
|
||||
|
||||
$comp = (int) $wpdb->get_var( "SELECT SUM(compressed) FROM `" . self::$archive_table . "` WHERE post_id = 400" );
|
||||
$this->assertSame( 2, $comp );
|
||||
}
|
||||
|
||||
public function test_archive_get_returns_values(): void {
|
||||
$rows = $this->archive_rows( 401, [
|
||||
[ 'meta_key' => 'hp_price', 'meta_value' => '500' ],
|
||||
[ 'meta_key' => 'hp_verified', 'meta_value' => '1' ],
|
||||
] );
|
||||
WPDO_Zone_Archive::archive_batch( $rows, false );
|
||||
|
||||
$result = WPDO_Zone_Archive::get( 401 );
|
||||
$this->assertCount( 2, $result );
|
||||
|
||||
$by_key = array_column( $result, 'meta_value', 'meta_key' );
|
||||
$this->assertSame( '500', $by_key['hp_price'] );
|
||||
$this->assertSame( '1', $by_key['hp_verified'] );
|
||||
}
|
||||
|
||||
public function test_archive_get_with_key_filter(): void {
|
||||
$rows = $this->archive_rows( 402, [
|
||||
[ 'meta_key' => 'hp_price', 'meta_value' => '250' ],
|
||||
[ 'meta_key' => 'hp_featured', 'meta_value' => '0' ],
|
||||
] );
|
||||
WPDO_Zone_Archive::archive_batch( $rows, false );
|
||||
|
||||
$result = WPDO_Zone_Archive::get( 402, 'hp_price' );
|
||||
$this->assertCount( 1, $result );
|
||||
$this->assertSame( 'hp_price', $result[0]['meta_key'] );
|
||||
}
|
||||
|
||||
public function test_archive_restore_writes_postmeta(): void {
|
||||
global $wpdb;
|
||||
$rows = $this->archive_rows( 403, [
|
||||
[ 'meta_key' => 'hp_price', 'meta_value' => '777' ],
|
||||
] );
|
||||
WPDO_Zone_Archive::archive_batch( $rows, false );
|
||||
|
||||
$restored = WPDO_Zone_Archive::restore( 403 );
|
||||
$this->assertSame( 1, $restored );
|
||||
|
||||
$pm = $GLOBALS['_wp_postmeta'][403]['hp_price'] ?? null;
|
||||
$this->assertSame( '777', $pm );
|
||||
|
||||
$remaining = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `" . self::$archive_table . "` WHERE post_id = 403" );
|
||||
$this->assertSame( 0, $remaining );
|
||||
}
|
||||
|
||||
public function test_archive_gzip_roundtrip(): void {
|
||||
$rows = $this->archive_rows( 404, [
|
||||
[ 'meta_key' => 'hp_description', 'meta_value' => str_repeat( 'Lorem ipsum ', 50 ) ],
|
||||
] );
|
||||
WPDO_Zone_Archive::archive_batch( $rows, true );
|
||||
|
||||
$result = WPDO_Zone_Archive::get( 404 );
|
||||
$this->assertCount( 1, $result );
|
||||
$this->assertStringContainsString( 'Lorem ipsum', $result[0]['meta_value'] );
|
||||
}
|
||||
|
||||
public function test_archive_delete_removes_rows(): void {
|
||||
global $wpdb;
|
||||
$rows = $this->archive_rows( 405, [
|
||||
[ 'meta_key' => 'hp_price', 'meta_value' => '1' ],
|
||||
] );
|
||||
WPDO_Zone_Archive::archive_batch( $rows, false );
|
||||
|
||||
WPDO_Zone_Archive::delete( 405 );
|
||||
|
||||
$count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `" . self::$archive_table . "` WHERE post_id = 405" );
|
||||
$this->assertSame( 0, $count );
|
||||
}
|
||||
|
||||
public function test_archive_stats_counts_correctly(): void {
|
||||
global $wpdb;
|
||||
$wpdb->query( "TRUNCATE TABLE `" . self::$archive_table . "`" );
|
||||
|
||||
WPDO_Zone_Archive::archive_batch( $this->archive_rows( 500, [
|
||||
[ 'meta_key' => 'k1', 'meta_value' => 'a' ],
|
||||
[ 'meta_key' => 'k2', 'meta_value' => 'b' ],
|
||||
] ), true );
|
||||
WPDO_Zone_Archive::archive_batch( $this->archive_rows( 502, [
|
||||
[ 'meta_key' => 'k3', 'meta_value' => 'c' ],
|
||||
] ), false );
|
||||
|
||||
$stats = WPDO_Zone_Archive::stats();
|
||||
$this->assertSame( 3, $stats['total_rows'] );
|
||||
$this->assertSame( 2, $stats['compressed_rows'] );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user