Skip to content

Commit 95b8d65

Browse files
authored
test: fix some coverage issues, refactored some of the pagination logic to accomplish this (#3674)
Signed-off-by: Andrei Aaron <[email protected]>
1 parent 4ad3fad commit 95b8d65

File tree

6 files changed

+154
-46
lines changed

6 files changed

+154
-46
lines changed

pkg/api/htpasswd_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,5 +538,45 @@ func TestHTPasswdWatcher(t *testing.T) {
538538
So(ok, ShouldBeTrue)
539539
So(present, ShouldBeTrue)
540540
})
541+
542+
Convey("Test htpasswd file with zero users warning", func() {
543+
// Create a buffer to capture log output
544+
logBuffer, multiWriter := test.CreateLogCapturingWriter(os.Stdout)
545+
capturingLogger := log.NewLoggerWithWriter("debug", multiWriter)
546+
547+
username, _ := test.GenerateRandomString()
548+
password, _ := test.GenerateRandomString()
549+
550+
htp := api.NewHTPasswd(capturingLogger)
551+
552+
// Create an empty htpasswd file (zero users)
553+
emptyPath := test.MakeHtpasswdFileFromString(t, "")
554+
555+
// Reload the empty file
556+
err := htp.Reload(emptyPath)
557+
So(err, ShouldBeNil)
558+
559+
// Verify the warning message is logged
560+
So(test.WaitForLogMessages(logBuffer, "loaded htpasswd file appears to have zero users", 1, 5*time.Second),
561+
ShouldBeTrue)
562+
563+
// Verify store is empty
564+
_, present := htp.Get(username)
565+
So(present, ShouldBeFalse)
566+
567+
// Now load a file with a user and verify the info message instead
568+
userPath := test.MakeHtpasswdFileFromString(t, test.GetBcryptCredString(username, password))
569+
570+
err = htp.Reload(userPath)
571+
So(err, ShouldBeNil)
572+
573+
// Verify the info message is logged
574+
So(test.WaitForLogMessages(logBuffer, "loaded htpasswd file", 1, 5*time.Second), ShouldBeTrue)
575+
576+
// Verify user is present
577+
ok, present := htp.Authenticate(username, password)
578+
So(ok, ShouldBeTrue)
579+
So(present, ShouldBeTrue)
580+
})
541581
})
542582
}

pkg/cli/server/root.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,11 @@ func validateStorageConfig(cfg *config.Config, logger zlog.Logger) error {
324324
})
325325
}
326326

327+
// Sort stores by route to ensure deterministic ordering
328+
slices.SortFunc(allStores, func(a, b storeInfo) int {
329+
return strings.Compare(a.route, b.route)
330+
})
331+
327332
// Validate each store
328333
for _, store := range allStores {
329334
route := store.route

pkg/cli/server/root_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,44 @@ storage:
12661266
os.Args = []string{"cli_test", "verify", tmpfile}
12671267
err = cli.NewServerRootCmd().Execute()
12681268
So(err, ShouldBeNil)
1269+
1270+
// Default local store is inside substore (should be rejected)
1271+
// default is at /tmp/zot-parent/subdir, /a is at /tmp/zot-parent
1272+
content = `{"storage":{"rootDirectory":"/tmp/zot-parent/subdir",
1273+
"subPaths": {"/a": {"rootDirectory": "/tmp/zot-parent"}}},
1274+
"http":{"address":"127.0.0.1","port":"8080","realm":"zot",
1275+
"auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`
1276+
err = os.WriteFile(tmpfile, []byte(content), 0o0600)
1277+
So(err, ShouldBeNil)
1278+
1279+
os.Args = []string{"cli_test", "verify", tmpfile}
1280+
err = cli.NewServerRootCmd().Execute()
1281+
So(err, ShouldNotBeNil)
1282+
// default storage is inside /a, validation reports this conflict
1283+
So(err.Error(), ShouldContainSubstring,
1284+
"invalid storage config, default storage root directory cannot be inside substore (route: /a) root directory")
1285+
1286+
// Default S3 store is inside substore, with S3, (should be rejected)
1287+
// default is at /zot-parent/subdir, /a is at /zot-parent
1288+
content = `{"storage":{"rootDirectory":"/zot-parent/subdir",
1289+
"storageDriver":{"name":"s3","rootdirectory":"/zot-parent/subdir","region":"us-east-2",
1290+
"bucket":"zot-storage","secure":true,"skipverify":false},
1291+
"dedupe":false,
1292+
"subPaths": {"/a": {"rootDirectory": "/zot-parent",
1293+
"storageDriver":{"name":"s3","rootdirectory":"/zot-parent","region":"us-east-2",
1294+
"bucket":"zot-storage","secure":true,"skipverify":false},
1295+
"dedupe":false}}},
1296+
"http":{"address":"127.0.0.1","port":"8080","realm":"zot",
1297+
"auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`
1298+
err = os.WriteFile(tmpfile, []byte(content), 0o0600)
1299+
So(err, ShouldBeNil)
1300+
1301+
os.Args = []string{"cli_test", "verify", tmpfile}
1302+
err = cli.NewServerRootCmd().Execute()
1303+
So(err, ShouldNotBeNil)
1304+
// default storage is inside /a, validation reports this conflict
1305+
So(err.Error(), ShouldContainSubstring,
1306+
"invalid storage config, default storage root directory cannot be inside substore (route: /a) root directory")
12691307
})
12701308

12711309
Convey("Test verify w/ authorization and w/o authentication", t, func(c C) {

pkg/extensions/search/cve/cve.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -339,21 +339,29 @@ func getConfigAndDigest(metaDB mTypes.MetaDB, manifestDigestStr string) (ispec.I
339339
return manifestData.Manifests[0].Config, manifestDigest, err
340340
}
341341

342+
func shouldIncludeCVE(cve cvemodel.CVE, searchedCVE, excludedCVE, severity string) bool {
343+
if severity != "" && (cvemodel.CompareSeverities(cve.Severity, severity) != 0) {
344+
return false
345+
}
346+
347+
if excludedCVE != "" && cve.ContainsStr(excludedCVE) {
348+
return false
349+
}
350+
351+
if !cve.ContainsStr(searchedCVE) {
352+
return false
353+
}
354+
355+
return true
356+
}
357+
342358
func filterCVEMap(cveMap map[string]cvemodel.CVE, searchedCVE, excludedCVE, severity string,
343359
pageFinder *CvePageFinder,
344360
) {
345361
searchedCVE = strings.ToUpper(searchedCVE)
346362

347363
for _, cve := range cveMap {
348-
if severity != "" && (cvemodel.CompareSeverities(cve.Severity, severity) != 0) {
349-
continue
350-
}
351-
352-
if excludedCVE != "" && cve.ContainsStr(excludedCVE) {
353-
continue
354-
}
355-
356-
if cve.ContainsStr(searchedCVE) {
364+
if shouldIncludeCVE(cve, searchedCVE, excludedCVE, severity) {
357365
pageFinder.Add(cve)
358366
}
359367
}
@@ -363,15 +371,7 @@ func filterCVEList(cveList []cvemodel.CVE, searchedCVE, excludedCVE, severity st
363371
searchedCVE = strings.ToUpper(searchedCVE)
364372

365373
for _, cve := range cveList {
366-
if severity != "" && (cvemodel.CompareSeverities(cve.Severity, severity) != 0) {
367-
continue
368-
}
369-
370-
if excludedCVE != "" && cve.ContainsStr(excludedCVE) {
371-
continue
372-
}
373-
374-
if cve.ContainsStr(searchedCVE) {
374+
if shouldIncludeCVE(cve, searchedCVE, excludedCVE, severity) {
375375
pageFinder.Add(cve)
376376
}
377377
}

pkg/extensions/search/cve/cve_internal_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,57 @@ func TestUtils(t *testing.T) {
136136
})
137137
So(tags, ShouldBeEmpty)
138138
})
139+
140+
Convey("shouldIncludeCVE filtering logic", func() {
141+
baseCVE := cvemodel.CVE{
142+
ID: "CVE-2024-0001",
143+
Severity: "HIGH",
144+
Title: "Test CVE 1",
145+
Description: "Description contains keyword",
146+
}
147+
148+
Convey("includes CVE when all filters pass", func() {
149+
// No filters
150+
So(shouldIncludeCVE(baseCVE, "", "", ""), ShouldBeTrue)
151+
152+
// Matching searchedCVE
153+
So(shouldIncludeCVE(baseCVE, "CVE-2024", "", ""), ShouldBeTrue)
154+
So(shouldIncludeCVE(baseCVE, "keyword", "", ""), ShouldBeTrue)
155+
156+
// Matching severity
157+
So(shouldIncludeCVE(baseCVE, "", "", "HIGH"), ShouldBeTrue)
158+
})
159+
160+
Convey("excludes CVE when severity doesn't match", func() {
161+
So(shouldIncludeCVE(baseCVE, "", "", "LOW"), ShouldBeFalse)
162+
So(shouldIncludeCVE(baseCVE, "", "", "MEDIUM"), ShouldBeFalse)
163+
So(shouldIncludeCVE(baseCVE, "", "", "CRITICAL"), ShouldBeFalse)
164+
})
165+
166+
Convey("excludes CVE when it contains excluded string", func() {
167+
So(shouldIncludeCVE(baseCVE, "", "keyword", ""), ShouldBeFalse)
168+
So(shouldIncludeCVE(baseCVE, "", "CVE-2024", ""), ShouldBeFalse)
169+
So(shouldIncludeCVE(baseCVE, "", "Test CVE", ""), ShouldBeFalse)
170+
})
171+
172+
Convey("excludes CVE when searchedCVE doesn't match", func() {
173+
So(shouldIncludeCVE(baseCVE, "CVE-2023", "", ""), ShouldBeFalse)
174+
So(shouldIncludeCVE(baseCVE, "notfound", "", ""), ShouldBeFalse)
175+
})
176+
177+
Convey("handles multiple filters combined", func() {
178+
// All filters match - should include
179+
So(shouldIncludeCVE(baseCVE, "CVE-2024", "", "HIGH"), ShouldBeTrue)
180+
181+
// Severity matches but excluded - should exclude
182+
So(shouldIncludeCVE(baseCVE, "", "keyword", "HIGH"), ShouldBeFalse)
183+
184+
// Searched matches but severity doesn't - should exclude
185+
So(shouldIncludeCVE(baseCVE, "CVE-2024", "", "LOW"), ShouldBeFalse)
186+
187+
// Everything matches but excluded - should exclude
188+
So(shouldIncludeCVE(baseCVE, "CVE-2024", "Test", "HIGH"), ShouldBeFalse)
189+
})
190+
})
139191
})
140192
}

pkg/extensions/search/resolver.go

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,34 +1440,7 @@ func expandedRepoInfo(ctx context.Context, repo string, metaDB mTypes.MetaDB, cv
14401440
dateSortedImages = append(dateSortedImages, imgSummary)
14411441
}
14421442

1443-
//nolint:varnamelen // standard comparison func signature
1444-
slices.SortFunc(dateSortedImages, func(a, b *gql_generated.ImageSummary) int {
1445-
// Handle nil and zero time cases: both are treated as oldest (come last in descending sort)
1446-
aIsZero := a.LastUpdated == nil || (a.LastUpdated != nil && a.LastUpdated.IsZero())
1447-
bIsZero := b.LastUpdated == nil || (b.LastUpdated != nil && b.LastUpdated.IsZero())
1448-
1449-
if aIsZero && bIsZero {
1450-
return 0
1451-
}
1452-
1453-
if aIsZero {
1454-
return 1 // a is zero/nil, b is not - a comes after b
1455-
}
1456-
1457-
if bIsZero {
1458-
return -1 // b is zero/nil, a is not - a comes before b
1459-
}
1460-
1461-
if a.LastUpdated.After(*b.LastUpdated) {
1462-
return -1
1463-
}
1464-
1465-
if a.LastUpdated.Equal(*b.LastUpdated) {
1466-
return 0
1467-
}
1468-
1469-
return 1
1470-
})
1443+
slices.SortFunc(dateSortedImages, pagination.ImgSortByUpdateTime)
14711444

14721445
return &gql_generated.RepoInfo{Summary: repoSummary, Images: dateSortedImages}, nil
14731446
}

0 commit comments

Comments
 (0)