src/goDebug: fix drive casing when substituting paths

Due to https://github.com/Microsoft/vscode/issues/9448#issuecomment-244804026
the drive casing may not be correct for filepaths on windows. This
change makes sure to capitalize the drive name for the paths to be substituted.

Although the local machine may not be windows, the remote machine
may be, so we check for the drive name on all paths.

Change-Id: I7993f6426f1d25d490b655c38598ab977acf774f
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/277963
Trust: Suzy Mueller <suzmue@golang.org>
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
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/src/debugAdapter/goDebug.ts b/src/debugAdapter/goDebug.ts
index 788af3d..ac3ece0 100644
--- a/src/debugAdapter/goDebug.ts
+++ b/src/debugAdapter/goDebug.ts
@@ -371,7 +371,18 @@
 	return filePath;
 }
 
-function normalizeSeparators(filePath: string): string {
+// normalizeSeparators will prepare the filepath for comparison in mapping from
+// local to debugger path and from debugger path to local path. All separators are
+// replaced with '/', and the drive name is capitalized for windows paths.
+// Exported for testing
+export function normalizeSeparators(filePath: string): string {
+	// Although the current machine may not be running windows,
+	// the remote machine may be and we need to fix the drive
+	// casing.
+	// This is a workaround for issue in https://github.com/Microsoft/vscode/issues/9448#issuecomment-244804026
+	if (filePath.indexOf(':') === 1) {
+		filePath = filePath.substr(0, 1).toUpperCase() + filePath.substr(1);
+	}
 	return filePath.replace(/\/|\\/g, '/');
 }
 
diff --git a/test/unit/goDebug.test.ts b/test/unit/goDebug.test.ts
new file mode 100644
index 0000000..686b5bb
--- /dev/null
+++ b/test/unit/goDebug.test.ts
@@ -0,0 +1,98 @@
+/*---------------------------------------------------------
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See LICENSE in the project root for license information.
+ *--------------------------------------------------------*/
+
+import * as assert from 'assert';
+import { normalizeSeparators } from '../../src/debugAdapter/goDebug';
+
+suite('NormalizeSeparators Tests', () => {
+	test('fix separator', () => {
+		const tt = [
+			{
+				input: 'path/to/file',
+				want: 'path/to/file',
+			},
+			{
+				input: '\\path\\to\\file',
+				want: '/path/to/file',
+			},
+			{
+				input: '/path/to\\file',
+				want: '/path/to/file',
+			},
+		];
+
+		for (const tc of tt) {
+			const got = normalizeSeparators(tc.input);
+			assert.strictEqual(got, tc.want);
+		}
+	});
+	test('fix drive casing', () => {
+		const tt = [
+			{
+				input: 'C:/path/to/file',
+				want: 'C:/path/to/file',
+			},
+			{
+				input: 'c:/path/to/file',
+				want: 'C:/path/to/file',
+			},
+			{
+				input: 'C:/path/to/file',
+				want: 'C:/path/to/file',
+			},
+			{
+				input: 'C:\\path\\to\\file',
+				want: 'C:/path/to/file',
+			},
+			{
+				input: 'c:\\path\\to\\file',
+				want: 'C:/path/to/file',
+			},
+			{
+				input: 'c:\\path\\to\\file',
+				want: 'C:/path/to/file',
+			}
+		];
+
+		for (const tc of tt) {
+			const got = normalizeSeparators(tc.input);
+			assert.strictEqual(got, tc.want);
+		}
+	});
+	test('relative paths', () => {
+		const tt = [
+			{
+				input: '../path/to/file',
+				want: '../path/to/file',
+			},
+			{
+				input: './path/to/file',
+				want: './path/to/file',
+			},
+			{
+				input: '..\\path\\to\\file',
+				want: '../path/to/file',
+			},
+			{
+				input: '.\\path\\to\\file',
+				want: './path/to/file',
+			},
+			{
+				input: '/path/to/../file',
+				want: '/path/to/../file',
+			},
+			{
+				input: 'c:\\path\\to\\..\\file',
+				want: 'C:/path/to/../file',
+			}
+		];
+
+		for (const tc of tt) {
+			const got = normalizeSeparators(tc.input);
+			assert.strictEqual(got, tc.want);
+		}
+	});
+
+});