1
16
17 package tar
18
19 import (
20 "archive/tar"
21 "io"
22 "os"
23 "path/filepath"
24 "regexp"
25 "testing"
26
27 "github.com/sirupsen/logrus"
28 "github.com/stretchr/testify/require"
29 )
30
31 func TestCompress(t *testing.T) {
32 baseTmpDir, err := os.MkdirTemp("", "compress-")
33 require.Nil(t, err)
34 defer os.RemoveAll(baseTmpDir)
35
36 for _, fileName := range []string{
37 "1.txt", "2.bin", "3.md",
38 } {
39 require.Nil(t, os.WriteFile(
40 filepath.Join(baseTmpDir, fileName),
41 []byte{1, 2, 3},
42 os.FileMode(0o644),
43 ))
44 }
45
46 subTmpDir := filepath.Join(baseTmpDir, "sub")
47 require.Nil(t, os.MkdirAll(subTmpDir, os.FileMode(0o755)))
48
49 for _, fileName := range []string{
50 "4.txt", "5.bin", "6.md",
51 } {
52 require.Nil(t, os.WriteFile(
53 filepath.Join(subTmpDir, fileName),
54 []byte{4, 5, 6},
55 os.FileMode(0o644),
56 ))
57 }
58
59 logrus.SetLevel(logrus.DebugLevel)
60
61 require.Nil(t, os.Symlink(
62 filepath.Join(baseTmpDir, "1.txt"),
63 filepath.Join(subTmpDir, "link"),
64 ))
65
66 excludes := []*regexp.Regexp{
67 regexp.MustCompile(".md"),
68 regexp.MustCompile("5"),
69 }
70
71 tarFilePath := filepath.Join(baseTmpDir, "res.tar.gz")
72 require.Nil(t, Compress(tarFilePath, baseTmpDir, excludes...))
73 require.FileExists(t, tarFilePath)
74
75 res := []string{"1.txt", "2.bin", "sub/4.txt", "sub/link"}
76 require.Nil(t, iterateTarball(
77 tarFilePath, func(_ *tar.Reader, header *tar.Header) (bool, error) {
78 require.Equal(t, res[0], header.Name)
79 res = res[1:]
80 return false, nil
81 }),
82 )
83 }
84
85 func TestCompressWithoutPreservingPath(t *testing.T) {
86 baseTmpDir, err := os.MkdirTemp("", "compress-")
87 require.Nil(t, err)
88 defer os.RemoveAll(baseTmpDir)
89
90 compressDir := filepath.Join(baseTmpDir, "to_compress")
91 require.Nil(t, os.MkdirAll(compressDir, os.FileMode(0o755)))
92
93 for _, fileName := range []string{
94 "1.txt", "2.bin", "3.md",
95 } {
96 require.Nil(t, os.WriteFile(
97 filepath.Join(compressDir, fileName),
98 []byte{1, 2, 3},
99 os.FileMode(0o644),
100 ))
101 }
102
103 logrus.SetLevel(logrus.DebugLevel)
104
105 tarFilePath := filepath.Join(baseTmpDir, "res.tar.gz")
106 require.Nil(t, CompressWithoutPreservingPath(tarFilePath, compressDir))
107 require.FileExists(t, tarFilePath)
108
109 res := []string{"1.txt", "2.bin", "3.md"}
110 require.Nil(t, iterateTarball(
111 tarFilePath, func(_ *tar.Reader, header *tar.Header) (bool, error) {
112 require.Equal(t, res[0], header.Name)
113 res = res[1:]
114 return false, nil
115 }),
116 )
117 }
118
119 func TestExtract(t *testing.T) {
120 tarball := []byte{
121 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xec, 0xd7,
122 0xdf, 0xea, 0x82, 0x30, 0x14, 0xc0, 0xf1, 0xfd, 0xfe, 0xd4, 0x73, 0xf4,
123 0x02, 0xb9, 0xb3, 0x9d, 0xb9, 0xd9, 0xe3, 0xa8, 0x08, 0x49, 0x69, 0xe2,
124 0x26, 0xf4, 0xf8, 0x31, 0x93, 0x2e, 0xba, 0x10, 0x8a, 0xe6, 0x08, 0xcf,
125 0xe7, 0x66, 0x0c, 0xc4, 0x1d, 0x2f, 0xbe, 0x30, 0x45, 0xe2, 0xae, 0x8e,
126 0x85, 0x05, 0x00, 0xa0, 0x95, 0xf2, 0xab, 0x30, 0x29, 0x8c, 0x7b, 0x71,
127 0xdf, 0x4f, 0x90, 0x09, 0x34, 0x29, 0x00, 0x48, 0xd4, 0x9a, 0x81, 0x90,
128 0x0a, 0x91, 0xed, 0x20, 0xf0, 0x5c, 0xa3, 0xc1, 0xba, 0xbc, 0x67, 0x00,
129 0x36, 0xb7, 0xe5, 0x31, 0x9f, 0x7b, 0xae, 0xea, 0xed, 0xcc, 0x7b, 0xa6,
130 0x2f, 0x79, 0xac, 0x5f, 0xe2, 0xe7, 0xf7, 0x2f, 0xf6, 0x08, 0x24, 0x22,
131 0x99, 0x14, 0x75, 0x1b, 0xf8, 0x8c, 0x37, 0xfa, 0x47, 0x9d, 0x52, 0xff,
132 0x4b, 0xa0, 0xfe, 0xd7, 0xcd, 0x0e, 0x05, 0x57, 0x81, 0xef, 0x00, 0xaf,
133 0xf7, 0x8f, 0x52, 0x1a, 0xea, 0x7f, 0x09, 0xff, 0x9b, 0x6d, 0xec, 0x11,
134 0x48, 0x44, 0xbe, 0xff, 0x73, 0xdd, 0x9e, 0x42, 0x9e, 0xe1, 0x7b, 0x30,
135 0xc6, 0xcc, 0xf4, 0x0f, 0x4f, 0xfd, 0x1b, 0xed, 0xef, 0xff, 0x92, 0xbb,
136 0xa6, 0xe3, 0xe5, 0xa5, 0xe9, 0xfa, 0xca, 0xda, 0xfd, 0x01, 0x33, 0x25,
137 0x54, 0x86, 0x8a, 0x7f, 0xf2, 0xa7, 0x65, 0xe5, 0xfd, 0x13, 0x42, 0xd6,
138 0xeb, 0x16, 0x00, 0x00, 0xff, 0xff, 0xe9, 0xde, 0xbe, 0xdf, 0x00, 0x12,
139 0x00, 0x00,
140 }
141 file, err := os.CreateTemp("", "tarball")
142 require.Nil(t, err)
143 defer os.Remove(file.Name())
144 _, err = file.Write(tarball)
145 require.Nil(t, err)
146
147 baseTmpDir, err := os.MkdirTemp("", "extract-")
148 require.Nil(t, err)
149 require.Nil(t, os.RemoveAll(baseTmpDir))
150 defer os.RemoveAll(baseTmpDir)
151
152 require.Nil(t, Extract(file.Name(), baseTmpDir))
153 res := []string{
154 filepath.Base(baseTmpDir),
155 "1.txt",
156 "2.bin",
157 "sub",
158 "4.txt",
159 "link",
160 }
161 require.Nil(t, filepath.Walk(
162 baseTmpDir,
163 func(filePath string, fileInfo os.FileInfo, err error) error {
164 require.Equal(t, res[0], fileInfo.Name())
165 if res[0] == "link" {
166 require.True(t, fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink)
167 }
168 res = res[1:]
169 return nil
170 },
171 ))
172 }
173
174 func TestReadFileFromGzippedTar(t *testing.T) {
175 baseTmpDir, err := os.MkdirTemp("", "tar-read-file-")
176 require.Nil(t, err)
177 defer os.RemoveAll(baseTmpDir)
178
179 const (
180 testFilePath = "test.txt"
181 testFileContents = "test-file-contents"
182 )
183 testTarPath := filepath.Join(baseTmpDir, "test.tar.gz")
184
185 require.Nil(t, os.WriteFile(
186 filepath.Join(baseTmpDir, testFilePath),
187 []byte(testFileContents),
188 os.FileMode(0o644),
189 ))
190 require.Nil(t, Compress(testTarPath, baseTmpDir, nil))
191
192 type args struct {
193 tarPath string
194 filePath string
195 }
196 type want struct {
197 fileContents string
198 shouldErr bool
199 }
200 cases := map[string]struct {
201 args args
202 want want
203 }{
204 "FoundFileInTar": {
205 args: args{
206 tarPath: testTarPath,
207 filePath: testFilePath,
208 },
209 want: want{fileContents: testFileContents},
210 },
211 "FileNotInTar": {
212 args: args{
213 tarPath: testTarPath,
214 filePath: "badfile.txt",
215 },
216 want: want{shouldErr: true},
217 },
218 }
219
220 for name, tc := range cases {
221 t.Run(name, func(t *testing.T) {
222 r, err := ReadFileFromGzippedTar(tc.args.tarPath, tc.args.filePath)
223 if tc.want.shouldErr {
224 require.Nil(t, r)
225 require.NotNil(t, err)
226 } else {
227 file, err := io.ReadAll(r)
228 require.Nil(t, err)
229 require.Equal(t, tc.want.fileContents, string(file))
230 }
231 })
232 }
233 }
234
View as plain text