github.com/quay/claircore@v1.5.28/rhel/rhcc/matcher_integration_test.go (about) 1 package rhcc 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io" 8 "net/http" 9 "net/http/httptest" 10 "os" 11 "path/filepath" 12 "testing" 13 14 "github.com/quay/zlog" 15 16 "github.com/quay/claircore" 17 "github.com/quay/claircore/datastore/postgres" 18 match_engine "github.com/quay/claircore/internal/matcher" 19 "github.com/quay/claircore/libvuln/driver" 20 "github.com/quay/claircore/libvuln/updates" 21 "github.com/quay/claircore/pkg/ctxlock" 22 "github.com/quay/claircore/test/integration" 23 testpostgres "github.com/quay/claircore/test/postgres" 24 ) 25 26 func TestMain(m *testing.M) { 27 var c int 28 defer func() { os.Exit(c) }() 29 defer integration.DBSetup()() 30 c = m.Run() 31 } 32 33 func TestMatcherIntegration(t *testing.T) { 34 t.Parallel() 35 36 type testcase struct { 37 Name string 38 cvemap string 39 indexReport string 40 cveID string 41 match bool 42 } 43 table := []testcase{ 44 { 45 Name: "Clair", 46 cvemap: "cve-2021-3762", 47 indexReport: "clair-rhel8-v3.5.5-4", 48 cveID: "RHSA-2021:3665", 49 match: true, 50 }, 51 { 52 Name: "Rook4.6", 53 cvemap: "cve-2020-8565", 54 indexReport: "rook-ceph-operator-container-4.6-115.d1788e1.release_4.6", 55 cveID: "RHSA-2021:2041", 56 match: true, 57 }, 58 { 59 Name: "Rook4.7", 60 cvemap: "cve-2020-8565", 61 indexReport: "rook-ceph-operator-container-4.7-159.76b9b11.release_4.7", 62 cveID: "RHSA-2021:2041", 63 match: false, 64 }, 65 } 66 67 for i := range table { 68 tt := &table[i] 69 t.Run(tt.Name, func(t *testing.T) { 70 t.Parallel() 71 integration.NeedDB(t) 72 ctx := zlog.Test(context.Background(), t) 73 pool := testpostgres.TestMatcherDB(ctx, t) 74 store := postgres.NewMatcherStore(pool) 75 m := &matcher{} 76 77 serveFile := filepath.Join("testdata", tt.cvemap+".xml") 78 fi, err := os.Stat(serveFile) 79 if err != nil { 80 t.Fatal(err) 81 } 82 tag := fmt.Sprintf(`"%d"`, fi.ModTime().UnixNano()) 83 srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 84 switch r.URL.Path { 85 case "/cvemap.xml": 86 w.Header().Set("etag", tag) 87 http.ServeFile(w, r, serveFile) 88 case "/cvemap.xml.bz2": 89 http.Error(w, "no bz2", http.StatusNotFound) 90 default: 91 t.Errorf("unexpected request: %s", r.URL) 92 http.Error(w, "???", http.StatusNotImplemented) 93 } 94 })) 95 defer srv.Close() 96 s := driver.NewUpdaterSet() 97 if err := s.Add(new(updater)); err != nil { 98 t.Error(err) 99 } 100 cfg := updates.Configs{ 101 updaterName: func(v any) error { 102 cfg := v.(*UpdaterConfig) 103 cfg.URL = srv.URL + "/cvemap.xml" 104 return nil 105 }, 106 } 107 108 locks, err := ctxlock.New(ctx, pool) 109 if err != nil { 110 t.Error(err) 111 } 112 defer locks.Close(ctx) 113 114 facs := make(map[string]driver.UpdaterSetFactory, 1) 115 facs[updaterName] = driver.StaticSet(s) 116 mgr, err := updates.NewManager(ctx, store, locks, srv.Client(), updates.WithFactories(facs), updates.WithConfigs(cfg)) 117 if err != nil { 118 t.Error(err) 119 } 120 121 // force update 122 if err := mgr.Run(ctx); err != nil { 123 t.Error(err) 124 } 125 126 f, err := os.Open(filepath.Join("testdata", fmt.Sprintf("%s-indexreport.json", tt.indexReport))) 127 if err != nil { 128 t.Fatalf("%v", err) 129 } 130 defer f.Close() 131 var ir claircore.IndexReport 132 if err := json.NewDecoder(f).Decode(&ir); err != nil { 133 t.Fatalf("failed to decode IndexReport: %v", err) 134 } 135 vr, err := match_engine.Match(ctx, &ir, []driver.Matcher{m}, store) 136 if err != nil { 137 t.Fatal(err) 138 } 139 found := false 140 vulns := vr.Vulnerabilities 141 for _, vuln := range vulns { 142 t.Log(vuln.Name) 143 if vuln.Name == tt.cveID { 144 found = true 145 } 146 } 147 if found != tt.match { 148 t.Fatalf("Expected to find %s in vulnerability report", tt.cveID) 149 } 150 if err := json.NewEncoder(io.Discard).Encode(&vr); err != nil { 151 t.Fatalf("failed to marshal VR: %v", err) 152 } 153 }) 154 } 155 }