@@ -59,6 +59,10 @@ const showLoadTestListErrorCmdId = 'e3-testsuite.showLoadTestListError';
5959let lastLoadError : string = '' ;
6060export let controller : vscode . TestController ;
6161export let runProfile : vscode . TestRunProfile ;
62+ export let runHandler : (
63+ request : vscode . TestRunRequest ,
64+ token : vscode . CancellationToken ,
65+ ) => Promise < void > ;
6266
6367// This method is called when your extension is activated
6468// Your extension is activated the very first time the command is executed
@@ -156,135 +160,136 @@ export function activateE3TestsuiteIntegration(context: vscode.ExtensionContext)
156160 } ) ;
157161 } ;
158162
159- runProfile = controller . createRunProfile (
160- 'e3-testsuite' ,
161- vscode . TestRunProfileKind . Run ,
162- async function ( request , token ) {
163- const ts = getTestsuite ( ) ;
164-
165- const enableEventSystem : boolean =
166- vscode . workspace . getConfiguration ( 'e3-testsuite' ) . get ( 'enableEventSystem' ) ?? true ;
163+ runHandler = async (
164+ request : vscode . TestRunRequest ,
165+ token : vscode . CancellationToken ,
166+ ) : Promise < void > => {
167+ const ts = getTestsuite ( ) ;
167168
168- const cmd = [ ts . python , ts . uri . fsPath , '--failure-exit-code=0' ] ;
169+ const enableEventSystem : boolean =
170+ vscode . workspace . getConfiguration ( 'e3-testsuite' ) . get ( 'enableEventSystem' ) ?? true ;
169171
170- const remainingSet : Set < vscode . TestItem > = new Set ( ) ;
171- function collectAll ( i : vscode . TestItem ) {
172- remainingSet . add ( i ) ;
173- i . children . forEach ( collectAll ) ;
174- }
175-
176- function onlyRootSelected ( rq : vscode . TestRunRequest ) {
177- return rq . include ?. length === 1 && rq . include [ 0 ] . id === getRootItemId ( ) ;
178- }
172+ const cmd = [ ts . python , ts . uri . fsPath , '--failure-exit-code=0' ] ;
179173
180- if ( request . include && ! onlyRootSelected ( request ) ) {
181- const testIds = new Set < string > ( ) ;
182- request . include . forEach ( collectAll ) ;
183- remainingSet . forEach ( ( item ) => {
184- const data =
185- testData . get ( item ) ??
186- // If item is a sub-result, it doesn't have data. So use its parent.
187- ( item . parent ? testData . get ( item . parent ) : undefined ) ;
188- if ( data ) {
189- testIds . add ( data . test_matcher ?? data . test_dir ) ;
190- }
191- } ) ;
174+ const remainingSet : Set < vscode . TestItem > = new Set ( ) ;
175+ function collectAll ( i : vscode . TestItem ) {
176+ remainingSet . add ( i ) ;
177+ i . children . forEach ( collectAll ) ;
178+ }
192179
193- assert ( testIds . size > 0 ) ;
194- cmd . push ( ...testIds ) ;
195- } else {
196- /**
197- * Do not append tests to the command line. Just run everything.
198- */
199- controller . items . forEach ( collectAll ) ;
200- }
180+ function onlyRootSelected ( rq : vscode . TestRunRequest ) {
181+ return rq . include ?. length === 1 && rq . include [ 0 ] . id === getRootItemId ( ) ;
182+ }
201183
202- const run = controller . createTestRun ( request , 'e3-testsuite' ) ;
203- run . appendOutput ( `Running: ${ cmd . map ( ( c ) => '"' + c + '"' ) . join ( ' ' ) } \n\r` ) ;
204-
205- const env = getEnv ( ) ;
206- if ( enableEventSystem ) {
207- const modulePath = context . asAbsolutePath ( 'media' ) ;
208- const module = 'e3_notify_vscode' ;
209- const hook = 'init_callback' ;
210- env [ 'PYTHONPATH' ] = ( env [ 'PYTHONPATH' ] ?? '' )
211- . split ( path . delimiter )
212- . filter ( ( v ) => ! ! v )
213- . concat ( modulePath )
214- . join ( path . delimiter ) ;
215- cmd . push ( `--notify-events=python:${ module } :${ hook } ` ) ;
216- }
184+ if ( request . include && ! onlyRootSelected ( request ) ) {
185+ const testIds = new Set < string > ( ) ;
186+ request . include . forEach ( collectAll ) ;
187+ remainingSet . forEach ( ( item ) => {
188+ const data =
189+ testData . get ( item ) ??
190+ // If item is a sub-result, it doesn't have data. So use its parent.
191+ ( item . parent ? testData . get ( item . parent ) : undefined ) ;
192+ if ( data ) {
193+ testIds . add ( data . test_matcher ?? data . test_dir ) ;
194+ }
195+ } ) ;
217196
197+ assert ( testIds . size > 0 ) ;
198+ cmd . push ( ...testIds ) ;
199+ } else {
218200 /**
219- * Append CLI args defined in settings
201+ * Do not append tests to the command line. Just run everything.
220202 */
221- cmd . push (
222- ...( vscode . workspace . getConfiguration ( 'e3-testsuite' ) . get < string [ ] > ( 'args' ) ?? [ ] ) ,
223- ) ;
203+ controller . items . forEach ( collectAll ) ;
204+ }
224205
225- const cwd = vscode . workspace . workspaceFolders ! [ 0 ] . uri . fsPath ;
226- await new Promise < void > ( ( resolve , reject ) => {
227- const p = spawn ( cmd [ 0 ] , cmd . splice ( 1 ) , {
228- cwd : cwd ,
229- env : env ,
230- } ) ;
231- token . onCancellationRequested ( ( ) => {
232- p . kill ( ) ;
233- run . appendOutput ( '\r\n*** Test run was cancelled' ) ;
234- remainingSet . forEach ( ( item ) =>
235- run . errored ( item , new vscode . TestMessage ( 'Test run was cancelled.' ) ) ,
236- ) ;
237- resolve ( ) ;
238- } ) ;
206+ const run = controller . createTestRun ( request , 'e3-testsuite' ) ;
207+ run . appendOutput ( `Running: ${ cmd . map ( ( c ) => '"' + c + '"' ) . join ( ' ' ) } \n\r` ) ;
208+
209+ const env = getEnv ( ) ;
210+ if ( enableEventSystem ) {
211+ const modulePath = context . asAbsolutePath ( 'media' ) ;
212+ const module = 'e3_notify_vscode' ;
213+ const hook = 'init_callback' ;
214+ env [ 'PYTHONPATH' ] = ( env [ 'PYTHONPATH' ] ?? '' )
215+ . split ( path . delimiter )
216+ . filter ( ( v ) => ! ! v )
217+ . concat ( modulePath )
218+ . join ( path . delimiter ) ;
219+ cmd . push ( `--notify-events=python:${ module } :${ hook } ` ) ;
220+ }
239221
240- if ( ! enableEventSystem ) {
241- remainingSet . forEach ( ( t ) => run . started ( t ) ) ;
242- }
222+ /**
223+ * Append CLI args defined in settings
224+ */
225+ cmd . push (
226+ ...( vscode . workspace . getConfiguration ( 'e3-testsuite' ) . get < string [ ] > ( 'args' ) ?? [ ] ) ,
227+ ) ;
243228
244- function handleLine ( line : string | Buffer ) {
245- const decodedLine : string =
246- typeof line === 'string' ? line : line . toLocaleString ( ) ;
229+ const cwd = vscode . workspace . workspaceFolders ! [ 0 ] . uri . fsPath ;
230+ await new Promise < void > ( ( resolve , reject ) => {
231+ const p = spawn ( cmd [ 0 ] , cmd . splice ( 1 ) , {
232+ cwd : cwd ,
233+ env : env ,
234+ } ) ;
235+ token . onCancellationRequested ( ( ) => {
236+ p . kill ( ) ;
237+ run . appendOutput ( '\r\n*** Test run was cancelled' ) ;
238+ remainingSet . forEach ( ( item ) =>
239+ run . errored ( item , new vscode . TestMessage ( 'Test run was cancelled.' ) ) ,
240+ ) ;
241+ resolve ( ) ;
242+ } ) ;
247243
248- if ( enableEventSystem ) {
249- handleTestsuiteEvents ( run , decodedLine , remainingSet ) ;
250- } else {
251- handleTestsuiteOutput ( run , decodedLine , remainingSet ) ;
252- }
244+ if ( ! enableEventSystem ) {
245+ remainingSet . forEach ( ( t ) => run . started ( t ) ) ;
246+ }
247+
248+ function handleLine ( line : string | Buffer ) {
249+ const decodedLine : string = typeof line === 'string' ? line : line . toLocaleString ( ) ;
250+
251+ if ( enableEventSystem ) {
252+ handleTestsuiteEvents ( run , decodedLine , remainingSet ) ;
253+ } else {
254+ handleTestsuiteOutput ( run , decodedLine , remainingSet ) ;
253255 }
254- p . stdout . pipe ( split ( ) ) . on ( 'data' , handleLine ) ;
255- p . stderr . pipe ( split ( ) ) . on ( 'data' , handleLine ) ;
256- p . on ( 'error' , reject ) ;
257- p . on ( 'close' , ( code ) => {
258- if ( code === 0 ) {
259- resolve ( ) ;
260- } else {
261- const md = new vscode . MarkdownString (
262- `Test run failed, see ` +
263- `[Output](command:testing.showMostRecentOutput)` ,
264- ) ;
265- md . isTrusted = true ;
266- const msg = new vscode . TestMessage ( md ) ;
267- remainingSet . forEach ( ( t ) => run . errored ( t , msg ) ) ;
268- run . end ( ) ;
269- reject (
270- Error ( 'Test run failed, see Test Results view for testsuite output.' ) ,
271- ) ;
272- }
273- } ) ;
274- } )
275- . then ( ( ) => {
276- if ( ! enableEventSystem ) {
277- const e3ResultsPath = path . join ( cwd , 'out' , 'new' ) ;
278- processTestsuiteResultIndex ( e3ResultsPath , run ) ;
279- }
280- } )
281- . finally ( ( ) => {
282- /**
283- * Always end the run, be it a nominal or an error end.
284- */
256+ }
257+ p . stdout . pipe ( split ( ) ) . on ( 'data' , handleLine ) ;
258+ p . stderr . pipe ( split ( ) ) . on ( 'data' , handleLine ) ;
259+ p . on ( 'error' , reject ) ;
260+ p . on ( 'close' , ( code ) => {
261+ if ( code === 0 ) {
262+ resolve ( ) ;
263+ } else {
264+ const md = new vscode . MarkdownString (
265+ `Test run failed, see ` + `[Output](command:testing.showMostRecentOutput)` ,
266+ ) ;
267+ md . isTrusted = true ;
268+ const msg = new vscode . TestMessage ( md ) ;
269+ remainingSet . forEach ( ( t ) => run . errored ( t , msg ) ) ;
285270 run . end ( ) ;
286- } ) ;
287- } ,
271+ reject ( Error ( 'Test run failed, see Test Results view for testsuite output.' ) ) ;
272+ }
273+ } ) ;
274+ } )
275+ . then ( ( ) => {
276+ if ( ! enableEventSystem ) {
277+ const e3ResultsPath = path . join ( cwd , 'out' , 'new' ) ;
278+ processTestsuiteResultIndex ( e3ResultsPath , run ) ;
279+ }
280+ } )
281+ . finally ( ( ) => {
282+ /**
283+ * Always end the run, be it a nominal or an error end.
284+ */
285+ run . end ( ) ;
286+ } ) ;
287+ } ;
288+
289+ runProfile = controller . createRunProfile (
290+ 'e3-testsuite' ,
291+ vscode . TestRunProfileKind . Run ,
292+ runHandler ,
288293 ) ;
289294
290295 function processTestsuiteResultIndex ( e3ResultsPath : string , run : vscode . TestRun ) {
0 commit comments