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>
156 lines
3.4 KiB
Go
156 lines
3.4 KiB
Go
package dcf_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io/fs"
|
|
"testing"
|
|
|
|
"sneak.berlin/go/dcf/pkg/dcf"
|
|
)
|
|
|
|
const cardRoot = "/mnt/card"
|
|
|
|
// newStore returns a store holding two images and one video of known sizes.
|
|
func newStore() *dcf.Store {
|
|
return &dcf.Store{
|
|
RootDirectory: cardRoot,
|
|
Images: []*dcf.Image{
|
|
{Object: dcf.Object{Size: 2000}},
|
|
{Object: dcf.Object{Size: 500}},
|
|
},
|
|
Videos: []*dcf.Video{
|
|
{Object: dcf.Object{Size: 9000}},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestObjectFullFilePath(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
object := dcf.Object{
|
|
DCFStoreRoot: cardRoot,
|
|
Path: "DCIM/100MSDCF/DSC00001.ARW",
|
|
}
|
|
|
|
want := cardRoot + "/DCIM/100MSDCF/DSC00001.ARW"
|
|
if got := object.FullFilePath(); got != want {
|
|
t.Fatalf("FullFilePath() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestStoreCounts(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
store := newStore()
|
|
|
|
if got := store.ImagesCount(); got != 2 {
|
|
t.Errorf("ImagesCount() = %d, want 2", got)
|
|
}
|
|
|
|
if got := store.VideosCount(); got != 1 {
|
|
t.Errorf("VideosCount() = %d, want 1", got)
|
|
}
|
|
}
|
|
|
|
func TestStoreSizes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
store := newStore()
|
|
|
|
if got := store.TotalImageSize(); got != 2500 {
|
|
t.Errorf("TotalImageSize() = %d, want 2500", got)
|
|
}
|
|
|
|
if got := store.TotalVideoSize(); got != 9000 {
|
|
t.Errorf("TotalVideoSize() = %d, want 9000", got)
|
|
}
|
|
|
|
if got := store.TotalSize(); got != 11500 {
|
|
t.Errorf("TotalSize() = %d, want 11500", got)
|
|
}
|
|
}
|
|
|
|
func TestStoreString(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
want := "Store{RootDirectory: /mnt/card, Images: 2, Videos: 1, " +
|
|
"TotalSize: 12 kB}"
|
|
if got := newStore().String(); got != want {
|
|
t.Fatalf("String() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestStoreStringShowsNegativeTotalAsZero(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
store := dcf.Store{
|
|
RootDirectory: cardRoot,
|
|
Images: []*dcf.Image{{Object: dcf.Object{Size: -1}}},
|
|
}
|
|
|
|
want := "Store{RootDirectory: /mnt/card, Images: 1, Videos: 0, " +
|
|
"TotalSize: 0 B}"
|
|
if got := store.String(); got != want {
|
|
t.Fatalf("String() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestImageString(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
image := dcf.Image{Object: dcf.Object{
|
|
Path: "DCIM/100MSDCF/DSC00001.ARW",
|
|
Size: 2000,
|
|
Extension: ".ARW",
|
|
}}
|
|
|
|
want := "Image{Path: DCIM/100MSDCF/DSC00001.ARW, Size: 2000, Extension: .ARW}"
|
|
if got := image.String(); got != want {
|
|
t.Fatalf("String() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestVideoString(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
video := dcf.Video{Object: dcf.Object{
|
|
Path: "PRIVATE/M4ROOT/CLIP/C0001.MP4",
|
|
Size: 9000,
|
|
Extension: ".MP4",
|
|
}}
|
|
|
|
want := "Video{Path: PRIVATE/M4ROOT/CLIP/C0001.MP4, Size: 9000, Extension: .MP4}"
|
|
if got := video.String(); got != want {
|
|
t.Fatalf("String() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestObjectHashOfObjectBuiltByHandReturnsError(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
object := dcf.Object{DCFStoreRoot: cardRoot, Path: "a.jpg"}
|
|
|
|
_, err := object.Hash()
|
|
if !errors.Is(err, fs.ErrInvalid) {
|
|
t.Fatalf("Hash() error = %v, want %v", err, fs.ErrInvalid)
|
|
}
|
|
}
|
|
|
|
func TestGetStoresAndGetStoreReturnCancellation(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx, cancel := context.WithCancel(t.Context())
|
|
cancel()
|
|
|
|
_, err := dcf.GetStores(ctx)
|
|
if !errors.Is(err, context.Canceled) {
|
|
t.Errorf("GetStores error = %v, want %v", err, context.Canceled)
|
|
}
|
|
|
|
_, err = dcf.GetStore(ctx)
|
|
if !errors.Is(err, context.Canceled) {
|
|
t.Errorf("GetStore error = %v, want %v", err, context.Canceled)
|
|
}
|
|
}
|