github.com/quay/claircore@v1.5.28/updater/offline_test.go (about)

     1  package updater
     2  
     3  import (
     4  	"archive/zip"
     5  	"bytes"
     6  	"context"
     7  	"encoding/json"
     8  	"io"
     9  	"net/http"
    10  	"net/url"
    11  	"os"
    12  	"path"
    13  	"path/filepath"
    14  	"testing"
    15  
    16  	"github.com/golang/mock/gomock"
    17  	"github.com/quay/zlog"
    18  
    19  	mock_updater "github.com/quay/claircore/test/mock/updater"
    20  	mock_driver "github.com/quay/claircore/test/mock/updater/driver/v1"
    21  	driver "github.com/quay/claircore/updater/driver/v1"
    22  )
    23  
    24  func TestOffline(t *testing.T) {
    25  	ctx := context.Background()
    26  	vs := &driver.ParsedVulnerabilities{
    27  		Updater:       t.Name(),
    28  		Vulnerability: []driver.Vulnerability{{}},
    29  	}
    30  	es := []driver.EnrichmentRecord{
    31  		{
    32  			Enrichment: json.RawMessage("null"),
    33  			Tags:       []string{"a"},
    34  		},
    35  	}
    36  	spool, err := os.CreateTemp(t.TempDir(), "")
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	defer spool.Close()
    41  
    42  	t.Run("Fetch", func(t *testing.T) {
    43  		ctx := zlog.Test(ctx, t)
    44  		ctl := gomock.NewController(t)
    45  		n := path.Dir(t.Name())
    46  
    47  		upd := mock_driver.NewMockUpdater(ctl)
    48  		upd.EXPECT().
    49  			Name().MinTimes(1).Return(n)
    50  		upd.EXPECT().
    51  			Fetch(matchCtx, matchZip, matchFp, matchClient).DoAndReturn(fetchFunc(t, es, vs))
    52  		fac := mock_driver.NewMockUpdaterFactory(ctl)
    53  		fac.EXPECT().
    54  			Name().MinTimes(1).Return(n)
    55  		fac.EXPECT().
    56  			Create(matchCtx, gomock.Nil()).Times(1).Return([]driver.Updater{upd}, nil)
    57  		store := mock_updater.NewMockStore(ctl)
    58  
    59  		u, err := New(ctx, &Options{
    60  			Store:     store,
    61  			Client:    &http.Client{},
    62  			Factories: []driver.UpdaterFactory{fac},
    63  		})
    64  		if err != nil {
    65  			t.Fatal(err)
    66  		}
    67  		defer func() {
    68  			if err := u.Close(); err != nil {
    69  				t.Error(err)
    70  			}
    71  		}()
    72  
    73  		if err := u.Fetch(ctx, nil, spool); err != nil {
    74  			t.Error(err)
    75  		}
    76  	})
    77  
    78  	t.Run("Parse", func(t *testing.T) {
    79  		ctx := zlog.Test(ctx, t)
    80  		ctl := gomock.NewController(t)
    81  		n := path.Dir(t.Name())
    82  
    83  		upd := mock_driver.NewMockUpdater(ctl)
    84  		upd.EXPECT().
    85  			Name().MinTimes(1).Return(n)
    86  		vp := mock_driver.NewMockVulnerabilityParser(ctl)
    87  		vp.EXPECT().
    88  			ParseVulnerability(matchCtx, matchFS).DoAndReturn(parseVuln)
    89  		ep := mock_driver.NewMockEnrichmentParser(ctl)
    90  		ep.EXPECT().
    91  			ParseEnrichment(matchCtx, matchFS).DoAndReturn(parseEnrich)
    92  		fac := mock_driver.NewMockUpdaterFactory(ctl)
    93  		fac.EXPECT().
    94  			Name().MinTimes(1).Return(n)
    95  		fac.EXPECT().
    96  			Create(matchCtx, gomock.Nil()).Times(1).Return([]driver.Updater{&mockparser{
    97  			Updater:             upd,
    98  			VulnerabilityParser: vp,
    99  			EnrichmentParser:    ep,
   100  		}}, nil)
   101  		store := mock_updater.NewMockStore(ctl)
   102  		store.EXPECT().
   103  			UpdateVulnerabilities(matchCtx, matchUUID, gomock.Eq(n), matchFp, gomock.Eq(vs)).Return(nil)
   104  		store.EXPECT().
   105  			UpdateEnrichments(matchCtx, matchUUID, gomock.Eq(n), matchFp, gomock.Eq(es)).Return(nil)
   106  
   107  		u, err := New(ctx, &Options{
   108  			Store:     store,
   109  			Client:    &http.Client{Transport: nil},
   110  			Factories: []driver.UpdaterFactory{fac},
   111  		})
   112  		if err != nil {
   113  			t.Fatal(err)
   114  		}
   115  		defer func() {
   116  			if err := u.Close(); err != nil {
   117  				t.Error(err)
   118  			}
   119  		}()
   120  
   121  		if err := u.Parse(ctx, spool); err != nil {
   122  			t.Error(err)
   123  		}
   124  	})
   125  
   126  	t.Run("Prev", func(t *testing.T) {
   127  		ctx := zlog.Test(ctx, t)
   128  		ctl := gomock.NewController(t)
   129  		n := path.Dir(t.Name())
   130  		if _, err := spool.Seek(0, io.SeekStart); err != nil {
   131  			t.Fatal(err)
   132  		}
   133  
   134  		upd := mock_driver.NewMockUpdater(ctl)
   135  		upd.EXPECT().Name().
   136  			MinTimes(1).
   137  			Return(n)
   138  		upd.EXPECT().Fetch(matchCtx, matchZip, matchFp, matchClient).
   139  			Times(1).
   140  			DoAndReturn(fetchFunc(t, es, vs))
   141  		fac := mock_driver.NewMockUpdaterFactory(ctl)
   142  		fac.EXPECT().Name().
   143  			MinTimes(1).
   144  			Return(n)
   145  		fac.EXPECT().Create(matchCtx, gomock.Nil()).
   146  			Times(1).
   147  			Return([]driver.Updater{upd}, nil)
   148  		store := mock_updater.NewMockStore(ctl)
   149  
   150  		u, err := New(ctx, &Options{
   151  			Store:     store,
   152  			Client:    &http.Client{Transport: nil},
   153  			Factories: []driver.UpdaterFactory{fac},
   154  		})
   155  		if err != nil {
   156  			t.Fatal(err)
   157  		}
   158  		defer func() {
   159  			if err := u.Close(); err != nil {
   160  				t.Error(err)
   161  			}
   162  		}()
   163  
   164  		if err := u.Fetch(ctx, spool, io.Discard); err != nil {
   165  			t.Error(err)
   166  		}
   167  	})
   168  }
   169  
   170  func TestOpenZip(t *testing.T) {
   171  	// Setup the zip
   172  	n := filepath.Join(t.TempDir(), "zip")
   173  	f, err := os.Create(n)
   174  	if err != nil {
   175  		t.Fatal(err)
   176  	}
   177  	defer f.Close()
   178  	const comment = `test`
   179  	w := zip.NewWriter(f)
   180  	w.SetComment((url.Values{exportHeader: {comment}}).Encode())
   181  	if err := w.Close(); err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	t.Run("Stat", func(t *testing.T) {
   186  		f, err := os.Open(n)
   187  		if err != nil {
   188  			t.Fatal(err)
   189  		}
   190  		defer f.Close()
   191  
   192  		r, c, err := openZip(f)
   193  		if err != nil {
   194  			t.Error(err)
   195  		}
   196  		if got, want := c, comment; got != want {
   197  			t.Errorf("got: %q, want: %q", got, want)
   198  		}
   199  		if r == nil {
   200  			t.Errorf("%v(%[1]T)", r)
   201  		}
   202  	})
   203  	t.Run("Seek", func(t *testing.T) {
   204  		f, err := os.Open(n)
   205  		if err != nil {
   206  			t.Fatal(err)
   207  		}
   208  		defer f.Close()
   209  		rd := struct {
   210  			io.ReaderAt
   211  			io.Seeker
   212  		}{
   213  			ReaderAt: f,
   214  			Seeker:   f,
   215  		}
   216  
   217  		r, c, err := openZip(&rd)
   218  		if err != nil {
   219  			t.Error(err)
   220  		}
   221  		if got, want := c, comment; got != want {
   222  			t.Errorf("got: %q, want: %q", got, want)
   223  		}
   224  		if r == nil {
   225  			t.Errorf("%v(%[1]T)", r)
   226  		}
   227  	})
   228  	t.Run("Size", func(t *testing.T) {
   229  		var buf bytes.Buffer
   230  		f, err := os.Open(n)
   231  		if err != nil {
   232  			t.Fatal(err)
   233  		}
   234  		defer f.Close()
   235  		if _, err := io.Copy(&buf, f); err != nil {
   236  			t.Fatal(err)
   237  		}
   238  		rd := bytes.NewReader(buf.Bytes())
   239  
   240  		r, c, err := openZip(rd)
   241  		if err != nil {
   242  			t.Error(err)
   243  		}
   244  		if got, want := c, comment; got != want {
   245  			t.Errorf("got: %q, want: %q", got, want)
   246  		}
   247  		if r == nil {
   248  			t.Errorf("%v(%[1]T)", r)
   249  		}
   250  	})
   251  	t.Run("Error", func(t *testing.T) {
   252  		f, err := os.Open(n)
   253  		if err != nil {
   254  			t.Fatal(err)
   255  		}
   256  		defer f.Close()
   257  		rd := struct {
   258  			io.ReaderAt
   259  		}{
   260  			ReaderAt: f,
   261  		}
   262  
   263  		_, _, err = openZip(&rd)
   264  		t.Log(err)
   265  		if err == nil {
   266  			t.Errorf("got: %v, want: nil", err)
   267  		}
   268  	})
   269  }