44 "context"
55 "crypto/rand"
66 "encoding/hex"
7+ "encoding/json"
78 "io"
89 "net/http"
910 "testing"
@@ -19,6 +20,8 @@ import (
1920 pgtest "github.com/quay/claircore/test/postgres"
2021)
2122
23+ var _ driver.Updater = (* updaterMock )(nil )
24+
2225type updaterMock struct {
2326 _name func () string
2427 _fetch func (_ context.Context , _ driver.Fingerprint ) (io.ReadCloser , driver.Fingerprint , error )
@@ -37,6 +40,30 @@ func (u *updaterMock) Parse(ctx context.Context, contents io.ReadCloser) ([]*cla
3740 return u ._parse (ctx , contents )
3841}
3942
43+ var (
44+ _ driver.Updater = (* enricherMock )(nil )
45+ _ driver.EnrichmentUpdater = (* enricherMock )(nil )
46+ )
47+
48+ type enricherMock struct {
49+ driver.NoopUpdater
50+ _name func () string
51+ _fetch func (_ context.Context , _ driver.Fingerprint ) (io.ReadCloser , driver.Fingerprint , error )
52+ _parse func (ctx context.Context , contents io.ReadCloser ) ([]driver.EnrichmentRecord , error )
53+ }
54+
55+ func (e enricherMock ) Name () string {
56+ return e ._name ()
57+ }
58+
59+ func (e enricherMock ) FetchEnrichment (ctx context.Context , fingerprint driver.Fingerprint ) (io.ReadCloser , driver.Fingerprint , error ) {
60+ return e ._fetch (ctx , fingerprint )
61+ }
62+
63+ func (e enricherMock ) ParseEnrichment (ctx context.Context , contents io.ReadCloser ) ([]driver.EnrichmentRecord , error ) {
64+ return e ._parse (ctx , contents )
65+ }
66+
4067// TestGC confirms the garbage collection of
4168// vulnerabilities works correctly.
4269func TestGC (t * testing.T ) {
@@ -60,6 +87,23 @@ func TestGC(t *testing.T) {
6087 },
6188 }
6289
90+ // mock returns exactly one random enrichment each time its Parse method is called.
91+ // each update operation will be associated with a single enrichment.
92+ mockEnrich := & enricherMock {
93+ _name : func () string { return "MockEnrichmentUpdater" },
94+ _fetch : func (_ context.Context , _ driver.Fingerprint ) (io.ReadCloser , driver.Fingerprint , error ) {
95+ return nil , "" , nil
96+ },
97+ _parse : func (ctx context.Context , contents io.ReadCloser ) ([]driver.EnrichmentRecord , error ) {
98+ return []driver.EnrichmentRecord {
99+ {
100+ Tags : []string {randString (t )},
101+ Enrichment : json .RawMessage ("{}" ),
102+ },
103+ }, nil
104+ },
105+ }
106+
63107 // these tests maintain a one:one relationship between
64108 // update operations and a linked vulnerability for simplicty.
65109 // in other words, each update operation inserts one vuln and
@@ -116,14 +160,22 @@ func TestGC(t *testing.T) {
116160 locks ,
117161 http .DefaultClient , // Used on purpose -- shouldn't actually get called by anything.
118162 updates .WithEnabled ([]string {}),
163+ updates .WithFactories (map [string ]driver.UpdaterSetFactory {
164+ "MockEnrichmentUpdater" : func () driver.UpdaterSetFactory {
165+ set := driver .NewUpdaterSet ()
166+ _ = set .Add (mockEnrich )
167+ return driver .StaticSet (set )
168+ }(),
169+ }),
119170 updates .WithOutOfTree ([]driver.Updater {mock }),
120171 )
121172 if err != nil {
122173 t .Fatalf ("failed creating update manager: %v" , err )
123174 }
124175
176+ t .Logf ("update Opts: %d" , tt .updateOps )
125177 // run updater n times to create n update operations
126- for i := 0 ; i < tt .updateOps ; i ++ {
178+ for range tt .updateOps {
127179 err := mgr .Run (ctx )
128180 if err != nil {
129181 t .Fatalf ("manager failed to run: %v" , err )
@@ -138,9 +190,16 @@ func TestGC(t *testing.T) {
138190 if len (ops ["MockUpdater" ]) != tt .updateOps {
139191 t .Fatalf ("%s got: %v want: %v" , tt .name , len (ops ["MockUpdater" ]), tt .updateOps )
140192 }
193+ ops , err = store .GetUpdateOperations (ctx , driver .EnrichmentKind )
194+ if err != nil {
195+ t .Fatalf ("failed obtaining enrichment update ops: %v" , err )
196+ }
197+ if len (ops ["MockEnrichmentUpdater" ]) != tt .updateOps {
198+ t .Fatalf ("%s got: %v want: %v" , tt .name , len (ops ["MockEnrichmentUpdater" ]), tt .updateOps )
199+ }
141200
142201 // run gc
143- expectedNotDone := Max ( tt .updateOps - tt .keep - GCThrottle , 0 )
202+ expectedNotDone := max ( 2 * ( tt .updateOps - tt .keep ) - GCThrottle , 0 )
144203 notDone , err := store .GC (ctx , tt .keep )
145204 switch {
146205 case err != nil :
@@ -153,14 +212,20 @@ func TestGC(t *testing.T) {
153212 if tt .updateOps < tt .keep {
154213 wantKeep = tt .updateOps
155214 }
156- ops , err = store .GetUpdateOperations (ctx , driver .VulnerabilityKind )
215+ expectedRemaining := 2 * wantKeep + expectedNotDone
216+
217+ updaterOps , err := store .GetUpdateOperations (ctx , driver .VulnerabilityKind )
157218 if err != nil {
158219 t .Fatalf ("failed obtaining update ops: %v" , err )
159220 }
160- t .Logf ("ops %v" , ops )
161- expectedRemaining := wantKeep + expectedNotDone
162- if len (ops ["MockUpdater" ]) != expectedRemaining {
163- t .Fatalf ("%s got: %v want: %v" , tt .name , len (ops ["MockUpdater" ]), expectedRemaining )
221+ t .Logf ("ops %v" , updaterOps )
222+ enricherOps , err := store .GetUpdateOperations (ctx , driver .EnrichmentKind )
223+ if err != nil {
224+ t .Fatalf ("failed obtaining enrichment update ops: %v" , err )
225+ }
226+ t .Logf ("ops %v" , enricherOps )
227+ if len (updaterOps ["MockUpdater" ])+ len (enricherOps ["MockEnrichmentUpdater" ]) != expectedRemaining {
228+ t .Fatalf ("%s got: %v want: %v" , tt .name , len (updaterOps ["MockUpdater" ])+ len (enricherOps ["MockEnrichmentUpdater" ]), expectedRemaining )
164229 }
165230 })
166231 }
@@ -174,10 +239,3 @@ func randString(t *testing.T) string {
174239 }
175240 return hex .EncodeToString (buf )
176241}
177-
178- func Max (x , y int ) int {
179- if x < y {
180- return y
181- }
182- return x
183- }
0 commit comments