test/integration/goDebug.test.ts: fix listening for output event

The previous implementation sometimes missed the desired output event.
Instead, start up several listeners that resolve when one of them
finds the desired output event.

Updates golang/vscode-go#1439

Change-Id: Ib30f9e50372c6456b1fcfc9ceb76014661f72754
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/315670
Trust: Suzy Mueller <suzmue@golang.org>
Run-TryBot: Suzy Mueller <suzmue@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/test/integration/goDebug.test.ts b/test/integration/goDebug.test.ts
index 2d2465c..130819a 100644
--- a/test/integration/goDebug.test.ts
+++ b/test/integration/goDebug.test.ts
@@ -781,19 +781,26 @@
 			await assertLocalVariableValue('strdat', '"Goodbye, World."');
 		});
 
-		async function waitForHelloGoodbyeOutput(dc: DebugClient, wantHello: boolean) {
-			let found = false;
-			while (!found) {
-				const event = await dc.waitForEvent('output');
-				if (event.body.output === 'Hello, World!\n' || event.body.output === 'Goodbye, World.\n') {
-					if (wantHello) {
-						assert.strictEqual(event.body.output, 'Hello, World!\n');
-					} else {
-						assert.strictEqual(event.body.output, 'Goodbye, World.\n');
-					}
-					found = true;
-				}
-			}
+		async function waitForHelloGoodbyeOutput(dc: DebugClient): Promise<DebugProtocol.Event> {
+			return await new Promise<DebugProtocol.Event>((resolve, reject) => {
+				const listen = () => {
+					dc.waitForEvent('output', 5_000)
+						.then((event) => {
+							// Run listen again to make sure we can get the next events.
+							listen();
+							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;
+							}
+						})
+						.catch((reason) => reject(reason));
+				};
+				// Start listening for an output event. Especially because
+				// logging is enabled in dlv-dap, there are many output events, and it is
+				// possible to miss them if we are not prepared to handle them.
+				listen();
+			});
 		}
 
 		test('should run program with cwd set (noDebug)', async () => {
@@ -811,7 +818,8 @@
 			};
 			const debugConfig = await initializeDebugConfig(config);
 			dc.launch(debugConfig);
-			await waitForHelloGoodbyeOutput(dc, true);
+			const event = await waitForHelloGoodbyeOutput(dc);
+			assert.strictEqual(event.body.output, 'Hello, World!\n');
 		});
 
 		test('should run program without cwd set (noDebug)', async () => {
@@ -828,7 +836,8 @@
 			};
 			const debugConfig = await initializeDebugConfig(config);
 			dc.launch(debugConfig);
-			await waitForHelloGoodbyeOutput(dc, false);
+			const event = await waitForHelloGoodbyeOutput(dc);
+			assert.strictEqual(event.body.output, 'Goodbye, World.\n');
 		});
 
 		test('should run file program with cwd set (noDebug)', async () => {
@@ -846,7 +855,8 @@
 			};
 			const debugConfig = await initializeDebugConfig(config);
 			dc.launch(debugConfig);
-			await waitForHelloGoodbyeOutput(dc, true);
+			const event = await waitForHelloGoodbyeOutput(dc);
+			assert.strictEqual(event.body.output, 'Hello, World!\n');
 		});
 		test('should run file program without cwd set (noDebug)', async () => {
 			const WD = path.join(DATA_ROOT, 'cwdTest');
@@ -862,7 +872,8 @@
 			};
 			const debugConfig = await initializeDebugConfig(config);
 			dc.launch(debugConfig);
-			await waitForHelloGoodbyeOutput(dc, false);
+			const event = await waitForHelloGoodbyeOutput(dc);
+			assert.strictEqual(event.body.output, 'Goodbye, World.\n');
 		});
 	});