1 package client
2
3 import (
4 "bytes"
5 "io"
6 "io/fs"
7 "os"
8 "path/filepath"
9 "runtime"
10 "strings"
11 "testing"
12 )
13
14 const targetsDir = "targets"
15
16 func TestCreates(t *testing.T) {
17 runningWindows := false
18 if runtime.GOOS == "windows" {
19 runningWindows = true
20 }
21 tmpDir := t.TempDir()
22 defer os.RemoveAll(tmpDir)
23 dir := filepath.Join(tmpDir, "repository")
24 os.Mkdir(dir, os.ModePerm)
25 os.Mkdir(filepath.Join(dir, "targets"), os.ModePerm)
26 if !runningWindows {
27 targetDirThatIsFile := filepath.Join(dir, "targets-that-isfile")
28 f, err := os.Create(targetDirThatIsFile)
29 if err != nil {
30 t.Fatalf("failed to create file: %s: %v", targetDirThatIsFile, err)
31 }
32 defer f.Close()
33 }
34 t.Cleanup(func() { rmrf(dir, t.Logf) })
35 t.Cleanup(func() { rmrf(tmpDir, t.Logf) })
36
37 tests := []struct {
38 name string
39 fsys fs.FS
40 td string
41 wantErr string
42 doNotRunOnWindows bool
43 }{{
44 name: "nil, error",
45 wantErr: "nil fs.FS",
46 }, {
47 name: "missing targets directory",
48 fsys: os.DirFS(dir),
49 td: "targets-not-there",
50 wantErr: "failed to open targets directory targets-not-there",
51 }, {
52 name: "targets directory is not a file",
53 fsys: os.DirFS(dir),
54 td: "targets-that-isfile",
55 wantErr: "targets directory not a directory targets-that-isfile",
56 doNotRunOnWindows: true,
57 }, {
58 name: "works, explicit targets",
59 fsys: os.DirFS(dir),
60 td: "targets",
61 }, {
62 name: "works, explicit targets",
63 fsys: os.DirFS(dir),
64 td: "targets",
65 }}
66
67 for _, tc := range tests {
68 if tc.doNotRunOnWindows {
69 t.Skip("Can't figure out how to make this work on windows")
70 }
71 _, err := NewFileRemoteStore(tc.fsys, tc.td)
72 if tc.wantErr != "" && err == nil {
73 t.Errorf("%q wanted error %s, got none", tc.name, tc.wantErr)
74 } else if tc.wantErr == "" && err != nil {
75 t.Errorf("%q did not want error, got: %v", tc.name, err)
76 } else if err != nil && !strings.Contains(err.Error(), tc.wantErr) {
77 t.Errorf("%q wanted error %s but got: %s", tc.name, tc.wantErr, err)
78 }
79 }
80 }
81
82 func TestBasicOps(t *testing.T) {
83 metas := map[string][]byte{
84 "root.json": []byte("root"),
85 "snapshot.json": []byte("snapshot"),
86 "timestamp": []byte("timestamp"),
87 }
88
89 fsys, dir, err := newTestFileStoreFS()
90 if err != nil {
91 t.Fatalf("Failed to create test FileStore")
92 }
93 t.Cleanup(func() { rmrf(dir, t.Logf) })
94 defer os.RemoveAll(dir)
95
96
97 for k, v := range targetFiles {
98 if err := fsys.addTarget(k, v); err != nil {
99 t.Errorf("failed to add target %s: %v", k, err)
100 }
101 rc, size, err := fsys.GetTarget(k)
102 if err != nil {
103 t.Errorf("failed to GetTarget %s: %v", k, err)
104 }
105 if size != int64(len(v)) {
106 t.Errorf("unexpected size returned for GetTarget: %s want %d got %d", k, len(v), size)
107 }
108 got, err := io.ReadAll(rc)
109 if err != nil {
110 t.Errorf("failed to ReadAll returned ReacCloser %s: %v", k, err)
111 }
112 if !bytes.Equal(v, got) {
113 t.Errorf("Read unexpected bytes, want: %s got: %s", string(k), string(got))
114 }
115 }
116 for k, v := range metas {
117 if err := fsys.addMeta(k, v); err != nil {
118 t.Errorf("failed to add meta %s %v", k, err)
119 }
120 rc, size, err := fsys.GetMeta(k)
121 if err != nil {
122 t.Errorf("failed to GetMeta %s: %v", k, err)
123 }
124 if size != int64(len(v)) {
125 t.Errorf("unexpected size returned for GetMeta: %s want %d got %d", k, len(v), size)
126 }
127 got, err := io.ReadAll(rc)
128 if err != nil {
129 t.Errorf("failed to ReadAll returned ReacCloser %s: %v", k, err)
130 }
131 if !bytes.Equal(v, got) {
132 t.Errorf("Read unexpected bytes, want: %s got: %s", string(k), string(got))
133 }
134 }
135 }
136
137
138 func (f *FileRemoteStore) addMeta(name string, data []byte) error {
139 return os.WriteFile(filepath.Join(f.testDir, name), data, os.ModePerm)
140 }
141
142 func (f *FileRemoteStore) addTarget(name string, data []byte) error {
143 fname := filepath.Join(f.testDir, targetsDir, name)
144 err := os.WriteFile(fname, data, os.ModePerm)
145 return err
146 }
147
148 func (f *FileRemoteStore) deleteMeta(name string) error {
149 return os.Remove(filepath.Join(f.testDir, name))
150 }
151
152 func (f *FileRemoteStore) deleteTarget(name string) error {
153 return os.Remove(filepath.Join(f.testDir, targetsDir, name))
154 }
155
156 func newTestFileStoreFS() (*FileRemoteStore, string, error) {
157 tmpDir := os.TempDir()
158 tufDir := filepath.Join(tmpDir, "tuf-file-store-test")
159
160 os.RemoveAll(tufDir)
161 os.Mkdir(tufDir, os.ModePerm)
162 os.Mkdir(filepath.Join(tufDir, targetsDir), os.ModePerm)
163 fs, err := NewFileRemoteStore(os.DirFS(tufDir), targetsDir)
164 fs.testDir = tufDir
165 return fs, tufDir, err
166 }
167
168
169
170 func rmrf(dir string, logger func(string, ...interface{})) {
171 if dir == "" {
172 logger("cowardly refusing to remove a not fully specified fir")
173 return
174 }
175 logger("Removing %s", dir)
176 d, err := os.Open(dir)
177 if err != nil {
178 logger("Failed to open %s: %v", dir, err)
179 return
180 }
181 defer d.Close()
182
183
184 names, err := d.Readdirnames(-1)
185 if err != nil {
186 logger("Failed to ReaddirNames %s: %v", dir, err)
187 return
188 }
189 for _, name := range names {
190 toRemove := filepath.Join(dir, name)
191 err = os.RemoveAll(toRemove)
192 if err != nil {
193 logger("Failed to RemoveAll %s: %v", toRemove, err)
194
195 }
196 }
197 }
198
View as plain text