blob: fe18c201a06b7f6a0342b0508a5e140e2e54036b [file] [log] [blame]
Julie Qiu60403662021-12-17 18:11:51 -05001// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build go1.17 && !windows
6// +build go1.17,!windows
7
8package main
9
10import (
Tatiana Bradleybca6ae22024-07-15 16:36:44 -040011 "context"
Damien Neil74a8e012022-08-10 14:26:13 -070012 "errors"
Julie Qiu60403662021-12-17 18:11:51 -050013 "os"
14 "os/exec"
Julie Qiu733040a2021-12-20 17:14:01 -050015 "path/filepath"
16 "runtime"
Damien Neil74a8e012022-08-10 14:26:13 -070017 "sort"
Julie Qiu733040a2021-12-20 17:14:01 -050018 "strings"
Julie Qiu60403662021-12-17 18:11:51 -050019 "testing"
Damien Neil2c15bf72022-09-13 16:09:01 -070020 "time"
Julie Qiu733040a2021-12-20 17:14:01 -050021
Damien Neil2c15bf72022-09-13 16:09:01 -070022 "github.com/google/go-cmp/cmp"
23 "github.com/google/go-cmp/cmp/cmpopts"
Tatiana Bradleybca6ae22024-07-15 16:36:44 -040024 "golang.org/x/vulndb/cmd/vulnreport/priority"
Tatiana Bradley2ff2c862024-05-06 17:34:29 -040025 "golang.org/x/vulndb/internal/cve5"
Tatiana Bradleybca6ae22024-07-15 16:36:44 -040026 "golang.org/x/vulndb/internal/gitrepo"
Tatiana Bradley0cbf4ff2023-05-12 16:14:27 -040027 "golang.org/x/vulndb/internal/osvutils"
Tatiana Bradley24e908f2023-08-29 14:10:18 -040028 "golang.org/x/vulndb/internal/proxy"
Julie Qiu733040a2021-12-20 17:14:01 -050029 "golang.org/x/vulndb/internal/report"
Julie Qiu60403662021-12-17 18:11:51 -050030)
31
Julie Qiu733040a2021-12-20 17:14:01 -050032func TestChecksBash(t *testing.T) {
Julie Qiu60403662021-12-17 18:11:51 -050033 bash, err := exec.LookPath("bash")
34 if err != nil {
35 t.Skipf("skipping: %v", err)
36 }
37
Tatiana Bradleyf75fb612023-10-11 10:57:25 -040038 // In short mode (used by presubmit checks), only do offline checks.
39 var cmd *exec.Cmd
40 if testing.Short() {
41 cmd = exec.Command(bash, "./checks.bash", "offline")
42 } else {
43 cmd = exec.Command(bash, "./checks.bash")
44 }
45
Julie Qiu60403662021-12-17 18:11:51 -050046 cmd.Stdout = os.Stdout
47 cmd.Stderr = os.Stderr
48 if err := cmd.Run(); err != nil {
49 t.Fatal(err)
50 }
51}
Julie Qiu733040a2021-12-20 17:14:01 -050052
Julie Qiu733040a2021-12-20 17:14:01 -050053func TestLintReports(t *testing.T) {
Julie Qiu733040a2021-12-20 17:14:01 -050054 if runtime.GOOS == "android" {
55 t.Skipf("android builder does not have access to reports/")
56 }
Damien Neil74a8e012022-08-10 14:26:13 -070057 allFiles := make(map[string]string)
58 var reports []string
Tatiana Bradleydefb5802022-11-18 16:26:39 -050059 for _, dir := range []string{report.YAMLDir, report.ExcludedDir} {
cui fliterc957d8f2022-09-14 06:13:32 +000060 files, err := os.ReadDir(dir)
Damien Neil74a8e012022-08-10 14:26:13 -070061 if err != nil && !errors.Is(err, os.ErrNotExist) {
62 t.Fatalf("unable to read %v/: %s", dir, err)
Julie Qiu733040a2021-12-20 17:14:01 -050063 }
Tatiana Bradley2551a342022-09-26 12:18:29 -040064 for _, file := range files {
65 if file.IsDir() {
Damien Neil74a8e012022-08-10 14:26:13 -070066 continue
67 }
Tatiana Bradley2551a342022-09-26 12:18:29 -040068 if filepath.Ext(file.Name()) != ".yaml" {
Jonathan Amsterdam90283d92022-08-22 15:01:49 -040069 continue
70 }
Tatiana Bradley2551a342022-09-26 12:18:29 -040071 filename := filepath.Join(dir, file.Name())
72 if allFiles[file.Name()] != "" {
73 t.Errorf("report appears in multiple locations: %v, %v", allFiles[file.Name()], filename)
Damien Neil74a8e012022-08-10 14:26:13 -070074 }
Tatiana Bradley2551a342022-09-26 12:18:29 -040075 allFiles[file.Name()] = filename
76 reports = append(reports, filename)
Damien Neil74a8e012022-08-10 14:26:13 -070077 }
78 }
Tatiana Bradleya435f712023-08-29 17:49:11 -040079
80 // Skip network calls in short mode.
81 var lint func(r *report.Report) []string
82 if testing.Short() {
83 lint = func(r *report.Report) []string {
84 return r.LintOffline()
85 }
86 } else {
Tatiana Bradley44ab8d22023-08-30 12:45:56 -040087 pc := proxy.NewDefaultClient()
Tatiana Bradleya435f712023-08-29 17:49:11 -040088 lint = func(r *report.Report) []string {
89 return r.Lint(pc)
90 }
91 }
92
Tatiana Bradleybca6ae22024-07-15 16:36:44 -040093 vulndb, err := gitrepo.Open(context.Background(), ".")
94 if err != nil {
95 t.Fatal(err)
96 }
97 rc, err := report.NewClient(vulndb)
98 if err != nil {
99 t.Fatal(err)
100 }
101 modulesToImports, err := priority.LoadModuleMap()
102 if err != nil {
103 t.Fatal(err)
104 }
105
Tatiana Bradleyadabd302023-11-20 13:52:02 -0500106 // Map from summaries to report paths, used to check for duplicate summaries.
107 summaries := make(map[string]string)
Damien Neil74a8e012022-08-10 14:26:13 -0700108 sort.Strings(reports)
Tatiana Bradley2551a342022-09-26 12:18:29 -0400109 for _, filename := range reports {
110 t.Run(filename, func(t *testing.T) {
111 r, err := report.Read(filename)
Julie Qiu733040a2021-12-20 17:14:01 -0500112 if err != nil {
Julie Qiue508e322022-01-04 15:12:43 -0500113 t.Fatal(err)
Julie Qiu733040a2021-12-20 17:14:01 -0500114 }
Tatiana Bradley77da7b62023-05-24 13:07:54 -0400115 if err := r.CheckFilename(filename); err != nil {
116 t.Error(err)
117 }
Tatiana Bradleya435f712023-08-29 17:49:11 -0400118 lints := lint(r)
Julie Qiu733040a2021-12-20 17:14:01 -0500119 if len(lints) > 0 {
120 t.Errorf(strings.Join(lints, "\n"))
121 }
Tatiana Bradley0fee2382024-06-14 14:25:47 -0400122 duplicates := make(map[string][]string)
Tatiana Bradley5c064e02023-05-23 14:29:53 -0400123 for _, alias := range r.Aliases() {
Tatiana Bradleybca6ae22024-07-15 16:36:44 -0400124 for _, r2 := range rc.ReportsByAlias(alias) {
125 if r2.ID != r.ID {
126 duplicates[r2.ID] = append(duplicates[r2.ID], alias)
127 }
Maceo Thompsone2eba222022-11-18 13:35:03 -0500128 }
129 }
Tatiana Bradleybca6ae22024-07-15 16:36:44 -0400130 for r2, aliases := range duplicates {
131 t.Errorf("report %s shares duplicate alias(es) %s with report %s", filename, aliases, r2)
Tatiana Bradley0fee2382024-06-14 14:25:47 -0400132 }
Tatiana Bradley922b5d42024-06-04 16:59:28 -0400133 // Ensure that each reviewed report has a unique summary.
134 if r.IsReviewed() {
135 if summary := r.Summary.String(); summary != "" {
136 if report, ok := summaries[summary]; ok {
137 t.Errorf("report %s shares duplicate summary %q with report %s", filename, summary, report)
138 } else {
139 summaries[summary] = filename
140 }
Tatiana Bradleyadabd302023-11-20 13:52:02 -0500141 }
142 }
Tatiana Bradleybca6ae22024-07-15 16:36:44 -0400143 // Ensure that no unreviewed reports are high priority.
144 // This can happen because the initial quick triage algorithm
145 // doesn't know about all affected modules - just the one
146 // listed in the Github issue.
147 if r.IsUnreviewed() {
148 pr, _ := priority.AnalyzeReport(r, rc, modulesToImports)
149 if pr.Priority == priority.High {
150 t.Errorf("UNREVIEWED report %s is high priority (should be REVIEWED) - reason: %s", filename, pr.Reason)
151 }
152 }
Tatiana Bradley2551a342022-09-26 12:18:29 -0400153 // Check that a correct OSV file was generated for each YAML report.
Damien Neil2c15bf72022-09-13 16:09:01 -0700154 if r.Excluded == "" {
Tatiana Bradleyb2598232024-06-21 18:36:29 -0400155 generated, err := r.ToOSV(time.Time{})
156 if err != nil {
157 t.Fatal(err)
158 }
Tatiana Bradleyf7620432023-05-25 11:11:56 -0400159 osvFilename := r.OSVFilename()
Tatiana Bradleydefb5802022-11-18 16:26:39 -0500160 current, err := report.ReadOSV(osvFilename)
Damien Neil2c15bf72022-09-13 16:09:01 -0700161 if err != nil {
162 t.Fatal(err)
163 }
Tatiana Bradley2551a342022-09-26 12:18:29 -0400164 if diff := cmp.Diff(generated, current, cmpopts.EquateEmpty()); diff != "" {
Tatiana Bradleydefb5802022-11-18 16:26:39 -0500165 t.Errorf("%s does not match report:\n%v", osvFilename, diff)
Damien Neil2c15bf72022-09-13 16:09:01 -0700166 }
Tatiana Bradley0cbf4ff2023-05-12 16:14:27 -0400167 if err := osvutils.ValidateExceptTimestamps(&current); err != nil {
168 t.Error(err)
169 }
Damien Neil2c15bf72022-09-13 16:09:01 -0700170 }
Maceo Thompsonb8b87b12022-10-20 15:14:42 -0400171 if r.CVEMetadata != nil {
Tatiana Bradley2ff2c862024-05-06 17:34:29 -0400172 generated, err := cve5.FromReport(r)
Maceo Thompsonb8b87b12022-10-20 15:14:42 -0400173 if err != nil {
174 t.Fatal(err)
175 }
Tatiana Bradleyf7620432023-05-25 11:11:56 -0400176 cvePath := r.CVEFilename()
Tatiana Bradley2ff2c862024-05-06 17:34:29 -0400177 current, err := cve5.Read(cvePath)
Maceo Thompsonb8b87b12022-10-20 15:14:42 -0400178 if err != nil {
179 t.Fatal(err)
180 }
181 if diff := cmp.Diff(generated, current, cmpopts.EquateEmpty()); diff != "" {
182 t.Errorf("%s does not match report:\n%v", cvePath, diff)
183 }
184
185 }
Julie Qiu733040a2021-12-20 17:14:01 -0500186 })
187 }
188}