1package filtering
2
3import (
4 "context"
5 "io"
6 "net/http"
7 "net/http/httptest"
8 "os"
9 "path/filepath"
10 "testing"
11
12 "github.com/stretchr/testify/require"
13)
14
15func TestDownloader_DownloadFile_RecoversWhenTargetDirDeletedConcurrently(t *testing.T) {
16 t.Parallel()
17
18 cacheDir := filepath.Join(t.TempDir(), "cache")
19 filename := filepath.Join("nested", "combined-part1.json")
20 localPath := filepath.Join(cacheDir, filename)
21 targetDir := filepath.Dir(localPath)
22
23 require.NoError(t, os.MkdirAll(targetDir, cacheDirPerm))
24
25 downloadStarted := make(chan struct{})
26 allowResponse := make(chan struct{})
27
28 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29 if r.URL.Path == "/"+filename {
30 close(downloadStarted)
31 <-allowResponse
32 _, _ = io.WriteString(w, `[{"trigger":{"url-filter":"test"},"action":{"type":"block"}}]`)
33 return
34 }
35 http.NotFound(w, r)
36 }))
37 defer server.Close()
38
39 d := NewDownloader(cacheDir)
40 d.baseURL = server.URL
41
42 type result struct {
43 path string
44 n int64
45 err error
46 }
47 resultCh := make(chan result, 1)
48 go func() {
49 path, n, err := d.downloadFile(context.Background(), filename)
50 resultCh <- result{path: path, n: n, err: err}
51 }()
52
53 <-downloadStarted
54 require.NoError(t, os.RemoveAll(targetDir))
55 close(allowResponse)
56
57 res := <-resultCh
58 require.NoError(t, res.err)
59 require.Equal(t, localPath, res.path)
60 require.Positive(t, res.n)
61
62 content, err := os.ReadFile(localPath)
63 require.NoError(t, err)
64 require.Contains(t, string(content), "url-filter")
65}
66
67func TestDownloader_RenameTempFile_RequiresDirectoryParent(t *testing.T) {
68 t.Parallel()
69
70 cacheDir := filepath.Join(t.TempDir(), "cache")
71 require.NoError(t, os.MkdirAll(cacheDir, cacheDirPerm))
72
73 tmpFile := filepath.Join(cacheDir, "payload.tmp")
74 require.NoError(t, os.WriteFile(tmpFile, []byte("payload"), manifestFilePerm))
75
76 parentAsFile := filepath.Join(cacheDir, "target")
77 require.NoError(t, os.WriteFile(parentAsFile, []byte("not-a-directory"), manifestFilePerm))
78
79 d := NewDownloader(cacheDir)
80
81 err := d.renameTempFile(tmpFile, filepath.Join(parentAsFile, "filter.json"))
82 require.Error(t, err)
83 require.Contains(t, err.Error(), "not a directory")
84}