src/testUtils: add test codelenses for Fuzz* functions

Add 'run test', 'debug test' codelenses for Fuzz* functions.

Updates golang/vscode-go#1794

Change-Id: I5089926fd6cabcaf844be21217a9a77baad09ca4
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/361935
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Suzy Mueller <suzmue@golang.org>
diff --git a/src/testUtils.ts b/src/testUtils.ts
index 3d4c1e7..3dc4e45 100644
--- a/src/testUtils.ts
+++ b/src/testUtils.ts
@@ -40,7 +40,7 @@
 const testFuncRegex = /^Test$|^Test\P{Ll}.*|^Example$|^Example\P{Ll}.*/u;
 const testMethodRegex = /^\(([^)]+)\)\.(Test|Test\P{Ll}.*)$/u;
 const benchmarkRegex = /^Benchmark$|^Benchmark\P{Ll}.*/u;
-
+const fuzzFuncRegx = /^Fuzz$|^Fuzz\P{Ll}.*/u;
 /**
  * Input to goTest.
  */
@@ -158,7 +158,7 @@
 	return children.filter(
 		(sym) =>
 			sym.kind === vscode.SymbolKind.Function &&
-			(testFuncRegex.test(sym.name) || (testify && testMethodRegex.test(sym.name)))
+			(testFuncRegex.test(sym.name) || fuzzFuncRegx.test(sym.name) || (testify && testMethodRegex.test(sym.name)))
 	);
 }
 
diff --git a/test/integration/codelens.test.ts b/test/integration/codelens.test.ts
index 5173a45..10ecaab 100644
--- a/test/integration/codelens.test.ts
+++ b/test/integration/codelens.test.ts
@@ -14,7 +14,7 @@
 import { updateGoVarsFromConfig } from '../../src/goInstallTools';
 import { GoRunTestCodeLensProvider } from '../../src/goRunTestCodelens';
 import { subTestAtCursor } from '../../src/goTest';
-import { getCurrentGoPath } from '../../src/util';
+import { getCurrentGoPath, getGoVersion } from '../../src/util';
 
 suite('Code lenses for testing and benchmarking', function () {
 	this.timeout(20000);
@@ -164,4 +164,24 @@
 			'Test함́ˆ˜'
 		]);
 	});
+
+	test('Test codelenses include valid fuzz function names', async function () {
+		if ((await getGoVersion()).lt('1.18')) {
+			this.skip();
+		}
+		const uri = vscode.Uri.file(path.join(fixturePath, 'codelens_go118_test.go'));
+		const testDocument = await vscode.workspace.openTextDocument(uri);
+		const codeLenses = await codeLensProvider.provideCodeLenses(testDocument, cancellationTokenSource.token);
+		assert.equal(codeLenses.length, 8, JSON.stringify(codeLenses, null, 2));
+		const found = [] as string[];
+		for (let i = 0; i < codeLenses.length; i++) {
+			const lens = codeLenses[i];
+			if (lens.command.command === 'go.test.cursor') {
+				found.push(lens.command.arguments[0].functionName);
+			}
+		}
+		found.sort();
+		// Results should match `go test -list`.
+		assert.deepStrictEqual(found, ['Fuzz', 'FuzzFunc', 'TestGo118']);
+	});
 });
diff --git a/test/testdata/codelens/codelens_go118_test.go b/test/testdata/codelens/codelens_go118_test.go
new file mode 100644
index 0000000..bd76567
--- /dev/null
+++ b/test/testdata/codelens/codelens_go118_test.go
@@ -0,0 +1,17 @@
+//go:build go1.18
+// +build go1.18
+
+package main
+
+import (
+	"testing"
+)
+
+func FuzzFunc(f *testing.F) {
+}
+
+func Fuzz(f *testing.F) {
+}
+
+func TestGo118(t *testing.T) {
+}