| // Copyright 2022 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. |
| |
| package report |
| |
| import ( |
| "path/filepath" |
| "testing" |
| "time" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/google/go-cmp/cmp/cmpopts" |
| "golang.org/x/vulndb/internal/gitrepo" |
| ) |
| |
| var ( |
| fname1 = "data/reports/GO-9999-0001.yaml" |
| r1 = Report{ |
| ID: "GO-9999-0001", |
| Modules: []*Module{ |
| {Module: "std"}, |
| }, |
| CVEMetadata: &CVEMeta{ |
| ID: "CVE-9999-0001", |
| }, |
| } |
| fname2 = "data/excluded/GO-9999-0002.yaml" |
| r2 = Report{ |
| ID: "GO-9999-0002", |
| Modules: []*Module{ |
| {Module: "example.com/fake/module"}, |
| }, |
| CVEMetadata: &CVEMeta{ |
| ID: "CVE-9999-0002", |
| }, |
| Excluded: ExcludedEffectivelyPrivate, |
| } |
| fname4 = "data/reports/GO-9999-0004.yaml" |
| r4 = Report{ |
| ID: "GO-9999-0004", |
| Modules: []*Module{ |
| {Module: "example.com/another/module"}, |
| }, |
| GHSAs: []string{ |
| "GHSA-9999-abcd-efgh", |
| }, |
| } |
| fname5 = "data/reports/GO-9999-0005.yaml" |
| r5 = Report{ |
| ID: "GO-9999-0005", |
| Modules: []*Module{ |
| {Module: "example.com/adiff/module"}, |
| }, |
| CVEs: []string{"CVE-9999-0005"}, |
| } |
| fname6 = "data/reports/GO-9999-0006.yaml" |
| r6 = Report{ |
| ID: "GO-9999-0006", |
| Modules: []*Module{ |
| {Module: "example.com/another/module"}, |
| }, |
| GHSAs: []string{"GHSA-9999-abcd-efgh"}, |
| } |
| |
| txtarFile = filepath.Join("testdata", "repo.txtar") |
| ) |
| |
| func TestList(t *testing.T) { |
| repo, err := gitrepo.ReadTxtarRepo(txtarFile, time.Now()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| rc, err := NewClient(repo) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| got := rc.List() |
| want := []*Report{&r1, &r2, &r4, &r5, &r6} |
| byID := func(a, b *Report) bool { return a.ID < b.ID } |
| if diff := cmp.Diff(got, want, cmpopts.SortSlices(byID)); diff != "" { |
| t.Errorf("mismatch (-got, +want): %s", diff) |
| } |
| } |
| |
| func TestXRef(t *testing.T) { |
| repo, err := gitrepo.ReadTxtarRepo(txtarFile, time.Now()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| rc, err := NewClient(repo) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| tests := []struct { |
| name string |
| r *Report |
| wantXrefs *Xrefs |
| wantMatches map[string][]string |
| }{ |
| { |
| name: "No matches", |
| r: &Report{ |
| Modules: []*Module{ |
| {Module: "example.com/unused/module"}, |
| }, |
| CVEMetadata: &CVEMeta{ |
| ID: "CVE-9999-0003", |
| }, |
| }, |
| wantXrefs: &Xrefs{ |
| Aliases: map[string][]*File{}, |
| Modules: map[string][]*File{}, |
| }, |
| }, |
| { |
| name: "Ignores std lib modules", |
| r: &Report{ |
| Modules: []*Module{ |
| {Module: "std"}, |
| }, |
| CVEs: []string{"CVE-9999-0003"}, |
| }, |
| wantXrefs: &Xrefs{ |
| Aliases: map[string][]*File{}, |
| Modules: map[string][]*File{}, |
| }, |
| }, |
| { |
| name: "Match on CVE (ignores std module)", |
| r: &Report{ |
| Modules: []*Module{ |
| {Module: "std"}, |
| }, |
| CVEs: []string{"CVE-9999-0001"}, |
| }, |
| wantXrefs: &Xrefs{ |
| Aliases: map[string][]*File{ |
| "CVE-9999-0001": { |
| {Filename: fname1, IssNum: 1, Report: &r1}, |
| }, |
| }, |
| Modules: map[string][]*File{}, |
| }, |
| }, |
| { |
| name: "Match on GHSA & module", |
| r: &r4, |
| wantXrefs: &Xrefs{ |
| Aliases: map[string][]*File{ |
| "GHSA-9999-abcd-efgh": { |
| {Filename: fname6, IssNum: 6, Report: &r6}, |
| }, |
| }, |
| Modules: map[string][]*File{ |
| "example.com/another/module": { |
| {Filename: fname6, IssNum: 6, Report: &r6}, |
| }, |
| }, |
| }, |
| }, |
| } |
| for _, tt := range tests { |
| t.Run(tt.name, func(t *testing.T) { |
| got := rc.XRef(tt.r) |
| if diff := cmp.Diff(got, tt.wantXrefs); diff != "" { |
| t.Errorf("XRef(): mismatch (-got, +want): %s", diff) |
| } |
| }) |
| } |
| } |
| |
| func TestReportsByAliases(t *testing.T) { |
| repo, err := gitrepo.ReadTxtarRepo(txtarFile, time.Now()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| rc, err := NewClient(repo) |
| if err != nil { |
| t.Fatal(err) |
| } |
| got := rc.ReportsByAlias("CVE-9999-0001") |
| want := []*Report{&r1} |
| |
| if diff := cmp.Diff(want, got); diff != "" { |
| t.Errorf("ReportsByAliases() mismatch (-want, +got): %s", diff) |
| } |
| } |
| |
| func TestAliasHasReport(t *testing.T) { |
| repo, err := gitrepo.ReadTxtarRepo(txtarFile, time.Now()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| rc, err := NewClient(repo) |
| if err != nil { |
| t.Fatal(err) |
| } |
| id := "CVE-9999-0001" |
| got := rc.AliasHasReport("CVE-9999-0001") |
| want := true |
| |
| if got != want { |
| t.Errorf("AliasHasReport(%s) = %t, want %t", id, got, want) |
| } |
| } |
| |
| func TestNewClient(t *testing.T) { |
| // Test that NewClient and NewTestClient have the same behavior. |
| repo, err := gitrepo.ReadTxtarRepo(txtarFile, time.Now()) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| c, err := NewClient(repo) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| files := map[string]*Report{ |
| fname1: &r1, fname2: &r2, fname4: &r4, fname5: &r5, fname6: &r6, |
| } |
| tc, err := NewTestClient(files) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| less := func(f1, f2 *File) bool { |
| return f1.ID < f2.ID |
| } |
| |
| if diff := cmp.Diff(c, tc, cmp.AllowUnexported(Client{}), |
| cmpopts.SortSlices(less)); diff != "" { |
| t.Errorf("NewClient() / NewTestClient() mismatch (-New, +NewTest): %s", diff) |
| } |
| } |