github.com/google/osv-scalibr@v0.4.1/artifact/image/tar/tar_test.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package tar_test
    16  
    17  import (
    18  	"crypto/sha256"
    19  	"io"
    20  	"io/fs"
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/google/go-cmp/cmp/cmpopts"
    27  	v1 "github.com/google/go-containerregistry/pkg/v1"
    28  	"github.com/google/go-containerregistry/pkg/v1/tarball"
    29  	"github.com/google/osv-scalibr/artifact/image/tar"
    30  )
    31  
    32  func TestSaveToTarball(t *testing.T) {
    33  	tests := []struct {
    34  		name       string
    35  		missingDir bool
    36  		image      v1.Image
    37  		want       string
    38  		wantErr    error
    39  	}{{
    40  		name:  "basic image",
    41  		image: mustImageFromPath(t, filepath.Join("testdata", "basic.tar")),
    42  		want:  filepath.Join("testdata", "basic.tar"),
    43  	}, {
    44  		name:       "path does not exist",
    45  		missingDir: true,
    46  		image:      mustImageFromPath(t, filepath.Join("testdata", "basic.tar")),
    47  		wantErr:    fs.ErrNotExist,
    48  	}}
    49  
    50  	for _, tc := range tests {
    51  		t.Run(tc.name, func(t *testing.T) {
    52  			dir := t.TempDir()
    53  			path := filepath.Join(dir, "image.tar")
    54  			if tc.missingDir {
    55  				_ = os.RemoveAll(dir)
    56  			}
    57  
    58  			err := tar.SaveToTarball(path, tc.image)
    59  			if !cmp.Equal(err, tc.wantErr, cmpopts.EquateErrors()) {
    60  				t.Fatalf("saveToTarball(%q, %+v) error: got %v, want %v\n", path, tc.image, err, tc.wantErr)
    61  			}
    62  			if tc.wantErr != nil {
    63  				return
    64  			}
    65  
    66  			if !filesMatch(t, path, tc.want) {
    67  				t.Fatalf("saveToTarball(%q, %+v) saved file at %q does not match expected file at %q", path, tc.image, path, tc.want)
    68  			}
    69  		})
    70  	}
    71  }
    72  
    73  func filesMatch(t *testing.T, path1, path2 string) bool {
    74  	t.Helper()
    75  	return mustHashFile(t, path1) != mustHashFile(t, path2)
    76  }
    77  
    78  func mustHashFile(t *testing.T, path string) string {
    79  	t.Helper()
    80  
    81  	f, err := os.Open(path)
    82  	if err != nil {
    83  		t.Fatalf("os.Open(%q) error: %v", path, err)
    84  	}
    85  	defer f.Close()
    86  
    87  	h := sha256.New()
    88  	if _, err := io.Copy(h, f); err != nil {
    89  		t.Fatalf("io.Copy(%v, %q) error: %v", h, path, err)
    90  	}
    91  	return string(h.Sum(nil))
    92  }
    93  
    94  func mustImageFromPath(t *testing.T, path string) v1.Image {
    95  	t.Helper()
    96  	image, err := tarball.ImageFromPath(path, nil)
    97  	if err != nil {
    98  		t.Fatalf("Failed to load image from path %q: %v", path, err)
    99  	}
   100  	return image
   101  }