1
16
17 package main
18
19 import (
20 "archive/tar"
21 "compress/gzip"
22 "fmt"
23 "io"
24 "os"
25 "path/filepath"
26 "reflect"
27 "strings"
28 "testing"
29 )
30
31 func TestTar(t *testing.T) {
32 tmp, err := os.MkdirTemp("", "testtar")
33 if err != nil {
34 t.Fatal(err)
35 }
36 defer os.RemoveAll(tmp)
37
38 if err := os.Mkdir(filepath.Join(tmp, "subdir"), os.FileMode(0755)); err != nil {
39 t.Fatal(err)
40 }
41 if err := os.WriteFile(filepath.Join(tmp, "file1"), []byte(`file1 data`), os.FileMode(0644)); err != nil {
42 t.Fatal(err)
43 }
44 if err := os.WriteFile(filepath.Join(tmp, "file2"), []byte(`file2 data`), os.FileMode(0644)); err != nil {
45 t.Fatal(err)
46 }
47 if err := os.WriteFile(filepath.Join(tmp, "subdir", "file4"), []byte(`file4 data`), os.FileMode(0644)); err != nil {
48 t.Fatal(err)
49 }
50
51 testCases := []struct {
52 desc string
53 dir string
54 outpath string
55 expectErr string
56 expect map[string]string
57 }{
58 {
59 desc: "Contents preserved and no self-reference",
60 dir: tmp,
61 outpath: filepath.Join(tmp, "out.tar.gz"),
62 expect: map[string]string{
63 "file1": "file1 data",
64 "file2": "file2 data",
65 "subdir/file4": "file4 data",
66 },
67 }, {
68 desc: "Errors if directory does not exist",
69 dir: filepath.Join(tmp, "does-not-exist"),
70 outpath: filepath.Join(tmp, "out.tar.gz"),
71 expectErr: "tar unable to stat directory",
72 },
73 }
74 for _, tc := range testCases {
75 t.Run(tc.desc, func(t *testing.T) {
76 err := tarDir(tc.dir, tc.outpath)
77 if err == nil {
78 defer os.Remove(tc.outpath)
79 }
80
81 switch {
82 case err != nil && len(tc.expectErr) == 0:
83 t.Fatalf("Expected nil error but got %q", err)
84 case err != nil && len(tc.expectErr) > 0:
85 if !strings.Contains(fmt.Sprint(err), tc.expectErr) {
86 t.Errorf("Expected error \n\t%q\nbut got\n\t%q", tc.expectErr, err)
87 }
88 return
89 case err == nil && len(tc.expectErr) > 0:
90 t.Fatalf("Expected error %q but got nil", tc.expectErr)
91 default:
92
93 }
94
95 data, err := readAllTar(tc.outpath)
96 if err != nil {
97 t.Fatalf("Failed to read tarball: %v", err)
98 }
99
100 if !reflect.DeepEqual(data, tc.expect) {
101 t.Errorf("Expected data %v but got %v", tc.expect, data)
102 }
103 })
104 }
105 }
106
107
108
109 func readAllTar(tarPath string) (map[string]string, error) {
110 tarPath, err := filepath.Abs(tarPath)
111 if err != nil {
112 return nil, err
113 }
114
115 fileReader, err := os.Open(tarPath)
116 if err != nil {
117 return nil, err
118 }
119 defer fileReader.Close()
120
121 gzStream, err := gzip.NewReader(fileReader)
122 if err != nil {
123 return nil, fmt.Errorf("couldn't uncompress reader: %w", err)
124 }
125 defer gzStream.Close()
126
127
128 tr := tar.NewReader(gzStream)
129 fileData := map[string]string{}
130 for {
131 hdr, err := tr.Next()
132 if err == io.EOF {
133 break
134 }
135 if err != nil {
136
137 return nil, err
138 }
139
140 b, err := io.ReadAll(tr)
141 if err != nil {
142 return nil, err
143 }
144 fileData[filepath.ToSlash(hdr.Name)] = string(b)
145 }
146 return fileData, nil
147 }
148
View as plain text