Skip to content

Commit 9c3e07d

Browse files
committed
Add MySQL proxy tests
1 parent a96e8bf commit 9c3e07d

File tree

9 files changed

+247
-0
lines changed

9 files changed

+247
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: WordPress MySQL Proxy Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
name: WordPress MySQL Proxy Tests
12+
runs-on: ubuntu-latest
13+
timeout-minutes: 20
14+
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
19+
- name: Set up PHP
20+
uses: shivammathur/setup-php@v2
21+
with:
22+
php-version: '7.4'
23+
24+
- name: Install Composer dependencies
25+
uses: ramsey/composer-install@v3
26+
with:
27+
ignore-cache: "yes"
28+
composer-options: "--optimize-autoloader"
29+
working-directory: packages/wp-mysql-proxy
30+
31+
- name: Run WordPress MySQL Proxy tests
32+
run: composer run test
33+
working-directory: packages/wp-mysql-proxy
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "wordpress/wp-mysql-proxy",
3+
"type": "library",
4+
"scripts": {
5+
"test": "phpunit"
6+
},
7+
"require-dev": {
8+
"phpunit/phpunit": "^8.5",
9+
"symfony/process": "^5.4"
10+
}
11+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit bootstrap="tests/bootstrap/bootstrap.php" colors="true" stopOnFailure="false">
3+
<testsuites>
4+
<testsuite name="WP MySQL Proxy Test Suite">
5+
<directory>tests/</directory>
6+
</testsuite>
7+
</testsuites>
8+
</phpunit>

packages/wp-mysql-proxy/src/mysql-server.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ public function __construct( MySQLQueryHandler $query_handler, $options = array(
672672

673673
public function start() {
674674
$this->socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
675+
socket_set_option( $this->socket, SOL_SOCKET, SO_REUSEADDR, 1 );
675676
socket_bind( $this->socket, '0.0.0.0', $this->port );
676677
socket_listen( $this->socket );
677678
echo "MySQL PHP Server listening on port {$this->port}...\n";
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
5+
class WP_MySQL_Proxy_MySQLi_Test extends TestCase {
6+
const PORT = 3306;
7+
8+
/** @var MySQL_Server_Process */
9+
private $server;
10+
11+
/** @var mysqli */
12+
private $mysqli;
13+
14+
public function setUp(): void {
15+
$this->server = new MySQL_Server_Process(
16+
array(
17+
'port' => self::PORT,
18+
'db_path' => ':memory:',
19+
)
20+
);
21+
22+
$this->mysqli = new mysqli( '127.0.0.1', 'WordPress', 'WordPress', 'WordPress', self::PORT );
23+
}
24+
25+
public function tearDown(): void {
26+
$this->server->stop();
27+
}
28+
29+
public function test_query(): void {
30+
$result = $this->mysqli->query( 'CREATE TABLE t (id INT PRIMARY KEY, name TEXT)' );
31+
$this->assertTrue( $result );
32+
33+
$result = $this->mysqli->query( 'INSERT INTO t (id, name) VALUES (123, "abc"), (456, "def")' );
34+
$this->assertEquals( 2, $result );
35+
}
36+
37+
public function test_prepared_statement(): void {
38+
// TODO: Implement prepared statements in the MySQL proxy.
39+
$this->markTestSkipped( 'Prepared statements are not supported yet.' );
40+
}
41+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
use PHPUnit\Framework\TestCase;
4+
5+
class WP_MySQL_Proxy_PDO_Test extends TestCase {
6+
const PORT = 3306;
7+
8+
/** @var MySQL_Server_Process */
9+
private $server;
10+
11+
/** @var PDO */
12+
private $pdo;
13+
14+
public function setUp(): void {
15+
$this->server = new MySQL_Server_Process(
16+
array(
17+
'port' => self::PORT,
18+
'db_path' => ':memory:',
19+
)
20+
);
21+
22+
$this->pdo = new PDO(
23+
sprintf( 'mysql:host=127.0.0.1;port=%d', self::PORT ),
24+
'WordPress',
25+
'WordPress'
26+
);
27+
}
28+
29+
public function tearDown(): void {
30+
$this->server->stop();
31+
}
32+
33+
public function test_exec(): void {
34+
$result = $this->pdo->exec( 'CREATE TABLE t (id INT PRIMARY KEY, name TEXT)' );
35+
$this->assertEquals( 0, $result );
36+
37+
$result = $this->pdo->exec( 'INSERT INTO t (id, name) VALUES (123, "abc"), (456, "def")' );
38+
$this->assertEquals( 2, $result );
39+
}
40+
41+
public function test_query(): void {
42+
$this->pdo->exec( 'CREATE TABLE t (id INT PRIMARY KEY, name TEXT)' );
43+
$this->pdo->exec( 'INSERT INTO t (id, name) VALUES (123, "abc"), (456, "def")' );
44+
45+
$result = $this->pdo->query( "SELECT 'test'" );
46+
$this->assertEquals( 'test', $result->fetchColumn() );
47+
48+
$result = $this->pdo->query( 'SELECT * FROM t' );
49+
$this->assertEquals( 2, $result->rowCount() );
50+
$this->assertEquals(
51+
array(
52+
array(
53+
'id' => 123,
54+
'name' => 'abc',
55+
),
56+
array(
57+
'id' => 456,
58+
'name' => 'def',
59+
),
60+
),
61+
$result->fetchAll( PDO::FETCH_ASSOC )
62+
);
63+
}
64+
65+
public function test_prepared_statement(): void {
66+
$this->pdo->exec( 'CREATE TABLE t (id INT PRIMARY KEY, name TEXT)' );
67+
$this->pdo->exec( 'INSERT INTO t (id, name) VALUES (123, "abc"), (456, "def")' );
68+
69+
$stmt = $this->pdo->prepare( 'SELECT * FROM t WHERE id = ?' );
70+
$stmt->execute( array( 123 ) );
71+
$this->assertEquals(
72+
array(
73+
array(
74+
'id' => 123,
75+
'name' => 'abc',
76+
),
77+
),
78+
$stmt->fetchAll( PDO::FETCH_ASSOC )
79+
);
80+
}
81+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
require_once __DIR__ . '/../../vendor/autoload.php';
4+
require_once __DIR__ . '/../../src/mysql-server.php';
5+
require_once __DIR__ . '/../../src/handler-sqlite-translation.php';
6+
require_once __DIR__ . '/mysql-server-process.php';
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Manages the MySQL server as a subprocess for tests
4+
*/
5+
6+
use Symfony\Component\Process\Process;
7+
8+
class MySQL_Server_Process {
9+
/** @var Process */
10+
private $process;
11+
12+
public function __construct( array $options = array() ) {
13+
$port = $options['port'] ?? 3306;
14+
$env = array_merge(
15+
$_ENV,
16+
array(
17+
'PORT' => $port,
18+
'DB_PATH' => $options['db_path'] ?? ':memory:',
19+
)
20+
);
21+
$this->process = new Process(
22+
array( PHP_BINARY, __DIR__ . '/run-server.php' ),
23+
null,
24+
$env
25+
);
26+
$this->process->start();
27+
28+
// Wait for the server to be ready.
29+
for ( $i = 0; $i < 20; $i++ ) {
30+
$connection = @fsockopen( '127.0.0.1', $port ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
31+
if ( $connection ) {
32+
fclose( $connection );
33+
return;
34+
}
35+
usleep( 100000 );
36+
}
37+
38+
// Connection timeed out.
39+
$this->stop();
40+
$error = $this->process->getErrorOutput();
41+
throw new Exception(
42+
sprintf( 'Server failed to start on port %d: %s', $port, $error )
43+
);
44+
}
45+
46+
public function stop(): void {
47+
if ( isset( $this->process ) ) {
48+
$this->process->stop();
49+
}
50+
}
51+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
require_once __DIR__ . '/../../../../php-polyfills.php';
4+
require_once __DIR__ . '/../../src/mysql-server.php';
5+
require_once __DIR__ . '/../../src/handler-sqlite-translation.php';
6+
7+
// Configuration.
8+
$port = (int) ( $_ENV['PORT'] ?? 3306 );
9+
$db_path = $_ENV['DB_PATH'] ?? ':memory:';
10+
11+
$server = new MySQLSocketServer(
12+
new SQLiteTranslationHandler( $db_path ),
13+
array( 'port' => $port )
14+
);
15+
$server->start();

0 commit comments

Comments
 (0)