github.com/pelicanplatform/pelican@v1.0.5/client/pack_test.go (about) 1 //go:build !windows 2 3 /*************************************************************** 4 * 5 * Copyright (C) 2023, Morgridge Institute for Research 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you 8 * may not use this file except in compliance with the License. You may 9 * obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 ***************************************************************/ 20 21 package client 22 23 import ( 24 "archive/tar" 25 "bytes" 26 "compress/gzip" 27 "io" 28 "io/fs" 29 "os" 30 "path/filepath" 31 "testing" 32 33 "github.com/stretchr/testify/assert" 34 "github.com/stretchr/testify/require" 35 ) 36 37 func createTestDirectory(t *testing.T, path string) { 38 subdirPath := filepath.Join(path, "subdir1") 39 siblingPath := filepath.Join(path, "foo.txt") 40 childPath := filepath.Join(path, "subdir1", "bar.txt") 41 err := os.Mkdir(subdirPath, 0750) 42 require.NoError(t, err) 43 err = os.WriteFile(siblingPath, []byte("foo"), 0640) 44 require.NoError(t, err) 45 err = os.WriteFile(childPath, []byte("bar"), 0440) 46 require.NoError(t, err) 47 } 48 49 func verifyTestDirectory(t *testing.T, testDirectory string) { 50 entryCount := 0 51 err := filepath.WalkDir(testDirectory, func(path string, dent fs.DirEntry, err error) error { 52 // Skip the top-level directory itself. 53 if len(testDirectory) >= len(path) { 54 return nil 55 } 56 switch path[len(testDirectory)+1:] { 57 case "subdir1": 58 fi, err := dent.Info() 59 require.NoError(t, err) 60 assert.True(t, fi.Mode().IsDir()) 61 assert.Equal(t, fi.Mode()&fs.ModePerm, fs.FileMode(0750)) 62 case "foo.txt": 63 fi, err := dent.Info() 64 require.NoError(t, err) 65 assert.True(t, fi.Mode().IsRegular()) 66 assert.Equal(t, fi.Mode()&fs.ModePerm, fs.FileMode(0640)) 67 buffer, err := os.ReadFile(path) 68 require.NoError(t, err) 69 assert.Equal(t, string(buffer), "foo") 70 case filepath.Join("subdir1", "bar.txt"): 71 fi, err := dent.Info() 72 require.NoError(t, err) 73 assert.True(t, fi.Mode().IsRegular()) 74 assert.Equal(t, fi.Mode()&fs.ModePerm, fs.FileMode(0440)) 75 buffer, err := os.ReadFile(path) 76 require.NoError(t, err) 77 assert.Equal(t, string(buffer), "bar") 78 default: 79 assert.Failf(t, "Unknown file encountered in directory", path) 80 } 81 entryCount += 1 82 return nil 83 }) 84 require.NoError(t, err) 85 assert.Equal(t, entryCount, 3) 86 } 87 88 func verifyTarball(t *testing.T, reader io.Reader) { 89 tr := tar.NewReader(reader) 90 entryCount := 0 91 for { 92 hdr, err := tr.Next() 93 if err == io.EOF { 94 break 95 } 96 require.NoError(t, err) 97 entryCount += 1 98 switch hdr.Name { 99 case "subdir1": 100 assert.Equal(t, hdr.Typeflag, uint8(tar.TypeDir)) 101 assert.Equal(t, hdr.Mode, int64(0750)) 102 case "foo.txt": 103 assert.Equal(t, hdr.Typeflag, uint8(tar.TypeReg)) 104 assert.Equal(t, hdr.Mode, int64(0640)) 105 buffer := new(bytes.Buffer) 106 _, err := io.Copy(buffer, tr) 107 require.NoError(t, err) 108 assert.Equal(t, buffer.String(), string([]byte("foo"))) 109 case filepath.Join("subdir1", "bar.txt"): 110 assert.Equal(t, hdr.Typeflag, uint8(tar.TypeReg)) 111 assert.Equal(t, hdr.Mode, int64(0440)) 112 buffer := new(bytes.Buffer) 113 _, err := io.Copy(buffer, tr) 114 require.NoError(t, err) 115 assert.True(t, bytes.Equal(buffer.Bytes(), []byte("bar"))) 116 default: 117 assert.Failf(t, "Unknown file encountered in tarball", hdr.Name) 118 } 119 } 120 assert.Equal(t, entryCount, 3) 121 } 122 123 func TestAutoPacker(t *testing.T) { 124 t.Parallel() 125 126 t.Run("create-tarfile", func(t *testing.T) { 127 dirname := t.TempDir() 128 129 createTestDirectory(t, dirname) 130 ap := newAutoPacker(dirname, tarBehavior) 131 verifyTarball(t, ap) 132 133 // Unwrap the GZIP stream, pass to the tarball verifier 134 ap = newAutoPacker(dirname, tarGZBehavior) 135 gzReader, err := gzip.NewReader(ap) 136 require.NoError(t, err) 137 verifyTarball(t, gzReader) 138 139 // Default behavior should be the same as the tar.gz 140 ap = newAutoPacker(dirname, autoBehavior) 141 gzReader, err = gzip.NewReader(ap) 142 require.NoError(t, err) 143 verifyTarball(t, gzReader) 144 }) 145 146 t.Run("unpack-tarfile", func(t *testing.T) { 147 dirnameSource := t.TempDir() 148 dirnameDest := t.TempDir() 149 150 createTestDirectory(t, dirnameSource) 151 ap := newAutoPacker(dirnameSource, tarGZBehavior) 152 153 aup := newAutoUnpacker(dirnameDest, autoBehavior) 154 _, err := io.Copy(aup, ap) 155 require.NoError(t, err) 156 157 require.NoError(t, aup.Error()) 158 verifyTestDirectory(t, dirnameDest) 159 }) 160 }