4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
import { CancellationTokenSource } from 'vs/base/common/cancellation' ;
7
- import { Disposable , toDisposable } from 'vs/base/common/lifecycle' ;
7
+ import { Disposable , DisposableStore , IDisposable , toDisposable } from 'vs/base/common/lifecycle' ;
8
8
import { IContextKey , IContextKeyService } from 'vs/platform/contextkey/common/contextkey' ;
9
9
import { createDecorator } from 'vs/platform/instantiation/common/instantiation' ;
10
10
import { IStorageService , StorageScope , StorageTarget } from 'vs/platform/storage/common/storage' ;
11
11
import { StoredValue } from 'vs/workbench/contrib/testing/common/storedValue' ;
12
12
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys' ;
13
13
import { ITestService } from 'vs/workbench/contrib/testing/common/testService' ;
14
14
import { TestService } from 'vs/workbench/contrib/testing/common/testServiceImpl' ;
15
- import { ITestRunProfile } from 'vs/workbench/contrib/testing/common/testTypes' ;
15
+ import { ITestRunProfile , TestRunProfileBitset } from 'vs/workbench/contrib/testing/common/testTypes' ;
16
16
import { Emitter , Event } from 'vs/base/common/event' ;
17
17
import { TestId } from 'vs/workbench/contrib/testing/common/testId' ;
18
18
import { WellDefinedPrefixTree } from 'vs/base/common/prefixTree' ;
19
+ import { ITestProfileService } from 'vs/workbench/contrib/testing/common/testProfileService' ;
20
+ import * as arrays from 'vs/base/common/arrays' ;
19
21
20
22
export const ITestingContinuousRunService = createDecorator < ITestingContinuousRunService > ( 'testingContinuousRunService' ) ;
21
23
@@ -56,10 +58,11 @@ export interface ITestingContinuousRunService {
56
58
isEnabled ( ) : boolean ;
57
59
58
60
/**
59
- * Starts a continuous auto run with a specific profile or set of profiles.
60
- * Globally if no test is given, for a specific test otherwise.
61
+ * Starts a continuous auto run with a specific set of profiles, or all
62
+ * default profiles in a group. Globally if no test is given,
63
+ * for a specific test otherwise.
61
64
*/
62
- start ( profile : ITestRunProfile [ ] , testId ?: string ) : void ;
65
+ start ( profile : ITestRunProfile [ ] | TestRunProfileBitset , testId ?: string ) : void ;
63
66
64
67
/**
65
68
* Stops any continuous run
@@ -72,8 +75,8 @@ export class TestingContinuousRunService extends Disposable implements ITestingC
72
75
declare readonly _serviceBrand : undefined ;
73
76
74
77
private readonly changeEmitter = new Emitter < string | undefined > ( ) ;
75
- private globallyRunning ?: CancellationTokenSource ;
76
- private readonly running = new WellDefinedPrefixTree < CancellationTokenSource > ( ) ;
78
+ private globallyRunning ?: IDisposable ;
79
+ private readonly running = new WellDefinedPrefixTree < IDisposable > ( ) ;
77
80
private readonly lastRun : StoredValue < Set < number > > ;
78
81
private readonly isGloballyOn : IContextKey < boolean > ;
79
82
@@ -87,6 +90,7 @@ export class TestingContinuousRunService extends Disposable implements ITestingC
87
90
@ITestService private readonly testService : TestService ,
88
91
@IStorageService storageService : IStorageService ,
89
92
@IContextKeyService contextKeyService : IContextKeyService ,
93
+ @ITestProfileService private readonly testProfileService : ITestProfileService ,
90
94
) {
91
95
super ( ) ;
92
96
this . isGloballyOn = TestingContextKeys . isContinuousModeOn . bindTo ( contextKeyService ) ;
@@ -133,45 +137,69 @@ export class TestingContinuousRunService extends Disposable implements ITestingC
133
137
}
134
138
135
139
/** @inheritdoc */
136
- public start ( profile : ITestRunProfile [ ] , testId ?: string ) : void {
140
+ public start ( profiles : ITestRunProfile [ ] | TestRunProfileBitset , testId ?: string ) : void {
141
+ const store = new DisposableStore ( ) ;
137
142
const cts = new CancellationTokenSource ( ) ;
143
+ store . add ( toDisposable ( ( ) => cts . dispose ( true ) ) ) ;
138
144
139
145
if ( testId === undefined ) {
140
146
this . isGloballyOn . set ( true ) ;
141
147
}
142
148
143
149
if ( ! testId ) {
144
- this . globallyRunning ?. dispose ( true ) ;
145
- this . globallyRunning = cts ;
150
+ this . globallyRunning ?. dispose ( ) ;
151
+ this . globallyRunning = store ;
146
152
} else {
147
153
this . running . mutate ( TestId . fromString ( testId ) . path , c => {
148
- c ?. dispose ( true ) ;
149
- return cts ;
154
+ c ?. dispose ( ) ;
155
+ return store ;
150
156
} ) ;
151
157
}
152
158
153
- this . lastRun . store ( new Set ( profile . map ( p => p . profileId ) ) ) ;
159
+ let actualProfiles : ITestRunProfile [ ] ;
160
+ if ( profiles instanceof Array ) {
161
+ actualProfiles = profiles ;
162
+ } else {
163
+ // restart the continuous run when default profiles change, if we were
164
+ // asked to run for a group
165
+ const getRelevant = ( ) => this . testProfileService . getGroupDefaultProfiles ( profiles )
166
+ . filter ( p => p . supportsContinuousRun && ( ! testId || TestId . root ( testId ) === p . controllerId ) ) ;
167
+ actualProfiles = getRelevant ( ) ;
168
+ store . add ( this . testProfileService . onDidChange ( ( ) => {
169
+ if ( ! arrays . equals ( getRelevant ( ) , actualProfiles ) ) {
170
+ this . start ( profiles , testId ) ;
171
+ }
172
+ } ) ) ;
173
+ }
154
174
155
- this . testService . startContinuousRun ( {
156
- continuous : true ,
157
- targets : profile . map ( p => ( {
158
- testIds : [ testId ?? p . controllerId ] ,
159
- controllerId : p . controllerId ,
160
- profileGroup : p . group ,
161
- profileId : p . profileId
162
- } ) ) ,
163
- } , cts . token ) ;
175
+ this . lastRun . store ( new Set ( actualProfiles . map ( p => p . profileId ) ) ) ;
176
+
177
+ if ( actualProfiles . length ) {
178
+ this . testService . startContinuousRun ( {
179
+ continuous : true ,
180
+ targets : actualProfiles . map ( p => ( {
181
+ testIds : [ testId ?? p . controllerId ] ,
182
+ controllerId : p . controllerId ,
183
+ profileGroup : p . group ,
184
+ profileId : p . profileId
185
+ } ) ) ,
186
+ } , cts . token ) ;
187
+ }
164
188
165
189
this . changeEmitter . fire ( testId ) ;
166
190
}
167
191
168
192
/** @inheritdoc */
169
193
public stop ( testId ?: string ) : void {
170
194
if ( ! testId ) {
171
- this . globallyRunning ?. dispose ( true ) ;
195
+ this . globallyRunning ?. dispose ( ) ;
172
196
this . globallyRunning = undefined ;
173
197
} else {
174
- this . running . delete ( TestId . fromString ( testId ) . path ) ?. dispose ( true ) ;
198
+ const cancellations = [ ...this . running . deleteRecursive ( TestId . fromString ( testId ) . path ) ] ;
199
+ // deleteRecursive returns a BFS order, reverse it so children are cancelled before parents
200
+ for ( let i = cancellations . length - 1 ; i >= 0 ; i -- ) {
201
+ cancellations [ i ] . dispose ( ) ;
202
+ }
175
203
}
176
204
177
205
if ( testId === undefined ) {
0 commit comments