@@ -8,7 +8,7 @@ import type {
88
99import { waSqliteSingleWorker } from '../../lib/index.js' ;
1010
11- const scriptModules = ( import . meta as any ) . glob ( './mptest/**/*test ' , {
11+ const scriptModules = import . meta. glob ( './mptest/**/*' , {
1212 as : 'raw' ,
1313 eager : true
1414} ) ;
@@ -68,6 +68,13 @@ interface ClientContext {
6868 pending : Set < Promise < void > > ;
6969}
7070
71+ interface TaskControl {
72+ promise : Promise < void > ;
73+ resolve : ( ) => void ;
74+ reject : ( err : unknown ) => void ;
75+ isResolved : ( ) => boolean ;
76+ }
77+
7178class MptestRunner {
7279 private clients = new Map < number , ClientContext > ( ) ;
7380 private pendingTasks = new Set < Promise < void > > ( ) ;
@@ -142,6 +149,32 @@ class MptestRunner {
142149 } ) ;
143150 }
144151
152+ private createTaskControl ( ) : TaskControl {
153+ let resolved = false ;
154+ let resolveFn : ( ) => void = ( ) => { } ;
155+ let rejectFn : ( err : unknown ) => void = ( ) => { } ;
156+ const promise = new Promise < void > ( ( resolve , reject ) => {
157+ resolveFn = ( ) => {
158+ if ( ! resolved ) {
159+ resolved = true ;
160+ resolve ( ) ;
161+ }
162+ } ;
163+ rejectFn = ( err ) => {
164+ if ( ! resolved ) {
165+ resolved = true ;
166+ reject ( err ) ;
167+ }
168+ } ;
169+ } ) ;
170+ return {
171+ promise,
172+ resolve : resolveFn ,
173+ reject : rejectFn ,
174+ isResolved : ( ) => resolved
175+ } ;
176+ }
177+
145178 private async scheduleTask (
146179 parent : ScriptContext ,
147180 clientId : number ,
@@ -150,6 +183,8 @@ class MptestRunner {
150183 taskLabel : string
151184 ) : Promise < void > {
152185 const client = await this . ensureClient ( clientId ) ;
186+ const taskControl = this . createTaskControl ( ) ;
187+ this . trackTask ( client , taskControl . promise ) ;
153188 const run = async ( ) => {
154189 await this . runScriptInternal (
155190 {
@@ -159,12 +194,19 @@ class MptestRunner {
159194 displayName : `${ parent . displayName } #client${ clientId } :${ taskLabel } `
160195 } ,
161196 script ,
162- startLine
197+ startLine ,
198+ taskControl
163199 ) ;
200+ taskControl . resolve ( ) ;
164201 } ;
165- const task = client . queue . then ( run ) ;
202+ const task = client . queue . then ( run ) . catch ( ( err ) => {
203+ if ( taskControl . isResolved ( ) ) {
204+ return ;
205+ }
206+ taskControl . reject ( err ) ;
207+ throw err ;
208+ } ) ;
166209 client . queue = task . catch ( ( ) => { } ) ;
167- this . trackTask ( client , task ) ;
168210 }
169211
170212 private async waitForAll ( timeoutMs : number ) : Promise < void > {
@@ -221,7 +263,8 @@ class MptestRunner {
221263 private async runScriptInternal (
222264 context : ScriptContext ,
223265 script : string ,
224- initialLine : number
266+ initialLine : number ,
267+ taskControl ?: TaskControl
225268 ) : Promise < void > {
226269 const result = new ResultBuffer ( ) ;
227270 let index = 0 ;
@@ -265,6 +308,10 @@ class MptestRunner {
265308 throw new Error (
266309 `${ context . displayName } :${ prevLine } expected [${ expectedRaw } ] but got [${ result . toString ( ) } ]`
267310 ) ;
311+ } else {
312+ console . log (
313+ `${ context . displayName } :${ prevLine } expected [${ expectedRaw } ] matched [${ result . toString ( ) } ]`
314+ ) ;
268315 }
269316 result . reset ( ) ;
270317 break ;
@@ -295,6 +342,10 @@ class MptestRunner {
295342 ) ;
296343 break ;
297344 }
345+ case 'finish' : {
346+ taskControl ?. resolve ( ) ;
347+ break ;
348+ }
298349 case 'wait' : {
299350 const target = command . args [ 0 ] ?? 'all' ;
300351 const timeout = command . args [ 1 ] ? Number ( command . args [ 1 ] ) : 10000 ;
@@ -323,7 +374,8 @@ class MptestRunner {
323374 displayName : baseName ( resolved )
324375 } ,
325376 subScript ,
326- 1
377+ 1 ,
378+ taskControl
327379 ) ;
328380 break ;
329381 }
@@ -374,8 +426,8 @@ class MptestRunner {
374426 if ( ! rows || rows . length === 0 ) {
375427 return false ;
376428 }
377- const row = rows [ 0 ] as SqliteRowRaw ;
378- const value = row [ 0 ] ;
429+ const rawRows = rows as SqliteRowRaw [ ] ;
430+ const value = rawRows [ 0 ] ?. [ 0 ] ;
379431 if ( value == null ) {
380432 return false ;
381433 }
@@ -404,12 +456,16 @@ class MptestRunner {
404456 if ( ! sql . trim ( ) ) {
405457 continue ;
406458 }
459+ if ( ! hasNonCommentContent ( sql ) ) {
460+ continue ;
461+ }
407462 const statement = context . connection . prepare ( sql , { rawResults : true } ) ;
408463 try {
409464 const { rows } = await statement . step ( ) ;
410465 if ( rows ) {
411- for ( const row of rows ) {
412- for ( const value of row as SqliteRowRaw ) {
466+ const rawRows = rows as SqliteRowRaw [ ] ;
467+ for ( const row of rawRows ) {
468+ for ( const value of row ) {
413469 result . append ( value ) ;
414470 }
415471 }
@@ -428,7 +484,9 @@ class MptestRunner {
428484}
429485
430486describe ( 'mptest scripts' , ( ) => {
431- for ( const script of topLevelScripts ) {
487+ // const scripts = topLevelScripts;
488+ const scripts = [ 'mptest/multiwrite01.test' ] ;
489+ for ( const script of scripts ) {
432490 test ( script , async ( ) => {
433491 const dbPath = `mptest-${ sanitizeForFilename ( script ) } -${ Math . random ( )
434492 . toString ( 36 )
@@ -861,6 +919,96 @@ function toHex(data: Uint8Array): string {
861919 return hex ;
862920}
863921
922+ function hasNonCommentContent ( sql : string ) : boolean {
923+ let i = 0 ;
924+ let inSingle = false ;
925+ let inDouble = false ;
926+ let inBracket = false ;
927+
928+ const advance = ( step = 1 ) => {
929+ i += step ;
930+ } ;
931+
932+ while ( i < sql . length ) {
933+ const c = sql [ i ] ;
934+ const next = sql [ i + 1 ] ;
935+
936+ if ( inSingle ) {
937+ if ( c === "'" ) {
938+ if ( next === "'" ) {
939+ advance ( 2 ) ;
940+ continue ;
941+ }
942+ inSingle = false ;
943+ advance ( ) ;
944+ continue ;
945+ }
946+ advance ( ) ;
947+ continue ;
948+ }
949+ if ( inDouble ) {
950+ if ( c === '"' ) {
951+ if ( next === '"' ) {
952+ advance ( 2 ) ;
953+ continue ;
954+ }
955+ inDouble = false ;
956+ advance ( ) ;
957+ continue ;
958+ }
959+ advance ( ) ;
960+ continue ;
961+ }
962+ if ( inBracket ) {
963+ if ( c === ']' ) {
964+ inBracket = false ;
965+ }
966+ advance ( ) ;
967+ continue ;
968+ }
969+
970+ if ( c === "'" ) {
971+ inSingle = true ;
972+ advance ( ) ;
973+ continue ;
974+ }
975+ if ( c === '"' ) {
976+ inDouble = true ;
977+ advance ( ) ;
978+ continue ;
979+ }
980+ if ( c === '[' ) {
981+ inBracket = true ;
982+ advance ( ) ;
983+ continue ;
984+ }
985+
986+ if ( c === '-' && next === '-' ) {
987+ advance ( 2 ) ;
988+ while ( i < sql . length && sql [ i ] !== '\n' ) {
989+ advance ( ) ;
990+ }
991+ continue ;
992+ }
993+ if ( c === '/' && next === '*' ) {
994+ advance ( 2 ) ;
995+ while ( i < sql . length && ! ( sql [ i ] === '*' && sql [ i + 1 ] === '/' ) ) {
996+ advance ( ) ;
997+ }
998+ if ( i < sql . length ) {
999+ advance ( 2 ) ;
1000+ }
1001+ continue ;
1002+ }
1003+ if ( / \s / . test ( c ?? '' ) ) {
1004+ advance ( ) ;
1005+ continue ;
1006+ }
1007+ return true ;
1008+ }
1009+ return false ;
1010+ }
1011+
8641012function sleepMs ( ms : number ) : Promise < void > {
8651013 if ( ms <= 0 ) {
8661014 return Promise . resolve ( ) ;
0 commit comments