github.com/anchore/syft@v1.38.2/internal/packagemetadata/completion_tester.go (about) 1 package packagemetadata 2 3 import ( 4 "reflect" 5 "testing" 6 ) 7 8 type CompletionTester struct { 9 saw []any 10 valid []any 11 ignore []any 12 } 13 14 func NewCompletionTester(t testing.TB, ignore ...any) *CompletionTester { 15 t.Helper() 16 tester := &CompletionTester{ 17 valid: AllTypes(), 18 ignore: ignore, 19 } 20 t.Cleanup(func() { 21 t.Helper() 22 tester.validate(t) 23 }) 24 return tester 25 } 26 27 func (tr *CompletionTester) Ignore(is ...any) { 28 tr.ignore = append(tr.ignore, keepNonNil(is...)...) 29 } 30 31 func (tr *CompletionTester) Expect(is ...any) { 32 tr.valid = append(tr.valid, keepNonNil(is...)...) 33 } 34 35 func (tr *CompletionTester) Tested(t testing.TB, m any) { 36 t.Helper() 37 38 if m == nil { 39 return 40 } 41 if len(tr.valid) == 0 { 42 t.Fatal("no valid metadata types to test against") 43 } 44 ty := reflect.TypeOf(m) 45 46 for _, v := range tr.ignore { 47 if reflect.TypeOf(v) == ty { 48 return 49 } 50 } 51 52 for _, v := range tr.valid { 53 if reflect.TypeOf(v) == ty { 54 tr.saw = append(tr.saw, m) 55 return 56 } 57 } 58 59 t.Fatalf("tested metadata type is not valid: %s", ty.Name()) 60 } 61 62 func (tr *CompletionTester) validate(t testing.TB) { 63 t.Helper() 64 65 count := make(map[reflect.Type]int) 66 for _, m := range tr.saw { 67 count[reflect.TypeOf(m)]++ 68 } 69 70 validations: 71 for _, v := range tr.valid { 72 ty := reflect.TypeOf(v) 73 74 for _, ignore := range tr.ignore { 75 if ty == reflect.TypeOf(ignore) { 76 // skip ignored types 77 continue validations 78 } 79 } 80 81 if c, exists := count[ty]; c == 0 || !exists { 82 t.Errorf("metadata type %s is not covered by a test", ty.Name()) 83 } 84 } 85 } 86 87 func keepNonNil(is ...any) []any { 88 var result []any 89 for _, i := range is { 90 if i != nil { 91 result = append(result, i) 92 } 93 } 94 return result 95 }