|
5 | 5 | package genericosv
|
6 | 6 |
|
7 | 7 | import (
|
| 8 | + "encoding/json" |
8 | 9 | "flag"
|
9 | 10 | "io/fs"
|
| 11 | + "os" |
10 | 12 | "path/filepath"
|
11 | 13 | "strings"
|
12 | 14 | "testing"
|
13 | 15 |
|
14 | 16 | "github.com/google/go-cmp/cmp"
|
15 | 17 | osvschema "github.com/google/osv-scanner/pkg/models"
|
| 18 | + "golang.org/x/vulndb/internal/proxy" |
16 | 19 | "golang.org/x/vulndb/internal/report"
|
17 | 20 | )
|
18 | 21 |
|
19 |
| -var update = flag.Bool("update", false, "if true, update test cases") |
| 22 | +var ( |
| 23 | + realProxy = flag.Bool("proxy", false, "if true, contact the real module proxy and update expected responses") |
| 24 | + update = flag.Bool("update", false, "if true, update test YAML reports to reflect new expected behavior") |
| 25 | +) |
20 | 26 |
|
21 | 27 | var (
|
22 |
| - testdataDir = "testdata" |
23 |
| - testOSVDir = filepath.Join(testdataDir, "osv") |
24 |
| - testYAMLDir = filepath.Join(testdataDir, "yaml") |
| 28 | + testdataDir = "testdata" |
| 29 | + testOSVDir = filepath.Join(testdataDir, "osv") |
| 30 | + testYAMLDir = filepath.Join(testdataDir, "yaml") |
| 31 | + proxyResponsesFile = filepath.Join(testdataDir, "proxy.json") |
25 | 32 | )
|
26 | 33 |
|
27 | 34 | // To update test cases to reflect new expected behavior:
|
28 | 35 | // go test ./internal/genericosv/... -update -run TestToReport
|
29 |
| -// |
30 |
| -// TODO(https://go.dev/issues/61769): mock out proxy calls in the non-update |
31 |
| -// case so that this test is hermetic. |
32 | 36 | func TestToReport(t *testing.T) {
|
33 |
| - t.Skip("need to mock out proxy calls") |
34 |
| - if err := filepath.WalkDir(testOSVDir, func(path string, f fs.DirEntry, err error) error { |
35 |
| - if err != nil { |
36 |
| - return err |
37 |
| - } |
38 |
| - if f.IsDir() || filepath.Ext(path) != ".json" { |
39 |
| - return nil |
40 |
| - } |
41 |
| - ghsaID := strings.TrimSuffix(f.Name(), ".json") |
42 |
| - t.Run(ghsaID, func(t *testing.T) { |
43 |
| - t.Parallel() |
44 |
| - osv := Entry{} |
45 |
| - if err := report.UnmarshalFromFile(path, &osv); err != nil { |
| 37 | + if *realProxy { |
| 38 | + defer func() { |
| 39 | + err := updateProxyResponses() |
| 40 | + if err != nil { |
46 | 41 | t.Fatal(err)
|
47 | 42 | }
|
48 |
| - got := osv.ToReport("GO-TEST-ID") |
49 |
| - yamlFile := filepath.Join(testYAMLDir, ghsaID+".yaml") |
50 |
| - if *update { |
51 |
| - if err := got.Write(yamlFile); err != nil { |
52 |
| - t.Fatal(err) |
53 |
| - } |
54 |
| - } |
55 |
| - want, err := report.Read(yamlFile) |
| 43 | + }() |
| 44 | + } else { |
| 45 | + err := setupMockProxy(t) |
| 46 | + if err != nil { |
| 47 | + t.Fatal(err) |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + // The outer test run forces the test to wait for all parallel tests |
| 52 | + // to finish before tearing down test. |
| 53 | + t.Run("run", func(t *testing.T) { |
| 54 | + if err := filepath.WalkDir(testOSVDir, func(path string, f fs.DirEntry, err error) error { |
56 | 55 | if err != nil {
|
57 |
| - t.Fatal(err) |
| 56 | + return err |
58 | 57 | }
|
59 |
| - if diff := cmp.Diff(want, got); diff != "" { |
60 |
| - t.Errorf("ToReport() mismatch (-want +got)\n%s", diff) |
| 58 | + if f.IsDir() || filepath.Ext(path) != ".json" { |
| 59 | + return nil |
61 | 60 | }
|
62 |
| - }) |
63 |
| - return nil |
64 |
| - }); err != nil { |
65 |
| - t.Fatal(err) |
66 |
| - } |
| 61 | + ghsaID := strings.TrimSuffix(f.Name(), ".json") |
| 62 | + t.Run(ghsaID, func(t *testing.T) { |
| 63 | + t.Parallel() |
| 64 | + |
| 65 | + osv := Entry{} |
| 66 | + if err := report.UnmarshalFromFile(path, &osv); err != nil { |
| 67 | + t.Fatal(err) |
| 68 | + } |
| 69 | + |
| 70 | + got := osv.ToReport("GO-TEST-ID") |
| 71 | + yamlFile := filepath.Join(testYAMLDir, ghsaID+".yaml") |
| 72 | + if *update { |
| 73 | + if err := got.Write(yamlFile); err != nil { |
| 74 | + t.Fatal(err) |
| 75 | + } |
| 76 | + } |
| 77 | + want, err := report.Read(yamlFile) |
| 78 | + if err != nil { |
| 79 | + t.Fatal(err) |
| 80 | + } |
| 81 | + if diff := cmp.Diff(want, got); diff != "" { |
| 82 | + t.Errorf("ToReport() mismatch (-want +got)\n%s", diff) |
| 83 | + } |
| 84 | + }) |
| 85 | + return nil |
| 86 | + }); err != nil { |
| 87 | + t.Fatal(err) |
| 88 | + } |
| 89 | + }) |
67 | 90 | }
|
68 | 91 |
|
69 | 92 | // TODO(https://go.dev/issues/61769): unskip test cases as we add features.
|
@@ -260,3 +283,37 @@ func TestAffectedToModules(t *testing.T) {
|
260 | 283 |
|
261 | 284 | }
|
262 | 285 | }
|
| 286 | + |
| 287 | +// Use saved responses from testdata/proxy.json instead of real proxy calls. |
| 288 | +func setupMockProxy(t *testing.T) error { |
| 289 | + t.Helper() |
| 290 | + |
| 291 | + b, err := os.ReadFile(proxyResponsesFile) |
| 292 | + if err != nil { |
| 293 | + return err |
| 294 | + } |
| 295 | + var responses map[string]*proxy.Response |
| 296 | + err = json.Unmarshal(b, &responses) |
| 297 | + if err != nil { |
| 298 | + return err |
| 299 | + } |
| 300 | + |
| 301 | + defaultProxyClient := proxy.DefaultClient |
| 302 | + testClient, cleanup := proxy.NewTestClient(responses) |
| 303 | + proxy.DefaultClient = testClient |
| 304 | + t.Cleanup(cleanup) |
| 305 | + t.Cleanup(func() { |
| 306 | + proxy.DefaultClient = defaultProxyClient |
| 307 | + }) |
| 308 | + |
| 309 | + return nil |
| 310 | +} |
| 311 | + |
| 312 | +// Write proxy responses for this run to testdata/proxy.json. |
| 313 | +func updateProxyResponses() error { |
| 314 | + responses, err := json.MarshalIndent(proxy.Responses(), "", "\t") |
| 315 | + if err != nil { |
| 316 | + return err |
| 317 | + } |
| 318 | + return os.WriteFile(proxyResponsesFile, responses, 0644) |
| 319 | +} |
0 commit comments