blob: 3eaa98404ece056cd626d7ddd8f299769a2b0575 [file] [log] [blame]
// 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)
}
})
}
})
}
}