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  }