github.com/anchore/syft@v1.38.2/cmd/syft/internal/options/cache_test.go (about) 1 package options 2 3 import ( 4 "io" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 "time" 10 11 "github.com/adrg/xdg" 12 "github.com/stretchr/testify/require" 13 14 "github.com/anchore/go-homedir" 15 "github.com/anchore/syft/internal" 16 "github.com/anchore/syft/internal/cache" 17 ) 18 19 func Test_defaultDir(t *testing.T) { 20 tmpDir := filepath.Join(t.TempDir(), "cache-temp") 21 xdgCacheDir := filepath.Join(tmpDir, "fake-xdg-cache") 22 homeDir := filepath.Join(tmpDir, "fake-home") 23 24 tests := []struct { 25 name string 26 env map[string]string 27 expected string 28 }{ 29 { 30 name: "no-xdg", 31 env: map[string]string{ 32 "HOME": homeDir, 33 }, 34 expected: homeDir, 35 }, 36 { 37 name: "xdg-cache", 38 env: map[string]string{ 39 "XDG_CACHE_HOME": xdgCacheDir, 40 }, 41 expected: xdgCacheDir, 42 }, 43 } 44 45 // capture all the initial environment variables to reset them before we reset library caches 46 env := map[string]string{ 47 "HOME": "", 48 "XDG_DATA_HOME": "", 49 "XDG_DATA_DIRS": "", 50 "XDG_CONFIG_HOME": "", 51 "XDG_CONFIG_DIRS": "", 52 "XDG_STATE_HOME": "", 53 "XDG_CACHE_HOME": "", 54 "XDG_RUNTIME_DIR": "", 55 } 56 for k := range env { 57 env[k] = os.Getenv(k) 58 } 59 60 for _, test := range tests { 61 t.Run(test.name, func(t *testing.T) { 62 restoreCache(t) 63 64 for k, v := range test.env { 65 patchEnv(t, k, v) 66 } 67 xdg.Reload() 68 69 got := defaultDir() 70 71 require.True(t, strings.HasPrefix(got, test.expected)) 72 }) 73 } 74 } 75 76 func Test_cacheOptions(t *testing.T) { 77 tmp := t.TempDir() 78 tests := []struct { 79 name string 80 opts Cache 81 test func(t *testing.T) 82 }{ 83 { 84 name: "disable-1", 85 opts: Cache{ 86 Dir: "some-dir", 87 TTL: "0", 88 }, 89 test: func(t *testing.T) { 90 c := cache.GetManager().GetCache("test-disable-1", "v-disable-1") 91 err := c.Write("key-disable-1", strings.NewReader("some-value-disable-1")) 92 require.NoError(t, err) 93 rdr, err := c.Read("key-disable-1") 94 require.Nil(t, rdr) 95 require.Error(t, err) 96 }, 97 }, 98 { 99 name: "disable-2", 100 opts: Cache{ 101 Dir: "some-dir", 102 TTL: "0s", 103 }, 104 test: func(t *testing.T) { 105 c := cache.GetManager().GetCache("test-disable-2", "v-disable-2") 106 err := c.Write("key-disable-2", strings.NewReader("some-value-disable-2")) 107 require.NoError(t, err) 108 rdr, err := c.Read("key-disable-2") 109 require.Nil(t, rdr) 110 require.Error(t, err) 111 }, 112 }, 113 114 { 115 name: "disable-3", 116 opts: Cache{ 117 Dir: "some-dir", 118 TTL: "0d", 119 }, 120 test: func(t *testing.T) { 121 c := cache.GetManager().GetCache("test-disable-3", "v-disable-3") 122 err := c.Write("key-disable-3", strings.NewReader("some-value-disable-3")) 123 require.NoError(t, err) 124 rdr, err := c.Read("key-disable-3") 125 require.Nil(t, rdr) 126 require.Error(t, err) 127 }, 128 }, 129 { 130 name: "in-memory", 131 opts: Cache{ 132 Dir: "", 133 TTL: "10m", 134 }, 135 test: func(t *testing.T) { 136 c := cache.GetManager().GetCache("test-mem", "v-mem") 137 err := c.Write("key-mem", strings.NewReader("some-value-mem")) 138 require.NoError(t, err) 139 rdr, err := c.Read("key-mem") 140 require.NotNil(t, rdr) 141 defer internal.CloseAndLogError(rdr, "") 142 require.NoError(t, err) 143 data, err := io.ReadAll(rdr) 144 require.NoError(t, err) 145 require.Equal(t, "some-value-mem", string(data)) 146 require.NoDirExists(t, filepath.Join("test-mem", "v-mem")) 147 }, 148 }, 149 { 150 name: "on disk", 151 opts: Cache{ 152 Dir: tmp, 153 TTL: "10m", 154 }, 155 test: func(t *testing.T) { 156 c := cache.GetManager().GetCache("test-disk", "v-disk") 157 err := c.Write("key-disk", strings.NewReader("some-value-disk")) 158 require.NoError(t, err) 159 rdr, err := c.Read("key-disk") 160 require.NotNil(t, rdr) 161 defer internal.CloseAndLogError(rdr, "") 162 require.NoError(t, err) 163 data, err := io.ReadAll(rdr) 164 require.NoError(t, err) 165 require.Equal(t, "some-value-disk", string(data)) 166 require.DirExists(t, filepath.Join(tmp, "test-disk", "v-disk")) 167 }, 168 }, 169 } 170 for _, test := range tests { 171 t.Run(test.name, func(t *testing.T) { 172 original := cache.GetManager() 173 defer cache.SetManager(original) 174 175 err := test.opts.PostLoad() 176 require.NoError(t, err) 177 178 test.test(t) 179 }) 180 } 181 } 182 183 func Test_parseDuration(t *testing.T) { 184 tests := []struct { 185 duration string 186 expect time.Duration 187 err require.ErrorAssertionFunc 188 }{ 189 { 190 duration: "0d", 191 expect: 0, 192 }, 193 { 194 duration: "0m", 195 expect: 0, 196 }, 197 { 198 duration: "0s", 199 expect: 0, 200 }, 201 { 202 duration: "0", 203 expect: 0, 204 }, 205 { 206 duration: "1d", 207 expect: 24 * time.Hour, 208 }, 209 { 210 duration: "7d", 211 expect: 7 * 24 * time.Hour, 212 }, 213 { 214 duration: "365D", 215 expect: 365 * 24 * time.Hour, 216 }, 217 { 218 duration: "7d1h1m1s", 219 expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second, 220 }, 221 { 222 duration: "7d 1h 1m 1s", 223 expect: 7*24*time.Hour + time.Hour + time.Minute + time.Second, 224 }, 225 { 226 duration: "2h", 227 expect: 2 * time.Hour, 228 }, 229 { 230 duration: "2h5m", 231 expect: 2*time.Hour + 5*time.Minute, 232 }, 233 { 234 duration: "2h 5m", 235 expect: 2*time.Hour + 5*time.Minute, 236 }, 237 { 238 duration: "d24h", 239 err: require.Error, 240 }, 241 } 242 243 for _, test := range tests { 244 t.Run(test.duration, func(t *testing.T) { 245 got, err := parseDuration(test.duration) 246 if test.err != nil { 247 test.err(t, err) 248 return 249 } else { 250 require.NoError(t, err) 251 } 252 require.Equal(t, test.expect, got) 253 }) 254 } 255 } 256 257 func Test_durationToString(t *testing.T) { 258 tests := []struct { 259 duration time.Duration 260 expect string 261 err require.ErrorAssertionFunc 262 }{ 263 { 264 expect: "1d", 265 duration: 24 * time.Hour, 266 }, 267 { 268 expect: "7d", 269 duration: 7 * 24 * time.Hour, 270 }, 271 { 272 expect: "7d1h1m1s", 273 duration: 7*24*time.Hour + time.Hour + time.Minute + time.Second, 274 }, 275 { 276 expect: "2h0m0s", 277 duration: 2 * time.Hour, 278 }, 279 { 280 expect: "2h5m0s", 281 duration: 2*time.Hour + 5*time.Minute, 282 }, 283 } 284 285 for _, test := range tests { 286 t.Run(test.expect, func(t *testing.T) { 287 got := durationToString(test.duration) 288 require.Equal(t, test.expect, got) 289 }) 290 } 291 } 292 293 // restoreCache ensures cache settings are restored after test 294 func restoreCache(t testing.TB) { 295 t.Helper() 296 origEnabled := homedir.CacheEnabled() 297 298 t.Cleanup(func() { 299 homedir.SetCacheEnable(origEnabled) 300 homedir.Reset() 301 }) 302 } 303 304 // patchEnv modifies an environment variable for the duration of the test 305 func patchEnv(t testing.TB, key, value string) { 306 t.Helper() 307 original := os.Getenv(key) 308 309 if value != "" { 310 os.Setenv(key, value) 311 } else { 312 os.Unsetenv(key) 313 } 314 315 t.Cleanup(func() { 316 if original != "" { 317 os.Setenv(key, original) 318 } else { 319 os.Unsetenv(key) 320 } 321 xdg.Reload() 322 }) 323 }