@@ -2,9 +2,11 @@ package match
22
33import (
44 "testing"
5+ "time"
56
67 "github.com/google/uuid"
78 "github.com/stretchr/testify/assert"
9+ "github.com/stretchr/testify/require"
810
911 "github.com/anchore/grype/grype/pkg"
1012 "github.com/anchore/grype/grype/vulnerability"
@@ -1352,6 +1354,42 @@ func TestShouldIgnore(t *testing.T) {
13521354 },
13531355 expected : false ,
13541356 },
1357+ {
1358+ name : "rule applies when expires-after is in the future" ,
1359+ match : exampleMatch ,
1360+ rule : IgnoreRule {
1361+ Vulnerability : exampleMatch .Vulnerability .ID ,
1362+ ExpiresAfter : time .Now ().UTC ().Add (48 * time .Hour ).Format (expiresAfterDateFmt ),
1363+ },
1364+ expected : true ,
1365+ },
1366+ {
1367+ name : "rule does not apply when expires-after is in the past" ,
1368+ match : exampleMatch ,
1369+ rule : IgnoreRule {
1370+ Vulnerability : exampleMatch .Vulnerability .ID ,
1371+ ExpiresAfter : time .Now ().UTC ().Add (- 48 * time .Hour ).Format (expiresAfterDateFmt ),
1372+ },
1373+ expected : false ,
1374+ },
1375+ {
1376+ name : "rule applies when expires-after is empty" ,
1377+ match : exampleMatch ,
1378+ rule : IgnoreRule {
1379+ Vulnerability : exampleMatch .Vulnerability .ID ,
1380+ ExpiresAfter : "" ,
1381+ },
1382+ expected : true ,
1383+ },
1384+ {
1385+ name : "rule applies (does not crash) when expires-after is malformed" ,
1386+ match : exampleMatch ,
1387+ rule : IgnoreRule {
1388+ Vulnerability : exampleMatch .Vulnerability .ID ,
1389+ ExpiresAfter : "not-a-date" ,
1390+ },
1391+ expected : true ,
1392+ },
13551393 }
13561394
13571395 for _ , testCase := range cases {
@@ -1361,3 +1399,44 @@ func TestShouldIgnore(t *testing.T) {
13611399 })
13621400 }
13631401}
1402+
1403+ func TestParseExpiresAfter (t * testing.T ) {
1404+ cases := []struct {
1405+ name string
1406+ input string
1407+ expectZero bool
1408+ expectError bool
1409+ expectDate string
1410+ }{
1411+ {name : "valid date" , input : "2026-12-31" , expectDate : "2026-12-31" },
1412+ {name : "empty string returns zero with no error" , input : "" , expectZero : true },
1413+ {name : "invalid format returns error" , input : "31-12-2026" , expectError : true },
1414+ {name : "not a date returns error" , input : "tomorrow" , expectError : true },
1415+ }
1416+
1417+ for _ , tc := range cases {
1418+ t .Run (tc .name , func (t * testing.T ) {
1419+ got , err := parseExpiresAfter (tc .input )
1420+ if tc .expectError {
1421+ require .Error (t , err )
1422+ return
1423+ }
1424+ require .NoError (t , err )
1425+ if tc .expectZero {
1426+ assert .True (t , got .IsZero ())
1427+ return
1428+ }
1429+ assert .Equal (t , tc .expectDate , got .Format (expiresAfterDateFmt ))
1430+ })
1431+ }
1432+ }
1433+
1434+ func TestIsExpiresAfterInPast (t * testing.T ) {
1435+ past := time .Now ().UTC ().Add (- 48 * time .Hour ).Format (expiresAfterDateFmt )
1436+ future := time .Now ().UTC ().Add (48 * time .Hour ).Format (expiresAfterDateFmt )
1437+
1438+ assert .True (t , isExpiresAfterInPast (past ), "a past date should be expired" )
1439+ assert .False (t , isExpiresAfterInPast (future ), "a future date should not be expired" )
1440+ assert .False (t , isExpiresAfterInPast ("" ), "empty string should not be expired" )
1441+ assert .False (t , isExpiresAfterInPast ("not-a-date" ), "malformed input should not be expired (defensive)" )
1442+ }
0 commit comments