client: de-flake client tests

Fixes #46419

Change-Id: Ifedc05f1f00dfca1fc0816df887588d9427d8fd2
Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/323132
Trust: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
diff --git a/client/cache.go b/client/cache.go
index 880e08a..20079cc 100644
--- a/client/cache.go
+++ b/client/cache.go
@@ -7,6 +7,7 @@
 import (
 	"encoding/json"
 	"go/build"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"time"
@@ -62,7 +63,7 @@
 }
 
 func (c *fsCache) ReadIndex(dbName string) (osv.DBIndex, time.Time, error) {
-	b, err := os.ReadFile(filepath.Join(cacheRoot, dbName, "index.json"))
+	b, err := ioutil.ReadFile(filepath.Join(cacheRoot, dbName, "index.json"))
 	if err != nil {
 		if os.IsNotExist(err) {
 			return nil, time.Time{}, nil
@@ -88,14 +89,14 @@
 	if err != nil {
 		return err
 	}
-	if err := os.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
+	if err := ioutil.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
 		return err
 	}
 	return nil
 }
 
 func (c *fsCache) ReadEntries(dbName string, p string) ([]*osv.Entry, error) {
-	b, err := os.ReadFile(filepath.Join(cacheRoot, dbName, p, "vulns.json"))
+	b, err := ioutil.ReadFile(filepath.Join(cacheRoot, dbName, p, "vulns.json"))
 	if err != nil {
 		if os.IsNotExist(err) {
 			return nil, nil
@@ -118,7 +119,7 @@
 	if err != nil {
 		return err
 	}
-	if err := os.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
+	if err := ioutil.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
 		return err
 	}
 	return nil
diff --git a/client/cache_test.go b/client/cache_test.go
index 70047f7..6510072 100644
--- a/client/cache_test.go
+++ b/client/cache_test.go
@@ -18,22 +18,18 @@
 	originalRoot := cacheRoot
 	defer func() { cacheRoot = originalRoot }()
 
-	tmp, err := os.MkdirTemp("", "vulndb-cache")
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer os.RemoveAll(tmp)
-	cacheRoot = tmp
+	tmpDir := t.TempDir()
+	cacheRoot = tmpDir
 
 	cache := &fsCache{}
 	dbName := "vulndb.golang.org"
 
-	_, _, err = cache.ReadIndex(dbName)
+	_, _, err := cache.ReadIndex(dbName)
 	if err != nil {
 		t.Fatalf("ReadIndex failed for non-existent database: %v", err)
 	}
 
-	if err = os.Mkdir(filepath.Join(tmp, dbName), 0777); err != nil {
+	if err = os.Mkdir(filepath.Join(tmpDir, dbName), 0777); err != nil {
 		t.Fatalf("os.Mkdir failed: %v", err)
 	}
 	_, _, err = cache.ReadIndex(dbName)
diff --git a/client/client.go b/client/client.go
index 1af768d..c7a22a0 100644
--- a/client/client.go
+++ b/client/client.go
@@ -35,7 +35,7 @@
 import (
 	"encoding/json"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"net/http"
 	"net/url"
 	"os"
@@ -60,7 +60,7 @@
 func (ls *localSource) Get(packages []string) ([]*osv.Entry, error) {
 	var entries []*osv.Entry
 	for _, p := range packages {
-		content, err := os.ReadFile(filepath.Join(ls.dir, p+".json"))
+		content, err := ioutil.ReadFile(filepath.Join(ls.dir, p+".json"))
 		if os.IsNotExist(err) {
 			continue
 		} else if err != nil {
@@ -77,7 +77,7 @@
 
 func (ls *localSource) Index() (osv.DBIndex, error) {
 	var index osv.DBIndex
-	b, err := os.ReadFile(filepath.Join(ls.dir, "index.json"))
+	b, err := ioutil.ReadFile(filepath.Join(ls.dir, "index.json"))
 	if err != nil {
 		return nil, err
 	}
@@ -131,7 +131,7 @@
 	if resp.StatusCode != http.StatusOK {
 		return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
 	}
-	b, err := io.ReadAll(resp.Body)
+	b, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		return nil, err
 	}
@@ -195,7 +195,7 @@
 			continue
 		}
 		// might want this to be a LimitedReader
-		content, err := io.ReadAll(resp.Body)
+		content, err := ioutil.ReadAll(resp.Body)
 		if err != nil {
 			return nil, err
 		}
@@ -248,11 +248,7 @@
 			}
 			c.sources = append(c.sources, hs)
 		case strings.HasPrefix(uri, "file://"):
-			url, err := url.Parse(uri)
-			if err != nil {
-				return nil, err
-			}
-			c.sources = append(c.sources, &localSource{dir: url.Path})
+			c.sources = append(c.sources, &localSource{dir: strings.TrimPrefix(uri, "file://")})
 		default:
 			return nil, fmt.Errorf("source %q has unsupported scheme", uri)
 		}
diff --git a/client/client_test.go b/client/client_test.go
index 51b3f21..c9c1eeb 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -7,6 +7,7 @@
 import (
 	"fmt"
 	"io/ioutil"
+	"net"
 	"net/http"
 	"os"
 	"path"
@@ -93,7 +94,13 @@
 	http.HandleFunc("/golang.org/example/one.json", serveTestVuln1)
 	http.HandleFunc("/golang.org/example/two.json", serveTestVuln2)
 	http.HandleFunc("/index.json", serveIndex)
-	go func() { http.ListenAndServe(":8080", nil) }()
+
+	l, err := net.Listen("tcp", "127.0.0.1:")
+	if err != nil {
+		t.Fatalf("failed to listen on 127.0.0.1: %s", err)
+	}
+	_, port, _ := net.SplitHostPort(l.Addr().String())
+	go func() { http.Serve(l, nil) }()
 
 	// Create a local file database.
 	localDBName, err := localDB(t)
@@ -110,11 +117,11 @@
 		summaries   map[string]string
 	}{
 		// Test the http client without any cache.
-		{name: "http-no-cache", source: "http://localhost:8080", createCache: func() Cache { return nil }, noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": ""}},
+		{name: "http-no-cache", source: "http://localhost:" + port, createCache: func() Cache { return nil }, noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": ""}},
 		// Test the http client with empty cache.
-		{name: "http-empty-cache", source: "http://localhost:8080", createCache: func() Cache { return &fsCache{} }, noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": ""}},
+		{name: "http-empty-cache", source: "http://localhost:" + port, createCache: func() Cache { return &fsCache{} }, noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": ""}},
 		// Test the client with non-stale cache containing a version of testVuln2 where Summary="cached".
-		{name: "http-cache", source: "http://localhost:8080", createCache: cachedTestVuln2("localhost"), noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": "cached"}},
+		{name: "http-cache", source: "http://localhost:" + port, createCache: cachedTestVuln2("localhost"), noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": "cached"}},
 		// Repeat the same for local file client.
 		{name: "file-no-cache", source: "file://" + localDBName, createCache: func() Cache { return nil }, noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": ""}},
 		{name: "file-empty-cache", source: "file://" + localDBName, createCache: func() Cache { return &fsCache{} }, noVulns: 2, summaries: map[string]string{"ID1": "", "ID2": ""}},
diff --git a/cmd/report2cve/main.go b/cmd/report2cve/main.go
index 66b8f18..d531352 100644
--- a/cmd/report2cve/main.go
+++ b/cmd/report2cve/main.go
@@ -8,6 +8,7 @@
 	"encoding/json"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"strings"
 
@@ -217,7 +218,7 @@
 	}
 
 	reportPath := os.Args[1]
-	b, err := os.ReadFile(reportPath)
+	b, err := ioutil.ReadFile(reportPath)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "failed to read %q: %s\n", reportPath, err)
 		os.Exit(1)
diff --git a/go.mod b/go.mod
index 1cc084f..dc3e07a 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,10 @@
 module golang.org/x/vulndb
 
-go 1.16
+go 1.17
 
 require (
 	github.com/google/go-cmp v0.5.4
 	golang.org/x/mod v0.4.1
+	golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
 	gopkg.in/yaml.v2 v2.4.0
 )
diff --git a/report/lint.go b/report/lint.go
index 7467e97..5cc8ccf 100644
--- a/report/lint.go
+++ b/report/lint.go
@@ -7,7 +7,7 @@
 import (
 	"errors"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"net/http"
 	"regexp"
 	"strings"
@@ -28,7 +28,7 @@
 		return nil, err
 	}
 	defer resp.Body.Close()
-	b, err := io.ReadAll(resp.Body)
+	b, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		return nil, err
 	}
@@ -45,7 +45,7 @@
 		return "", err
 	}
 	defer resp.Body.Close()
-	b, err := io.ReadAll(resp.Body)
+	b, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		return "", err
 	}