@@ -20,9 +20,13 @@ package evaluator
2020
2121import (
2222 "testing"
23+ "time"
2324
25+ ecc "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1"
2426 "github.com/stretchr/testify/assert"
2527 "github.com/stretchr/testify/require"
28+
29+ "github.com/conforma/cli/internal/policy"
2630)
2731
2832func TestLen (t * testing.T ) {
@@ -256,3 +260,145 @@ func TestGet(t *testing.T) {
256260 })
257261 }
258262}
263+
264+ // MockConfigProvider implements ConfigProvider interface for testing
265+ type MockConfigProvider struct {
266+ effectiveTime time.Time
267+ }
268+
269+ func (m * MockConfigProvider ) EffectiveTime () time.Time {
270+ return m .effectiveTime
271+ }
272+
273+ func (m * MockConfigProvider ) SigstoreOpts () (policy.SigstoreOpts , error ) {
274+ return policy.SigstoreOpts {}, nil
275+ }
276+
277+ func (m * MockConfigProvider ) Spec () ecc.EnterpriseContractPolicySpec {
278+ return ecc.EnterpriseContractPolicySpec {}
279+ }
280+
281+ func TestCollectVolatileConfigItems (t * testing.T ) {
282+ // Create a fixed time for testing
283+ fixedTime := time .Date (2025 , 8 , 18 , 12 , 0 , 0 , 0 , time .UTC )
284+
285+ tests := []struct {
286+ name string
287+ items * Criteria
288+ volatileCriteria []ecc.VolatileCriteria
289+ configProvider ConfigProvider
290+ expectedItems * Criteria
291+ expectedSuccess bool
292+ }{
293+ {
294+ name : "Successful scenario - criteria within time range" ,
295+ items : & Criteria {
296+ digestItems : make (map [string ][]string ),
297+ defaultItems : []string {"existing-item" },
298+ },
299+ volatileCriteria : []ecc.VolatileCriteria {
300+ {
301+ Value : "volatile-item-1" ,
302+ EffectiveOn : "2025-08-01T00:00:00Z" ,
303+ EffectiveUntil : "2025-08-31T23:59:59Z" ,
304+ ImageRef : "quay.io/test/image:latest" ,
305+ },
306+ {
307+ Value : "volatile-item-2" ,
308+ EffectiveOn : "2025-08-10T00:00:00Z" ,
309+ EffectiveUntil : "2025-08-20T23:59:59Z" ,
310+ ImageDigest : "sha256:abc123" ,
311+ },
312+ },
313+ configProvider : & MockConfigProvider {effectiveTime : fixedTime },
314+ expectedItems : & Criteria {
315+ digestItems : map [string ][]string {
316+ "quay.io/test/image:latest" : {"volatile-item-1" },
317+ "sha256:abc123" : {"volatile-item-2" },
318+ },
319+ defaultItems : []string {"existing-item" },
320+ },
321+ expectedSuccess : true ,
322+ },
323+ {
324+ name : "Failed scenario - criteria outside time range" ,
325+ items : & Criteria {
326+ digestItems : make (map [string ][]string ),
327+ defaultItems : []string {"existing-item" },
328+ },
329+ volatileCriteria : []ecc.VolatileCriteria {
330+ {
331+ Value : "expired-item" ,
332+ EffectiveOn : "2025-07-01T00:00:00Z" ,
333+ EffectiveUntil : "2025-07-31T23:59:59Z" ,
334+ ImageUrl : "quay.io/test/expired" ,
335+ },
336+ {
337+ Value : "future-item" ,
338+ EffectiveOn : "2025-09-01T00:00:00Z" ,
339+ EffectiveUntil : "2025-09-30T23:59:59Z" ,
340+ ImageRef : "quay.io/test/future" ,
341+ },
342+ },
343+ configProvider : & MockConfigProvider {effectiveTime : fixedTime },
344+ expectedItems : & Criteria {
345+ digestItems : make (map [string ][]string ),
346+ defaultItems : []string {"existing-item" },
347+ },
348+ expectedSuccess : true , // Function doesn't fail, just doesn't add items
349+ },
350+ {
351+ name : "Warning scenario - invalid time formats" ,
352+ items : & Criteria {
353+ digestItems : make (map [string ][]string ),
354+ defaultItems : []string {"existing-item" },
355+ },
356+ volatileCriteria : []ecc.VolatileCriteria {
357+ {
358+ Value : "partial-invalid-item" ,
359+ EffectiveOn : "2025-08-01T00:00:00Z" , // Valid format
360+ EffectiveUntil : "not-a-date" , // Invalid format
361+ ImageDigest : "sha256:def456" ,
362+ },
363+ },
364+ configProvider : & MockConfigProvider {effectiveTime : fixedTime },
365+ expectedItems : & Criteria {
366+ digestItems : map [string ][]string {
367+ "sha256:def456" : {"partial-invalid-item" },
368+ },
369+ defaultItems : []string {"existing-item" },
370+ },
371+ expectedSuccess : true , // Function handles invalid times gracefully
372+ },
373+ }
374+
375+ for _ , tt := range tests {
376+ t .Run (tt .name , func (t * testing.T ) {
377+ // Create a copy of the initial items to avoid modifying the test data
378+ initialItems := & Criteria {
379+ digestItems : make (map [string ][]string ),
380+ defaultItems : make ([]string , len (tt .items .defaultItems )),
381+ }
382+ copy (initialItems .defaultItems , tt .items .defaultItems )
383+ for k , v := range tt .items .digestItems {
384+ initialItems .digestItems [k ] = make ([]string , len (v ))
385+ copy (initialItems .digestItems [k ], v )
386+ }
387+
388+ // Call the function
389+ result := collectVolatileConfigItems (initialItems , tt .volatileCriteria , tt .configProvider )
390+
391+ // Verify the result
392+ if tt .expectedSuccess {
393+ require .Equal (t , tt .expectedItems .defaultItems , result .defaultItems , "defaultItems mismatch" )
394+ require .Equal (t , len (tt .expectedItems .digestItems ), len (result .digestItems ), "digestItems count mismatch" )
395+
396+ for expectedKey , expectedValues := range tt .expectedItems .digestItems {
397+ actualValues , exists := result .digestItems [expectedKey ]
398+ require .True (t , exists , "Expected key %s not found in result" , expectedKey )
399+ require .Equal (t , expectedValues , actualValues , "Values mismatch for key %s" , expectedKey )
400+ }
401+ }
402+ })
403+ }
404+ }
0 commit comments