11import assert from 'assert' ;
2+ import { existsSync } from 'fs' ;
23import { suite , test } from 'mocha' ;
34import * as vscode from 'vscode' ;
45import { adaExtState } from '../../../src/extension' ;
6+ import { getProjectFile } from '../../../src/helpers' ;
57import {
68 CustomTaskDefinition ,
79 PROJECT_FROM_CONFIG ,
810 createAdaTaskProvider ,
911 createSparkTaskProvider ,
1012} from '../../../src/taskProviders' ;
11- import { activate } from '../utils' ;
13+ import { activate , exe } from '../utils' ;
1214
1315suite ( 'GPR Tasks Provider' , function ( ) {
16+ let projectPath : string ;
17+
1418 this . beforeAll ( async ( ) => {
1519 await activate ( ) ;
20+ projectPath = await getProjectFile ( ) ;
1621 } ) ;
1722
23+ /**
24+ * Check that the list of offered Ada tasks is expected.
25+ */
1826 test ( 'Ada tasks list' , async ( ) => {
1927 const prov = createAdaTaskProvider ( ) ;
2028 const tasks = await prov . provideTasks ( ) ;
2129 assert . notStrictEqual ( tasks , undefined ) ;
2230
23- const expectedTasksNames : string [ ] = [
24- 'ada: Build current project - kind: buildProject' ,
25- 'ada: Check current file - kind: checkFile' ,
26- 'ada: Clean current project - kind: cleanProject' ,
27- 'ada: Build main - main1.adb - kind: buildMain' ,
28- 'ada: Build and run main - main1.adb - kind: buildAndRunMain' ,
29- 'ada: Build main - test.adb - kind: buildMain' ,
30- 'ada: Build and run main - test.adb - kind: buildAndRunMain' ,
31- ] ;
31+ const expectedTasksList = `
32+ ada: Build current project - kind: buildProject
33+ ada: Check current file - kind: checkFile
34+ ada: Clean current project - kind: cleanProject
35+ ada: Build main - src/main1.adb - kind: buildMain
36+ ada: Run main - src/main1.adb - kind: runMain
37+ ada: Build and run main - src/main1.adb - kind: buildAndRunMain
38+ ada: Build main - src/test.adb - kind: buildMain
39+ ada: Run main - src/test.adb - kind: runMain
40+ ada: Build and run main - src/test.adb - kind: buildAndRunMain` . trim ( ) ;
3241
33- assert . strictEqual (
34- tasks
35- . map (
36- ( t ) =>
37- `${ t . source } : ${ t . name } - kind: ${
38- ( t . definition as CustomTaskDefinition ) . configuration . kind
39- } `
40- )
41- . join ( '\n' ) ,
42- expectedTasksNames . join ( '\n' )
43- ) ;
42+ const actualTaskList = tasks
43+ . map (
44+ ( t ) =>
45+ `${ t . source } : ${ t . name } - kind: ${
46+ ( t . definition as CustomTaskDefinition ) . configuration . kind
47+ } `
48+ )
49+ . join ( '\n' ) ;
50+ assert . strictEqual ( actualTaskList , expectedTasksList ) ;
4451 } ) ;
4552
53+ /**
54+ * Check that the list of offered SPARK tasks is expected.
55+ */
4656 test ( 'Spark tasks list' , async ( ) => {
4757 await adaExtState . adaClient . onReady ( ) ;
4858 const prov = createSparkTaskProvider ( ) ;
@@ -65,6 +75,71 @@ suite('GPR Tasks Provider', function () {
6575 ) ;
6676 } ) ;
6777
78+ test ( 'Automatic clean command' , async ( ) => {
79+ const task = ( await vscode . tasks . fetchTasks ( { type : 'ada' } ) ) . find (
80+ ( t ) => t . name == 'Clean current project'
81+ ) ;
82+ assert ( task ) ;
83+
84+ /**
85+ * Check the command line of the clean task.
86+ */
87+ const actualCmd = getCmdLine ( task . execution as vscode . ShellExecution ) ;
88+ /**
89+ * The workspace doesn't define an ada.projectFile setting, so the full
90+ * path of the project file is obtained from ALS and used in the command
91+ * line.
92+ */
93+ const expectedCmd = `gprclean -P ${ projectPath } ` ;
94+ assert . equal ( actualCmd , expectedCmd ) ;
95+
96+ /**
97+ * Now try running the task.
98+ */
99+ const status = await runTaskAndGetResult ( task ) ;
100+ assert . equal ( status , 0 ) ;
101+ assert ( ! existsSync ( 'obj/main1' + exe ) ) ;
102+ } ) ;
103+
104+ test ( 'Automatic buildMain command' , async ( ) => {
105+ const task = ( await vscode . tasks . fetchTasks ( { type : 'ada' } ) ) . find (
106+ ( t ) => t . name == 'Build main - src/main1.adb'
107+ ) ;
108+ assert ( task ) ;
109+
110+ /**
111+ * Check the command line of the build task.
112+ */
113+ const actualCmd = getCmdLine ( task . execution as vscode . ShellExecution ) ;
114+ /**
115+ * The workspace doesn't define an ada.projectFile setting, so the full
116+ * path of the project file is obtained from ALS and used in the command
117+ * line.
118+ */
119+ const expectedCmd = `gprbuild -P ${ projectPath } src/main1.adb -cargs:ada -gnatef` ;
120+ assert . equal ( actualCmd , expectedCmd ) ;
121+
122+ /**
123+ * Now try running the task.
124+ */
125+ const status = await runTaskAndGetResult ( task ) ;
126+ assert . equal ( status , 0 ) ;
127+
128+ console . info ( `cwd=${ process . cwd ( ) } ` ) ;
129+ /**
130+ * Check that the executable is produced. The project defines a
131+ * different name for the executable produced by main1.adb.
132+ */
133+ assert ( vscode . workspace . workspaceFolders ) ;
134+ assert (
135+ existsSync ( `${ vscode . workspace . workspaceFolders [ 0 ] . uri . fsPath } /obj/main1exec` + exe )
136+ ) ;
137+ } ) ;
138+
139+ /**
140+ * Check that starting from a User-defined task, the task provider is able
141+ * to resolve it into a complete task with the expected command line.
142+ */
68143 test ( 'Resolving task' , async ( ) => {
69144 const prov = createAdaTaskProvider ( ) ;
70145
@@ -73,6 +148,7 @@ suite('GPR Tasks Provider', function () {
73148 configuration : {
74149 kind : 'buildProject' ,
75150 projectFile : PROJECT_FROM_CONFIG ,
151+ args : [ '-d' ] ,
76152 } ,
77153 } ;
78154 const task = new vscode . Task ( def , vscode . TaskScope . Workspace , 'My Task' , 'ada' ) ;
@@ -82,14 +158,28 @@ suite('GPR Tasks Provider', function () {
82158 assert ( resolved . execution ) ;
83159
84160 const exec = resolved . execution as vscode . ShellExecution ;
85- const actualCmd = [ exec . command ] . concat ( exec . args ) . join ( ' ' ) ;
86161
87- const expectedCmd = `gprbuild -P ${ def . configuration . projectFile } "-cargs:ada" -gnatef` ;
162+ const actualCmd = getCmdLine ( exec ) ;
163+
164+ /**
165+ * This task defines the projectFile field as config:ada.projectFile so
166+ * this is reflected as is in the command line. However running this
167+ * task will fail because the workspace doesn't define the
168+ * ada.projectFile setting.
169+ */
170+ const expectedCmd = 'gprbuild -P ${config:ada.projectFile} -d -cargs:ada -gnatef' ;
88171
89172 assert . strictEqual ( actualCmd , expectedCmd ) ;
173+
174+ const status = runTaskAndGetResult ( resolved ) ;
175+ /**
176+ * The task should fail because the ada.projectFile is not set so the
177+ * command line cannot be resolved.
178+ */
179+ assert . notEqual ( status , 0 ) ;
90180 } ) ;
91181
92- test ( 'Resolving task with main ' , async ( ) => {
182+ test ( 'Resolving task buildMain ' , async ( ) => {
93183 const prov = createAdaTaskProvider ( ) ;
94184
95185 const def : CustomTaskDefinition = {
@@ -107,24 +197,26 @@ suite('GPR Tasks Provider', function () {
107197 assert ( resolved . execution ) ;
108198
109199 const exec = resolved . execution as vscode . ShellExecution ;
110- const actualCmd = [ exec . command ] . concat ( exec . args ) . join ( ' ' ) ;
200+ const actualCmd = getCmdLine ( exec ) ;
111201
112- const expectedCmd = `gprbuild -P ${ def . configuration . projectFile } ${
113- def . configuration . main ?? ''
114- } "-cargs:ada" -gnatef`;
202+ assert ( def . configuration . main ) ;
203+ const expectedCmd =
204+ `gprbuild -P \${config:ada.projectFile} ${ def . configuration . main } ` +
205+ `-cargs:ada -gnatef` ;
115206
116207 assert . strictEqual ( actualCmd , expectedCmd ) ;
117208 } ) ;
118209
119- test ( 'Resolving task with run main ' , async ( ) => {
210+ test ( 'Resolving task runMain ' , async ( ) => {
120211 const prov = createAdaTaskProvider ( ) ;
121212
122213 const def : CustomTaskDefinition = {
123214 type : 'ada' ,
124215 configuration : {
125- kind : 'buildAndRunMain ' ,
216+ kind : 'runMain ' ,
126217 projectFile : PROJECT_FROM_CONFIG ,
127218 main : 'src/main1.adb' ,
219+ mainArgs : [ 'arg1' , 'arg2' ] ,
128220 } ,
129221 } ;
130222 const task = new vscode . Task ( def , vscode . TaskScope . Workspace , 'My Task' , 'ada' ) ;
@@ -134,14 +226,84 @@ suite('GPR Tasks Provider', function () {
134226 assert ( resolved . execution ) ;
135227
136228 const exec = resolved . execution as vscode . ShellExecution ;
137- const actualCmd = [ exec . command ] . concat ( exec . args ) . join ( ' ' ) ;
229+ const actualCmd = getCmdLine ( exec ) ;
138230
139231 // Note that the executable is named differently than the source file
140232 // via project attributes
141- const expectedCmd = `gprbuild -P ${ def . configuration . projectFile } ${
142- def . configuration . main ?? ''
143- } "-cargs:ada" -gnatef && obj/main1exec${ process . platform == 'win32' ? '.exe' : '' } `;
233+ assert ( def . configuration . main ) ;
234+ const expectedCmd = `obj/main1exec${ exe } arg1 arg2` ;
144235
145236 assert . strictEqual ( actualCmd , expectedCmd ) ;
146237 } ) ;
238+
239+ test ( 'buildAndRunMain task' , async ( ) => {
240+ const adaTasks = await vscode . tasks . fetchTasks ( { type : 'ada' } ) ;
241+ const task = adaTasks . find ( ( v ) => v . name == 'Build and run main - src/main1.adb' ) ;
242+ assert ( task ) ;
243+
244+ const execStatus : number | undefined = await runTaskAndGetResult ( task ) ;
245+
246+ assert . equal ( execStatus , 0 ) ;
247+ } ) ;
248+
249+ /**
250+ * Test that buildAndRunMain fails when configured with non-existing tasks
251+ */
252+ test ( 'buildAndRunMain failure' , async ( ) => {
253+ const prov = createAdaTaskProvider ( ) ;
254+ let def : CustomTaskDefinition = {
255+ type : 'ada' ,
256+ configuration : {
257+ kind : 'buildAndRunMain' ,
258+ buildTask : 'non existing task' ,
259+ } ,
260+ } ;
261+ let task = new vscode . Task ( def , vscode . TaskScope . Workspace , 'Task 1' , 'ada' ) ;
262+ let resolved = await prov . resolveTask ( task ) ;
263+ assert ( resolved ) ;
264+ /**
265+ * The expected code when errors occur before the invocation of the
266+ * build and run tasks is 2.
267+ */
268+ assert . equal ( await runTaskAndGetResult ( resolved ) , 2 ) ;
269+
270+ def = {
271+ type : 'ada' ,
272+ configuration : {
273+ kind : 'buildAndRunMain' ,
274+ buildTask : 'ada: Build current project' , // Existing build task
275+ runTask : 'non existing task' ,
276+ } ,
277+ } ;
278+ task = new vscode . Task ( def , vscode . TaskScope . Workspace , 'Task 2' , 'ada' ) ;
279+ resolved = await prov . resolveTask ( task ) ;
280+ assert ( resolved ) ;
281+ assert . equal ( await runTaskAndGetResult ( resolved ) , 2 ) ;
282+ } ) ;
147283} ) ;
284+
285+ async function runTaskAndGetResult ( task : vscode . Task ) : Promise < number | undefined > {
286+ return await new Promise ( ( resolve ) => {
287+ const disposable = vscode . tasks . onDidEndTaskProcess ( ( e ) => {
288+ if ( e . execution . task == task ) {
289+ disposable . dispose ( ) ;
290+ resolve ( e . exitCode ) ;
291+ }
292+ } ) ;
293+
294+ void vscode . tasks . executeTask ( task ) ;
295+ } ) ;
296+ }
297+
298+ function getCmdLine ( exec : vscode . ShellExecution ) {
299+ return [ exec . command ]
300+ . concat ( exec . args )
301+ . map ( ( s ) => {
302+ if ( typeof s == 'object' ) {
303+ return s . value ;
304+ } else {
305+ return s ;
306+ }
307+ } )
308+ . join ( ' ' ) ;
309+ }
0 commit comments