github.com/quay/claircore@v1.5.28/libindex/libindex_test.go (about)

     1  package libindex
     2  
     3  import (
     4  	"context"
     5  	"crypto/sha256"
     6  	"errors"
     7  	"io"
     8  	"strconv"
     9  	"testing"
    10  
    11  	"github.com/golang/mock/gomock"
    12  	"github.com/quay/zlog"
    13  
    14  	"github.com/quay/claircore"
    15  	indexer "github.com/quay/claircore/test/mock/indexer"
    16  )
    17  
    18  func createTestVulns(n int) []claircore.Vulnerability {
    19  	vulns := []claircore.Vulnerability{}
    20  	for i := 0; i < n; i++ {
    21  		vulns = append(vulns, claircore.Vulnerability{
    22  			ID:                 strconv.Itoa(i),
    23  			Name:               "CVE-2018-20187",
    24  			Links:              "https://www.cve.org/CVERecord?id=CVE-2018-20187",
    25  			Updater:            "alpine-community-v3.10-updater",
    26  			FixedInVersion:     "2.9.0-r0",
    27  			NormalizedSeverity: claircore.Unknown,
    28  			Package: &claircore.Package{
    29  				Name: "botan",
    30  				Kind: claircore.BINARY,
    31  			},
    32  		})
    33  	}
    34  	return vulns
    35  }
    36  
    37  func digest(inp string) claircore.Digest {
    38  	h := sha256.New()
    39  	io.WriteString(h, inp)
    40  	d, err := claircore.NewDigest("sha256", h.Sum(nil))
    41  	if err != nil {
    42  		panic(err)
    43  	}
    44  	return d
    45  }
    46  
    47  func TestAffectedManifests(t *testing.T) {
    48  	ctx := context.Background()
    49  	tt := []struct {
    50  		name                 string
    51  		inputVulns           []claircore.Vulnerability
    52  		numExpectedVulns     int
    53  		numExpectedManifests int
    54  		err                  bool
    55  		mockStore            func(t *testing.T) indexer.Store
    56  	}{
    57  		{
    58  			name:                 "SimplePath",
    59  			inputVulns:           createTestVulns(2),
    60  			numExpectedVulns:     2,
    61  			numExpectedManifests: 2,
    62  			mockStore: func(t *testing.T) indexer.Store {
    63  				ctrl := gomock.NewController(t)
    64  				s := indexer.NewMockStore(ctrl)
    65  				s.EXPECT().AffectedManifests(gomock.Any(), gomock.Any(), gomock.Any()).Return(
    66  					[]claircore.Digest{
    67  						digest("first digest"),
    68  						digest("second digest"),
    69  					},
    70  					nil,
    71  				).MaxTimes(2)
    72  				return s
    73  			},
    74  		},
    75  		{
    76  			name:                 "ManyVulns",
    77  			inputVulns:           createTestVulns(40),
    78  			numExpectedVulns:     40,
    79  			numExpectedManifests: 40,
    80  			mockStore: func(t *testing.T) indexer.Store {
    81  				ctrl := gomock.NewController(t)
    82  				s := indexer.NewMockStore(ctrl)
    83  				s.EXPECT().AffectedManifests(gomock.Any(), gomock.Any(), gomock.Any()).Return(
    84  					[]claircore.Digest{
    85  						digest("first digest"),
    86  						digest("second digest"),
    87  					},
    88  					nil,
    89  				).MaxTimes(40)
    90  				return s
    91  			},
    92  		},
    93  	}
    94  
    95  	for _, table := range tt {
    96  		t.Run(table.name, func(t *testing.T) {
    97  			ctx := zlog.Test(ctx, t)
    98  			s := table.mockStore(t)
    99  			li := &Libindex{store: s}
   100  
   101  			affected, err := li.AffectedManifests(ctx, table.inputVulns)
   102  			if (err == nil) == table.err {
   103  				t.Fatalf("did not expect error: %v", err)
   104  			}
   105  
   106  			if table.numExpectedVulns != len(affected.Vulnerabilities) {
   107  				t.Fatalf("got: %d vulnerabilities, want: %d", len(affected.Vulnerabilities), table.numExpectedVulns)
   108  			}
   109  			if table.numExpectedManifests != len(affected.Vulnerabilities) {
   110  				t.Fatalf("got: %d vulnerabilities, want: %d", len(affected.Vulnerabilities), table.numExpectedManifests)
   111  			}
   112  		})
   113  	}
   114  
   115  	t.Run("CancelledContext", func(t *testing.T) {
   116  		for _, table := range tt {
   117  			t.Run(table.name, func(t *testing.T) {
   118  				ctx := zlog.Test(ctx, t)
   119  				ctx, cancel := context.WithCancelCause(ctx)
   120  				want := errors.New("early cancel")
   121  				cancel(want)
   122  				s := table.mockStore(t)
   123  				li := &Libindex{store: s}
   124  
   125  				a, err := li.AffectedManifests(ctx, table.inputVulns)
   126  				if err == nil {
   127  					t.Errorf("did not expect error: %v", err)
   128  				}
   129  				if a != nil {
   130  					t.Errorf("did not expect result: %v", a)
   131  				}
   132  				if !errors.Is(err, want) {
   133  					t.Errorf("got: %v, want: %v", err, want)
   134  				}
   135  			})
   136  		}
   137  	})
   138  }
   139  
   140  func BenchmarkAffectedManifests(b *testing.B) {
   141  	ctx := context.Background()
   142  	// create store
   143  	ctrl := gomock.NewController(b)
   144  	s := indexer.NewMockStore(ctrl)
   145  	var check claircore.CheckVulnernableFunc
   146  	s.EXPECT().AffectedManifests(gomock.Any(), gomock.Any(), gomock.AssignableToTypeOf(check)).Return(
   147  		[]claircore.Digest{
   148  			digest("first digest"),
   149  			digest("second digest"),
   150  		},
   151  		nil,
   152  	).MaxTimes(100 * b.N)
   153  
   154  	ctx = zlog.Test(ctx, b)
   155  	li := &Libindex{store: s}
   156  
   157  	b.ResetTimer()
   158  	for n := 0; n < b.N; n++ {
   159  		_, err := li.AffectedManifests(ctx, createTestVulns(100))
   160  		if err != nil {
   161  			b.Fatalf("did not expect error: %v", err)
   162  		}
   163  	}
   164  }