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
160 lines
5.1 KiB
PHP
160 lines
5.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
/**
|
|
* Integration test: WPDO_Post_Migration::benchmark_query() (v2.10.2).
|
|
*
|
|
* Verifies the benchmark method produces sensible timing comparison
|
|
* between wp_postmeta JOIN and flat-table JOIN for the same logical query.
|
|
*
|
|
* Tests focus on the API contract (input → output shape) since wall-clock
|
|
* timing is non-deterministic. Real performance numbers come from running
|
|
* `wp wpdo post-benchmark` on dev10 production data.
|
|
*/
|
|
class PostBenchmarkTest extends TestCase {
|
|
|
|
private const POSTS = 'wp_itest_posts';
|
|
private const POSTMETA = 'wp_itest_postmeta';
|
|
private const FLAT = 'wp_itest_wpdo_post_wc_product';
|
|
|
|
public static function setUpBeforeClass(): void {
|
|
global $wpdb;
|
|
|
|
if ( ! class_exists( 'WPDO_Schema_Manager' ) ) {
|
|
require_once WPDO_PLUGIN_DIR . 'includes/engine/class-tmdo-schema-manager.php';
|
|
}
|
|
if ( ! class_exists( 'WPDO_Post_Migration' ) ) {
|
|
require_once WPDO_PLUGIN_DIR . 'includes/migration/class-tmdo-post-migration.php';
|
|
}
|
|
|
|
$wpdb->query( 'DROP TABLE IF EXISTS `' . self::POSTS . '`' );
|
|
$wpdb->query(
|
|
'CREATE TABLE `' . self::POSTS . '` (
|
|
ID bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
|
post_type varchar(20) NOT NULL DEFAULT \'post\',
|
|
post_status varchar(20) NOT NULL DEFAULT \'publish\',
|
|
PRIMARY KEY (ID),
|
|
KEY post_type (post_type)
|
|
) DEFAULT CHARACTER SET utf8mb4'
|
|
);
|
|
|
|
$wpdb->query( 'DROP TABLE IF EXISTS `' . self::POSTMETA . '`' );
|
|
$wpdb->query(
|
|
'CREATE TABLE `' . self::POSTMETA . '` (
|
|
meta_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
|
post_id bigint(20) 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))
|
|
) DEFAULT CHARACTER SET utf8mb4'
|
|
);
|
|
|
|
$wpdb->query( 'DROP TABLE IF EXISTS `' . self::FLAT . '`' );
|
|
$wpdb->query(
|
|
'CREATE TABLE `' . self::FLAT . '` (
|
|
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
|
post_id bigint(20) unsigned NOT NULL,
|
|
_price decimal(18,6) DEFAULT NULL,
|
|
PRIMARY KEY (id),
|
|
UNIQUE KEY uk_post_id (post_id),
|
|
KEY idx__price (_price)
|
|
) DEFAULT CHARACTER SET utf8mb4'
|
|
);
|
|
|
|
// Seed 50 products with _price = 10..59 in both tables.
|
|
for ( $i = 1; $i <= 50; $i++ ) {
|
|
$wpdb->insert( self::POSTS, array( 'ID' => $i, 'post_type' => 'product', 'post_status' => 'publish' ) );
|
|
$price = (string) ( 10 + $i );
|
|
$wpdb->insert( self::POSTMETA, array( 'post_id' => $i, 'meta_key' => '_price', 'meta_value' => $price ) );
|
|
$wpdb->insert( self::FLAT, array( 'post_id' => $i, '_price' => $price ) );
|
|
}
|
|
}
|
|
|
|
public static function tearDownAfterClass(): void {
|
|
global $wpdb;
|
|
$wpdb->query( 'DROP TABLE IF EXISTS `' . self::POSTS . '`' );
|
|
$wpdb->query( 'DROP TABLE IF EXISTS `' . self::POSTMETA . '`' );
|
|
$wpdb->query( 'DROP TABLE IF EXISTS `' . self::FLAT . '`' );
|
|
}
|
|
|
|
// ── benchmark_query() ────────────────────────────────────────────────────
|
|
|
|
public function test_benchmark_returns_expected_shape(): void {
|
|
$result = WPDO_Post_Migration::benchmark_query(
|
|
'product',
|
|
'_price',
|
|
'>=',
|
|
'30',
|
|
self::FLAT,
|
|
5
|
|
);
|
|
|
|
$this->assertArrayHasKey( 'samples', $result );
|
|
$this->assertArrayHasKey( 'postmeta_avg_ms', $result );
|
|
$this->assertArrayHasKey( 'flat_avg_ms', $result );
|
|
$this->assertArrayHasKey( 'speedup', $result );
|
|
$this->assertArrayHasKey( 'postmeta_rows', $result );
|
|
$this->assertArrayHasKey( 'flat_rows', $result );
|
|
|
|
$this->assertSame( 5, $result['samples'] );
|
|
$this->assertGreaterThan( 0.0, $result['postmeta_avg_ms'] );
|
|
$this->assertGreaterThan( 0.0, $result['flat_avg_ms'] );
|
|
}
|
|
|
|
public function test_benchmark_finds_same_rows_via_both_paths(): void {
|
|
// _price >= 30 should match products 20..50 (i.e. 31 rows).
|
|
$result = WPDO_Post_Migration::benchmark_query(
|
|
'product',
|
|
'_price',
|
|
'>=',
|
|
'30',
|
|
self::FLAT,
|
|
3
|
|
);
|
|
|
|
// Both paths must return the same count — verifies router correctness.
|
|
$this->assertSame( $result['postmeta_rows'], $result['flat_rows'] );
|
|
$this->assertGreaterThan( 0, $result['postmeta_rows'] );
|
|
}
|
|
|
|
public function test_benchmark_speedup_is_positive_number(): void {
|
|
$result = WPDO_Post_Migration::benchmark_query(
|
|
'product',
|
|
'_price',
|
|
'=',
|
|
'25',
|
|
self::FLAT,
|
|
3
|
|
);
|
|
|
|
$this->assertIsFloat( $result['speedup'] );
|
|
$this->assertGreaterThan( 0.0, $result['speedup'] );
|
|
}
|
|
|
|
public function test_benchmark_rejects_zero_samples(): void {
|
|
$this->expectException( InvalidArgumentException::class );
|
|
WPDO_Post_Migration::benchmark_query( 'product', '_price', '=', '25', self::FLAT, 0 );
|
|
}
|
|
|
|
public function test_benchmark_rejects_invalid_compare(): void {
|
|
$this->expectException( InvalidArgumentException::class );
|
|
WPDO_Post_Migration::benchmark_query( 'product', '_price', 'BOGUS', '25', self::FLAT, 3 );
|
|
}
|
|
|
|
public function test_benchmark_throws_when_flat_table_missing(): void {
|
|
$this->expectException( RuntimeException::class );
|
|
WPDO_Post_Migration::benchmark_query(
|
|
'product',
|
|
'_price',
|
|
'=',
|
|
'25',
|
|
'wp_itest_nonexistent_flat',
|
|
3
|
|
);
|
|
}
|
|
}
|