d36bb954d1
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
119 lines
4.0 KiB
PHP
119 lines
4.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Integration test for WPDO_Installer::install_v2_tables() — PR-2 v2.0.0 schema.
|
|
*
|
|
* Verifies idempotent table creation for:
|
|
* - wp_*_wpdo_audit
|
|
* - wp_*_wpdo_shadow_diffs
|
|
* - wp_*_wpdo_site_metrics
|
|
* - wp_*_wpdo_uni_options
|
|
*
|
|
* @covers WPDO_Installer::install_v2_tables
|
|
* @covers WPDO_Installer::v2_tables_status
|
|
*/
|
|
class InstallerV2Test extends TestCase {
|
|
|
|
public static function setUpBeforeClass(): void {
|
|
// Drop v2 tables for a clean slate.
|
|
global $wpdb;
|
|
$p = $wpdb->prefix;
|
|
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_audit`" );
|
|
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_shadow_diffs`" );
|
|
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_site_metrics`" );
|
|
$wpdb->query( "DROP TABLE IF EXISTS `{$p}wpdo_uni_options`" );
|
|
}
|
|
|
|
public function test_v2_tables_initially_absent(): void {
|
|
$status = WPDO_Installer::v2_tables_status();
|
|
foreach ( $status as $table => $exists ) {
|
|
$this->assertFalse( $exists, "Expected {$table} to NOT exist initially" );
|
|
}
|
|
}
|
|
|
|
public function test_install_v2_tables_creates_all_four(): void {
|
|
WPDO_Installer::install_v2_tables();
|
|
|
|
$status = WPDO_Installer::v2_tables_status();
|
|
foreach ( $status as $table => $exists ) {
|
|
$this->assertTrue( $exists, "Expected {$table} to exist after install_v2_tables()" );
|
|
}
|
|
}
|
|
|
|
public function test_install_v2_tables_is_idempotent(): void {
|
|
WPDO_Installer::install_v2_tables();
|
|
WPDO_Installer::install_v2_tables(); // Second call must not error.
|
|
WPDO_Installer::install_v2_tables(); // Third for good measure.
|
|
|
|
$status = WPDO_Installer::v2_tables_status();
|
|
$this->assertCount( 4, $status );
|
|
$this->assertTrue( array_reduce( $status, static fn( $carry, $v ) => $carry && $v, true ) );
|
|
}
|
|
|
|
public function test_audit_table_has_required_columns(): void {
|
|
global $wpdb;
|
|
$p = $wpdb->prefix;
|
|
$cols = $wpdb->get_col( "SHOW COLUMNS FROM `{$p}wpdo_audit`" );
|
|
|
|
// PR-2 spec: op, value_before, value_after, source, trace_id are required.
|
|
foreach ( array( 'op', 'value_before', 'value_after', 'source', 'trace_id' ) as $required ) {
|
|
$this->assertContains( $required, $cols, "wpdo_audit missing column {$required}" );
|
|
}
|
|
}
|
|
|
|
public function test_shadow_diffs_table_has_required_columns(): void {
|
|
global $wpdb;
|
|
$p = $wpdb->prefix;
|
|
$cols = $wpdb->get_col( "SHOW COLUMNS FROM `{$p}wpdo_shadow_diffs`" );
|
|
|
|
foreach ( array( 'entity_type', 'entity_id', 'meta_key', 'postmeta_value', 'zone_value', 'diff_hash' ) as $required ) {
|
|
$this->assertContains( $required, $cols, "wpdo_shadow_diffs missing column {$required}" );
|
|
}
|
|
}
|
|
|
|
public function test_uni_options_has_unique_index_on_option_name(): void {
|
|
global $wpdb;
|
|
$p = $wpdb->prefix;
|
|
$indexes = $wpdb->get_results(
|
|
$wpdb->prepare(
|
|
'SELECT INDEX_NAME, COLUMN_NAME, NON_UNIQUE FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
|
|
$p . 'wpdo_uni_options'
|
|
),
|
|
ARRAY_A
|
|
);
|
|
|
|
$found_unique = false;
|
|
foreach ( $indexes as $idx ) {
|
|
if ( 'option_name' === $idx['COLUMN_NAME'] && '0' === (string) $idx['NON_UNIQUE'] ) {
|
|
$found_unique = true;
|
|
break;
|
|
}
|
|
}
|
|
$this->assertTrue( $found_unique, 'Expected UNIQUE index on wpdo_uni_options.option_name' );
|
|
}
|
|
|
|
public function test_audit_table_indexes_for_query_performance(): void {
|
|
global $wpdb;
|
|
$p = $wpdb->prefix;
|
|
$indexes = $wpdb->get_col(
|
|
$wpdb->prepare(
|
|
'SELECT DISTINCT INDEX_NAME FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s',
|
|
$p . 'wpdo_audit'
|
|
)
|
|
);
|
|
|
|
// Performance-critical indexes per Part F.3 schema spec.
|
|
foreach ( array( 'idx_entity', 'idx_meta_key', 'idx_ts', 'idx_trace' ) as $required ) {
|
|
$this->assertContains( $required, $indexes, "wpdo_audit missing index {$required}" );
|
|
}
|
|
}
|
|
|
|
public static function tearDownAfterClass(): void {
|
|
// Leave v2 tables in place for subsequent tests / dev convenience.
|
|
// Cleanup happens via wp wpdo cleanup-uae-tables --confirm in real upgrades.
|
|
}
|
|
}
|