@theia/task 1.45.0 → 1.46.0-next.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +193 -193
  2. package/lib/browser/index.d.ts +6 -6
  3. package/lib/browser/index.js +33 -33
  4. package/lib/browser/process/process-task-contribution.d.ts +6 -6
  5. package/lib/browser/process/process-task-contribution.js +43 -43
  6. package/lib/browser/process/process-task-frontend-module.d.ts +2 -2
  7. package/lib/browser/process/process-task-frontend-module.js +27 -27
  8. package/lib/browser/process/process-task-resolver.d.ts +17 -17
  9. package/lib/browser/process/process-task-resolver.js +101 -101
  10. package/lib/browser/provided-task-configurations.d.ts +43 -43
  11. package/lib/browser/provided-task-configurations.js +213 -213
  12. package/lib/browser/provided-task-configurations.spec.d.ts +1 -1
  13. package/lib/browser/provided-task-configurations.spec.js +43 -43
  14. package/lib/browser/quick-open-task.d.ts +144 -144
  15. package/lib/browser/quick-open-task.d.ts.map +1 -1
  16. package/lib/browser/quick-open-task.js +752 -748
  17. package/lib/browser/quick-open-task.js.map +1 -1
  18. package/lib/browser/task-configuration-manager.d.ts +64 -64
  19. package/lib/browser/task-configuration-manager.js +261 -261
  20. package/lib/browser/task-configuration-model.d.ts +32 -32
  21. package/lib/browser/task-configuration-model.js +79 -79
  22. package/lib/browser/task-configurations.d.ts +127 -127
  23. package/lib/browser/task-configurations.js +486 -486
  24. package/lib/browser/task-contribution.d.ts +182 -182
  25. package/lib/browser/task-contribution.js +206 -206
  26. package/lib/browser/task-definition-registry.d.ts +38 -38
  27. package/lib/browser/task-definition-registry.js +134 -134
  28. package/lib/browser/task-definition-registry.spec.d.ts +1 -1
  29. package/lib/browser/task-definition-registry.spec.js +170 -170
  30. package/lib/browser/task-frontend-contribution.d.ts +56 -56
  31. package/lib/browser/task-frontend-contribution.js +358 -358
  32. package/lib/browser/task-frontend-module.d.ts +5 -5
  33. package/lib/browser/task-frontend-module.js +79 -79
  34. package/lib/browser/task-name-resolver.d.ts +13 -13
  35. package/lib/browser/task-name-resolver.js +67 -67
  36. package/lib/browser/task-node.d.ts +9 -9
  37. package/lib/browser/task-node.js +17 -17
  38. package/lib/browser/task-preferences.d.ts +4 -4
  39. package/lib/browser/task-preferences.js +40 -40
  40. package/lib/browser/task-problem-matcher-registry.d.ts +40 -40
  41. package/lib/browser/task-problem-matcher-registry.js +309 -309
  42. package/lib/browser/task-problem-pattern-registry.d.ts +23 -23
  43. package/lib/browser/task-problem-pattern-registry.js +210 -210
  44. package/lib/browser/task-schema-updater.d.ts +58 -58
  45. package/lib/browser/task-schema-updater.js +688 -688
  46. package/lib/browser/task-service.d.ts +279 -279
  47. package/lib/browser/task-service.js +1119 -1119
  48. package/lib/browser/task-source-resolver.d.ts +9 -9
  49. package/lib/browser/task-source-resolver.js +51 -51
  50. package/lib/browser/task-templates.d.ts +13 -13
  51. package/lib/browser/task-templates.js +161 -161
  52. package/lib/browser/task-terminal-widget-manager.d.ts +44 -44
  53. package/lib/browser/task-terminal-widget-manager.js +228 -228
  54. package/lib/browser/tasks-monaco-contribution.d.ts +1 -1
  55. package/lib/browser/tasks-monaco-contribution.js +27 -27
  56. package/lib/common/index.d.ts +4 -4
  57. package/lib/common/index.js +31 -31
  58. package/lib/common/problem-matcher-protocol.d.ts +124 -124
  59. package/lib/common/problem-matcher-protocol.js +132 -132
  60. package/lib/common/process/task-protocol.d.ts +68 -68
  61. package/lib/common/process/task-protocol.js +33 -33
  62. package/lib/common/task-common-module.d.ts +7 -7
  63. package/lib/common/task-common-module.js +33 -33
  64. package/lib/common/task-protocol.d.ts +192 -192
  65. package/lib/common/task-protocol.js +137 -137
  66. package/lib/common/task-util.d.ts +22 -22
  67. package/lib/common/task-util.js +46 -46
  68. package/lib/common/task-watcher.d.ts +17 -17
  69. package/lib/common/task-watcher.js +86 -86
  70. package/lib/node/custom/custom-task-runner-backend-module.d.ts +2 -2
  71. package/lib/node/custom/custom-task-runner-backend-module.js +36 -36
  72. package/lib/node/custom/custom-task-runner-contribution.d.ts +6 -6
  73. package/lib/node/custom/custom-task-runner-contribution.js +42 -42
  74. package/lib/node/custom/custom-task-runner.d.ts +15 -15
  75. package/lib/node/custom/custom-task-runner.js +69 -69
  76. package/lib/node/custom/custom-task.d.ts +20 -20
  77. package/lib/node/custom/custom-task.js +78 -78
  78. package/lib/node/index.d.ts +3 -3
  79. package/lib/node/index.js +30 -30
  80. package/lib/node/process/process-task-runner-backend-module.d.ts +2 -2
  81. package/lib/node/process/process-task-runner-backend-module.js +36 -36
  82. package/lib/node/process/process-task-runner-contribution.d.ts +6 -6
  83. package/lib/node/process/process-task-runner-contribution.js +43 -43
  84. package/lib/node/process/process-task-runner.d.ts +60 -60
  85. package/lib/node/process/process-task-runner.js +355 -355
  86. package/lib/node/process/process-task.d.ts +26 -26
  87. package/lib/node/process/process-task.js +135 -135
  88. package/lib/node/process/process-task.spec.d.ts +1 -1
  89. package/lib/node/process/process-task.spec.js +29 -29
  90. package/lib/node/task-abstract-line-matcher.d.ts +49 -49
  91. package/lib/node/task-abstract-line-matcher.js +273 -273
  92. package/lib/node/task-backend-application-contribution.d.ts +8 -8
  93. package/lib/node/task-backend-application-contribution.js +48 -48
  94. package/lib/node/task-backend-module.d.ts +3 -3
  95. package/lib/node/task-backend-module.js +50 -50
  96. package/lib/node/task-line-matchers.d.ts +27 -27
  97. package/lib/node/task-line-matchers.js +121 -121
  98. package/lib/node/task-manager.d.ts +55 -55
  99. package/lib/node/task-manager.js +135 -135
  100. package/lib/node/task-problem-collector.d.ts +10 -10
  101. package/lib/node/task-problem-collector.js +57 -57
  102. package/lib/node/task-problem-collector.spec.d.ts +1 -1
  103. package/lib/node/task-problem-collector.spec.js +310 -310
  104. package/lib/node/task-runner-protocol.d.ts +16 -16
  105. package/lib/node/task-runner-protocol.js +19 -19
  106. package/lib/node/task-runner.d.ts +50 -50
  107. package/lib/node/task-runner.js +97 -97
  108. package/lib/node/task-server.d.ts +39 -39
  109. package/lib/node/task-server.js +237 -237
  110. package/lib/node/task-server.slow-spec.d.ts +1 -1
  111. package/lib/node/task-server.slow-spec.js +395 -395
  112. package/lib/node/task.d.ts +50 -50
  113. package/lib/node/task.js +77 -77
  114. package/lib/node/test/task-test-container.d.ts +2 -2
  115. package/lib/node/test/task-test-container.js +58 -58
  116. package/package.json +14 -14
  117. package/src/browser/index.ts +22 -22
  118. package/src/browser/process/process-task-contribution.ts +31 -31
  119. package/src/browser/process/process-task-frontend-module.ts +27 -27
  120. package/src/browser/process/process-task-resolver.ts +89 -89
  121. package/src/browser/provided-task-configurations.spec.ts +46 -46
  122. package/src/browser/provided-task-configurations.ts +213 -213
  123. package/src/browser/quick-open-task.ts +831 -827
  124. package/src/browser/style/index.css +19 -19
  125. package/src/browser/task-configuration-manager.ts +256 -256
  126. package/src/browser/task-configuration-model.ts +101 -101
  127. package/src/browser/task-configurations.ts +508 -508
  128. package/src/browser/task-contribution.ts +266 -266
  129. package/src/browser/task-definition-registry.spec.ts +203 -203
  130. package/src/browser/task-definition-registry.ts +131 -131
  131. package/src/browser/task-frontend-contribution.ts +402 -402
  132. package/src/browser/task-frontend-module.ts +86 -86
  133. package/src/browser/task-name-resolver.ts +55 -55
  134. package/src/browser/task-node.ts +37 -37
  135. package/src/browser/task-preferences.ts +40 -40
  136. package/src/browser/task-problem-matcher-registry.ts +308 -308
  137. package/src/browser/task-problem-pattern-registry.ts +196 -196
  138. package/src/browser/task-schema-updater.ts +701 -701
  139. package/src/browser/task-service.ts +1164 -1164
  140. package/src/browser/task-source-resolver.ts +36 -36
  141. package/src/browser/task-templates.ts +168 -168
  142. package/src/browser/task-terminal-widget-manager.ts +224 -224
  143. package/src/browser/tasks-monaco-contribution.ts +27 -27
  144. package/src/common/index.ts +20 -20
  145. package/src/common/problem-matcher-protocol.ts +234 -234
  146. package/src/common/process/task-protocol.ts +97 -97
  147. package/src/common/task-common-module.ts +34 -34
  148. package/src/common/task-protocol.ts +317 -317
  149. package/src/common/task-util.ts +43 -43
  150. package/src/common/task-watcher.ts +78 -78
  151. package/src/node/custom/custom-task-runner-backend-module.ts +37 -37
  152. package/src/node/custom/custom-task-runner-contribution.ts +30 -30
  153. package/src/node/custom/custom-task-runner.ts +60 -60
  154. package/src/node/custom/custom-task.ts +73 -73
  155. package/src/node/index.ts +19 -19
  156. package/src/node/process/process-task-runner-backend-module.ts +37 -37
  157. package/src/node/process/process-task-runner-contribution.ts +31 -31
  158. package/src/node/process/process-task-runner.ts +371 -371
  159. package/src/node/process/process-task.spec.ts +30 -30
  160. package/src/node/process/process-task.ts +144 -144
  161. package/src/node/task-abstract-line-matcher.ts +312 -312
  162. package/src/node/task-backend-application-contribution.ts +36 -36
  163. package/src/node/task-backend-module.ts +57 -57
  164. package/src/node/task-line-matchers.ts +127 -127
  165. package/src/node/task-manager.ts +129 -129
  166. package/src/node/task-problem-collector.spec.ts +338 -338
  167. package/src/node/task-problem-collector.ts +62 -62
  168. package/src/node/task-runner-protocol.ts +33 -33
  169. package/src/node/task-runner.ts +96 -96
  170. package/src/node/task-server.slow-spec.ts +444 -444
  171. package/src/node/task-server.ts +263 -263
  172. package/src/node/task.ts +103 -103
  173. package/src/node/test/task-test-container.ts +63 -63
@@ -1,396 +1,396 @@
1
- "use strict";
2
- // *****************************************************************************
3
- // Copyright (C) 2017-2019 Ericsson and others.
4
- //
5
- // This program and the accompanying materials are made available under the
6
- // terms of the Eclipse Public License v. 2.0 which is available at
7
- // http://www.eclipse.org/legal/epl-2.0.
8
- //
9
- // This Source Code may also be made available under the following Secondary
10
- // Licenses when the conditions for such availability set forth in the Eclipse
11
- // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
- // with the GNU Classpath Exception which is available at
13
- // https://www.gnu.org/software/classpath/license.html.
14
- //
15
- // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
- // *****************************************************************************
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- // tslint:disable-next-line:no-implicit-dependencies
19
- require("reflect-metadata");
20
- const task_test_container_1 = require("./test/task-test-container");
21
- const backend_application_1 = require("@theia/core/lib/node/backend-application");
22
- const common_1 = require("../common");
23
- const os_1 = require("@theia/core/lib/common/os");
24
- const node_1 = require("@theia/core/lib/node");
25
- const terminal_protocol_1 = require("@theia/terminal/lib/common/terminal-protocol");
26
- const expect_1 = require("@theia/core/lib/common/test/expect");
27
- const test_web_socket_channel_1 = require("@theia/core/lib/node/messaging/test/test-web-socket-channel");
28
- const chai_1 = require("chai");
29
- const buffering_stream_1 = require("@theia/terminal/lib/node/buffering-stream");
30
- // test scripts that we bundle with tasks
31
- const commandShortRunning = './task';
32
- const commandShortRunningOsx = './task-osx';
33
- const commandShortRunningWindows = '.\\task.bat';
34
- const commandLongRunning = './task-long-running';
35
- const commandLongRunningOsx = './task-long-running-osx';
36
- const commandLongRunningWindows = '.\\task-long-running.bat';
37
- const bogusCommand = 'thisisnotavalidcommand';
38
- const commandUnixNoop = 'true';
39
- const commandWindowsNoop = 'rundll32.exe';
40
- /** Expects argv to be ['a', 'b', 'c'] */
41
- const script0 = './test-arguments-0.js';
42
- /** Expects argv to be ['a', 'b', ' c'] */
43
- const script1 = './test-arguments-1.js';
44
- /** Expects argv to be ['a', 'b', 'c"'] */
45
- const script2 = './test-arguments-2.js';
46
- // we use test-resources subfolder ('<theia>/packages/task/test-resources/'),
47
- // as workspace root, for these tests
48
- const wsRootUri = node_1.FileUri.create(__dirname).resolve('../../test-resources');
49
- const wsRoot = node_1.FileUri.fsPath(wsRootUri);
50
- describe('Task server / back-end', function () {
51
- this.timeout(10000);
52
- let backend;
53
- let server;
54
- let taskServer;
55
- let taskWatcher;
56
- beforeEach(async () => {
57
- delete process.env['THEIA_TASK_TEST_DEBUG'];
58
- const testContainer = (0, task_test_container_1.createTaskTestContainer)();
59
- taskWatcher = testContainer.get(common_1.TaskWatcher);
60
- taskServer = testContainer.get(common_1.TaskServer);
61
- taskServer.setClient(taskWatcher.getTaskClient());
62
- backend = testContainer.get(backend_application_1.BackendApplication);
63
- server = await backend.start(3000, 'localhost');
64
- });
65
- afterEach(async () => {
66
- const _backend = backend;
67
- const _server = server;
68
- backend = undefined;
69
- taskServer = undefined;
70
- taskWatcher = undefined;
71
- server = undefined;
72
- _backend['onStop']();
73
- _server.close();
74
- });
75
- it('task running in terminal - expected data is received from the terminal ws server', async function () {
76
- const someString = 'someSingleWordString';
77
- // create task using terminal process
78
- const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
79
- const taskInfo = await taskServer.run(createProcessTaskConfig('shell', `${command} ${someString}`), wsRoot);
80
- const terminalId = taskInfo.terminalId;
81
- const messagesToWaitFor = 10;
82
- const messages = [];
83
- // check output of task on terminal is what we expect
84
- const expected = `${os_1.isOSX ? 'tasking osx' : 'tasking'}... ${someString}`;
85
- // hook-up to terminal's ws and confirm that it outputs expected tasks' output
86
- await new Promise((resolve, reject) => {
87
- const setup = new test_web_socket_channel_1.TestWebSocketChannelSetup({ server, path: `${terminal_protocol_1.terminalsPath}/${terminalId}` });
88
- const stringBuffer = new buffering_stream_1.StringBufferingStream();
89
- setup.connectionProvider.listen(`${terminal_protocol_1.terminalsPath}/${terminalId}`, (path, channel) => {
90
- channel.onMessage(e => stringBuffer.push(e().readString()));
91
- channel.onError(reject);
92
- channel.onClose(() => reject(new Error('Channel has been closed')));
93
- }, false);
94
- stringBuffer.onData(currentMessage => {
95
- // Instead of waiting for one message from the terminal, we wait for several ones as the very first message can be something unexpected.
96
- // For instance: `nvm is not compatible with the \"PREFIX\" environment variable: currently set to \"/usr/local\"\r\n`
97
- messages.unshift(currentMessage);
98
- if (currentMessage.includes(expected)) {
99
- resolve();
100
- }
101
- else if (messages.length >= messagesToWaitFor) {
102
- reject(new Error(`expected sub-string not found in terminal output. Expected: "${expected}" vs Actual messages: ${JSON.stringify(messages)}`));
103
- }
104
- });
105
- });
106
- });
107
- it('task using raw process - task server success response shall not contain a terminal id', async function () {
108
- const someString = 'someSingleWordString';
109
- const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
110
- const executable = node_1.FileUri.fsPath(wsRootUri.resolve(command));
111
- // create task using raw process
112
- const taskInfo = await taskServer.run(createProcessTaskConfig('process', executable, [someString]), wsRoot);
113
- await new Promise((resolve, reject) => {
114
- const toDispose = taskWatcher.onTaskExit((event) => {
115
- if (event.taskId === taskInfo.taskId && event.code === 0) {
116
- if (typeof taskInfo.terminalId === 'number') {
117
- resolve();
118
- }
119
- else {
120
- reject(new Error(`terminal id was expected to be a number, got: ${typeof taskInfo.terminalId}`));
121
- }
122
- toDispose.dispose();
123
- }
124
- });
125
- });
126
- });
127
- it('task is executed successfully with cwd as a file URI', async function () {
128
- const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
129
- const config = createProcessTaskConfig('shell', command, undefined, node_1.FileUri.create(wsRoot).toString());
130
- const taskInfo = await taskServer.run(config, wsRoot);
131
- await checkSuccessfulProcessExit(taskInfo, taskWatcher);
132
- });
133
- it('task is executed successfully using terminal process', async function () {
134
- const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
135
- const taskInfo = await taskServer.run(createProcessTaskConfig('shell', command, undefined), wsRoot);
136
- await checkSuccessfulProcessExit(taskInfo, taskWatcher);
137
- });
138
- it('task is executed successfully using raw process', async function () {
139
- const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
140
- const executable = node_1.FileUri.fsPath(wsRootUri.resolve(command));
141
- const taskInfo = await taskServer.run(createProcessTaskConfig('process', executable, []));
142
- await checkSuccessfulProcessExit(taskInfo, taskWatcher);
143
- });
144
- it('task without a specific runner is executed successfully using as a process', async function () {
145
- const command = os_1.isWindows ? commandWindowsNoop : commandUnixNoop;
146
- // there's no runner registered for the 'npm' task type
147
- const taskConfig = createTaskConfig('npm', command, []);
148
- const taskInfo = await taskServer.run(taskConfig, wsRoot);
149
- await checkSuccessfulProcessExit(taskInfo, taskWatcher);
150
- });
151
- it('task can successfully execute command found in system path using a terminal process', async function () {
152
- const command = os_1.isWindows ? commandWindowsNoop : commandUnixNoop;
153
- const opts = createProcessTaskConfig('shell', command, []);
154
- const taskInfo = await taskServer.run(opts, wsRoot);
155
- await checkSuccessfulProcessExit(taskInfo, taskWatcher);
156
- });
157
- it('task can successfully execute command found in system path using a raw process', async function () {
158
- const command = os_1.isWindows ? commandWindowsNoop : commandUnixNoop;
159
- const taskInfo = await taskServer.run(createProcessTaskConfig('process', command, []), wsRoot);
160
- await checkSuccessfulProcessExit(taskInfo, taskWatcher);
161
- });
162
- it('task using type "shell" can be killed', async function () {
163
- const taskInfo = await taskServer.run(createTaskConfigTaskLongRunning('shell'), wsRoot);
164
- const exitStatusPromise = getExitStatus(taskInfo, taskWatcher);
165
- taskServer.kill(taskInfo.taskId);
166
- const exitStatus = await exitStatusPromise;
167
- // node-pty reports different things on Linux/macOS vs Windows when
168
- // killing a process. This is not ideal, but that's how things are
169
- // currently. Ideally, its behavior should be aligned as much as
170
- // possible on what node's child_process module does.
171
- if (os_1.isWindows) {
172
- // On Windows, node-pty just reports an exit code of 0.
173
- (0, chai_1.expect)(exitStatus).equals(0);
174
- }
175
- else {
176
- // On Linux/macOS, node-pty sends SIGHUP by default, for some reason.
177
- (0, chai_1.expect)(exitStatus).equals('SIGHUP');
178
- }
179
- });
180
- it('task using type "process" can be killed', async function () {
181
- const taskInfo = await taskServer.run(createTaskConfigTaskLongRunning('process'), wsRoot);
182
- const exitStatusPromise = getExitStatus(taskInfo, taskWatcher);
183
- taskServer.kill(taskInfo.taskId);
184
- const exitStatus = await exitStatusPromise;
185
- // node-pty reports different things on Linux/macOS vs Windows when
186
- // killing a process. This is not ideal, but that's how things are
187
- // currently. Ideally, its behavior should be aligned as much as
188
- // possible on what node's child_process module does.
189
- if (os_1.isWindows) {
190
- // On Windows, node-pty just reports an exit code of 0.
191
- (0, chai_1.expect)(exitStatus).equals(0);
192
- }
193
- else {
194
- // On Linux/macOS, node-pty sends SIGHUP by default, for some reason.
195
- (0, chai_1.expect)(exitStatus).equals('SIGHUP');
196
- }
197
- });
198
- /**
199
- * TODO: Figure out how to debug a process that correctly starts but exits with a return code > 0
200
- */
201
- it('task using terminal process can handle command that does not exist', async function () {
202
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', bogusCommand, []), wsRoot);
203
- const code = await new Promise((resolve, reject) => {
204
- taskWatcher.onTaskExit((event) => {
205
- if (event.taskId !== taskInfo.taskId || event.code === undefined) {
206
- reject(new Error(JSON.stringify(event)));
207
- }
208
- else {
209
- resolve(event.code);
210
- }
211
- });
212
- });
213
- // node-pty reports different things on Linux/macOS vs Windows when
214
- // killing a process. This is not ideal, but that's how things are
215
- // currently. Ideally, its behavior should be aligned as much as
216
- // possible on what node's child_process module does.
217
- if (os_1.isWindows) {
218
- (0, chai_1.expect)(code).equals(1);
219
- }
220
- else {
221
- (0, chai_1.expect)(code).equals(127);
222
- }
223
- });
224
- it('task using raw process can handle command that does not exist', async function () {
225
- const p = taskServer.run(createProcessTaskConfig2('process', bogusCommand, []), wsRoot);
226
- await (0, expect_1.expectThrowsAsync)(p, 'ENOENT');
227
- });
228
- it('getTasks(ctx) returns tasks according to created context', async function () {
229
- const context1 = 'aContext';
230
- const context2 = 'anotherContext';
231
- // create some tasks: 4 for context1, 2 for context2
232
- const task1 = await taskServer.run(createTaskConfigTaskLongRunning('shell'), context1);
233
- const task2 = await taskServer.run(createTaskConfigTaskLongRunning('process'), context2);
234
- const task3 = await taskServer.run(createTaskConfigTaskLongRunning('shell'), context1);
235
- const task4 = await taskServer.run(createTaskConfigTaskLongRunning('process'), context2);
236
- const task5 = await taskServer.run(createTaskConfigTaskLongRunning('shell'), context1);
237
- const task6 = await taskServer.run(createTaskConfigTaskLongRunning('process'), context1);
238
- const runningTasksCtx1 = await taskServer.getTasks(context1); // should return 4 tasks
239
- const runningTasksCtx2 = await taskServer.getTasks(context2); // should return 2 tasks
240
- const runningTasksAll = await taskServer.getTasks(); // should return 6 tasks
241
- if (runningTasksCtx1.length !== 4) {
242
- throw new Error(`Error: unexpected number of running tasks for context 1: expected: 4, actual: ${runningTasksCtx1.length}`);
243
- }
244
- if (runningTasksCtx2.length !== 2) {
245
- throw new Error(`Error: unexpected number of running tasks for context 2: expected: 2, actual: ${runningTasksCtx1.length}`);
246
- }
247
- if (runningTasksAll.length !== 6) {
248
- throw new Error(`Error: unexpected total number of running tasks for all contexts: expected: 6, actual: ${runningTasksCtx1.length}`);
249
- }
250
- // cleanup
251
- await taskServer.kill(task1.taskId);
252
- await taskServer.kill(task2.taskId);
253
- await taskServer.kill(task3.taskId);
254
- await taskServer.kill(task4.taskId);
255
- await taskServer.kill(task5.taskId);
256
- await taskServer.kill(task6.taskId);
257
- });
258
- it('creating and killing a bunch of tasks works as expected', async function () {
259
- // const command = isWindows ? command_absolute_path_long_running_windows : command_absolute_path_long_running;
260
- const numTasks = 20;
261
- const taskInfo = [];
262
- // create a mix of terminal and raw processes
263
- for (let i = 0; i < numTasks; i++) {
264
- if (i % 2 === 0) {
265
- taskInfo.push(await taskServer.run(createTaskConfigTaskLongRunning('shell')));
266
- }
267
- else {
268
- taskInfo.push(await taskServer.run(createTaskConfigTaskLongRunning('process')));
269
- }
270
- }
271
- const numRunningTasksAfterCreated = await taskServer.getTasks();
272
- for (let i = 0; i < taskInfo.length; i++) {
273
- await taskServer.kill(taskInfo[i].taskId);
274
- }
275
- const numRunningTasksAfterKilled = await taskServer.getTasks();
276
- if (numRunningTasksAfterCreated.length !== numTasks) {
277
- throw new Error(`Error: unexpected number of running tasks: expected: ${numTasks}, actual: ${numRunningTasksAfterCreated.length}`);
278
- }
279
- if (numRunningTasksAfterKilled.length !== 0) {
280
- throw new Error(`Error: remaining running tasks, after all killed: expected: 0, actual: ${numRunningTasksAfterKilled.length}`);
281
- }
282
- });
283
- it('shell task should execute the command as a whole if not arguments are specified', async function () {
284
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', `node ${script0} debug-hint:0a a b c`));
285
- const exitStatus = await getExitStatus(taskInfo, taskWatcher);
286
- (0, chai_1.expect)(exitStatus).eq(0);
287
- });
288
- it('shell task should fail if user defines a full command line and arguments', async function () {
289
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', `node ${script0} debug-hint:0b a b c`, []));
290
- const exitStatus = await getExitStatus(taskInfo, taskWatcher);
291
- (0, chai_1.expect)(exitStatus).not.eq(0);
292
- });
293
- it('shell task should be able to exec using simple arguments', async function () {
294
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script0, 'debug-hint:0c', 'a', 'b', 'c']));
295
- const exitStatus = await getExitStatus(taskInfo, taskWatcher);
296
- (0, chai_1.expect)(exitStatus).eq(0);
297
- });
298
- it('shell task should be able to run using arguments containing whitespace', async function () {
299
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script1, 'debug-hint:1', 'a', 'b', ' c']));
300
- const exitStatus = await getExitStatus(taskInfo, taskWatcher);
301
- (0, chai_1.expect)(exitStatus).eq(0);
302
- });
303
- it('shell task will fail if user specify problematic arguments', async function () {
304
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script2, 'debug-hint:2a', 'a', 'b', 'c"']));
305
- const exitStatus = await getExitStatus(taskInfo, taskWatcher);
306
- (0, chai_1.expect)(exitStatus).not.eq(0);
307
- });
308
- it('shell task should be able to run using arguments specifying which quoting method to use', async function () {
309
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script2, 'debug-hint:2b', 'a', 'b', { value: 'c"', quoting: 'escape' }]));
310
- const exitStatus = await getExitStatus(taskInfo, taskWatcher);
311
- (0, chai_1.expect)(exitStatus).eq(0);
312
- });
313
- it('shell task should be able to run using arguments with forbidden characters but no whitespace', async function () {
314
- const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', ['-e', 'setTimeout(console.log,1000,1+2)']));
315
- const exitStatus = await getExitStatus(taskInfo, taskWatcher);
316
- (0, chai_1.expect)(exitStatus).eq(0);
317
- });
318
- });
319
- function createTaskConfig(taskType, command, args) {
320
- const options = {
321
- label: 'test task',
322
- type: taskType,
323
- _source: '/source/folder',
324
- _scope: '/source/folder',
325
- command,
326
- args,
327
- options: { cwd: wsRoot }
328
- };
329
- return options;
330
- }
331
- function createProcessTaskConfig(processType, command, args, cwd = wsRoot) {
332
- return {
333
- label: 'test task',
334
- type: processType,
335
- _source: '/source/folder',
336
- _scope: '/source/folder',
337
- command,
338
- args,
339
- options: { cwd },
340
- };
341
- }
342
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
343
- function createProcessTaskConfig2(processType, command, args) {
344
- return {
345
- label: 'test task',
346
- type: processType,
347
- command,
348
- args,
349
- options: { cwd: wsRoot },
350
- };
351
- }
352
- function createTaskConfigTaskLongRunning(processType) {
353
- return {
354
- label: '[Task] long running test task (~300s)',
355
- type: processType,
356
- _source: '/source/folder',
357
- _scope: '/source/folder',
358
- options: { cwd: wsRoot },
359
- command: commandLongRunning,
360
- windows: {
361
- command: node_1.FileUri.fsPath(wsRootUri.resolve(commandLongRunningWindows)),
362
- options: { cwd: wsRoot }
363
- },
364
- osx: {
365
- command: node_1.FileUri.fsPath(wsRootUri.resolve(commandLongRunningOsx))
366
- }
367
- };
368
- }
369
- function checkSuccessfulProcessExit(taskInfo, taskWatcher) {
370
- return new Promise((resolve, reject) => {
371
- const toDispose = taskWatcher.onTaskExit((event) => {
372
- if (event.taskId === taskInfo.taskId && event.code === 0) {
373
- toDispose.dispose();
374
- resolve();
375
- }
376
- });
377
- });
378
- }
379
- function getExitStatus(taskInfo, taskWatcher) {
380
- return new Promise((resolve, reject) => {
381
- taskWatcher.onTaskExit((event) => {
382
- if (event.taskId === taskInfo.taskId) {
383
- if (typeof event.signal === 'string') {
384
- resolve(event.signal);
385
- }
386
- else if (typeof event.code === 'number') {
387
- resolve(event.code);
388
- }
389
- else {
390
- reject(new Error('no code nor signal'));
391
- }
392
- }
393
- });
394
- });
395
- }
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2017-2019 Ericsson and others.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ // tslint:disable-next-line:no-implicit-dependencies
19
+ require("reflect-metadata");
20
+ const task_test_container_1 = require("./test/task-test-container");
21
+ const backend_application_1 = require("@theia/core/lib/node/backend-application");
22
+ const common_1 = require("../common");
23
+ const os_1 = require("@theia/core/lib/common/os");
24
+ const node_1 = require("@theia/core/lib/node");
25
+ const terminal_protocol_1 = require("@theia/terminal/lib/common/terminal-protocol");
26
+ const expect_1 = require("@theia/core/lib/common/test/expect");
27
+ const test_web_socket_channel_1 = require("@theia/core/lib/node/messaging/test/test-web-socket-channel");
28
+ const chai_1 = require("chai");
29
+ const buffering_stream_1 = require("@theia/terminal/lib/node/buffering-stream");
30
+ // test scripts that we bundle with tasks
31
+ const commandShortRunning = './task';
32
+ const commandShortRunningOsx = './task-osx';
33
+ const commandShortRunningWindows = '.\\task.bat';
34
+ const commandLongRunning = './task-long-running';
35
+ const commandLongRunningOsx = './task-long-running-osx';
36
+ const commandLongRunningWindows = '.\\task-long-running.bat';
37
+ const bogusCommand = 'thisisnotavalidcommand';
38
+ const commandUnixNoop = 'true';
39
+ const commandWindowsNoop = 'rundll32.exe';
40
+ /** Expects argv to be ['a', 'b', 'c'] */
41
+ const script0 = './test-arguments-0.js';
42
+ /** Expects argv to be ['a', 'b', ' c'] */
43
+ const script1 = './test-arguments-1.js';
44
+ /** Expects argv to be ['a', 'b', 'c"'] */
45
+ const script2 = './test-arguments-2.js';
46
+ // we use test-resources subfolder ('<theia>/packages/task/test-resources/'),
47
+ // as workspace root, for these tests
48
+ const wsRootUri = node_1.FileUri.create(__dirname).resolve('../../test-resources');
49
+ const wsRoot = node_1.FileUri.fsPath(wsRootUri);
50
+ describe('Task server / back-end', function () {
51
+ this.timeout(10000);
52
+ let backend;
53
+ let server;
54
+ let taskServer;
55
+ let taskWatcher;
56
+ beforeEach(async () => {
57
+ delete process.env['THEIA_TASK_TEST_DEBUG'];
58
+ const testContainer = (0, task_test_container_1.createTaskTestContainer)();
59
+ taskWatcher = testContainer.get(common_1.TaskWatcher);
60
+ taskServer = testContainer.get(common_1.TaskServer);
61
+ taskServer.setClient(taskWatcher.getTaskClient());
62
+ backend = testContainer.get(backend_application_1.BackendApplication);
63
+ server = await backend.start(3000, 'localhost');
64
+ });
65
+ afterEach(async () => {
66
+ const _backend = backend;
67
+ const _server = server;
68
+ backend = undefined;
69
+ taskServer = undefined;
70
+ taskWatcher = undefined;
71
+ server = undefined;
72
+ _backend['onStop']();
73
+ _server.close();
74
+ });
75
+ it('task running in terminal - expected data is received from the terminal ws server', async function () {
76
+ const someString = 'someSingleWordString';
77
+ // create task using terminal process
78
+ const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
79
+ const taskInfo = await taskServer.run(createProcessTaskConfig('shell', `${command} ${someString}`), wsRoot);
80
+ const terminalId = taskInfo.terminalId;
81
+ const messagesToWaitFor = 10;
82
+ const messages = [];
83
+ // check output of task on terminal is what we expect
84
+ const expected = `${os_1.isOSX ? 'tasking osx' : 'tasking'}... ${someString}`;
85
+ // hook-up to terminal's ws and confirm that it outputs expected tasks' output
86
+ await new Promise((resolve, reject) => {
87
+ const setup = new test_web_socket_channel_1.TestWebSocketChannelSetup({ server, path: `${terminal_protocol_1.terminalsPath}/${terminalId}` });
88
+ const stringBuffer = new buffering_stream_1.StringBufferingStream();
89
+ setup.connectionProvider.listen(`${terminal_protocol_1.terminalsPath}/${terminalId}`, (path, channel) => {
90
+ channel.onMessage(e => stringBuffer.push(e().readString()));
91
+ channel.onError(reject);
92
+ channel.onClose(() => reject(new Error('Channel has been closed')));
93
+ }, false);
94
+ stringBuffer.onData(currentMessage => {
95
+ // Instead of waiting for one message from the terminal, we wait for several ones as the very first message can be something unexpected.
96
+ // For instance: `nvm is not compatible with the \"PREFIX\" environment variable: currently set to \"/usr/local\"\r\n`
97
+ messages.unshift(currentMessage);
98
+ if (currentMessage.includes(expected)) {
99
+ resolve();
100
+ }
101
+ else if (messages.length >= messagesToWaitFor) {
102
+ reject(new Error(`expected sub-string not found in terminal output. Expected: "${expected}" vs Actual messages: ${JSON.stringify(messages)}`));
103
+ }
104
+ });
105
+ });
106
+ });
107
+ it('task using raw process - task server success response shall not contain a terminal id', async function () {
108
+ const someString = 'someSingleWordString';
109
+ const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
110
+ const executable = node_1.FileUri.fsPath(wsRootUri.resolve(command));
111
+ // create task using raw process
112
+ const taskInfo = await taskServer.run(createProcessTaskConfig('process', executable, [someString]), wsRoot);
113
+ await new Promise((resolve, reject) => {
114
+ const toDispose = taskWatcher.onTaskExit((event) => {
115
+ if (event.taskId === taskInfo.taskId && event.code === 0) {
116
+ if (typeof taskInfo.terminalId === 'number') {
117
+ resolve();
118
+ }
119
+ else {
120
+ reject(new Error(`terminal id was expected to be a number, got: ${typeof taskInfo.terminalId}`));
121
+ }
122
+ toDispose.dispose();
123
+ }
124
+ });
125
+ });
126
+ });
127
+ it('task is executed successfully with cwd as a file URI', async function () {
128
+ const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
129
+ const config = createProcessTaskConfig('shell', command, undefined, node_1.FileUri.create(wsRoot).toString());
130
+ const taskInfo = await taskServer.run(config, wsRoot);
131
+ await checkSuccessfulProcessExit(taskInfo, taskWatcher);
132
+ });
133
+ it('task is executed successfully using terminal process', async function () {
134
+ const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
135
+ const taskInfo = await taskServer.run(createProcessTaskConfig('shell', command, undefined), wsRoot);
136
+ await checkSuccessfulProcessExit(taskInfo, taskWatcher);
137
+ });
138
+ it('task is executed successfully using raw process', async function () {
139
+ const command = os_1.isWindows ? commandShortRunningWindows : (os_1.isOSX ? commandShortRunningOsx : commandShortRunning);
140
+ const executable = node_1.FileUri.fsPath(wsRootUri.resolve(command));
141
+ const taskInfo = await taskServer.run(createProcessTaskConfig('process', executable, []));
142
+ await checkSuccessfulProcessExit(taskInfo, taskWatcher);
143
+ });
144
+ it('task without a specific runner is executed successfully using as a process', async function () {
145
+ const command = os_1.isWindows ? commandWindowsNoop : commandUnixNoop;
146
+ // there's no runner registered for the 'npm' task type
147
+ const taskConfig = createTaskConfig('npm', command, []);
148
+ const taskInfo = await taskServer.run(taskConfig, wsRoot);
149
+ await checkSuccessfulProcessExit(taskInfo, taskWatcher);
150
+ });
151
+ it('task can successfully execute command found in system path using a terminal process', async function () {
152
+ const command = os_1.isWindows ? commandWindowsNoop : commandUnixNoop;
153
+ const opts = createProcessTaskConfig('shell', command, []);
154
+ const taskInfo = await taskServer.run(opts, wsRoot);
155
+ await checkSuccessfulProcessExit(taskInfo, taskWatcher);
156
+ });
157
+ it('task can successfully execute command found in system path using a raw process', async function () {
158
+ const command = os_1.isWindows ? commandWindowsNoop : commandUnixNoop;
159
+ const taskInfo = await taskServer.run(createProcessTaskConfig('process', command, []), wsRoot);
160
+ await checkSuccessfulProcessExit(taskInfo, taskWatcher);
161
+ });
162
+ it('task using type "shell" can be killed', async function () {
163
+ const taskInfo = await taskServer.run(createTaskConfigTaskLongRunning('shell'), wsRoot);
164
+ const exitStatusPromise = getExitStatus(taskInfo, taskWatcher);
165
+ taskServer.kill(taskInfo.taskId);
166
+ const exitStatus = await exitStatusPromise;
167
+ // node-pty reports different things on Linux/macOS vs Windows when
168
+ // killing a process. This is not ideal, but that's how things are
169
+ // currently. Ideally, its behavior should be aligned as much as
170
+ // possible on what node's child_process module does.
171
+ if (os_1.isWindows) {
172
+ // On Windows, node-pty just reports an exit code of 0.
173
+ (0, chai_1.expect)(exitStatus).equals(0);
174
+ }
175
+ else {
176
+ // On Linux/macOS, node-pty sends SIGHUP by default, for some reason.
177
+ (0, chai_1.expect)(exitStatus).equals('SIGHUP');
178
+ }
179
+ });
180
+ it('task using type "process" can be killed', async function () {
181
+ const taskInfo = await taskServer.run(createTaskConfigTaskLongRunning('process'), wsRoot);
182
+ const exitStatusPromise = getExitStatus(taskInfo, taskWatcher);
183
+ taskServer.kill(taskInfo.taskId);
184
+ const exitStatus = await exitStatusPromise;
185
+ // node-pty reports different things on Linux/macOS vs Windows when
186
+ // killing a process. This is not ideal, but that's how things are
187
+ // currently. Ideally, its behavior should be aligned as much as
188
+ // possible on what node's child_process module does.
189
+ if (os_1.isWindows) {
190
+ // On Windows, node-pty just reports an exit code of 0.
191
+ (0, chai_1.expect)(exitStatus).equals(0);
192
+ }
193
+ else {
194
+ // On Linux/macOS, node-pty sends SIGHUP by default, for some reason.
195
+ (0, chai_1.expect)(exitStatus).equals('SIGHUP');
196
+ }
197
+ });
198
+ /**
199
+ * TODO: Figure out how to debug a process that correctly starts but exits with a return code > 0
200
+ */
201
+ it('task using terminal process can handle command that does not exist', async function () {
202
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', bogusCommand, []), wsRoot);
203
+ const code = await new Promise((resolve, reject) => {
204
+ taskWatcher.onTaskExit((event) => {
205
+ if (event.taskId !== taskInfo.taskId || event.code === undefined) {
206
+ reject(new Error(JSON.stringify(event)));
207
+ }
208
+ else {
209
+ resolve(event.code);
210
+ }
211
+ });
212
+ });
213
+ // node-pty reports different things on Linux/macOS vs Windows when
214
+ // killing a process. This is not ideal, but that's how things are
215
+ // currently. Ideally, its behavior should be aligned as much as
216
+ // possible on what node's child_process module does.
217
+ if (os_1.isWindows) {
218
+ (0, chai_1.expect)(code).equals(1);
219
+ }
220
+ else {
221
+ (0, chai_1.expect)(code).equals(127);
222
+ }
223
+ });
224
+ it('task using raw process can handle command that does not exist', async function () {
225
+ const p = taskServer.run(createProcessTaskConfig2('process', bogusCommand, []), wsRoot);
226
+ await (0, expect_1.expectThrowsAsync)(p, 'ENOENT');
227
+ });
228
+ it('getTasks(ctx) returns tasks according to created context', async function () {
229
+ const context1 = 'aContext';
230
+ const context2 = 'anotherContext';
231
+ // create some tasks: 4 for context1, 2 for context2
232
+ const task1 = await taskServer.run(createTaskConfigTaskLongRunning('shell'), context1);
233
+ const task2 = await taskServer.run(createTaskConfigTaskLongRunning('process'), context2);
234
+ const task3 = await taskServer.run(createTaskConfigTaskLongRunning('shell'), context1);
235
+ const task4 = await taskServer.run(createTaskConfigTaskLongRunning('process'), context2);
236
+ const task5 = await taskServer.run(createTaskConfigTaskLongRunning('shell'), context1);
237
+ const task6 = await taskServer.run(createTaskConfigTaskLongRunning('process'), context1);
238
+ const runningTasksCtx1 = await taskServer.getTasks(context1); // should return 4 tasks
239
+ const runningTasksCtx2 = await taskServer.getTasks(context2); // should return 2 tasks
240
+ const runningTasksAll = await taskServer.getTasks(); // should return 6 tasks
241
+ if (runningTasksCtx1.length !== 4) {
242
+ throw new Error(`Error: unexpected number of running tasks for context 1: expected: 4, actual: ${runningTasksCtx1.length}`);
243
+ }
244
+ if (runningTasksCtx2.length !== 2) {
245
+ throw new Error(`Error: unexpected number of running tasks for context 2: expected: 2, actual: ${runningTasksCtx1.length}`);
246
+ }
247
+ if (runningTasksAll.length !== 6) {
248
+ throw new Error(`Error: unexpected total number of running tasks for all contexts: expected: 6, actual: ${runningTasksCtx1.length}`);
249
+ }
250
+ // cleanup
251
+ await taskServer.kill(task1.taskId);
252
+ await taskServer.kill(task2.taskId);
253
+ await taskServer.kill(task3.taskId);
254
+ await taskServer.kill(task4.taskId);
255
+ await taskServer.kill(task5.taskId);
256
+ await taskServer.kill(task6.taskId);
257
+ });
258
+ it('creating and killing a bunch of tasks works as expected', async function () {
259
+ // const command = isWindows ? command_absolute_path_long_running_windows : command_absolute_path_long_running;
260
+ const numTasks = 20;
261
+ const taskInfo = [];
262
+ // create a mix of terminal and raw processes
263
+ for (let i = 0; i < numTasks; i++) {
264
+ if (i % 2 === 0) {
265
+ taskInfo.push(await taskServer.run(createTaskConfigTaskLongRunning('shell')));
266
+ }
267
+ else {
268
+ taskInfo.push(await taskServer.run(createTaskConfigTaskLongRunning('process')));
269
+ }
270
+ }
271
+ const numRunningTasksAfterCreated = await taskServer.getTasks();
272
+ for (let i = 0; i < taskInfo.length; i++) {
273
+ await taskServer.kill(taskInfo[i].taskId);
274
+ }
275
+ const numRunningTasksAfterKilled = await taskServer.getTasks();
276
+ if (numRunningTasksAfterCreated.length !== numTasks) {
277
+ throw new Error(`Error: unexpected number of running tasks: expected: ${numTasks}, actual: ${numRunningTasksAfterCreated.length}`);
278
+ }
279
+ if (numRunningTasksAfterKilled.length !== 0) {
280
+ throw new Error(`Error: remaining running tasks, after all killed: expected: 0, actual: ${numRunningTasksAfterKilled.length}`);
281
+ }
282
+ });
283
+ it('shell task should execute the command as a whole if not arguments are specified', async function () {
284
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', `node ${script0} debug-hint:0a a b c`));
285
+ const exitStatus = await getExitStatus(taskInfo, taskWatcher);
286
+ (0, chai_1.expect)(exitStatus).eq(0);
287
+ });
288
+ it('shell task should fail if user defines a full command line and arguments', async function () {
289
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', `node ${script0} debug-hint:0b a b c`, []));
290
+ const exitStatus = await getExitStatus(taskInfo, taskWatcher);
291
+ (0, chai_1.expect)(exitStatus).not.eq(0);
292
+ });
293
+ it('shell task should be able to exec using simple arguments', async function () {
294
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script0, 'debug-hint:0c', 'a', 'b', 'c']));
295
+ const exitStatus = await getExitStatus(taskInfo, taskWatcher);
296
+ (0, chai_1.expect)(exitStatus).eq(0);
297
+ });
298
+ it('shell task should be able to run using arguments containing whitespace', async function () {
299
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script1, 'debug-hint:1', 'a', 'b', ' c']));
300
+ const exitStatus = await getExitStatus(taskInfo, taskWatcher);
301
+ (0, chai_1.expect)(exitStatus).eq(0);
302
+ });
303
+ it('shell task will fail if user specify problematic arguments', async function () {
304
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script2, 'debug-hint:2a', 'a', 'b', 'c"']));
305
+ const exitStatus = await getExitStatus(taskInfo, taskWatcher);
306
+ (0, chai_1.expect)(exitStatus).not.eq(0);
307
+ });
308
+ it('shell task should be able to run using arguments specifying which quoting method to use', async function () {
309
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', [script2, 'debug-hint:2b', 'a', 'b', { value: 'c"', quoting: 'escape' }]));
310
+ const exitStatus = await getExitStatus(taskInfo, taskWatcher);
311
+ (0, chai_1.expect)(exitStatus).eq(0);
312
+ });
313
+ it('shell task should be able to run using arguments with forbidden characters but no whitespace', async function () {
314
+ const taskInfo = await taskServer.run(createProcessTaskConfig2('shell', 'node', ['-e', 'setTimeout(console.log,1000,1+2)']));
315
+ const exitStatus = await getExitStatus(taskInfo, taskWatcher);
316
+ (0, chai_1.expect)(exitStatus).eq(0);
317
+ });
318
+ });
319
+ function createTaskConfig(taskType, command, args) {
320
+ const options = {
321
+ label: 'test task',
322
+ type: taskType,
323
+ _source: '/source/folder',
324
+ _scope: '/source/folder',
325
+ command,
326
+ args,
327
+ options: { cwd: wsRoot }
328
+ };
329
+ return options;
330
+ }
331
+ function createProcessTaskConfig(processType, command, args, cwd = wsRoot) {
332
+ return {
333
+ label: 'test task',
334
+ type: processType,
335
+ _source: '/source/folder',
336
+ _scope: '/source/folder',
337
+ command,
338
+ args,
339
+ options: { cwd },
340
+ };
341
+ }
342
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
343
+ function createProcessTaskConfig2(processType, command, args) {
344
+ return {
345
+ label: 'test task',
346
+ type: processType,
347
+ command,
348
+ args,
349
+ options: { cwd: wsRoot },
350
+ };
351
+ }
352
+ function createTaskConfigTaskLongRunning(processType) {
353
+ return {
354
+ label: '[Task] long running test task (~300s)',
355
+ type: processType,
356
+ _source: '/source/folder',
357
+ _scope: '/source/folder',
358
+ options: { cwd: wsRoot },
359
+ command: commandLongRunning,
360
+ windows: {
361
+ command: node_1.FileUri.fsPath(wsRootUri.resolve(commandLongRunningWindows)),
362
+ options: { cwd: wsRoot }
363
+ },
364
+ osx: {
365
+ command: node_1.FileUri.fsPath(wsRootUri.resolve(commandLongRunningOsx))
366
+ }
367
+ };
368
+ }
369
+ function checkSuccessfulProcessExit(taskInfo, taskWatcher) {
370
+ return new Promise((resolve, reject) => {
371
+ const toDispose = taskWatcher.onTaskExit((event) => {
372
+ if (event.taskId === taskInfo.taskId && event.code === 0) {
373
+ toDispose.dispose();
374
+ resolve();
375
+ }
376
+ });
377
+ });
378
+ }
379
+ function getExitStatus(taskInfo, taskWatcher) {
380
+ return new Promise((resolve, reject) => {
381
+ taskWatcher.onTaskExit((event) => {
382
+ if (event.taskId === taskInfo.taskId) {
383
+ if (typeof event.signal === 'string') {
384
+ resolve(event.signal);
385
+ }
386
+ else if (typeof event.code === 'number') {
387
+ resolve(event.code);
388
+ }
389
+ else {
390
+ reject(new Error('no code nor signal'));
391
+ }
392
+ }
393
+ });
394
+ });
395
+ }
396
396
  //# sourceMappingURL=task-server.slow-spec.js.map