Stacks: Only merge photos with trusted time and location #1668
This commit is contained in:
parent
f7cc802e6c
commit
22b0a44fa7
10 changed files with 711 additions and 581 deletions
|
@ -610,136 +610,6 @@ func (m *Photo) SetDescription(desc, source string) {
|
|||
m.DescriptionSrc = source
|
||||
}
|
||||
|
||||
// SetTakenAt changes the photo date if not empty and from the same source.
|
||||
func (m *Photo) SetTakenAt(taken, local time.Time, zone, source string) {
|
||||
if taken.IsZero() || taken.Year() < 1000 || taken.Year() > txt.YearMax {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[source] < SrcPriority[m.TakenSrc] && !m.TakenAt.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
// Remove time zone if time was extracted from file name.
|
||||
if source == SrcName {
|
||||
zone = ""
|
||||
}
|
||||
|
||||
// Round times to avoid jitter.
|
||||
taken = taken.Round(time.Second).UTC()
|
||||
|
||||
// Default local time to taken if zero or invalid.
|
||||
if local.IsZero() || local.Year() < 1000 {
|
||||
local = taken
|
||||
} else {
|
||||
local = local.Round(time.Second)
|
||||
}
|
||||
|
||||
// Don't update older date.
|
||||
if SrcPriority[source] <= SrcPriority[SrcAuto] && !m.TakenAt.IsZero() && taken.After(m.TakenAt) {
|
||||
return
|
||||
}
|
||||
|
||||
// Set UTC time and date source.
|
||||
m.TakenAt = taken
|
||||
m.TakenAtLocal = local
|
||||
m.TakenSrc = source
|
||||
|
||||
if zone == time.UTC.String() && m.TimeZone != "" {
|
||||
// Location exists, set local time from UTC.
|
||||
m.TakenAtLocal = m.GetTakenAtLocal()
|
||||
} else if zone != "" {
|
||||
// Apply new time zone.
|
||||
m.TimeZone = zone
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
} else if m.TimeZoneUTC() {
|
||||
// Local is UTC.
|
||||
m.TimeZone = zone
|
||||
m.TakenAtLocal = taken
|
||||
} else if m.TimeZone != "" {
|
||||
// Apply existing time zone.
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
}
|
||||
|
||||
m.UpdateDateFields()
|
||||
}
|
||||
|
||||
// TimeZoneUTC tests if the current time zone is UTC.
|
||||
func (m *Photo) TimeZoneUTC() bool {
|
||||
return strings.EqualFold(m.TimeZone, time.UTC.String())
|
||||
}
|
||||
|
||||
// UpdateTimeZone updates the time zone.
|
||||
func (m *Photo) UpdateTimeZone(zone string) {
|
||||
if zone == "" || zone == time.UTC.String() || zone == m.TimeZone {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[m.TakenSrc] >= SrcPriority[SrcManual] && m.TimeZone != "" {
|
||||
return
|
||||
}
|
||||
|
||||
if m.TimeZoneUTC() {
|
||||
m.TimeZone = zone
|
||||
m.TakenAtLocal = m.GetTakenAtLocal()
|
||||
} else {
|
||||
m.TimeZone = zone
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateDateFields updates internal date fields.
|
||||
func (m *Photo) UpdateDateFields() {
|
||||
if m.TakenAt.IsZero() || m.TakenAt.Year() < 1000 {
|
||||
return
|
||||
}
|
||||
|
||||
if m.TakenAtLocal.IsZero() || m.TakenAtLocal.Year() < 1000 {
|
||||
m.TakenAtLocal = m.TakenAt
|
||||
}
|
||||
|
||||
// Set date to unknown if file system date is about the same as indexing time.
|
||||
if m.TakenSrc == SrcAuto && m.TakenAt.After(m.CreatedAt.Add(-24*time.Hour)) {
|
||||
m.PhotoYear = UnknownYear
|
||||
m.PhotoMonth = UnknownMonth
|
||||
m.PhotoDay = UnknownDay
|
||||
} else if m.TakenSrc != SrcManual {
|
||||
m.PhotoYear = m.TakenAtLocal.Year()
|
||||
m.PhotoMonth = int(m.TakenAtLocal.Month())
|
||||
m.PhotoDay = m.TakenAtLocal.Day()
|
||||
}
|
||||
}
|
||||
|
||||
// SetCoordinates changes the photo lat, lng and altitude if not empty and from an acceptable source.
|
||||
func (m *Photo) SetCoordinates(lat, lng float32, altitude int, source string) {
|
||||
m.SetAltitude(altitude, source)
|
||||
|
||||
if lat == 0.0 && lng == 0.0 {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[source] < SrcPriority[m.PlaceSrc] && m.HasLatLng() {
|
||||
return
|
||||
}
|
||||
|
||||
m.PhotoLat = lat
|
||||
m.PhotoLng = lng
|
||||
m.PlaceSrc = source
|
||||
}
|
||||
|
||||
// SetAltitude sets the photo altitude if not empty and from an acceptable source.
|
||||
func (m *Photo) SetAltitude(altitude int, source string) {
|
||||
if altitude == 0 && source != SrcManual {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[source] < SrcPriority[m.PlaceSrc] {
|
||||
return
|
||||
}
|
||||
|
||||
m.PhotoAltitude = altitude
|
||||
}
|
||||
|
||||
// SetCamera updates the camera.
|
||||
func (m *Photo) SetCamera(camera *Camera, source string) {
|
||||
if camera == nil {
|
||||
|
|
121
internal/entity/photo_datetime.go
Normal file
121
internal/entity/photo_datetime.go
Normal file
|
@ -0,0 +1,121 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
)
|
||||
|
||||
// TrustedTime tests if the photo has a known date and time from a trusted source.
|
||||
func (m *Photo) TrustedTime() bool {
|
||||
if SrcPriority[m.TakenSrc] <= SrcPriority[SrcEstimate] {
|
||||
return false
|
||||
} else if m.TakenAt.IsZero() || m.TakenAtLocal.IsZero() {
|
||||
return false
|
||||
} else if m.TimeZone == "" || m.TimeZoneUTC() {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// SetTakenAt changes the photo date if not empty and from the same source.
|
||||
func (m *Photo) SetTakenAt(taken, local time.Time, zone, source string) {
|
||||
if taken.IsZero() || taken.Year() < 1000 || taken.Year() > txt.YearMax {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[source] < SrcPriority[m.TakenSrc] && !m.TakenAt.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
// Remove time zone if time was extracted from file name.
|
||||
if source == SrcName {
|
||||
zone = ""
|
||||
}
|
||||
|
||||
// Round times to avoid jitter.
|
||||
taken = taken.Round(time.Second).UTC()
|
||||
|
||||
// Default local time to taken if zero or invalid.
|
||||
if local.IsZero() || local.Year() < 1000 {
|
||||
local = taken
|
||||
} else {
|
||||
local = local.Round(time.Second)
|
||||
}
|
||||
|
||||
// Don't update older date.
|
||||
if SrcPriority[source] <= SrcPriority[SrcAuto] && !m.TakenAt.IsZero() && taken.After(m.TakenAt) {
|
||||
return
|
||||
}
|
||||
|
||||
// Set UTC time and date source.
|
||||
m.TakenAt = taken
|
||||
m.TakenAtLocal = local
|
||||
m.TakenSrc = source
|
||||
|
||||
if zone == time.UTC.String() && m.TimeZone != "" {
|
||||
// Location exists, set local time from UTC.
|
||||
m.TakenAtLocal = m.GetTakenAtLocal()
|
||||
} else if zone != "" {
|
||||
// Apply new time zone.
|
||||
m.TimeZone = zone
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
} else if m.TimeZoneUTC() {
|
||||
// Local is UTC.
|
||||
m.TimeZone = zone
|
||||
m.TakenAtLocal = taken
|
||||
} else if m.TimeZone != "" {
|
||||
// Apply existing time zone.
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
}
|
||||
|
||||
m.UpdateDateFields()
|
||||
}
|
||||
|
||||
// TimeZoneUTC tests if the current time zone is UTC.
|
||||
func (m *Photo) TimeZoneUTC() bool {
|
||||
return strings.EqualFold(m.TimeZone, time.UTC.String())
|
||||
}
|
||||
|
||||
// UpdateTimeZone updates the time zone.
|
||||
func (m *Photo) UpdateTimeZone(zone string) {
|
||||
if zone == "" || zone == time.UTC.String() || zone == m.TimeZone {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[m.TakenSrc] >= SrcPriority[SrcManual] && m.TimeZone != "" {
|
||||
return
|
||||
}
|
||||
|
||||
if m.TimeZoneUTC() {
|
||||
m.TimeZone = zone
|
||||
m.TakenAtLocal = m.GetTakenAtLocal()
|
||||
} else {
|
||||
m.TimeZone = zone
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateDateFields updates internal date fields.
|
||||
func (m *Photo) UpdateDateFields() {
|
||||
if m.TakenAt.IsZero() || m.TakenAt.Year() < 1000 {
|
||||
return
|
||||
}
|
||||
|
||||
if m.TakenAtLocal.IsZero() || m.TakenAtLocal.Year() < 1000 {
|
||||
m.TakenAtLocal = m.TakenAt
|
||||
}
|
||||
|
||||
// Set date to unknown if file system date is about the same as indexing time.
|
||||
if m.TakenSrc == SrcAuto && m.TakenAt.After(m.CreatedAt.Add(-24*time.Hour)) {
|
||||
m.PhotoYear = UnknownYear
|
||||
m.PhotoMonth = UnknownMonth
|
||||
m.PhotoDay = UnknownDay
|
||||
} else if m.TakenSrc != SrcManual {
|
||||
m.PhotoYear = m.TakenAtLocal.Year()
|
||||
m.PhotoMonth = int(m.TakenAtLocal.Month())
|
||||
m.PhotoDay = m.TakenAtLocal.Day()
|
||||
}
|
||||
}
|
331
internal/entity/photo_datetime_test.go
Normal file
331
internal/entity/photo_datetime_test.go
Normal file
|
@ -0,0 +1,331 @@
|
|||
package entity
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPhoto_TrustedTime(t *testing.T) {
|
||||
t.Run("MissingTakenAt", func(t *testing.T) {
|
||||
m := Photo{ID: 1, TakenAt: time.Time{}, TakenAtLocal: TimeStamp(), TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.TrustedTime())
|
||||
})
|
||||
t.Run("MissingTakenAtLocal", func(t *testing.T) {
|
||||
m := Photo{ID: 1, TakenAt: TimeStamp(), TakenAtLocal: time.Time{}, TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.TrustedTime())
|
||||
})
|
||||
t.Run("MissingTimeZone", func(t *testing.T) {
|
||||
n := TimeStamp()
|
||||
m := Photo{ID: 1, TakenAt: n, TakenAtLocal: n, TakenSrc: SrcMeta, TimeZone: ""}
|
||||
assert.False(t, m.TrustedTime())
|
||||
})
|
||||
t.Run("SrcAuto", func(t *testing.T) {
|
||||
n := TimeStamp()
|
||||
m := Photo{ID: 1, TakenAt: n, TakenAtLocal: n, TakenSrc: SrcAuto, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.TrustedTime())
|
||||
})
|
||||
t.Run("SrcEstimate", func(t *testing.T) {
|
||||
n := TimeStamp()
|
||||
m := Photo{ID: 1, TakenAt: n, TakenAtLocal: n, TakenSrc: SrcEstimate, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.TrustedTime())
|
||||
})
|
||||
t.Run("SrcMeta", func(t *testing.T) {
|
||||
n := TimeStamp()
|
||||
m := Photo{ID: 1, TakenAt: n, TakenAtLocal: n, TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.True(t, m.TrustedTime())
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_SetTakenAt(t *testing.T) {
|
||||
t.Run("empty taken", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
m.SetTakenAt(time.Time{}, time.Time{}, "", SrcManual)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
})
|
||||
t.Run("taken not from the same source", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
m.SetTakenAt(time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), "", SrcAuto)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
})
|
||||
t.Run("from name", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
m.TimeZone = ""
|
||||
m.TakenSrc = SrcAuto
|
||||
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
assert.Equal(t, SrcAuto, m.TakenSrc)
|
||||
|
||||
m.SetTakenAt(time.Date(2011, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, 11, 11, 10, 7, 18, 0, time.UTC), "America/New_York", SrcName)
|
||||
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
assert.Equal(t, SrcName, m.TakenSrc)
|
||||
|
||||
assert.Equal(t, time.Date(2011, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2019, 11, 11, 10, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("success", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
|
||||
m.SetTakenAt(time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcMeta)
|
||||
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 10, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("fallback", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
|
||||
t.Logf("SRC, ZONE, UTC, LOCAL: %s / %s / %s /%s", m.TakenSrc, m.TimeZone, m.TakenAt, m.TakenAtLocal)
|
||||
|
||||
m.SetTakenAt(time.Date(2019, time.December, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, time.December, 11, 10, 7, 18, 0, time.UTC), "", SrcAuto)
|
||||
|
||||
t.Logf("SRC, ZONE, UTC, LOCAL: %s / %s / %s /%s", m.TakenSrc, m.TimeZone, m.TakenAt, m.TakenAtLocal)
|
||||
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
|
||||
newTime := time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC)
|
||||
|
||||
expected := time.Date(2013, time.November, 11, 8, 7, 18, 0, time.UTC)
|
||||
|
||||
m.TimeZone = "Europe/Berlin"
|
||||
|
||||
m.SetTakenAt(newTime, newTime, "", SrcName)
|
||||
|
||||
assert.Equal(t, expected, m.TakenAt)
|
||||
assert.Equal(t, m.GetTakenAtLocal(), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("time zone", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
|
||||
zone := "Europe/Berlin"
|
||||
|
||||
loc, _ := time.LoadLocation(zone)
|
||||
|
||||
newTime := time.Date(2013, 11, 11, 9, 7, 18, 0, loc)
|
||||
|
||||
m.SetTakenAt(newTime, newTime, zone, SrcName)
|
||||
|
||||
assert.Equal(t, newTime.UTC(), m.TakenAt)
|
||||
assert.Equal(t, newTime, m.TakenAtLocal)
|
||||
})
|
||||
t.Run("time > max year", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
m.SetTakenAt(time.Date(2123, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2123, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcManual)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("success with empty takenAtLocal", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
m.SetTakenAt(time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Time{}, "test", SrcXmp)
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("don't update older date", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC)}
|
||||
photo.SetTakenAt(time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2014, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcAuto)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
})
|
||||
t.Run("set local time from utc", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), TimeZone: "Europe/Berlin"}
|
||||
photo.SetTakenAt(time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2014, 12, 11, 10, 7, 18, 0, time.UTC), time.UTC.String(), SrcManual)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 10, 07, 18, 0, time.UTC), photo.TakenAtLocal)
|
||||
})
|
||||
t.Run("local is UTC", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), TimeZone: time.UTC.String()}
|
||||
photo.SetTakenAt(time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2014, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcManual)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 9, 07, 18, 0, time.UTC), photo.TakenAtLocal)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_UpdateTimeZone(t *testing.T) {
|
||||
t.Run("PhotoTimeZone", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("PhotoTimeZone")
|
||||
|
||||
takenLocal := time.Date(2015, time.May, 17, 23, 2, 46, 0, time.UTC)
|
||||
takenJerusalemUtc := time.Date(2015, time.May, 17, 20, 2, 46, 0, time.UTC)
|
||||
takenShanghaiUtc := time.Date(2015, time.May, 17, 15, 2, 46, 0, time.UTC)
|
||||
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
assert.Equal(t, takenLocal, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
zone1 := "Asia/Jerusalem"
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenJerusalemUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenJerusalemUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
zone2 := "Asia/Shanghai"
|
||||
|
||||
m.UpdateTimeZone(zone2)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
zone3 := "UTC"
|
||||
|
||||
m.UpdateTimeZone(zone3)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
})
|
||||
t.Run("VideoTimeZone", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("VideoTimeZone")
|
||||
|
||||
takenUtc := time.Date(2015, 5, 17, 17, 48, 46, 0, time.UTC)
|
||||
takenJerusalem := time.Date(2015, time.May, 17, 20, 48, 46, 0, time.UTC)
|
||||
takenShanghaiUtc := time.Date(2015, time.May, 17, 12, 48, 46, 0, time.UTC)
|
||||
|
||||
assert.Equal(t, "UTC", m.TimeZone)
|
||||
assert.Equal(t, takenUtc, m.TakenAt)
|
||||
assert.Equal(t, takenUtc, m.TakenAtLocal)
|
||||
|
||||
zone1 := "Asia/Jerusalem"
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
|
||||
zone2 := "Asia/Shanghai"
|
||||
|
||||
m.UpdateTimeZone(zone2)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
|
||||
zone3 := "UTC"
|
||||
|
||||
m.UpdateTimeZone(zone3)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
})
|
||||
t.Run("UTC", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
m.TimeZone = "UTC"
|
||||
|
||||
zone := "Europe/Berlin"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, m.GetTakenAtLocal(), m.TakenAtLocal)
|
||||
})
|
||||
|
||||
t.Run("Europe/Berlin", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
|
||||
zone := "Europe/Berlin"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, m.GetTakenAt(), m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
})
|
||||
|
||||
t.Run("America/New_York", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
m.TimeZone = "Europe/Berlin"
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
|
||||
zone := "America/New_York"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "Europe/Berlin", m.TimeZone)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, m.GetTakenAt(), m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
})
|
||||
|
||||
t.Run("manual", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
m.TimeZone = "Europe/Berlin"
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
m.TakenSrc = SrcManual
|
||||
|
||||
zone := "America/New_York"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "Europe/Berlin", m.TimeZone)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "Europe/Berlin", m.TimeZone)
|
||||
})
|
||||
t.Run("zone = UTC", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), TimeZone: "Europe/Berlin"}
|
||||
photo.UpdateTimeZone("")
|
||||
assert.Equal(t, time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
assert.Equal(t, "Europe/Berlin", photo.TimeZone)
|
||||
})
|
||||
}
|
|
@ -114,7 +114,7 @@ var PhotoFixtures = PhotoMap{
|
|||
PhotoPrivate: false,
|
||||
PhotoScan: false,
|
||||
PhotoPanorama: false,
|
||||
TimeZone: "",
|
||||
TimeZone: "Europe/Berlin",
|
||||
Place: PlaceFixtures.Pointer("Germany"),
|
||||
PlaceID: PlaceFixtures.Pointer("Germany").ID,
|
||||
PlaceSrc: "manual",
|
||||
|
@ -951,7 +951,7 @@ var PhotoFixtures = PhotoMap{
|
|||
PhotoPrivate: false,
|
||||
PhotoScan: false,
|
||||
PhotoPanorama: false,
|
||||
TimeZone: "",
|
||||
TimeZone: "Europe/Berlin",
|
||||
Place: PlaceFixtures.Pointer("Germany"),
|
||||
PlaceID: PlaceFixtures.Pointer("Germany").ID,
|
||||
PlaceSrc: SrcMeta,
|
||||
|
@ -1428,7 +1428,7 @@ var PhotoFixtures = PhotoMap{
|
|||
PhotoPrivate: false,
|
||||
PhotoScan: false,
|
||||
PhotoPanorama: false,
|
||||
TimeZone: "",
|
||||
TimeZone: "America/Mexico_City",
|
||||
Place: PlaceFixtures.Pointer("mexico"),
|
||||
PlaceID: PlaceFixtures.Pointer("mexico").ID,
|
||||
PlaceSrc: SrcMeta,
|
||||
|
@ -1489,7 +1489,7 @@ var PhotoFixtures = PhotoMap{
|
|||
PhotoPrivate: false,
|
||||
PhotoScan: false,
|
||||
PhotoPanorama: false,
|
||||
TimeZone: "",
|
||||
TimeZone: "America/Mexico_City",
|
||||
Place: PlaceFixtures.Pointer("mexico"),
|
||||
PlaceID: PlaceFixtures.Pointer("mexico").ID,
|
||||
PlaceSrc: SrcMeta,
|
||||
|
@ -1550,7 +1550,7 @@ var PhotoFixtures = PhotoMap{
|
|||
PhotoPrivate: false,
|
||||
PhotoScan: false,
|
||||
PhotoPanorama: true,
|
||||
TimeZone: "",
|
||||
TimeZone: "America/Mexico_City",
|
||||
Place: PlaceFixtures.Pointer("mexico"),
|
||||
PlaceID: PlaceFixtures.Pointer("mexico").ID,
|
||||
PlaceSrc: SrcMeta,
|
||||
|
@ -1611,7 +1611,7 @@ var PhotoFixtures = PhotoMap{
|
|||
PhotoPrivate: false,
|
||||
PhotoScan: false,
|
||||
PhotoPanorama: true,
|
||||
TimeZone: "",
|
||||
TimeZone: "America/Mexico_City",
|
||||
Place: PlaceFixtures.Pointer("mexico"),
|
||||
PlaceID: PlaceFixtures.Pointer("mexico").ID,
|
||||
PlaceSrc: SrcMeta,
|
||||
|
|
|
@ -12,6 +12,36 @@ import (
|
|||
"gopkg.in/photoprism/go-tz.v2/tz"
|
||||
)
|
||||
|
||||
// SetCoordinates changes the photo lat, lng and altitude if not empty and from an acceptable source.
|
||||
func (m *Photo) SetCoordinates(lat, lng float32, altitude int, source string) {
|
||||
m.SetAltitude(altitude, source)
|
||||
|
||||
if lat == 0.0 && lng == 0.0 {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[source] < SrcPriority[m.PlaceSrc] && m.HasLatLng() {
|
||||
return
|
||||
}
|
||||
|
||||
m.PhotoLat = lat
|
||||
m.PhotoLng = lng
|
||||
m.PlaceSrc = source
|
||||
}
|
||||
|
||||
// SetAltitude sets the photo altitude if not empty and from an acceptable source.
|
||||
func (m *Photo) SetAltitude(altitude int, source string) {
|
||||
if altitude == 0 && source != SrcManual {
|
||||
return
|
||||
}
|
||||
|
||||
if SrcPriority[source] < SrcPriority[m.PlaceSrc] {
|
||||
return
|
||||
}
|
||||
|
||||
m.PhotoAltitude = altitude
|
||||
}
|
||||
|
||||
// UnknownLocation tests if the photo has an unknown location.
|
||||
func (m *Photo) UnknownLocation() bool {
|
||||
return m.CellID == "" || m.CellID == UnknownLocation.ID || m.NoLatLng()
|
||||
|
@ -48,6 +78,11 @@ func (m *Photo) HasLocation() bool {
|
|||
return !m.UnknownLocation()
|
||||
}
|
||||
|
||||
// TrustedLocation tests if the photo has a known location from a trusted source.
|
||||
func (m *Photo) TrustedLocation() bool {
|
||||
return m.HasLocation() && SrcPriority[m.PlaceSrc] > SrcPriority[SrcEstimate]
|
||||
}
|
||||
|
||||
// LocationLoaded tests if the photo has a known location that is currently loaded.
|
||||
func (m *Photo) LocationLoaded() bool {
|
||||
if m.Cell == nil {
|
||||
|
|
|
@ -7,6 +7,146 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPhoto_SetAltitude(t *testing.T) {
|
||||
t.Run("ViaSetCoordinates", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(0, 0, 5, SrcManual)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("Update", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(5, SrcManual)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("SkipUpdate", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(5, SrcEstimate)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("UpdateEmptyAltitude", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PlaceSrc: SrcMeta, PhotoLat: float32(1.234), PhotoLng: float32(4.321), PhotoAltitude: 0}
|
||||
|
||||
m.SetAltitude(-5, SrcAuto)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(-5, SrcEstimate)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(-5, SrcMeta)
|
||||
assert.Equal(t, -5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("ZeroAltitudeManual", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PlaceSrc: SrcManual, PhotoLat: float32(1.234), PhotoLng: float32(4.321), PhotoAltitude: 5}
|
||||
|
||||
m.SetAltitude(0, SrcManual)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_SetCoordinates(t *testing.T) {
|
||||
t.Run("empty coordinates", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(0, 0, 5, SrcManual)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("same source new values", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcMeta)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source lower priority", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcName)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source equal priority", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcKeyword)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source higher priority", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo21")
|
||||
assert.Equal(t, SrcEstimate, m.PlaceSrc)
|
||||
assert.Equal(t, float32(0), m.PhotoLat)
|
||||
assert.Equal(t, float32(0), m.PhotoLng)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcMeta)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source highest priority (manual)", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcManual)
|
||||
assert.Equal(t, SrcManual, m.PlaceSrc)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_UnknownLocation(t *testing.T) {
|
||||
t.Run("no_location", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("19800101_000002_D640C559")
|
||||
|
@ -30,6 +170,25 @@ func TestPhoto_UnknownLocation(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestPhoto_TrustedLocation(t *testing.T) {
|
||||
t.Run("SrcAuto", func(t *testing.T) {
|
||||
m := Photo{ID: 1, CellID: "s2:479a03fda18c", PhotoLat: 1, PhotoLng: -1, PlaceSrc: SrcAuto}
|
||||
assert.False(t, m.TrustedLocation())
|
||||
})
|
||||
t.Run("SrcEstimate", func(t *testing.T) {
|
||||
m := Photo{ID: 1, CellID: "s2:479a03fda18c", PhotoLat: 1, PhotoLng: -1, PlaceSrc: SrcEstimate}
|
||||
assert.False(t, m.TrustedLocation())
|
||||
})
|
||||
t.Run("SrcMetaTrue", func(t *testing.T) {
|
||||
m := Photo{ID: 1, CellID: "s2:479a03fda18c", PhotoLat: 1, PhotoLng: -1, PlaceSrc: SrcMeta}
|
||||
assert.True(t, m.TrustedLocation())
|
||||
})
|
||||
t.Run("SrcMetaFalse", func(t *testing.T) {
|
||||
m := Photo{ID: 1, CellID: "s2:479a03fda18c", PhotoLat: 0, PhotoLng: 0, PlaceSrc: SrcMeta}
|
||||
assert.False(t, m.TrustedLocation())
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_HasLocation(t *testing.T) {
|
||||
t.Run("false", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("19800101_000002_D640C559")
|
||||
|
|
|
@ -20,31 +20,43 @@ func (m *Photo) ResolvePrimary() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Stackable tests if the photo may be stacked.
|
||||
func (m *Photo) Stackable() bool {
|
||||
if !m.HasID() || m.PhotoStack == IsUnstacked || m.PhotoName == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Identical returns identical photos that can be merged.
|
||||
func (m *Photo) Identical(includeMeta, includeUuid bool) (identical Photos, err error) {
|
||||
if m.PhotoStack == IsUnstacked || m.PhotoName == "" {
|
||||
if !m.Stackable() {
|
||||
return identical, nil
|
||||
}
|
||||
|
||||
includeMeta = includeMeta && m.TrustedLocation() && m.TrustedTime()
|
||||
includeUuid = includeUuid && rnd.IsUUID(m.UUID)
|
||||
|
||||
switch {
|
||||
case includeMeta && includeUuid && m.HasLocation() && m.TakenSrc == SrcMeta && rnd.IsUUID(m.UUID):
|
||||
case includeMeta && includeUuid:
|
||||
if err := Db().
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND photo_stack > -1 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND place_src <> 'estimate' AND photo_stack > -1 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
"OR (uuid = ? AND photo_stack > -1)"+
|
||||
"OR (photo_path = ? AND photo_name = ?)",
|
||||
m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.UUID, m.PhotoPath, m.PhotoName).
|
||||
Order("photo_quality DESC, id ASC").Find(&identical).Error; err != nil {
|
||||
return identical, err
|
||||
}
|
||||
case includeMeta && m.HasLocation() && m.TakenSrc == SrcMeta:
|
||||
case includeMeta:
|
||||
if err := Db().
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND photo_stack > -1 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
Where("(taken_at = ? AND taken_src = 'meta' AND place_src <> 'estimate' AND photo_stack > -1 AND cell_id = ? AND camera_serial = ? AND camera_id = ?) "+
|
||||
"OR (photo_path = ? AND photo_name = ?)",
|
||||
m.TakenAt, m.CellID, m.CameraSerial, m.CameraID, m.PhotoPath, m.PhotoName).
|
||||
Order("photo_quality DESC, id ASC").Find(&identical).Error; err != nil {
|
||||
return identical, err
|
||||
}
|
||||
case includeUuid && rnd.IsUUID(m.UUID):
|
||||
case includeUuid:
|
||||
if err := Db().
|
||||
Where("(uuid = ? AND photo_stack > -1) OR (photo_path = ? AND photo_name = ?)",
|
||||
m.UUID, m.PhotoPath, m.PhotoName).
|
||||
|
|
|
@ -2,10 +2,38 @@ package entity
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPhoto_Stackable(t *testing.T) {
|
||||
t.Run("IsStackable", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PhotoUID: "pr32t8j3feogit2t", PhotoName: "foo", PhotoStack: IsStackable, TakenAt: TimeStamp(), TakenAtLocal: time.Time{}, TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.True(t, m.Stackable())
|
||||
})
|
||||
t.Run("IsStacked", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PhotoUID: "pr32t8j3feogit2t", PhotoName: "foo", PhotoStack: IsStacked, TakenAt: TimeStamp(), TakenAtLocal: time.Time{}, TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.True(t, m.Stackable())
|
||||
})
|
||||
t.Run("NoName", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PhotoUID: "pr32t8j3feogit2t", PhotoName: "", TakenAt: time.Time{}, TakenAtLocal: TimeStamp(), TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.Stackable())
|
||||
})
|
||||
t.Run("IsUnstacked", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PhotoUID: "pr32t8j3feogit2t", PhotoName: "foo", PhotoStack: IsUnstacked, TakenAt: TimeStamp(), TakenAtLocal: time.Time{}, TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.Stackable())
|
||||
})
|
||||
t.Run("NoID", func(t *testing.T) {
|
||||
m := Photo{ID: 0, PhotoUID: "pr32t8j3feogit2t", PhotoName: "foo", PhotoStack: IsStacked, TakenAt: TimeStamp(), TakenAtLocal: time.Time{}, TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.Stackable())
|
||||
})
|
||||
t.Run("NoPhotoUID", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PhotoUID: "", PhotoName: "foo", PhotoStack: IsStacked, TakenAt: TimeStamp(), TakenAtLocal: time.Time{}, TakenSrc: SrcMeta, TimeZone: "Europe/Berlin"}
|
||||
assert.False(t, m.Stackable())
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_IdenticalIdentical(t *testing.T) {
|
||||
t.Run("success", func(t *testing.T) {
|
||||
photo := PhotoFixtures.Get("Photo19")
|
||||
|
|
|
@ -28,7 +28,7 @@ func (m *Photo) QualityScore() (score int) {
|
|||
score++
|
||||
}
|
||||
|
||||
if SrcPriority[m.PlaceSrc] > SrcPriority[SrcEstimate] {
|
||||
if m.TrustedLocation() {
|
||||
score++
|
||||
}
|
||||
|
||||
|
|
|
@ -273,438 +273,6 @@ func TestPhoto_SetDescription(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestPhoto_SetTakenAt(t *testing.T) {
|
||||
t.Run("empty taken", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
m.SetTakenAt(time.Time{}, time.Time{}, "", SrcManual)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
})
|
||||
t.Run("taken not from the same source", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
m.SetTakenAt(time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), "", SrcAuto)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
})
|
||||
t.Run("from name", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
m.TimeZone = ""
|
||||
m.TakenSrc = SrcAuto
|
||||
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
assert.Equal(t, SrcAuto, m.TakenSrc)
|
||||
|
||||
m.SetTakenAt(time.Date(2011, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, 11, 11, 10, 7, 18, 0, time.UTC), "America/New_York", SrcName)
|
||||
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
assert.Equal(t, SrcName, m.TakenSrc)
|
||||
|
||||
assert.Equal(t, time.Date(2011, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2019, 11, 11, 10, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("success", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
|
||||
m.SetTakenAt(time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcMeta)
|
||||
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 10, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("fallback", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
|
||||
t.Logf("SRC, ZONE, UTC, LOCAL: %s / %s / %s /%s", m.TakenSrc, m.TimeZone, m.TakenAt, m.TakenAtLocal)
|
||||
|
||||
m.SetTakenAt(time.Date(2019, time.December, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2019, time.December, 11, 10, 7, 18, 0, time.UTC), "", SrcAuto)
|
||||
|
||||
t.Logf("SRC, ZONE, UTC, LOCAL: %s / %s / %s /%s", m.TakenSrc, m.TimeZone, m.TakenAt, m.TakenAtLocal)
|
||||
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
|
||||
newTime := time.Date(2013, time.November, 11, 9, 7, 18, 0, time.UTC)
|
||||
|
||||
expected := time.Date(2013, time.November, 11, 8, 7, 18, 0, time.UTC)
|
||||
|
||||
m.TimeZone = "Europe/Berlin"
|
||||
|
||||
m.SetTakenAt(newTime, newTime, "", SrcName)
|
||||
|
||||
assert.Equal(t, expected, m.TakenAt)
|
||||
assert.Equal(t, m.GetTakenAtLocal(), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("time zone", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
|
||||
zone := "Europe/Berlin"
|
||||
|
||||
loc, _ := time.LoadLocation(zone)
|
||||
|
||||
newTime := time.Date(2013, 11, 11, 9, 7, 18, 0, loc)
|
||||
|
||||
m.SetTakenAt(newTime, newTime, zone, SrcName)
|
||||
|
||||
assert.Equal(t, newTime.UTC(), m.TakenAt)
|
||||
assert.Equal(t, newTime, m.TakenAtLocal)
|
||||
})
|
||||
t.Run("time > max year", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
m.SetTakenAt(time.Date(2123, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2123, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcManual)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("success with empty takenAtLocal", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
m.SetTakenAt(time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Time{}, "test", SrcXmp)
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAt)
|
||||
assert.Equal(t, time.Date(2019, 12, 11, 9, 7, 18, 0, time.UTC), m.TakenAtLocal)
|
||||
})
|
||||
t.Run("don't update older date", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC)}
|
||||
photo.SetTakenAt(time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2014, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcAuto)
|
||||
assert.Equal(t, time.Date(2013, 11, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
})
|
||||
t.Run("set local time from utc", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), TimeZone: "Europe/Berlin"}
|
||||
photo.SetTakenAt(time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2014, 12, 11, 10, 7, 18, 0, time.UTC), time.UTC.String(), SrcManual)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 10, 07, 18, 0, time.UTC), photo.TakenAtLocal)
|
||||
})
|
||||
t.Run("local is UTC", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), TimeZone: time.UTC.String()}
|
||||
photo.SetTakenAt(time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC),
|
||||
time.Date(2014, 12, 11, 10, 7, 18, 0, time.UTC), "", SrcManual)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
assert.Equal(t, time.Date(2014, 12, 11, 9, 07, 18, 0, time.UTC), photo.TakenAtLocal)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_UpdateTimeZone(t *testing.T) {
|
||||
t.Run("PhotoTimeZone", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("PhotoTimeZone")
|
||||
|
||||
takenLocal := time.Date(2015, time.May, 17, 23, 2, 46, 0, time.UTC)
|
||||
takenJerusalemUtc := time.Date(2015, time.May, 17, 20, 2, 46, 0, time.UTC)
|
||||
takenShanghaiUtc := time.Date(2015, time.May, 17, 15, 2, 46, 0, time.UTC)
|
||||
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
assert.Equal(t, takenLocal, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
zone1 := "Asia/Jerusalem"
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenJerusalemUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenJerusalemUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
zone2 := "Asia/Shanghai"
|
||||
|
||||
m.UpdateTimeZone(zone2)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
|
||||
zone3 := "UTC"
|
||||
|
||||
m.UpdateTimeZone(zone3)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenLocal, m.TakenAtLocal)
|
||||
})
|
||||
t.Run("VideoTimeZone", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("VideoTimeZone")
|
||||
|
||||
takenUtc := time.Date(2015, 5, 17, 17, 48, 46, 0, time.UTC)
|
||||
takenJerusalem := time.Date(2015, time.May, 17, 20, 48, 46, 0, time.UTC)
|
||||
takenShanghaiUtc := time.Date(2015, time.May, 17, 12, 48, 46, 0, time.UTC)
|
||||
|
||||
assert.Equal(t, "UTC", m.TimeZone)
|
||||
assert.Equal(t, takenUtc, m.TakenAt)
|
||||
assert.Equal(t, takenUtc, m.TakenAtLocal)
|
||||
|
||||
zone1 := "Asia/Jerusalem"
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
|
||||
m.UpdateTimeZone(zone1)
|
||||
|
||||
assert.Equal(t, zone1, m.TimeZone)
|
||||
assert.Equal(t, takenUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
|
||||
zone2 := "Asia/Shanghai"
|
||||
|
||||
m.UpdateTimeZone(zone2)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
|
||||
zone3 := "UTC"
|
||||
|
||||
m.UpdateTimeZone(zone3)
|
||||
|
||||
assert.Equal(t, zone2, m.TimeZone)
|
||||
assert.Equal(t, takenShanghaiUtc, m.TakenAt)
|
||||
assert.Equal(t, takenJerusalem, m.TakenAtLocal)
|
||||
})
|
||||
t.Run("UTC", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
m.TimeZone = "UTC"
|
||||
|
||||
zone := "Europe/Berlin"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, m.GetTakenAtLocal(), m.TakenAtLocal)
|
||||
})
|
||||
|
||||
t.Run("Europe/Berlin", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
|
||||
zone := "Europe/Berlin"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "", m.TimeZone)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, m.GetTakenAt(), m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
})
|
||||
|
||||
t.Run("America/New_York", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
m.TimeZone = "Europe/Berlin"
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
|
||||
zone := "America/New_York"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "Europe/Berlin", m.TimeZone)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, m.GetTakenAt(), m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
})
|
||||
|
||||
t.Run("manual", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo12")
|
||||
m.TimeZone = "Europe/Berlin"
|
||||
m.TakenAt = m.GetTakenAt()
|
||||
m.TakenSrc = SrcManual
|
||||
|
||||
zone := "America/New_York"
|
||||
|
||||
takenAt := m.TakenAt
|
||||
takenAtLocal := m.TakenAtLocal
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "Europe/Berlin", m.TimeZone)
|
||||
|
||||
m.UpdateTimeZone(zone)
|
||||
|
||||
assert.Equal(t, takenAt, m.TakenAt)
|
||||
assert.Equal(t, takenAtLocal, m.TakenAtLocal)
|
||||
assert.Equal(t, "Europe/Berlin", m.TimeZone)
|
||||
})
|
||||
t.Run("zone = UTC", func(t *testing.T) {
|
||||
photo := &Photo{TakenAt: time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), TimeZone: "Europe/Berlin"}
|
||||
photo.UpdateTimeZone("")
|
||||
assert.Equal(t, time.Date(2015, 11, 11, 9, 7, 18, 0, time.UTC), photo.TakenAt)
|
||||
assert.Equal(t, "Europe/Berlin", photo.TimeZone)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_SetAltitude(t *testing.T) {
|
||||
t.Run("ViaSetCoordinates", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(0, 0, 5, SrcManual)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("Update", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(5, SrcManual)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("SkipUpdate", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(5, SrcEstimate)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("UpdateEmptyAltitude", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PlaceSrc: SrcMeta, PhotoLat: float32(1.234), PhotoLng: float32(4.321), PhotoAltitude: 0}
|
||||
|
||||
m.SetAltitude(-5, SrcAuto)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(-5, SrcEstimate)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
|
||||
m.SetAltitude(-5, SrcMeta)
|
||||
assert.Equal(t, -5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("ZeroAltitudeManual", func(t *testing.T) {
|
||||
m := Photo{ID: 1, PlaceSrc: SrcManual, PhotoLat: float32(1.234), PhotoLng: float32(4.321), PhotoAltitude: 5}
|
||||
|
||||
m.SetAltitude(0, SrcManual)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_SetCoordinates(t *testing.T) {
|
||||
t.Run("empty coordinates", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(0, 0, 5, SrcManual)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("same source new values", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcMeta)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source lower priority", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcName)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source equal priority", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcKeyword)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source higher priority", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo21")
|
||||
assert.Equal(t, SrcEstimate, m.PlaceSrc)
|
||||
assert.Equal(t, float32(0), m.PhotoLat)
|
||||
assert.Equal(t, float32(0), m.PhotoLng)
|
||||
assert.Equal(t, 0, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcMeta)
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
t.Run("different source highest priority (manual)", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo15")
|
||||
assert.Equal(t, SrcMeta, m.PlaceSrc)
|
||||
assert.Equal(t, float32(1.234), m.PhotoLat)
|
||||
assert.Equal(t, float32(4.321), m.PhotoLng)
|
||||
assert.Equal(t, 3, m.PhotoAltitude)
|
||||
|
||||
m.SetCoordinates(5.555, 5.555, 5, SrcManual)
|
||||
assert.Equal(t, SrcManual, m.PlaceSrc)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLat)
|
||||
assert.Equal(t, float32(5.555), m.PhotoLng)
|
||||
assert.Equal(t, 5, m.PhotoAltitude)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPhoto_Delete(t *testing.T) {
|
||||
t.Run("not permanent", func(t *testing.T) {
|
||||
m := PhotoFixtures.Get("Photo16")
|
||||
|
@ -951,22 +519,28 @@ func TestPhoto_Updates(t *testing.T) {
|
|||
func TestPhoto_SetFavorite(t *testing.T) {
|
||||
t.Run("set to true", func(t *testing.T) {
|
||||
photo := Photo{PhotoFavorite: true}
|
||||
photo.Save()
|
||||
|
||||
err := photo.SetFavorite(false)
|
||||
if err != nil {
|
||||
if err := photo.Save(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := photo.SetFavorite(false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, false, photo.PhotoFavorite)
|
||||
})
|
||||
t.Run("set to false", func(t *testing.T) {
|
||||
photo := Photo{PhotoFavorite: false}
|
||||
photo.Save()
|
||||
|
||||
err := photo.SetFavorite(true)
|
||||
if err != nil {
|
||||
if err := photo.Save(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := photo.SetFavorite(true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, true, photo.PhotoFavorite)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue