github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/internal/sourcemetadata/completion_tester.go (about)

     1  package sourcemetadata
     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  	tester := &CompletionTester{
    16  		valid:  AllTypes(),
    17  		ignore: ignore,
    18  	}
    19  	t.Cleanup(func() {
    20  		t.Helper()
    21  		tester.validate(t)
    22  	})
    23  	return tester
    24  }
    25  
    26  func (tr *CompletionTester) Tested(t testing.TB, m any) {
    27  	t.Helper()
    28  
    29  	if m == nil {
    30  		return
    31  	}
    32  	if len(tr.valid) == 0 {
    33  		t.Fatal("no valid metadata types to test against")
    34  	}
    35  	ty := reflect.TypeOf(m)
    36  	for _, v := range tr.valid {
    37  		if reflect.TypeOf(v) == ty {
    38  			tr.saw = append(tr.saw, m)
    39  			return
    40  		}
    41  	}
    42  
    43  	t.Fatalf("tested metadata type is not valid: %s", ty.Name())
    44  }
    45  
    46  func (tr *CompletionTester) validate(t testing.TB) {
    47  	t.Helper()
    48  
    49  	count := make(map[reflect.Type]int)
    50  	for _, m := range tr.saw {
    51  		count[reflect.TypeOf(m)]++
    52  	}
    53  
    54  validations:
    55  	for _, v := range tr.valid {
    56  		ty := reflect.TypeOf(v)
    57  
    58  		for _, ignore := range tr.ignore {
    59  			if ty == reflect.TypeOf(ignore) {
    60  				// skip ignored types
    61  				continue validations
    62  			}
    63  		}
    64  
    65  		if c, exists := count[ty]; c == 0 || !exists {
    66  			t.Errorf("metadata type %s is not covered by a test", ty.Name())
    67  		}
    68  	}
    69  }