12 "github.com/stretchr/testify/require"
15 func TestImagesArePrivateSharedAndWrittenOnce(t *testing.T) {
16 root, err := openAgent(filepath.Join(t.TempDir(), "agent"))
17 require.NoError(t, err)
20 dir: filepath.Join(root.dir, "children", "House"),
21 config: AgentConfig{Parent: root.config.Name},
24 require.Equal(t, root.Images().dir, child.Images().dir)
26 data := imageTestPNG(t, 3, 2)
27 sum := sha256.Sum256(data)
28 expected := hex.EncodeToString(sum[:]) + ".png"
29 store := root.Images()
30 name, err := store.Save(data)
31 require.NoError(t, err)
32 require.Equal(t, expected, name)
34 info, err := os.Stat(filepath.Join(store.dir, name))
35 require.NoError(t, err)
36 require.Equal(t, os.FileMode(0o600), info.Mode().Perm())
38 var workers sync.WaitGroup
42 saved, saveErr := child.Images().Save(data)
43 require.NoError(t, saveErr)
44 require.Equal(t, name, saved)
50 again, err := os.Stat(filepath.Join(store.dir, name))
51 require.NoError(t, err)
52 require.True(t, os.SameFile(info, again))
54 files, err := os.ReadDir(store.dir)
55 require.NoError(t, err)
56 require.Len(t, files, 1)
58 actual, err := store.Read(name)
59 require.NoError(t, err)
60 require.Equal(t, data, actual)
63 func TestImageStoreRejectsLargeUnsupportedAndUnsafeImages(t *testing.T) {
64 store := &ImageStore{dir: filepath.Join(t.TempDir(), imageDirName)}
65 _, err := store.Save(bytes.Repeat([]byte{0}, imageMaxBytes+1))
66 require.ErrorContains(t, err, "exceeds 20 MB")
68 _, err = store.Save([]byte("not an image"))
69 require.ErrorContains(t, err, "JPEG, PNG, or WebP")
71 _, err = store.Read("../secret.png")
72 require.ErrorContains(t, err, "invalid image name")
74 _, err = os.Stat(store.dir)
75 require.ErrorIs(t, err, os.ErrNotExist)
78 func TestBackupKeepsImagesAndTheirModes(t *testing.T) {
80 store := &ImageStore{dir: filepath.Join(dir, imageDirName)}
81 data := imageTestPNG(t, 2, 2)
82 name, err := store.Save(data)
83 require.NoError(t, err)
84 require.NoError(t, os.WriteFile(filepath.Join(store.dir, ".image-incomplete"), []byte("partial"), 0o600))
87 archive := filepath.Join(t.TempDir(), "images.tar.gz")
88 require.NoError(t, backupCopy(t.Context(), dir, stage, archive))
90 _, err = backupArchive(t.Context(), stage, archive)
91 require.NoError(t, err)
93 restored := t.TempDir()
94 require.NoError(t, backupRestore(t.Context(), archive, restored))
96 actual, err := (&ImageStore{dir: filepath.Join(restored, imageDirName)}).Read(name)
97 require.NoError(t, err)
98 require.Equal(t, data, actual)
100 info, err := os.Stat(filepath.Join(restored, imageDirName, name))
101 require.NoError(t, err)
102 require.Equal(t, os.FileMode(0o600), info.Mode().Perm())
104 _, err = os.Stat(filepath.Join(restored, imageDirName, ".image-incomplete"))
105 require.ErrorIs(t, err, os.ErrNotExist)
108 func TestImageMarkersKeepCaptionAndOnlySafeNames(t *testing.T) {
109 name := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.png"
110 text := imageText([]string{name}, "Read the label.")
111 require.Equal(t, "[image "+name+"]\nRead the label.", text)
112 require.Equal(t, []string{name}, imageFiles(text+"\n[image ../secret.png]\ntext [image "+name+"]"))