test(2meet-data-optimizer): add live test runner and failing shadow_read write suite
- Add tests/live: a `wp eval-file` runner (PASS/FAIL/XFAIL/XPASS/SKIP) with fixtures that override entity modes in process (pre_option) and read native / flat values with plain SQL, so WP core meta flows run for real - shadow_write suite reproduces the dev36 finding: in shadow_read, update_*_meta returns false and native meta is never written (3 XFAIL marked for PR-056); the dual_write control passes - Move the dev36 integration harness into tests/live/tools; outputs go to cwd / $TMDO_LIVE_OUT, site URL and path are env-configurable - Verify: wp --path=<dev36> eval-file tests/live/run.php shadow_write → 1 passed, 3 xfail; unit 658 OK, integration 480 OK, phpcs (phpcs.xml) 0, stan OK - PR: PR-052
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/**
|
||||
* dev36 integration seeder — goes through the real APIs (HivePress models, WC CRUD,
|
||||
* wp_insert_user / update_*_meta) so every write passes the Hook Bus exactly like prod.
|
||||
*
|
||||
* Usage: wp eval-file seed.php <kind> <count> [tag]
|
||||
* kind: vendors | listings | requests | reviews | products | orders | terms
|
||||
*/
|
||||
|
||||
use HivePress\Models;
|
||||
|
||||
add_filter( 'pre_wp_mail', '__return_true' );
|
||||
// WC Tracks pings pixel.wp.com ~3x per product save (~180 ms each); irrelevant to the test.
|
||||
add_filter( 'pre_http_request', function ( $r, $a, $url ) { return false !== strpos( $url, 'pixel.wp.com' ) ? array( 'headers' => array(), 'body' => '', 'response' => array( 'code' => 200, 'message' => 'OK' ), 'cookies' => array() ) : $r; }, 1, 3 );
|
||||
wp_defer_term_counting( true );
|
||||
wp_defer_comment_counting( true );
|
||||
|
||||
$kind = $args[0] ?? '';
|
||||
$count = (int) ( $args[1] ?? 0 );
|
||||
$tag = $args[2] ?? 'b1';
|
||||
mt_srand( crc32( $kind . $tag ) );
|
||||
|
||||
$cities = array( 'Taipei', 'Taichung', 'Kaohsiung', 'Tainan', 'Hsinchu', 'Keelung' );
|
||||
|
||||
function s36_pick_ids( $post_type, $limit = 5000 ) {
|
||||
global $wpdb;
|
||||
return array_map( 'intval', $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type=%s AND post_status='publish' ORDER BY RAND() LIMIT %d", $post_type, $limit ) ) );
|
||||
}
|
||||
|
||||
$t0 = microtime( true );
|
||||
$q0 = get_num_queries();
|
||||
$ok = 0;
|
||||
|
||||
switch ( $kind ) {
|
||||
case 'vendors':
|
||||
for ( $i = 0; $i < $count; $i++ ) {
|
||||
$login = "s36v_{$tag}_{$i}";
|
||||
$uid = wp_insert_user( array( 'user_login' => $login, 'user_email' => "$login@example.test", 'user_pass' => wp_generate_password(), 'role' => 'contributor', 'first_name' => "F$i", 'last_name' => "L$i", 'description' => "Vendor $i bio" ) );
|
||||
if ( is_wp_error( $uid ) ) { continue; }
|
||||
update_user_meta( $uid, 'billing_city', $cities[ $i % 6 ] );
|
||||
update_user_meta( $uid, 'billing_phone', '09' . mt_rand( 10000000, 99999999 ) );
|
||||
update_user_meta( $uid, 'facebook', "https://facebook.com/$login" );
|
||||
update_user_meta( $uid, 'login_count', mt_rand( 1, 300 ) );
|
||||
$v = ( new Models\Vendor() )->fill( array( 'name' => "Vendor $tag $i", 'description' => 'Seeded vendor', 'status' => 'publish', 'user' => $uid, 'verified' => (bool) mt_rand( 0, 1 ) ) );
|
||||
if ( $v->save() ) {
|
||||
update_post_meta( $v->get_id(), 'hp_hourly_rate', mt_rand( 10, 300 ) );
|
||||
update_post_meta( $v->get_id(), 'hp_rating', mt_rand( 10, 50 ) / 10 );
|
||||
$ok++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'listings':
|
||||
global $wpdb;
|
||||
$vendors = $wpdb->get_results( "SELECT ID, post_author FROM {$wpdb->posts} WHERE post_type='hp_vendor' AND post_status='publish'" );
|
||||
$cats = get_terms( array( 'taxonomy' => 'hp_listing_category', 'hide_empty' => false, 'fields' => 'ids' ) );
|
||||
for ( $i = 0; $i < $count; $i++ ) {
|
||||
$v = $vendors[ array_rand( $vendors ) ];
|
||||
$l = ( new Models\Listing() )->fill( array(
|
||||
'title' => "Listing $tag $i " . $cities[ $i % 6 ],
|
||||
'description' => str_repeat( 'Seeded listing body. ', 8 ),
|
||||
'status' => ( mt_rand( 1, 10 ) <= 9 ) ? 'publish' : 'draft',
|
||||
'user' => (int) $v->post_author,
|
||||
'vendor' => (int) $v->ID,
|
||||
'featured' => mt_rand( 1, 20 ) === 1,
|
||||
'verified' => mt_rand( 1, 3 ) === 1,
|
||||
'categories' => $cats ? array( $cats[ array_rand( $cats ) ] ) : array(),
|
||||
) );
|
||||
if ( $l->save() ) {
|
||||
$id = $l->get_id();
|
||||
update_post_meta( $id, 'hp_price', mt_rand( 100, 50000 ) );
|
||||
update_post_meta( $id, 'hp_hourly_rate', mt_rand( 10, 300 ) );
|
||||
update_post_meta( $id, 'hp_warranty', mt_rand( 0, 24 ) );
|
||||
$ok++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'requests':
|
||||
$users = get_users( array( 'fields' => 'ID', 'number' => 3000, 'orderby' => 'rand' ) );
|
||||
for ( $i = 0; $i < $count; $i++ ) {
|
||||
$r = ( new Models\Request() )->fill( array( 'title' => "Request $tag $i", 'description' => 'Need help', 'status' => 'publish', 'user' => (int) $users[ array_rand( $users ) ] ) );
|
||||
if ( $r->save() ) {
|
||||
update_post_meta( $r->get_id(), 'hp_budget', mt_rand( 500, 90000 ) );
|
||||
update_post_meta( $r->get_id(), 'hp_due_date', gmdate( 'Y-m-d', time() + mt_rand( 1, 90 ) * DAY_IN_SECONDS ) );
|
||||
$ok++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'reviews':
|
||||
$listings = s36_pick_ids( 'hp_listing' );
|
||||
$users = get_users( array( 'fields' => array( 'ID', 'display_name', 'user_email' ), 'number' => 3000, 'orderby' => 'rand' ) );
|
||||
for ( $i = 0; $i < $count; $i++ ) {
|
||||
$u = $users[ array_rand( $users ) ];
|
||||
$rv = ( new Models\Review() )->fill( array( 'text' => "Review $tag $i", 'rating' => mt_rand( 1, 5 ), 'approved' => 1, 'author' => (int) $u->ID, 'author__display_name' => $u->display_name, 'author__email' => $u->user_email, 'listing' => $listings[ array_rand( $listings ) ] ) );
|
||||
if ( $rv->save() ) { $ok++; }
|
||||
}
|
||||
break;
|
||||
|
||||
case 'terms':
|
||||
for ( $i = 0; $i < $count; $i++ ) {
|
||||
$t = wp_insert_term( "Cat $tag $i", 'hp_listing_category' );
|
||||
if ( ! is_wp_error( $t ) ) {
|
||||
update_term_meta( $t['term_id'], 'hp_sort_order', $i );
|
||||
update_term_meta( $t['term_id'], 'hp_icon', 'star' );
|
||||
$ok++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'products':
|
||||
$pcats = get_terms( array( 'taxonomy' => 'product_cat', 'hide_empty' => false, 'fields' => 'ids' ) );
|
||||
for ( $i = 0; $i < $count; $i++ ) {
|
||||
$p = new WC_Product_Simple();
|
||||
$p->set_name( "Product $tag $i" );
|
||||
$p->set_status( 'publish' );
|
||||
$reg = mt_rand( 100, 20000 );
|
||||
$p->set_regular_price( (string) $reg );
|
||||
if ( mt_rand( 1, 4 ) === 1 ) { $p->set_sale_price( (string) (int) ( $reg * 0.8 ) ); }
|
||||
$p->set_sku( "S36-$tag-$i" );
|
||||
$p->set_manage_stock( true );
|
||||
$p->set_stock_quantity( mt_rand( 0, 500 ) );
|
||||
if ( $pcats ) { $p->set_category_ids( array( $pcats[ array_rand( $pcats ) ] ) ); }
|
||||
if ( $p->save() ) { $ok++; }
|
||||
}
|
||||
break;
|
||||
|
||||
case 'orders':
|
||||
$products = wc_get_products( array( 'limit' => 2000, 'status' => 'publish', 'orderby' => 'rand', 'return' => 'ids' ) );
|
||||
$users = get_users( array( 'fields' => 'ID', 'number' => 3000, 'orderby' => 'rand' ) );
|
||||
$statuses = array( 'completed', 'completed', 'processing', 'on-hold', 'cancelled', 'refunded' );
|
||||
for ( $i = 0; $i < $count; $i++ ) {
|
||||
$o = wc_create_order( array( 'customer_id' => (int) $users[ array_rand( $users ) ] ) );
|
||||
if ( is_wp_error( $o ) ) { continue; }
|
||||
$n = mt_rand( 1, 3 );
|
||||
for ( $j = 0; $j < $n; $j++ ) { $o->add_product( wc_get_product( $products[ array_rand( $products ) ] ), mt_rand( 1, 3 ) ); }
|
||||
$o->set_billing_city( $cities[ $i % 6 ] );
|
||||
$o->set_billing_email( "buyer$i@example.test" );
|
||||
$o->calculate_totals( false );
|
||||
$o->set_status( $statuses[ array_rand( $statuses ) ] );
|
||||
$o->save();
|
||||
$ok++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
WP_CLI::error( "unknown kind $kind" );
|
||||
}
|
||||
|
||||
wp_defer_term_counting( false );
|
||||
wp_defer_comment_counting( false );
|
||||
|
||||
$el = microtime( true ) - $t0;
|
||||
$q = get_num_queries() - $q0;
|
||||
WP_CLI::log( sprintf( 'SEED %s x%d ok=%d %.1fs %.2f ms/item %.1f queries/item mode(post=%s,user=%s,term=%s,comment=%s)',
|
||||
$kind, $count, $ok, $el, $ok ? $el * 1000 / $ok : 0, $ok ? $q / $ok : 0,
|
||||
...( class_exists( 'TMDO_Mode_Manager' ) ? array( TMDO_Mode_Manager::get( 'post' ), TMDO_Mode_Manager::get( 'user' ), TMDO_Mode_Manager::get( 'term' ), TMDO_Mode_Manager::get( 'comment' ) ) : array( 'NO-TMDO', '-', '-', '-' ) ) ) );
|
||||
Reference in New Issue
Block a user