Files
photocli/internal/photos/photos_test.go
T
Ein Anderssono fffb30023b
pipeline / test (push) Has been cancelled
pipeline / build (push) Has been cancelled
v0.8.0: enrich XMP metadata
2026-06-15 01:21:49 +02:00

789 lines
24 KiB
Go

//go:build test
package photos
import (
"encoding/json"
"testing"
)
func TestParseAlbumsJSON(t *testing.T) {
tests := []struct {
name string
json string
want []Album
wantErr bool
}{
{
name: "empty albums",
json: `{"albums":[]}`,
want: []Album{},
},
{
name: "single album",
json: `{"albums":[{"id":"abc","title":"Vacation"}]}`,
want: []Album{{ID: "abc", Title: "Vacation"}},
},
{
name: "multiple albums",
json: `{"albums":[{"id":"a1","title":"Album1"},{"id":"a2","title":"Album2"}]}`,
want: []Album{{ID: "a1", Title: "Album1"}, {ID: "a2", Title: "Album2"}},
},
{
name: "invalid json",
json: `not json`,
wantErr: true,
},
{
name: "missing albums key",
json: `{}`,
want: []Album{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseAlbumsJSON(tt.json)
if (err != nil) != tt.wantErr {
t.Errorf("ParseAlbumsJSON() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.wantErr {
return
}
if len(got) != len(tt.want) {
t.Errorf("ParseAlbumsJSON() got %d albums, want %d", len(got), len(tt.want))
return
}
for i := range got {
if got[i] != tt.want[i] {
t.Errorf("ParseAlbumsJSON()[%d] = %+v, want %+v", i, got[i], tt.want[i])
}
}
})
}
}
func TestParseAssetsJSON(t *testing.T) {
tests := []struct {
name string
json string
want []Asset
wantTotal int
wantErr bool
errMsg string
}{
{
name: "empty assets",
json: `{"assets":[],"total":0}`,
want: []Asset{},
wantTotal: 0,
},
{
name: "single asset",
json: `{"assets":[{"id":"asset1","filename":"IMG_0001.JPG"}],"total":1}`,
want: []Asset{{ID: "asset1", Filename: "IMG_0001.JPG"}},
wantTotal: 1,
},
{
name: "asset with metadata",
json: `{"assets":[{"id":"a1","filename":"IMG.JPG","cloud":"local","mediaType":"image","pixelWidth":4032,"pixelHeight":3024,"duration":0,"isFavorite":true,"hasAdjustments":false,"resources":[{"type":"photo","filename":"IMG.JPG","uti":"public.heic","local":true}]}],"total":1}`,
want: []Asset{{
ID: "a1", Filename: "IMG.JPG", Cloud: "local",
MediaType: "image", PixelWidth: 4032, PixelHeight: 3024,
IsFavorite: true, HasAdjustments: false,
Resources: []AssetResource{{Type: "photo", Filename: "IMG.JPG", UTI: "public.heic", Local: true}},
}},
wantTotal: 1,
},
{
name: "video asset with duration",
json: `{"assets":[{"id":"v1","filename":"clip.mov","cloud":"cloud","mediaType":"video","pixelWidth":1920,"pixelHeight":1080,"duration":12.5}],"total":1}`,
want: []Asset{{
ID: "v1", Filename: "clip.mov", Cloud: "cloud",
MediaType: "video", PixelWidth: 1920, PixelHeight: 1080, Duration: 12.5,
}},
wantTotal: 1,
},
{
name: "multiple assets",
json: `{"assets":[{"id":"a1","filename":"a.jpg"},{"id":"a2","filename":"b.jpg"},{"id":"a3","filename":"c.jpg"}],"total":3}`,
want: []Asset{{ID: "a1", Filename: "a.jpg"}, {ID: "a2", Filename: "b.jpg"}, {ID: "a3", Filename: "c.jpg"}},
wantTotal: 3,
},
{
name: "asset with creationDate",
json: `{"assets":[{"id":"d1","filename":"photo.jpg","creationDate":"2024-06-15T12:30:00+0200"}],"total":1}`,
want: func() []Asset {
d := "2024-06-15T12:30:00+0200"
return []Asset{{ID: "d1", Filename: "photo.jpg", CreationDate: &d}}
}(),
wantTotal: 1,
},
{
name: "error response",
json: `{"error":"album not found"}`,
wantErr: true,
errMsg: "album not found",
},
{
name: "invalid json",
json: `not json`,
wantErr: true,
},
{
name: "empty error is not an error",
json: `{"error":"","assets":[{"id":"a1","filename":"IMG.JPG"}],"total":1}`,
want: []Asset{{ID: "a1", Filename: "IMG.JPG"}},
wantTotal: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, total, err := ParseAssetsJSON(tt.json)
if (err != nil) != tt.wantErr {
t.Errorf("ParseAssetsJSON() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.wantErr {
if tt.errMsg != "" && err.Error() != tt.errMsg {
t.Errorf("ParseAssetsJSON() error = %q, want %q", err.Error(), tt.errMsg)
}
return
}
if total != tt.wantTotal {
t.Errorf("ParseAssetsJSON() total = %d, want %d", total, tt.wantTotal)
}
if len(got) != len(tt.want) {
t.Errorf("ParseAssetsJSON() got %d assets, want %d", len(got), len(tt.want))
return
}
for i := range got {
if !equalAsset(got[i], tt.want[i]) {
t.Errorf("ParseAssetsJSON()[%d] = %+v, want %+v", i, got[i], tt.want[i])
}
}
})
}
}
func TestParseAssetsJSONExtendedMetadata(t *testing.T) {
created := "2024-01-01T00:00:00Z"
modified := "2024-01-02T00:00:00Z"
assets, total, err := ParseAssetsJSON(`{"assets":[{"id":"x1","filename":"IMG.HEIC","mediaType":"image","mediaSubtypes":["photoLive","photoHDR"],"sourceType":"userLibrary","playbackStyle":"livePhoto","pixelWidth":1,"pixelHeight":2,"creationDate":"2024-01-01T00:00:00Z","modificationDate":"2024-01-02T00:00:00Z","duration":3.5,"isFavorite":true,"isHidden":true,"hasAdjustments":true,"location":{"latitude":59.1,"longitude":18.2,"altitude":10,"horizontalAccuracy":5},"burstIdentifier":"burst","representsBurst":true,"burstSelectionTypes":["autoPick"],"adjustmentInfo":{"formatIdentifier":"fmt","formatVersion":"1","baseFilename":"base.heic"},"resources":[{"type":"adjustmentData","filename":"adj.plist","uti":"public.plist","local":true,"size":42}]}],"total":1}`)
if err != nil || total != 1 || len(assets) != 1 {
t.Fatalf("ParseAssetsJSON err=%v total=%d len=%d", err, total, len(assets))
}
a := assets[0]
if a.CreationDate == nil || *a.CreationDate != created || a.ModificationDate == nil || *a.ModificationDate != modified {
t.Fatalf("unexpected dates: %+v", a)
}
if a.Location == nil || a.Location.Latitude != 59.1 || a.Location.Longitude != 18.2 || !a.IsHidden || !a.HasAdjustments || !a.RepresentsBurst {
t.Fatalf("unexpected extended metadata: %+v", a)
}
if len(a.MediaSubtypes) != 2 || a.SourceType != "userLibrary" || a.PlaybackStyle != "livePhoto" || len(a.BurstSelectionTypes) != 1 {
t.Fatalf("unexpected type metadata: %+v", a)
}
if a.AdjustmentInfo == nil || a.AdjustmentInfo.FormatIdentifier != "fmt" || a.Resources[0].Size != 42 {
t.Fatalf("unexpected adjustment/resource metadata: %+v", a)
}
}
func TestParsePlacemarkJSON(t *testing.T) {
p, err := ParsePlacemarkJSON(`{"placemark":{"country":"Sweden","countryCode":"SE","locality":"Stockholm","formattedAddress":"Stockholm, Sweden","areasOfInterest":["Gamla stan"]}}`)
if err != nil {
t.Fatal(err)
}
if p.Country != "Sweden" || p.CountryCode != "SE" || p.Locality != "Stockholm" || len(p.AreasOfInterest) != 1 {
t.Fatalf("unexpected placemark: %+v", p)
}
if _, err := ParsePlacemarkJSON(`{"error":"geocode failed"}`); err == nil || err.Error() != "geocode failed" {
t.Fatalf("expected geocode error, got %v", err)
}
if _, err := ParsePlacemarkJSON(`bad`); err == nil {
t.Fatal("expected invalid JSON error")
}
}
func TestCgoBridgeReverseGeocode(t *testing.T) {
SetTestGeocodeJSON(`{"placemark":{"country":"Sweden","locality":"Stockholm"}}`)
p, err := (&CgoBridge{}).ReverseGeocode(59.3293, 18.0686)
if err != nil {
t.Fatal(err)
}
if p.Country != "Sweden" || p.Locality != "Stockholm" {
t.Fatalf("unexpected placemark: %+v", p)
}
SetTestGeocodeJSON(`{"error":"no network"}`)
if _, err := (&CgoBridge{}).ReverseGeocode(0, 0); err == nil || err.Error() != "no network" {
t.Fatalf("expected geocode error, got %v", err)
}
SetTestGeocodeNull()
if _, err := (&CgoBridge{}).ReverseGeocode(0, 0); err != errBridgeNil {
t.Fatalf("expected nil bridge error, got %v", err)
}
}
func TestParseTreeJSON(t *testing.T) {
tests := []struct {
name string
json string
want []CollectionNode
wantErr bool
errMsg string
}{
{
name: "empty tree",
json: `{"collections":[]}`,
want: []CollectionNode{},
},
{
name: "nested tree",
json: `{"collections":[{"id":"f1","name":"Trips","kind":"folder","children":[{"id":"f2","name":"Italy 2024","kind":"folder","children":[{"id":"a1","name":"Venice","kind":"album","children":[]}]}]},{"id":"a2","name":"Favorites","kind":"album","children":[]}]}`,
want: []CollectionNode{
{ID: "f1", Name: "Trips", Kind: "folder", Children: []CollectionNode{{ID: "f2", Name: "Italy 2024", Kind: "folder", Children: []CollectionNode{{ID: "a1", Name: "Venice", Kind: "album"}}}}},
{ID: "a2", Name: "Favorites", Kind: "album"},
},
},
{
name: "error response",
json: `{"error":"library unavailable"}`,
wantErr: true,
errMsg: "library unavailable",
},
{
name: "invalid json",
json: `not json`,
wantErr: true,
},
{
name: "missing collections key",
json: `{}`,
want: nil,
},
{
name: "empty error is not an error",
json: `{"error":"","collections":[{"id":"a9","name":"Root Album","kind":"album"}]}`,
want: []CollectionNode{{ID: "a9", Name: "Root Album", Kind: "album"}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseTreeJSON(tt.json)
if (err != nil) != tt.wantErr {
t.Errorf("ParseTreeJSON() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.wantErr {
if tt.errMsg != "" && err.Error() != tt.errMsg {
t.Errorf("ParseTreeJSON() error = %q, want %q", err.Error(), tt.errMsg)
}
return
}
if len(got) != len(tt.want) {
t.Errorf("ParseTreeJSON() got %d collections, want %d", len(got), len(tt.want))
return
}
for i := range got {
if !equalCollectionNode(got[i], tt.want[i]) {
t.Errorf("ParseTreeJSON()[%d] = %+v, want %+v", i, got[i], tt.want[i])
}
}
})
}
}
func TestAlbumsResponseUnmarshal(t *testing.T) {
raw := `{"albums":[{"id":"x","title":"Y"}]}`
var resp AlbumsResponse
if err := json.Unmarshal([]byte(raw), &resp); err != nil {
t.Fatal(err)
}
if len(resp.Albums) != 1 || resp.Albums[0].ID != "x" || resp.Albums[0].Title != "Y" {
t.Errorf("got %+v", resp.Albums)
}
}
func TestAssetsResponseUnmarshal(t *testing.T) {
raw := `{"assets":[{"id":"z","filename":"IMG_9999.JPG"}],"total":1}`
var resp AssetsResponse
if err := json.Unmarshal([]byte(raw), &resp); err != nil {
t.Fatal(err)
}
if len(resp.Assets) != 1 || resp.Assets[0].ID != "z" || resp.Assets[0].Filename != "IMG_9999.JPG" {
t.Errorf("got %+v", resp.Assets)
}
if resp.Total != 1 {
t.Errorf("got total %d, want 1", resp.Total)
}
}
func TestTreeResponseUnmarshal(t *testing.T) {
raw := `{"collections":[{"id":"f1","name":"Trips","kind":"folder","children":[{"id":"a1","name":"Venice","kind":"album"}]}]}`
var resp TreeResponse
if err := json.Unmarshal([]byte(raw), &resp); err != nil {
t.Fatal(err)
}
if len(resp.Collections) != 1 || resp.Collections[0].ID != "f1" || resp.Collections[0].Name != "Trips" || len(resp.Collections[0].Children) != 1 || resp.Collections[0].Children[0].ID != "a1" || resp.Collections[0].Children[0].Name != "Venice" {
t.Errorf("got %+v", resp.Collections)
}
}
func TestErrorResponseUnmarshal(t *testing.T) {
raw := `{"error":"oops"}`
var resp ErrorResponse
if err := json.Unmarshal([]byte(raw), &resp); err != nil {
t.Fatal(err)
}
if resp.Error != "oops" {
t.Errorf("got %q", resp.Error)
}
}
func TestCgoBridgeImplementsBridge(t *testing.T) {
var _ Bridge = &CgoBridge{}
}
func TestCgoBridgeListAlbumsViaStub(t *testing.T) {
SetTestAlbumsJSON(`{"albums":[{"id":"abc","title":"TestAlbum"}]}`)
bridge := &CgoBridge{}
albums, err := bridge.ListAlbums()
if err != nil {
t.Fatal(err)
}
if len(albums) != 1 || albums[0].ID != "abc" || albums[0].Title != "TestAlbum" {
t.Errorf("got %+v", albums)
}
}
func TestCgoBridgeListAssetsViaStub(t *testing.T) {
SetTestAssetsJSON(`{"assets":[{"id":"asset-1","filename":"A.JPG"},{"id":"asset-2","filename":"B.JPG"}],"total":2}`)
bridge := &CgoBridge{}
assets, _, err := bridge.ListAssets("any")
if err != nil {
t.Fatal(err)
}
if len(assets) != 2 {
t.Errorf("got %d assets", len(assets))
}
if assets[0].Filename != "A.JPG" || assets[1].Filename != "B.JPG" {
t.Errorf("got %+v", assets)
}
}
func TestCgoBridgeListAssetsErrorViaStub(t *testing.T) {
SetTestAssetsJSON(`{"error":"album not found"}`)
bridge := &CgoBridge{}
_, _, err := bridge.ListAssets("bad-id")
if err == nil || err.Error() != "album not found" {
t.Errorf("got %v", err)
}
}
func TestCgoBridgeListTreeViaStub(t *testing.T) {
SetTestTreeJSON(`{"collections":[{"id":"f1","name":"Trips","kind":"folder","children":[{"id":"f2","name":"Italy 2024","kind":"folder","children":[{"id":"a1","name":"Venice","kind":"album"}]}]},{"id":"a2","name":"Favorites","kind":"album"}]}`)
bridge := &CgoBridge{}
tree, err := bridge.ListTree()
if err != nil {
t.Fatal(err)
}
if len(tree) != 2 {
t.Errorf("got %d collections", len(tree))
}
if tree[0].ID != "f1" || tree[0].Name != "Trips" || len(tree[0].Children) != 1 || tree[0].Children[0].ID != "f2" || tree[0].Children[0].Name != "Italy 2024" {
t.Errorf("got %+v", tree)
}
if tree[1].ID != "a2" || tree[1].Name != "Favorites" || tree[1].Kind != "album" {
t.Errorf("got %+v", tree)
}
}
func TestCgoBridgeListTreeNil(t *testing.T) {
SetTestTreeNull()
defer SetTestTreeJSON(`{"collections":[]}`)
bridge := &CgoBridge{}
_, err := bridge.ListTree()
if err != errBridgeNil {
t.Errorf("got %v, want %v", err, errBridgeNil)
}
}
func TestCgoBridgeRequestAccessGranted(t *testing.T) {
SetTestAccessRC(0)
bridge := &CgoBridge{}
if err := bridge.RequestAccess(); err != nil {
t.Errorf("got %v", err)
}
}
func TestCgoBridgeRequestAccessDenied(t *testing.T) {
SetTestAccessRC(-1)
bridge := &CgoBridge{}
err := bridge.RequestAccess()
if err == nil {
t.Fatal("expected error")
}
if err != errAccessDenied {
t.Errorf("got %v, want %v", err, errAccessDenied)
}
}
func TestCgoBridgeListAlbumsNil(t *testing.T) {
SetTestAlbumsNull()
defer SetTestAlbumsJSON(`{"albums":[]}`)
bridge := &CgoBridge{}
_, err := bridge.ListAlbums()
if err != errBridgeNil {
t.Errorf("got %v, want %v", err, errBridgeNil)
}
}
func TestCgoBridgeListAssetsNil(t *testing.T) {
SetTestAssetsNull()
defer SetTestAssetsJSON(`{"assets":[],"total":0}`)
bridge := &CgoBridge{}
_, _, err := bridge.ListAssets("any")
if err != errBridgeNil {
t.Errorf("got %v, want %v", err, errBridgeNil)
}
}
func TestErrAccessDeniedMessage(t *testing.T) {
if errAccessDenied.Error() == "" {
t.Error("errAccessDenied should have a message")
}
}
func TestErrBridgeNilMessage(t *testing.T) {
if errBridgeNil.Error() == "" {
t.Error("errBridgeNil should have a message")
}
}
func TestParseExportResultJSON(t *testing.T) {
tests := []struct {
name string
json string
want ExportResult
wantErr bool
errMsg string
}{
{
name: "success",
json: `{"filename":"0000_test.jpg","size":1024,"cloud":"local"}`,
want: ExportResult{Filename: "0000_test.jpg", Size: 1024, Cloud: "local"},
},
{
name: "cloud asset",
json: `{"filename":"photo.jpg","size":2048,"cloud":"cloud"}`,
want: ExportResult{Filename: "photo.jpg", Size: 2048, Cloud: "cloud"},
},
{
name: "error response",
json: `{"error":"write failed","cloud":"local"}`,
wantErr: true,
errMsg: "write failed",
},
{
name: "invalid json",
json: `not json`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseExportResultJSON(tt.json)
if (err != nil) != tt.wantErr {
t.Errorf("ParseExportResultJSON() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.wantErr {
if tt.errMsg != "" && err.Error() != tt.errMsg {
t.Errorf("ParseExportResultJSON() error = %q, want %q", err.Error(), tt.errMsg)
}
return
}
if got != tt.want {
t.Errorf("ParseExportResultJSON() = %+v, want %+v", got, tt.want)
}
})
}
}
func equalCollectionNode(a, b CollectionNode) bool {
if a.ID != b.ID || a.Name != b.Name || a.Kind != b.Kind || len(a.Children) != len(b.Children) {
return false
}
for i := range a.Children {
if !equalCollectionNode(a.Children[i], b.Children[i]) {
return false
}
}
return true
}
func equalAsset(a, b Asset) bool {
if a.ID != b.ID || a.Filename != b.Filename || a.Cloud != b.Cloud || a.MediaType != b.MediaType || a.PixelWidth != b.PixelWidth || a.PixelHeight != b.PixelHeight || a.Duration != b.Duration || a.IsFavorite != b.IsFavorite || a.HasAdjustments != b.HasAdjustments {
return false
}
if (a.CreationDate == nil) != (b.CreationDate == nil) {
return false
}
if a.CreationDate != nil && b.CreationDate != nil && *a.CreationDate != *b.CreationDate {
return false
}
if len(a.Resources) != len(b.Resources) {
return false
}
for i := range a.Resources {
if a.Resources[i] != b.Resources[i] {
return false
}
}
return true
}
func TestCgoBridgeExportPreviewViaStub(t *testing.T) {
SetTestExportPreviewJSON(`{"filename":"0001_img.jpg","size":2048,"cloud":"local"}`)
defer SetTestExportPreviewJSON(`{"filename":"0000_test.jpg","size":1024,"cloud":"local"}`)
bridge := &CgoBridge{}
result, err := bridge.ExportPreview("asset-1", "/tmp", 1024, 85, 0)
if err != nil {
t.Fatal(err)
}
if result.Filename != "0001_img.jpg" {
t.Errorf("got filename %q, want %q", result.Filename, "0001_img.jpg")
}
if result.Size != 2048 {
t.Errorf("got size %d, want %d", result.Size, 2048)
}
if result.Cloud != "local" {
t.Errorf("got cloud %q, want %q", result.Cloud, "local")
}
}
func TestCgoBridgeExportPreviewWithSlotViaStub(t *testing.T) {
SetTestExportPreviewJSON(`{"filename":"slot_img.jpg","size":4096,"cloud":"cloud"}`)
defer SetTestExportPreviewJSON(`{"filename":"0000_test.jpg","size":1024,"cloud":"local"}`)
bridge := &CgoBridge{}
result, err := bridge.ExportPreviewWithSlot("asset-1", "/tmp", 2048, 85, 0, 1)
if err != nil {
t.Fatal(err)
}
if result.Filename != "slot_img.jpg" {
t.Errorf("got filename %q", result.Filename)
}
if result.Cloud != "cloud" {
t.Errorf("got cloud %q, want %q", result.Cloud, "cloud")
}
}
func TestCgoBridgeExportOriginalViaStub(t *testing.T) {
SetTestExportOriginalJSON(`{"filename":"original.jpg","size":8192,"cloud":"local"}`)
defer SetTestExportOriginalJSON(`{"filename":"test.jpg","size":2048,"cloud":"cloud"}`)
bridge := &CgoBridge{}
result, err := bridge.ExportOriginal("asset-1", "/tmp", 0)
if err != nil {
t.Fatal(err)
}
if result.Filename != "original.jpg" {
t.Errorf("got filename %q, want %q", result.Filename, "original.jpg")
}
if result.Size != 8192 {
t.Errorf("got size %d, want %d", result.Size, 8192)
}
}
func TestCgoBridgeExportOriginalWithSlotViaStub(t *testing.T) {
SetTestExportOriginalJSON(`{"filename":"slot_orig.heic","size":16384,"cloud":"local"}`)
defer SetTestExportOriginalJSON(`{"filename":"test.jpg","size":2048,"cloud":"cloud"}`)
bridge := &CgoBridge{}
result, err := bridge.ExportOriginalWithSlot("asset-1", "/tmp", 0, 2)
if err != nil {
t.Fatal(err)
}
if result.Filename != "slot_orig.heic" {
t.Errorf("got filename %q", result.Filename)
}
}
func TestCgoBridgeExportPreviewErrorViaStub(t *testing.T) {
SetTestExportPreviewJSON(`{"error":"disk full","cloud":"local"}`)
defer SetTestExportPreviewJSON(`{"filename":"0000_test.jpg","size":1024,"cloud":"local"}`)
bridge := &CgoBridge{}
_, err := bridge.ExportPreview("asset-1", "/tmp", 1024, 85, 0)
if err == nil {
t.Fatal("expected error")
}
if err.Error() != "disk full" {
t.Errorf("got error %q, want %q", err.Error(), "disk full")
}
}
func TestCgoBridgeExportOriginalErrorViaStub(t *testing.T) {
SetTestExportOriginalJSON(`{"error":"write failed","cloud":"local"}`)
defer SetTestExportOriginalJSON(`{"filename":"test.jpg","size":2048,"cloud":"cloud"}`)
bridge := &CgoBridge{}
_, err := bridge.ExportOriginal("asset-1", "/tmp", 0)
if err == nil {
t.Fatal("expected error")
}
if err.Error() != "write failed" {
t.Errorf("got error %q, want %q", err.Error(), "write failed")
}
}
func TestCgoBridgeExportSkippedResult(t *testing.T) {
SetTestExportPreviewJSON(`{"filename":"skip.jpg","size":0,"cloud":"local","skipped":true}`)
defer SetTestExportPreviewJSON(`{"filename":"0000_test.jpg","size":1024,"cloud":"local"}`)
bridge := &CgoBridge{}
result, err := bridge.ExportPreview("asset-1", "/tmp", 1024, 85, 0)
if err != nil {
t.Fatal(err)
}
if !result.Skipped {
t.Error("expected Skipped to be true")
}
}
func TestCgoBridgeCancelAndIsCancelled(t *testing.T) {
bridge := &CgoBridge{}
if bridge.IsCancelled() {
t.Error("should not be cancelled initially")
}
bridge.Cancel()
if !bridge.IsCancelled() {
t.Error("should be cancelled after Cancel()")
}
}
func TestGetProgressSlotsReturnsSlots(t *testing.T) {
slots := GetProgressSlots()
if slots == nil {
t.Errorf("GetProgressSlots should return slots in test build")
}
if len(slots) != 16 {
t.Errorf("GetProgressSlots should return 16 slots, got %d", len(slots))
}
}
func TestResetProgressSlotsNoPanic(t *testing.T) {
ResetProgressSlots()
}
func TestGetProgressSlotCount(t *testing.T) {
count := GetProgressSlotCount()
if count != 16 {
t.Errorf("expected 16, got %d", count)
}
}
func TestCgoBridgeExportPreviewNilStub(t *testing.T) {
SetTestExportPreviewJSONNull()
defer SetTestExportPreviewJSON(`{"filename":"0000_test.jpg","size":1024,"cloud":"local"}`)
bridge := &CgoBridge{}
_, err := bridge.ExportPreview("asset-1", "/tmp", 1024, 85, 0)
if err == nil {
t.Fatal("expected errBridgeNil")
}
if err != errBridgeNil {
t.Errorf("got %v, want %v", err, errBridgeNil)
}
}
func TestCgoBridgeExportOriginalNilStub(t *testing.T) {
SetTestExportOriginalJSONNull()
defer SetTestExportOriginalJSON(`{"filename":"test.jpg","size":2048,"cloud":"cloud"}`)
bridge := &CgoBridge{}
_, err := bridge.ExportOriginal("asset-1", "/tmp", 0)
if err == nil {
t.Fatal("expected errBridgeNil")
}
if err != errBridgeNil {
t.Errorf("got %v, want %v", err, errBridgeNil)
}
}
func TestCgoBridgeExportPreviewWithSlotNilStub(t *testing.T) {
SetTestExportPreviewJSONNull()
defer SetTestExportPreviewJSON(`{"filename":"0000_test.jpg","size":1024,"cloud":"local"}`)
bridge := &CgoBridge{}
_, err := bridge.ExportPreviewWithSlot("asset-1", "/tmp", 1024, 85, 0, 0)
if err == nil {
t.Fatal("expected errBridgeNil")
}
if err != errBridgeNil {
t.Errorf("got %v, want %v", err, errBridgeNil)
}
}
func TestCgoBridgeExportOriginalWithSlotNilStub(t *testing.T) {
SetTestExportOriginalJSONNull()
defer SetTestExportOriginalJSON(`{"filename":"test.jpg","size":2048,"cloud":"cloud"}`)
bridge := &CgoBridge{}
_, err := bridge.ExportOriginalWithSlot("asset-1", "/tmp", 0, 0)
if err == nil {
t.Fatal("expected errBridgeNil")
}
if err != errBridgeNil {
t.Errorf("got %v, want %v", err, errBridgeNil)
}
}
func TestGetProgressSlotsWithActiveSlot(t *testing.T) {
ResetProgressSlots()
slots := GetProgressSlots()
if len(slots) != 16 {
t.Errorf("expected 16 slots, got %d", len(slots))
}
for i, s := range slots {
if s.Active {
t.Errorf("slot %d should not be active after reset", i)
}
}
}
func TestResetProgressSlotsClearsState(t *testing.T) {
ResetProgressSlots()
slots := GetProgressSlots()
if len(slots) > 0 && slots[0].Active {
t.Errorf("slot should be inactive after reset")
}
}
func TestGetProgressSlotsZeroCount(t *testing.T) {
SetTestProgressSlotCount(0)
defer SetTestProgressSlotCount(3)
slots := GetProgressSlots()
if slots != nil {
t.Errorf("expected nil with zero count, got %v", slots)
}
}
func TestGetProgressSlotsNullPointer(t *testing.T) {
SetTestProgressSlotsNull(1)
defer SetTestProgressSlotsNull(0)
slots := GetProgressSlots()
if slots != nil {
t.Errorf("expected nil with null pointer, got %v", slots)
}
}
func TestExportProgressSlotType(t *testing.T) {
slot := ExportProgressSlot{
Active: true,
Progress: 0.75,
BytesDone: 512,
BytesTotal: 1024,
}
if !slot.Active {
t.Error("expected Active to be true")
}
if slot.Progress != 0.75 {
t.Errorf("expected Progress 0.75, got %f", slot.Progress)
}
}