@@ -8,6 +8,48 @@ import * as fs from 'fs';
8
8
import * as assert from 'assert' ;
9
9
import { WindowsTerminal } from './windowsTerminal' ;
10
10
import * as path from 'path' ;
11
+ import { getProcessList } from 'windows-process-tree' ;
12
+ import * as psList from 'ps-list' ;
13
+
14
+ interface IProcessState {
15
+ // Whether the PID must exist or must not exist
16
+ [ pid : number ] : boolean ;
17
+ }
18
+
19
+ function pollForProcessState ( desiredState : IProcessState , intervalMs : number = 100 , timeoutMs : number = 2000 ) : Promise < void > {
20
+ return new Promise < void > ( resolve => {
21
+ let tries = 0 ;
22
+ const interval = setInterval ( ( ) => {
23
+ psList ( { all : true } ) . then ( ps => {
24
+ let success = true ;
25
+ const pids = Object . keys ( desiredState ) . map ( k => parseInt ( k , 10 ) ) ;
26
+ pids . forEach ( pid => {
27
+ if ( desiredState [ pid ] ) {
28
+ if ( ! ps . some ( p => p . pid === pid ) ) {
29
+ success = false ;
30
+ }
31
+ } else {
32
+ if ( ps . some ( p => p . pid === pid ) ) {
33
+ success = false ;
34
+ }
35
+ }
36
+ } ) ;
37
+ if ( success ) {
38
+ clearInterval ( interval ) ;
39
+ resolve ( ) ;
40
+ return ;
41
+ }
42
+ tries ++ ;
43
+ if ( tries * intervalMs >= timeoutMs ) {
44
+ clearInterval ( interval ) ;
45
+ const processListing = pids . map ( k => `${ k } : ${ desiredState [ k ] } ` ) . join ( '\n' ) ;
46
+ assert . fail ( `Bad process state, expected:\n${ processListing } ` ) ;
47
+ resolve ( ) ;
48
+ }
49
+ } ) ;
50
+ } , intervalMs ) ;
51
+ } ) ;
52
+ }
11
53
12
54
if ( process . platform === 'win32' ) {
13
55
describe ( 'WindowsTerminal' , ( ) => {
@@ -18,15 +60,34 @@ if (process.platform === 'win32') {
18
60
// Add done call to deferred function queue to ensure the kill call has completed
19
61
( < any > term ) . _defer ( done ) ;
20
62
} ) ;
21
- it ( 'should kill the process tree' , ( done ) => {
63
+ it ( 'should kill the process tree' , function ( done : Mocha . Done ) : void {
64
+ this . timeout ( 5000 ) ;
65
+
22
66
const term = new WindowsTerminal ( 'cmd.exe' , [ ] , { } ) ;
23
67
// Start a sub-process
24
- term . write ( 'powershell.exe' ) ;
25
- const proc = cp . execSync ( `tasklist /fi "PID eq ${ term . pid } "` ) ;
26
- const index = proc . toString ( ) . indexOf ( term . pid . toString ( ) ) ;
27
- console . log ( '******* ' + index + ', ' + proc . toString ( ) ) ;
28
- // term.pid
29
- // term.kill();
68
+ term . write ( 'powershell.exe\r' ) ;
69
+ term . write ( 'notepad.exe\r' ) ;
70
+ term . write ( 'node.exe\r' ) ;
71
+ setTimeout ( ( ) => {
72
+ getProcessList ( term . pid , list => {
73
+ assert . equal ( list . length , 4 ) ;
74
+ assert . equal ( list [ 0 ] . name , 'cmd.exe' ) ;
75
+ assert . equal ( list [ 1 ] . name , 'powershell.exe' ) ;
76
+ assert . equal ( list [ 2 ] . name , 'notepad.exe' ) ;
77
+ assert . equal ( list [ 3 ] . name , 'node.exe' ) ;
78
+ term . kill ( ) ;
79
+ const desiredState : IProcessState = { } ;
80
+ desiredState [ list [ 0 ] . pid ] = false ;
81
+ desiredState [ list [ 1 ] . pid ] = false ;
82
+ desiredState [ list [ 2 ] . pid ] = true ;
83
+ desiredState [ list [ 3 ] . pid ] = false ;
84
+ pollForProcessState ( desiredState ) . then ( ( ) => {
85
+ // Kill notepad before done
86
+ process . kill ( list [ 2 ] . pid ) ;
87
+ done ( ) ;
88
+ } ) ;
89
+ } ) ;
90
+ } , 1000 ) ;
30
91
} ) ;
31
92
} ) ;
32
93
0 commit comments