GetStores replaces GetDCFStores: it takes a context, has no count argument and returns a plain slice. GetStore returns the one mounted card, or ErrNoStore or ErrMultipleStores. Each Object keeps the fs.FS its card was read through, and Hash reads through it, so tests can use fstest.MapFS. A cancelled context stops the read before the next directory. Library errors wrap with %w. Model: opus-5-5 Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
88 lines
1.9 KiB
Go
88 lines
1.9 KiB
Go
package dcf
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"testing"
|
|
)
|
|
|
|
// newMountPoint returns a temporary directory holding the given directories.
|
|
func newMountPoint(t *testing.T, directories ...string) string {
|
|
t.Helper()
|
|
|
|
root := t.TempDir()
|
|
|
|
for _, directory := range directories {
|
|
err := os.MkdirAll(filepath.Join(root, directory), 0o750)
|
|
if err != nil {
|
|
t.Fatalf("MkdirAll: %v", err)
|
|
}
|
|
}
|
|
|
|
return root
|
|
}
|
|
|
|
func TestIsDCFMountPoint(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
cases := map[string]bool{
|
|
"DCIM": true,
|
|
"PRIVATE/M4ROOT": true,
|
|
"M4ROOT": false,
|
|
"PRIVATE": false,
|
|
}
|
|
|
|
for directory, want := range cases {
|
|
got := isDCFMountPoint(newMountPoint(t, directory))
|
|
if got != want {
|
|
t.Errorf("isDCFMountPoint with only %q = %v, want %v",
|
|
directory, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIsDCFMountPointIgnoresPlainFile(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
root := t.TempDir()
|
|
|
|
err := os.WriteFile(filepath.Join(root, "DCIM"), nil, 0o600)
|
|
if err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
if isDCFMountPoint(root) {
|
|
t.Fatal("isDCFMountPoint counted a plain file named DCIM as a directory")
|
|
}
|
|
}
|
|
|
|
func TestIsDCFMountPointIgnoresSymlink(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
outside := newMountPoint(t, "M4ROOT")
|
|
|
|
for _, link := range []string{dcimDirectory, privateDirectory, m4RootDirectory} {
|
|
root := newMountPoint(t, filepath.Dir(link))
|
|
addSymlink(t, root, link, outside)
|
|
|
|
if isDCFMountPoint(root) {
|
|
t.Errorf("isDCFMountPoint counted a symlink at %s as a directory", link)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFilterDCFMountPointsKeepsThoseHoldingAStore(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
first := newMountPoint(t, "DCIM")
|
|
second := newMountPoint(t, "PRIVATE/M4ROOT")
|
|
|
|
got := filterDCFMountPoints([]string{newMountPoint(t), first, second})
|
|
|
|
want := []string{first, second}
|
|
if !slices.Equal(got, want) {
|
|
t.Errorf("filterDCFMountPoints = %v, want %v", got, want)
|
|
}
|
|
}
|