...

Source file src/github.com/sigstore/cosign/v2/pkg/oci/mutate/map_test.go

Documentation: github.com/sigstore/cosign/v2/pkg/oci/mutate

     1  //
     2  // Copyright 2021 The Sigstore Authors.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  
    16  package mutate
    17  
    18  import (
    19  	"context"
    20  	"errors"
    21  	"testing"
    22  
    23  	"github.com/google/go-containerregistry/pkg/v1/mutate"
    24  	"github.com/google/go-containerregistry/pkg/v1/random"
    25  	"github.com/google/go-containerregistry/pkg/v1/types"
    26  	"github.com/sigstore/cosign/v2/pkg/oci"
    27  	"github.com/sigstore/cosign/v2/pkg/oci/signed"
    28  )
    29  
    30  func TestMapImage(t *testing.T) {
    31  	i, err := random.Image(300 /* bytes */, 3 /* layers */)
    32  	if err != nil {
    33  		t.Fatalf("random.Image() = %v", err)
    34  	}
    35  	si := signed.Image(i)
    36  
    37  	t.Run("one call to identity mutator", func(t *testing.T) {
    38  		calls := 0
    39  		rsi, err := Map(context.Background(), si, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
    40  			calls++
    41  			return se, nil
    42  		})
    43  		if err != nil {
    44  			t.Fatalf("Map() = %v", err)
    45  		}
    46  		if rsi != si {
    47  			t.Fatalf("Map() = %#v, wanted %#v", rsi, si)
    48  		}
    49  		if calls != 1 {
    50  			t.Fatalf("Map called %d times, wanted 1", calls)
    51  		}
    52  	})
    53  
    54  	t.Run("error propagates", func(t *testing.T) {
    55  		want := errors.New("this is the error I expect")
    56  		_, got := Map(context.Background(), si, func(_ context.Context, _ oci.SignedEntity) (oci.SignedEntity, error) {
    57  			return nil, want
    58  		})
    59  		if !errors.Is(got, want) {
    60  			t.Fatalf("Map() = %v, wanted %v", got, want)
    61  		}
    62  	})
    63  
    64  	t.Run("new result image", func(t *testing.T) {
    65  		i, err := random.Image(300 /* bytes */, 3 /* layers */)
    66  		if err != nil {
    67  			t.Fatalf("random.Image() = %v", err)
    68  		}
    69  		want := signed.Image(i)
    70  
    71  		got, err := Map(context.Background(), si, func(_ context.Context, _ oci.SignedEntity) (oci.SignedEntity, error) {
    72  			return want, nil
    73  		})
    74  		if err != nil {
    75  			t.Fatalf("Map() = %v", err)
    76  		}
    77  		if got != want {
    78  			t.Fatalf("Map() = %#v, wanted %#v", got, want)
    79  		}
    80  	})
    81  
    82  	t.Run("filtered image", func(t *testing.T) {
    83  		got, err := Map(context.Background(), si, func(_ context.Context, _ oci.SignedEntity) (oci.SignedEntity, error) {
    84  			return nil, nil
    85  		})
    86  		if err != nil {
    87  			t.Fatalf("Map() = %v", err)
    88  		}
    89  		if got != nil {
    90  			t.Fatalf("Map() = %#v, wanted nil", got)
    91  		}
    92  	})
    93  }
    94  
    95  func TestMapImageIndex(t *testing.T) {
    96  	ii, err := random.Index(300 /* bytes */, 3 /* layers */, 2 /* images */)
    97  	if err != nil {
    98  		t.Fatalf("random.Image() = %v", err)
    99  	}
   100  	ii2, err := random.Index(300 /* bytes */, 3 /* layers */, 2 /* images */)
   101  	if err != nil {
   102  		t.Fatalf("random.Image() = %v", err)
   103  	}
   104  	sii := signed.ImageIndex(mutate.AppendManifests(ii, mutate.IndexAddendum{
   105  		Add: ii2,
   106  	}))
   107  
   108  	t.Run("six calls to identity mutator", func(t *testing.T) {
   109  		calls := 0
   110  		after := 0
   111  		rsi, err := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
   112  			calls++
   113  			if IsAfterChildren(ctx) {
   114  				after++
   115  			}
   116  			return se, nil
   117  		})
   118  		if err != nil {
   119  			t.Fatalf("Map() = %v", err)
   120  		}
   121  		if rsi != sii {
   122  			t.Fatalf("Map() = %#v, wanted %#v", rsi, sii)
   123  		}
   124  		if calls != 6 {
   125  			t.Fatalf("Map called %d times, wanted 6", calls)
   126  		}
   127  		if after != 0 {
   128  			t.Fatalf("Map called %d times (w/ after), wanted 0", after)
   129  		}
   130  	})
   131  
   132  	t.Run("just one call to root index w/ ErrSkipChildren", func(t *testing.T) {
   133  		calls := 0
   134  		_, err := Map(context.Background(), sii, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
   135  			calls++
   136  			if se != sii {
   137  				t.Errorf("Wanted mutator called on %#v, got call on %#v", sii, se)
   138  			}
   139  			return se, ErrSkipChildren
   140  		})
   141  		if err != nil {
   142  			t.Fatalf("Map() = %v", err)
   143  		}
   144  		if calls != 1 {
   145  			t.Fatalf("Map called %d times, wanted 1", calls)
   146  		}
   147  	})
   148  
   149  	t.Run("two calls to mutator with IsAfterChildren", func(t *testing.T) {
   150  		before := 0
   151  		after := 0
   152  		rsi, err := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
   153  			if IsBeforeChildren(ctx) {
   154  				before++
   155  			}
   156  			if IsAfterChildren(ctx) {
   157  				after++
   158  			}
   159  			if sii, ok := se.(oci.SignedImageIndex); ok {
   160  				return sii, nil
   161  			}
   162  			i, err := random.Image(300 /* bytes */, 3 /* layers */)
   163  			if err != nil {
   164  				t.Fatalf("random.Image() = %v", err)
   165  			}
   166  			return signed.Image(i), nil
   167  		})
   168  		if err != nil {
   169  			t.Fatalf("Map() = %v", err)
   170  		}
   171  		if rsi == sii {
   172  			t.Fatalf("Map() = %#v, wanted something new!", rsi)
   173  		}
   174  		if before != 2 {
   175  			t.Fatalf("Map called %d times (w/ before), wanted 2", before)
   176  		}
   177  		if after != 2 {
   178  			t.Fatalf("Map called %d times (w/ after), wanted 2", after)
   179  		}
   180  	})
   181  
   182  	t.Run("test filtering images", func(t *testing.T) {
   183  		rsi, err := Map(context.Background(), sii, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
   184  			if _, ok := se.(oci.SignedImage); ok {
   185  				return nil, nil
   186  			}
   187  			return se, nil
   188  		})
   189  		if err != nil {
   190  			t.Fatalf("Map() = %v", err)
   191  		}
   192  		if rsi == sii {
   193  			t.Fatalf("Map() = %#v, wanted something new!", rsi)
   194  		}
   195  		// Make sure no images remain!
   196  		im, err := rsi.(oci.SignedImageIndex).IndexManifest()
   197  		if err != nil {
   198  			t.Fatalf("IndexManifest() = %v", err)
   199  		}
   200  		for _, desc := range im.Manifests {
   201  			if desc.MediaType == types.DockerManifestSchema2 {
   202  				t.Error("Found an image media type!")
   203  			}
   204  		}
   205  	})
   206  
   207  	t.Run("test filtering indices", func(t *testing.T) {
   208  		rsi, err := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
   209  			if IsBeforeChildren(ctx) && se != sii {
   210  				return nil, nil
   211  			}
   212  			return se, nil
   213  		})
   214  		if err != nil {
   215  			t.Fatalf("Map() = %v", err)
   216  		}
   217  		if rsi == sii {
   218  			t.Fatalf("Map() = %#v, wanted something new!", rsi)
   219  		}
   220  		// Make sure no indices remain!
   221  		im, err := rsi.(oci.SignedImageIndex).IndexManifest()
   222  		if err != nil {
   223  			t.Fatalf("IndexManifest() = %v", err)
   224  		}
   225  		for _, desc := range im.Manifests {
   226  			if desc.MediaType != types.DockerManifestSchema2 {
   227  				t.Errorf("MediaType = %s, wanted %s", desc.MediaType, types.DockerManifestSchema2)
   228  			}
   229  		}
   230  	})
   231  
   232  	t.Run("error propagates from child image", func(t *testing.T) {
   233  		want := errors.New("this is the error I expect")
   234  		_, got := Map(context.Background(), sii, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
   235  			if _, ok := se.(oci.SignedImage); !ok {
   236  				return se, nil
   237  			}
   238  			return nil, want
   239  		})
   240  		if !errors.Is(got, want) {
   241  			t.Fatalf("Map() = %v, wanted %v", got, want)
   242  		}
   243  	})
   244  
   245  	t.Run("error propagates from child index", func(t *testing.T) {
   246  		want := errors.New("this is the error I expect")
   247  		_, got := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
   248  			if IsBeforeChildren(ctx) && se != sii {
   249  				return nil, want
   250  			}
   251  			return se, nil
   252  		})
   253  		if !errors.Is(got, want) {
   254  			t.Fatalf("Map() = %v, wanted %v", got, want)
   255  		}
   256  	})
   257  }
   258  

View as plain text