all: fix for Windows

- Form file:// URLs correctly
- Stub out a Unix-specific API
- Don't do an exact string match on environment variable names

Change-Id: I695142bd77adbbd9f665380a75f86fb9a701f3f3
Reviewed-on: https://go-review.googlesource.com/c/pkgsite-metrics/+/506298
Auto-Submit: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/internal/govulncheck/govulncheck.go b/internal/govulncheck/govulncheck.go
index 01914cd..2f41567 100644
--- a/internal/govulncheck/govulncheck.go
+++ b/internal/govulncheck/govulncheck.go
@@ -14,8 +14,9 @@
 	"fmt"
 	"net/http"
 	"os/exec"
+	"path/filepath"
+	"runtime"
 	"strings"
-	"syscall"
 	"time"
 
 	"golang.org/x/pkgsite-metrics/internal/bigquery"
@@ -280,8 +281,12 @@
 
 	stdOut := bytes.Buffer{}
 	stdErr := bytes.Buffer{}
+	uri := "file://" + vulndbDir
+	if runtime.GOOS == "windows" {
+		uri = "file:///" + filepath.ToSlash(vulndbDir)
+	}
 	govulncheckCmd := exec.Command(govulncheckPath, "-mode", modeFlag,
-		"-json", "-db=file://"+vulndbDir, "-C="+dir, pattern)
+		"-json", "-db="+uri, "-C="+dir, pattern)
 
 	govulncheckCmd.Stdout = &stdOut
 	govulncheckCmd.Stderr = &stdErr
@@ -291,7 +296,7 @@
 		return nil, errors.New(stdErr.String())
 	}
 	stats.ScanSeconds = time.Since(start).Seconds()
-	stats.ScanMemory = uint64(govulncheckCmd.ProcessState.SysUsage().(*syscall.Rusage).Maxrss)
+	stats.ScanMemory = getMemoryUsage(govulncheckCmd)
 
 	handler := NewMetricsHandler()
 	err := govulncheckapi.HandleJSON(&stdOut, handler)
@@ -300,3 +305,8 @@
 	}
 	return handler.Findings(), nil
 }
+
+// getMemoryUsage is overridden with a Unix-specific function on Linux.
+var getMemoryUsage = func(c *exec.Cmd) uint64 {
+	return 0
+}
diff --git a/internal/govulncheck/govulncheck_unix.go b/internal/govulncheck/govulncheck_unix.go
new file mode 100644
index 0000000..8a7d501
--- /dev/null
+++ b/internal/govulncheck/govulncheck_unix.go
@@ -0,0 +1,18 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build unix
+
+package govulncheck
+
+import (
+	"os/exec"
+	"syscall"
+)
+
+func init() {
+	getMemoryUsage = func(c *exec.Cmd) uint64 {
+		return uint64(c.ProcessState.SysUsage().(*syscall.Rusage).Maxrss)
+	}
+}
diff --git a/internal/worker/analysis_test.go b/internal/worker/analysis_test.go
index dd5f094..3469859 100644
--- a/internal/worker/analysis_test.go
+++ b/internal/worker/analysis_test.go
@@ -172,6 +172,11 @@
 	if i := strings.LastIndexByte(got.Error, ':'); i > 0 {
 		got.Error = got.Error[i+2:]
 	}
+	// And the platform-specific part.
+	if i := strings.LastIndex(got.Error, "not found in"); i > 0 {
+		got.Error = got.Error[:i+len("not found in")]
+	}
+
 	want = &analysis.Result{
 		ModulePath:    modulePath,
 		Version:       version,
@@ -179,7 +184,7 @@
 		BinaryName:    "bad",
 		WorkVersion:   wv,
 		ErrorCategory: "MISC",
-		Error:         "executable file not found in $PATH",
+		Error:         "executable file not found in",
 	}
 	diff(want, got)
 }
diff --git a/internal/worker/govulncheck_scan_test.go b/internal/worker/govulncheck_scan_test.go
index eb0b067..ac18604 100644
--- a/internal/worker/govulncheck_scan_test.go
+++ b/internal/worker/govulncheck_scan_test.go
@@ -10,6 +10,7 @@
 	"fmt"
 	"io"
 	"path/filepath"
+	"runtime"
 	"strings"
 	"testing"
 
@@ -137,7 +138,7 @@
 			if got := stats.ScanSeconds; got <= 0 {
 				t.Errorf("scan time not collected or negative: %v", got)
 			}
-			if got := stats.ScanMemory; got <= 0 {
+			if got := stats.ScanMemory; got <= 0 && runtime.GOOS == "linux" {
 				t.Errorf("scan memory not collected or negative: %v", got)
 			}
 		})