| // 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 cvelistrepo |
| |
| import ( |
| "context" |
| "flag" |
| "fmt" |
| "os" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/google/go-cmp/cmp/cmpopts" |
| "golang.org/x/vulndb/internal/cveschema" |
| "golang.org/x/vulndb/internal/cveschema5" |
| "golang.org/x/vulndb/internal/gitrepo" |
| ) |
| |
| var update = flag.Bool("update", false, "update the .txtar files with real CVE data (this takes a while)") |
| |
| var ( |
| v4txtar = "testdata/v4.txtar" |
| v5txtar = "testdata/v5.txtar" |
| cveIDs = []string{ |
| "CVE-2021-0001", |
| "CVE-2021-0010", |
| "CVE-2021-1384", |
| "CVE-2020-9283", |
| "CVE-2022-39213", |
| } |
| ) |
| |
| func TestMain(m *testing.M) { |
| flag.Parse() |
| if *update { |
| ctx := context.Background() |
| if err := WriteTxtarRepo(ctx, URLv4, v4txtar, cveIDs); err != nil { |
| fail(err) |
| } |
| if err := WriteTxtarRepo(ctx, URLv5, v5txtar, cveIDs); err != nil { |
| fail(err) |
| } |
| } |
| os.Exit(m.Run()) |
| } |
| |
| func fail(err error) { |
| fmt.Fprintln(os.Stderr, err) |
| os.Exit(1) |
| } |
| |
| func TestFiles(t *testing.T) { |
| for _, tc := range []struct { |
| name string |
| txtarFile string |
| want []File |
| }{ |
| { |
| name: "v4", |
| txtarFile: v4txtar, |
| want: []File{ |
| {DirPath: "2020/9xxx", Filename: "CVE-2020-9283.json", Year: 2020, Number: 9283}, |
| {DirPath: "2021/0xxx", Filename: "CVE-2021-0001.json", Year: 2021, Number: 1}, |
| {DirPath: "2021/0xxx", Filename: "CVE-2021-0010.json", Year: 2021, Number: 10}, |
| {DirPath: "2021/1xxx", Filename: "CVE-2021-1384.json", Year: 2021, Number: 1384}, |
| {DirPath: "2022/39xxx", Filename: "CVE-2022-39213.json", Year: 2022, Number: 39213}, |
| }, |
| }, |
| { |
| name: "v5", |
| txtarFile: v5txtar, |
| want: []File{ |
| {DirPath: "cves/2020/9xxx", Filename: "CVE-2020-9283.json", Year: 2020, Number: 9283}, |
| {DirPath: "cves/2021/0xxx", Filename: "CVE-2021-0001.json", Year: 2021, Number: 1}, |
| {DirPath: "cves/2021/0xxx", Filename: "CVE-2021-0010.json", Year: 2021, Number: 10}, |
| {DirPath: "cves/2021/1xxx", Filename: "CVE-2021-1384.json", Year: 2021, Number: 1384}, |
| {DirPath: "cves/2022/39xxx", Filename: "CVE-2022-39213.json", Year: 2022, Number: 39213}, |
| }, |
| }, |
| } { |
| t.Run(tc.name, func(t *testing.T) { |
| repo, commit, err := gitrepo.TxtarRepoAndHead(tc.txtarFile) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| got, err := Files(repo, commit) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| opt := cmpopts.IgnoreFields(File{}, "TreeHash", "BlobHash") |
| if diff := cmp.Diff(tc.want, got, cmp.AllowUnexported(File{}), opt); diff != "" { |
| t.Errorf("mismatch (-want, +got):\n%s", diff) |
| } |
| }) |
| } |
| } |
| |
| func TestFetchCVE(t *testing.T) { |
| for _, tc := range []struct { |
| name string |
| txtarFile string |
| newCVE func() CVE |
| }{ |
| { |
| name: "v4", |
| txtarFile: v4txtar, |
| newCVE: func() CVE { return new(cveschema.CVE) }, |
| }, |
| { |
| name: "v5", |
| txtarFile: v5txtar, |
| newCVE: func() CVE { return new(cveschema5.CVERecord) }, |
| }, |
| } { |
| t.Run(tc.name, func(t *testing.T) { |
| ctx := context.Background() |
| repo, _, err := gitrepo.TxtarRepoAndHead(tc.txtarFile) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| for _, id := range cveIDs { |
| t.Run(id, func(t *testing.T) { |
| cve := tc.newCVE() |
| if err := FetchCVE(ctx, repo, id, cve); err != nil { |
| t.Fatal(err) |
| } |
| if got, want := cveID(cve), id; got != want { |
| t.Errorf("FetchCVE(%s) ID = %s, want %s", id, got, want) |
| } |
| }) |
| } |
| }) |
| } |
| } |
| |
| func cveID(cve CVE) string { |
| switch c := cve.(type) { |
| case *cveschema5.CVERecord: |
| return c.Metadata.ID |
| case *cveschema.CVE: |
| return c.Metadata.ID |
| default: |
| return "invalid" |
| } |
| } |
| |
| func TestParse(t *testing.T) { |
| for _, tc := range []struct { |
| name string |
| txtarFile string |
| newCVE func() CVE |
| }{ |
| { |
| name: "v4", |
| txtarFile: v4txtar, |
| newCVE: func() CVE { return new(cveschema.CVE) }, |
| }, |
| { |
| name: "v5", |
| txtarFile: v5txtar, |
| newCVE: func() CVE { return new(cveschema5.CVERecord) }, |
| }, |
| } { |
| t.Run(tc.name, func(t *testing.T) { |
| repo, commit, err := gitrepo.TxtarRepoAndHead(tc.txtarFile) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| files, err := Files(repo, commit) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| for _, file := range files { |
| t.Run(file.Filename, func(t *testing.T) { |
| cve := tc.newCVE() |
| if err := Parse(repo, file, cve); err != nil { |
| t.Fatal(err) |
| } |
| want := cveschema5.FindCVE(file.Filename) |
| if got := cveID(cve); got != want { |
| t.Errorf("ParseCVE(%s) ID = %s, want %s", file.Filename, got, want) |
| t.Log(cve) |
| } |
| }) |
| } |
| }) |
| } |
| } |