test/integration/goDebug: make invalid flag test faster

This test is to check if the debugging session fails
somehow if an invalid dlv flag is passed.
Previously, this test relied on the timeout of dap server
start. (See spawnDlvDapServerProcess and its use of
30_000msec timeout) That was why this test always took
30sec to complete.

This CL changes the test to wait for the output message
that includes the usage error information, instead of
waiting for the timeout.

I think we can also improve spawnDlvDapServerProcess
to fail sooner when dlv server start up failure is observed
instead of relaying on the timeout. However, the start up
logic is complex enough. I am reluctant to add more
complexity to optimize for this less common failure case.

Change-Id: I16069dc1c6879ce137b7799366e36e429500ea53
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/418899
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/test/integration/goDebug.test.ts b/test/integration/goDebug.test.ts
index 4fcd372..24c3ecd 100644
--- a/test/integration/goDebug.test.ts
+++ b/test/integration/goDebug.test.ts
@@ -511,6 +511,24 @@
 	}
 
 	/**
+	 * Helper function to create a promise that's resolved when
+	 * output event with any of the provided strings is observed.
+	 */
+	async function waitForOutputMessage(dc: DebugClient, ...patterns: string[]): Promise<DebugProtocol.Event> {
+		return await new Promise<DebugProtocol.Event>((resolve, reject) => {
+			dc.on('output', (event) => {
+				for (const pattern of patterns) {
+					if (event.body.output.includes(pattern)) {
+						// Resolve when we have found the event that we want.
+						resolve(event);
+						return;
+					}
+				}
+			});
+		});
+	}
+
+	/**
 	 * Helper function to assert that a variable has a particular value.
 	 * This should be called when the program is stopped.
 	 *
@@ -775,7 +793,6 @@
 				this.skip(); // not working in dlv-dap.
 			}
 
-			// TODO(hyangah): why does it take 30sec?
 			const PROGRAM = path.join(DATA_ROOT, 'baseTest');
 			const config = {
 				name: 'Launch',
@@ -785,13 +802,16 @@
 				program: PROGRAM,
 				dlvFlags: ['--invalid']
 			};
-			try {
-				await initializeDebugConfig(config);
-				await dc.initializeRequest();
-			} catch (err) {
-				return;
-			}
-			throw new Error('does not report error on invalid delve flag');
+
+			await initializeDebugConfig(config);
+
+			await Promise.race([
+				// send an initialize request, which triggers launchDelveDAP
+				// from the thin adapter. We expect no response.
+				dc.initializeRequest().then(() => Promise.reject('unexpected initialization success')),
+				// we expect the useful error message.
+				waitForOutputMessage(dc, 'Error: unknown flag: --invalid')
+			]);
 		});
 
 		test('should run program with showLog=false and logOutput specified', async () => {
@@ -951,15 +971,7 @@
 		});
 
 		async function waitForHelloGoodbyeOutput(dc: DebugClient): Promise<DebugProtocol.Event> {
-			return await new Promise<DebugProtocol.Event>((resolve, reject) => {
-				dc.on('output', (event) => {
-					if (event.body.output === 'Hello, World!\n' || event.body.output === 'Goodbye, World.\n') {
-						// Resolve when we have found the event that we want.
-						resolve(event);
-						return;
-					}
-				});
-			});
+			return waitForOutputMessage(dc, 'Hello, World!\n', 'Goodbye, World.\n');
 		}
 
 		test('should run program with cwd set (noDebug)', async () => {