Skip to content

Commit 3f4153f

Browse files
committed
Deduplicate native parser verification
1 parent 34b17f8 commit 3f4153f

6 files changed

Lines changed: 135 additions & 199 deletions

File tree

.github/workflows/mysql-parser-extension-tests.yml

Lines changed: 2 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -165,91 +165,11 @@ jobs:
165165
run: cargo build
166166
working-directory: packages/php-ext-wp-mysql-parser
167167

168-
- name: Run native parser smoke tests
168+
- name: Verify native parser extension
169169
if: matrix.native
170-
run: |
171-
php -d extension="$GITHUB_WORKSPACE/packages/php-ext-wp-mysql-parser/target/debug/libwp_mysql_parser.so" -r '
172-
require "src/load.php";
173-
$lexer = new WP_MySQL_Lexer( "SELECT ID, post_title FROM wp_posts WHERE ID IN (1, 2, 3)" );
174-
if ( ! ( $lexer instanceof WP_MySQL_Native_Lexer ) ) {
175-
fwrite( STDERR, "Native lexer is not available.\n" );
176-
exit( 1 );
177-
}
178-
$tokens = $lexer->native_token_stream();
179-
$rules = include "src/mysql/mysql-grammar.php";
180-
$grammar = new WP_Parser_Grammar( $rules );
181-
$parser = new WP_MySQL_Parser( $grammar, $tokens );
182-
$parser_reflection = new ReflectionObject( $parser );
183-
if ( ! $parser_reflection->hasProperty( "native" ) ) {
184-
fwrite( STDERR, "WP_MySQL_Parser did not select the native parser delegate.\n" );
185-
exit( 1 );
186-
}
187-
$native_property = $parser_reflection->getProperty( "native" );
188-
$native_property->setAccessible( true );
189-
if ( ! ( $native_property->getValue( $parser ) instanceof WP_MySQL_Native_Parser ) ) {
190-
fwrite( STDERR, "WP_MySQL_Parser did not select the native parser delegate.\n" );
191-
exit( 1 );
192-
}
193-
$ast = $parser->parse();
194-
if ( ! $ast instanceof WP_MySQL_Native_Parser_Node || "query" !== $ast->rule_name ) {
195-
fwrite( STDERR, "Native parser did not produce the expected query AST.\n" );
196-
exit( 1 );
197-
}
198-
'
170+
run: php -d extension="$GITHUB_WORKSPACE/packages/php-ext-wp-mysql-parser/target/debug/libwp_mysql_parser.so" tests/tools/verify-native-parser-extension.php
199171
working-directory: packages/mysql-on-sqlite
200172

201-
- name: Verify SQLite driver selects the native parser path
202-
if: matrix.native
203-
run: |
204-
php -d extension="$GITHUB_WORKSPACE/packages/php-ext-wp-mysql-parser/target/debug/libwp_mysql_parser.so" -r '
205-
require "packages/mysql-on-sqlite/src/load.php";
206-
$lexer = new WP_MySQL_Lexer( "SELECT 1" );
207-
if ( ! ( $lexer instanceof WP_MySQL_Native_Lexer ) ) {
208-
fwrite( STDERR, "Native lexer is not available.\n" );
209-
exit( 1 );
210-
}
211-
$driver = new WP_PDO_MySQL_On_SQLite( "mysql-on-sqlite:path=:memory:;dbname=wp;" );
212-
$parser = $driver->create_parser( "SELECT 1" );
213-
$parser_reflection = new ReflectionObject( $parser );
214-
if ( ! $parser_reflection->hasProperty( "native" ) ) {
215-
fwrite( STDERR, "SQLite driver did not create a native parser delegate.\n" );
216-
exit( 1 );
217-
}
218-
$native_property = $parser_reflection->getProperty( "native" );
219-
$native_property->setAccessible( true );
220-
if ( ! ( $native_property->getValue( $parser ) instanceof WP_MySQL_Native_Parser ) ) {
221-
fwrite( STDERR, "SQLite driver did not create a native parser delegate.\n" );
222-
exit( 1 );
223-
}
224-
$parser->next_query();
225-
$ast = $parser->get_query_ast();
226-
if ( ! ( $ast instanceof WP_MySQL_Native_Parser_Node ) ) {
227-
fwrite( STDERR, "SQLite driver did not return a native-backed AST.\n" );
228-
exit( 1 );
229-
}
230-
$reflection = new ReflectionObject( $ast );
231-
if ( $reflection->hasProperty( "native_ast" ) || $reflection->hasProperty( "native_node_index" ) ) {
232-
fwrite( STDERR, "Native wrapper still stores Rust AST handle properties.\n" );
233-
exit( 1 );
234-
}
235-
$first = $ast->get_first_child_node();
236-
if ( ! ( $first instanceof WP_MySQL_Native_Parser_Node ) ) {
237-
fwrite( STDERR, "Native wrapper did not return a native-backed child node.\n" );
238-
exit( 1 );
239-
}
240-
if ( $first !== $ast->get_first_child_node() ) {
241-
fwrite( STDERR, "Native wrapper identity is not stable across reads.\n" );
242-
exit( 1 );
243-
}
244-
$synthetic = new WP_Parser_Node( 0, "synthetic" );
245-
$first->append_child( $synthetic );
246-
$same_first = $ast->get_first_child_node();
247-
if ( $same_first !== $first || ! in_array( $synthetic, $same_first->get_children(), true ) ) {
248-
fwrite( STDERR, "Materialized native wrapper was lost from the parent cache.\n" );
249-
exit( 1 );
250-
}
251-
'
252-
253173
- name: Run full PHPUnit suite with parser extension
254174
if: matrix.native
255175
env:

.github/workflows/wp-tests-phpunit-native-extension-setup.sh

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -115,78 +115,69 @@ cat > "$WP_DIR/native-verify-extension.php" <<'EOF'
115115
<?php
116116
require_once '/var/www/src/wp-content/plugins/sqlite-database-integration/wp-includes/database/load.php';
117117
118+
function wp_sqlite_native_parser_verification_fail( string $message ): void {
119+
fwrite( STDERR, $message . "\n" );
120+
exit( 1 );
121+
}
122+
123+
function wp_sqlite_assert_native_parser_delegate( WP_MySQL_Parser $parser, string $message ): void {
124+
$parser_reflection = new ReflectionObject( $parser );
125+
if ( ! $parser_reflection->hasProperty( 'native' ) ) {
126+
wp_sqlite_native_parser_verification_fail( $message );
127+
}
128+
129+
$native_property = $parser_reflection->getProperty( 'native' );
130+
$native_property->setAccessible( true );
131+
if ( ! ( $native_property->getValue( $parser ) instanceof WP_MySQL_Native_Parser ) ) {
132+
wp_sqlite_native_parser_verification_fail( $message );
133+
}
134+
}
135+
118136
$lexer = new WP_MySQL_Lexer( 'SELECT 1' );
119137
if ( ! ( $lexer instanceof WP_MySQL_Native_Lexer ) ) {
120-
fwrite( STDERR, "Native lexer is not available in the WordPress PHP test container.\n" );
121-
exit( 1 );
138+
wp_sqlite_native_parser_verification_fail( 'Native lexer is not available in the WordPress PHP test container.' );
122139
}
123140
124141
$tokens = $lexer->native_token_stream();
125142
$rules = include '/var/www/src/wp-content/plugins/sqlite-database-integration/wp-includes/database/mysql/mysql-grammar.php';
126143
$grammar = new WP_Parser_Grammar( $rules );
127144
$parser = new WP_MySQL_Parser( $grammar, $tokens );
128-
$parser_reflection = new ReflectionObject( $parser );
129-
if ( ! $parser_reflection->hasProperty( 'native' ) ) {
130-
fwrite( STDERR, "WordPress PHP test container did not select the native parser delegate.\n" );
131-
exit( 1 );
132-
}
133-
$native_property = $parser_reflection->getProperty( 'native' );
134-
$native_property->setAccessible( true );
135-
if ( ! ( $native_property->getValue( $parser ) instanceof WP_MySQL_Native_Parser ) ) {
136-
fwrite( STDERR, "WordPress PHP test container did not select the native parser delegate.\n" );
137-
exit( 1 );
138-
}
145+
wp_sqlite_assert_native_parser_delegate( $parser, 'WordPress PHP test container did not select the native parser delegate.' );
139146
140147
$parser_ast = $parser->parse();
141148
if ( ! ( $parser_ast instanceof WP_MySQL_Native_Parser_Node ) ) {
142-
fwrite( STDERR, "Native parser did not produce a native-backed AST in the WordPress PHP test container.\n" );
143-
exit( 1 );
149+
wp_sqlite_native_parser_verification_fail( 'Native parser did not produce a native-backed AST in the WordPress PHP test container.' );
144150
}
145151
146152
$driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' );
147153
$parser = $driver->create_parser( 'SELECT 1' );
148-
$parser_reflection = new ReflectionObject( $parser );
149-
if ( ! $parser_reflection->hasProperty( 'native' ) ) {
150-
fwrite( STDERR, "WordPress PHP test container SQLite driver did not create a native parser delegate.\n" );
151-
exit( 1 );
152-
}
153-
$native_property = $parser_reflection->getProperty( 'native' );
154-
$native_property->setAccessible( true );
155-
if ( ! ( $native_property->getValue( $parser ) instanceof WP_MySQL_Native_Parser ) ) {
156-
fwrite( STDERR, "WordPress PHP test container SQLite driver did not create a native parser delegate.\n" );
157-
exit( 1 );
158-
}
154+
wp_sqlite_assert_native_parser_delegate( $parser, 'WordPress PHP test container SQLite driver did not create a native parser delegate.' );
159155
$parser->next_query();
160156
$ast = $parser->get_query_ast();
161157
162158
if ( ! ( $ast instanceof WP_MySQL_Native_Parser_Node ) ) {
163-
fwrite( STDERR, "WordPress PHP test container did not select the native-backed AST.\n" );
164-
exit( 1 );
159+
wp_sqlite_native_parser_verification_fail( 'WordPress PHP test container did not select the native-backed AST.' );
165160
}
166161
167162
$reflection = new ReflectionObject( $ast );
168163
if ( $reflection->hasProperty( 'native_ast' ) || $reflection->hasProperty( 'native_node_index' ) ) {
169-
fwrite( STDERR, "Native wrapper still stores Rust AST handle properties.\n" );
170-
exit( 1 );
164+
wp_sqlite_native_parser_verification_fail( 'Native wrapper still stores Rust AST handle properties.' );
171165
}
172166
173167
$first = $ast->get_first_child_node();
174168
if ( ! ( $first instanceof WP_MySQL_Native_Parser_Node ) ) {
175-
fwrite( STDERR, "Native wrapper did not return a native-backed child node.\n" );
176-
exit( 1 );
169+
wp_sqlite_native_parser_verification_fail( 'Native wrapper did not return a native-backed child node.' );
177170
}
178171
179172
if ( $first !== $ast->get_first_child_node() ) {
180-
fwrite( STDERR, "Native wrapper identity is not stable across reads.\n" );
181-
exit( 1 );
173+
wp_sqlite_native_parser_verification_fail( 'Native wrapper identity is not stable across reads.' );
182174
}
183175
184176
$synthetic = new WP_Parser_Node( 0, 'synthetic' );
185177
$first->append_child( $synthetic );
186178
$same_first = $ast->get_first_child_node();
187179
if ( $same_first !== $first || ! in_array( $synthetic, $same_first->get_children(), true ) ) {
188-
fwrite( STDERR, "Materialized native wrapper was lost from the parent cache.\n" );
189-
exit( 1 );
180+
wp_sqlite_native_parser_verification_fail( 'Materialized native wrapper was lost from the parent cache.' );
190181
}
191182
EOF
192183

@@ -197,7 +188,7 @@ const file = process.argv[2];
197188
const marker = "require_once ABSPATH . 'wp-settings.php';";
198189
const guard = [
199190
'/*',
200-
' * Native parser CI guard. This file is generated by the SQLite integration workflow.',
191+
' * Native parser extension guard. This file is generated by the SQLite integration workflow.',
201192
' */',
202193
"require_once dirname( __DIR__, 3 ) . '/native-verify-extension.php';",
203194
].join( '\n' );

.github/workflows/wp-tests-phpunit-run.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
* Wrap the "composer run wp-tests-php" command to process tests
33
* that are expected to error and fail at the moment.
44
*
5-
* This makes sure that the CI job passes, while explicitly tracking
6-
* the issues that need to be addressed. Ideally, over time this script
7-
* will become obsolete when all errors and failures are resolved.
5+
* Unexpected errors/failures still fail the workflow. Expected failures that
6+
* stop happening are reported so this allowlist can be reduced over time.
87
*/
98
const { execSync } = require( 'child_process' );
109
const fs = require( 'fs' );

packages/mysql-on-sqlite/tests/bootstrap.php

Lines changed: 1 addition & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -10,82 +10,7 @@
1010
}
1111

1212
if ( '1' === getenv( 'WP_SQLITE_REQUIRE_NATIVE_PARSER_EXTENSION' ) ) {
13-
if ( ! class_exists( 'WP_MySQL_Native_Lexer', false ) || ! class_exists( 'WP_MySQL_Native_Parser', false ) ) {
14-
fwrite( STDERR, "Native MySQL parser extension is required for this PHPUnit run.\n" );
15-
exit( 1 );
16-
}
17-
18-
$native_parser_lexer = new WP_MySQL_Lexer( 'SELECT 1' );
19-
if ( ! ( $native_parser_lexer instanceof WP_MySQL_Native_Lexer ) ) {
20-
fwrite( STDERR, "WP_MySQL_Lexer did not resolve to the native implementation.\n" );
21-
exit( 1 );
22-
}
23-
24-
$native_parser_tokens = $native_parser_lexer->native_token_stream();
25-
$native_parser_rules = include __DIR__ . '/../src/mysql/mysql-grammar.php';
26-
$native_parser_grammar = new WP_Parser_Grammar( $native_parser_rules );
27-
$native_parser = new WP_MySQL_Parser( $native_parser_grammar, $native_parser_tokens );
28-
$native_parser_reflection = new ReflectionObject( $native_parser );
29-
if ( ! $native_parser_reflection->hasProperty( 'native' ) ) {
30-
fwrite( STDERR, "WP_MySQL_Parser did not create a native parser delegate.\n" );
31-
exit( 1 );
32-
}
33-
$native_parser_property = $native_parser_reflection->getProperty( 'native' );
34-
$native_parser_property->setAccessible( true );
35-
if ( ! ( $native_parser_property->getValue( $native_parser ) instanceof WP_MySQL_Native_Parser ) ) {
36-
fwrite( STDERR, "WP_MySQL_Parser did not create a native parser delegate.\n" );
37-
exit( 1 );
38-
}
39-
40-
$native_parser_ast = $native_parser->parse();
41-
if ( ! ( $native_parser_ast instanceof WP_MySQL_Native_Parser_Node ) ) {
42-
fwrite( STDERR, "Native parser did not produce a native-backed AST.\n" );
43-
exit( 1 );
44-
}
45-
46-
$native_parser_driver = new WP_PDO_MySQL_On_SQLite( 'mysql-on-sqlite:path=:memory:;dbname=wp;' );
47-
$native_parser_driver_parser = $native_parser_driver->create_parser( 'SELECT 1' );
48-
$native_parser_driver_reflection = new ReflectionObject( $native_parser_driver_parser );
49-
if ( ! $native_parser_driver_reflection->hasProperty( 'native' ) ) {
50-
fwrite( STDERR, "WP_PDO_MySQL_On_SQLite did not create a native parser delegate.\n" );
51-
exit( 1 );
52-
}
53-
$native_parser_driver_property = $native_parser_driver_reflection->getProperty( 'native' );
54-
$native_parser_driver_property->setAccessible( true );
55-
if ( ! ( $native_parser_driver_property->getValue( $native_parser_driver_parser ) instanceof WP_MySQL_Native_Parser ) ) {
56-
fwrite( STDERR, "WP_PDO_MySQL_On_SQLite did not create a native parser delegate.\n" );
57-
exit( 1 );
58-
}
59-
60-
$native_parser_driver_parser->next_query();
61-
$native_parser_driver_ast = $native_parser_driver_parser->get_query_ast();
62-
if ( ! ( $native_parser_driver_ast instanceof WP_MySQL_Native_Parser_Node ) ) {
63-
fwrite( STDERR, "WP_PDO_MySQL_On_SQLite did not produce a native-backed AST.\n" );
64-
exit( 1 );
65-
}
66-
67-
$native_parser_driver_child = $native_parser_driver_ast->get_first_child_node();
68-
if ( ! ( $native_parser_driver_child instanceof WP_MySQL_Native_Parser_Node ) ) {
69-
fwrite( STDERR, "WP_PDO_MySQL_On_SQLite did not produce native-backed child AST nodes.\n" );
70-
exit( 1 );
71-
}
72-
73-
unset(
74-
$native_parser_ast,
75-
$native_parser,
76-
$native_parser_grammar,
77-
$native_parser_rules,
78-
$native_parser_tokens,
79-
$native_parser_lexer,
80-
$native_parser_driver,
81-
$native_parser_driver_parser,
82-
$native_parser_reflection,
83-
$native_parser_property,
84-
$native_parser_driver_reflection,
85-
$native_parser_driver_property,
86-
$native_parser_driver_ast,
87-
$native_parser_driver_child
88-
);
13+
require_once __DIR__ . '/tools/verify-native-parser-extension.php';
8914
}
9015

9116
// Configure the test environment.

0 commit comments

Comments
 (0)