mirror of https://github.com/stashapp/stash.git
650 lines
14 KiB
Go
650 lines
14 KiB
Go
package scene
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
|
|
"github.com/stashapp/stash/pkg/manager/jsonschema"
|
|
"github.com/stashapp/stash/pkg/models"
|
|
"github.com/stashapp/stash/pkg/models/mocks"
|
|
"github.com/stashapp/stash/pkg/utils"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
sceneID = 1
|
|
noImageID = 2
|
|
errImageID = 3
|
|
|
|
studioID = 4
|
|
missingStudioID = 5
|
|
errStudioID = 6
|
|
|
|
// noGalleryID = 7
|
|
// errGalleryID = 8
|
|
|
|
noTagsID = 11
|
|
errTagsID = 12
|
|
|
|
noMoviesID = 13
|
|
errMoviesID = 14
|
|
errFindMovieID = 15
|
|
|
|
noMarkersID = 16
|
|
errMarkersID = 17
|
|
errFindPrimaryTagID = 18
|
|
errFindByMarkerID = 19
|
|
)
|
|
|
|
const (
|
|
url = "url"
|
|
checksum = "checksum"
|
|
oshash = "oshash"
|
|
title = "title"
|
|
phash = -3846826108889195
|
|
date = "2001-01-01"
|
|
rating = 5
|
|
ocounter = 2
|
|
organized = true
|
|
details = "details"
|
|
size = "size"
|
|
duration = 1.23
|
|
durationStr = "1.23"
|
|
videoCodec = "videoCodec"
|
|
audioCodec = "audioCodec"
|
|
format = "format"
|
|
width = 100
|
|
height = 100
|
|
framerate = 3.21
|
|
framerateStr = "3.21"
|
|
bitrate = 1
|
|
)
|
|
|
|
const (
|
|
studioName = "studioName"
|
|
// galleryChecksum = "galleryChecksum"
|
|
|
|
validMovie1 = 1
|
|
validMovie2 = 2
|
|
invalidMovie = 3
|
|
|
|
movie1Name = "movie1Name"
|
|
movie2Name = "movie2Name"
|
|
|
|
movie1Scene = 1
|
|
movie2Scene = 2
|
|
)
|
|
|
|
var names = []string{
|
|
"name1",
|
|
"name2",
|
|
}
|
|
|
|
var imageBytes = []byte("imageBytes")
|
|
|
|
var stashID = models.StashID{
|
|
StashID: "StashID",
|
|
Endpoint: "Endpoint",
|
|
}
|
|
var stashIDs = []*models.StashID{
|
|
&stashID,
|
|
}
|
|
|
|
const imageBase64 = "aW1hZ2VCeXRlcw=="
|
|
|
|
var (
|
|
createTime = time.Date(2001, 01, 01, 0, 0, 0, 0, time.UTC)
|
|
updateTime = time.Date(2002, 01, 01, 0, 0, 0, 0, time.UTC)
|
|
)
|
|
|
|
func createFullScene(id int) models.Scene {
|
|
return models.Scene{
|
|
ID: id,
|
|
Title: models.NullString(title),
|
|
AudioCodec: models.NullString(audioCodec),
|
|
Bitrate: models.NullInt64(bitrate),
|
|
Checksum: models.NullString(checksum),
|
|
Date: models.SQLiteDate{
|
|
String: date,
|
|
Valid: true,
|
|
},
|
|
Details: models.NullString(details),
|
|
Duration: sql.NullFloat64{
|
|
Float64: duration,
|
|
Valid: true,
|
|
},
|
|
Format: models.NullString(format),
|
|
Framerate: sql.NullFloat64{
|
|
Float64: framerate,
|
|
Valid: true,
|
|
},
|
|
Height: models.NullInt64(height),
|
|
OCounter: ocounter,
|
|
OSHash: models.NullString(oshash),
|
|
Phash: models.NullInt64(phash),
|
|
Rating: models.NullInt64(rating),
|
|
Organized: organized,
|
|
Size: models.NullString(size),
|
|
VideoCodec: models.NullString(videoCodec),
|
|
Width: models.NullInt64(width),
|
|
URL: models.NullString(url),
|
|
CreatedAt: models.SQLiteTimestamp{
|
|
Timestamp: createTime,
|
|
},
|
|
UpdatedAt: models.SQLiteTimestamp{
|
|
Timestamp: updateTime,
|
|
},
|
|
}
|
|
}
|
|
|
|
func createEmptyScene(id int) models.Scene {
|
|
return models.Scene{
|
|
ID: id,
|
|
CreatedAt: models.SQLiteTimestamp{
|
|
Timestamp: createTime,
|
|
},
|
|
UpdatedAt: models.SQLiteTimestamp{
|
|
Timestamp: updateTime,
|
|
},
|
|
}
|
|
}
|
|
|
|
func createFullJSONScene(image string) *jsonschema.Scene {
|
|
return &jsonschema.Scene{
|
|
Title: title,
|
|
Checksum: checksum,
|
|
Date: date,
|
|
Details: details,
|
|
OCounter: ocounter,
|
|
OSHash: oshash,
|
|
Phash: utils.PhashToString(phash),
|
|
Rating: rating,
|
|
Organized: organized,
|
|
URL: url,
|
|
File: &jsonschema.SceneFile{
|
|
AudioCodec: audioCodec,
|
|
Bitrate: bitrate,
|
|
Duration: durationStr,
|
|
Format: format,
|
|
Framerate: framerateStr,
|
|
Height: height,
|
|
Size: size,
|
|
VideoCodec: videoCodec,
|
|
Width: width,
|
|
},
|
|
CreatedAt: models.JSONTime{
|
|
Time: createTime,
|
|
},
|
|
UpdatedAt: models.JSONTime{
|
|
Time: updateTime,
|
|
},
|
|
Cover: image,
|
|
StashIDs: []models.StashID{
|
|
stashID,
|
|
},
|
|
}
|
|
}
|
|
|
|
func createEmptyJSONScene() *jsonschema.Scene {
|
|
return &jsonschema.Scene{
|
|
File: &jsonschema.SceneFile{},
|
|
CreatedAt: models.JSONTime{
|
|
Time: createTime,
|
|
},
|
|
UpdatedAt: models.JSONTime{
|
|
Time: updateTime,
|
|
},
|
|
}
|
|
}
|
|
|
|
type basicTestScenario struct {
|
|
input models.Scene
|
|
expected *jsonschema.Scene
|
|
err bool
|
|
}
|
|
|
|
var scenarios = []basicTestScenario{
|
|
{
|
|
createFullScene(sceneID),
|
|
createFullJSONScene(imageBase64),
|
|
false,
|
|
},
|
|
{
|
|
createEmptyScene(noImageID),
|
|
createEmptyJSONScene(),
|
|
false,
|
|
},
|
|
{
|
|
createFullScene(errImageID),
|
|
nil,
|
|
true,
|
|
},
|
|
}
|
|
|
|
func TestToJSON(t *testing.T) {
|
|
mockSceneReader := &mocks.SceneReaderWriter{}
|
|
|
|
imageErr := errors.New("error getting image")
|
|
|
|
mockSceneReader.On("GetCover", sceneID).Return(imageBytes, nil).Once()
|
|
mockSceneReader.On("GetCover", noImageID).Return(nil, nil).Once()
|
|
mockSceneReader.On("GetCover", errImageID).Return(nil, imageErr).Once()
|
|
|
|
mockSceneReader.On("GetStashIDs", sceneID).Return(stashIDs, nil).Once()
|
|
mockSceneReader.On("GetStashIDs", noImageID).Return(nil, nil).Once()
|
|
|
|
for i, s := range scenarios {
|
|
scene := s.input
|
|
json, err := ToBasicJSON(mockSceneReader, &scene)
|
|
|
|
switch {
|
|
case !s.err && err != nil:
|
|
t.Errorf("[%d] unexpected error: %s", i, err.Error())
|
|
case s.err && err == nil:
|
|
t.Errorf("[%d] expected error not returned", i)
|
|
default:
|
|
assert.Equal(t, s.expected, json, "[%d]", i)
|
|
}
|
|
}
|
|
|
|
mockSceneReader.AssertExpectations(t)
|
|
}
|
|
|
|
func createStudioScene(studioID int) models.Scene {
|
|
return models.Scene{
|
|
StudioID: models.NullInt64(int64(studioID)),
|
|
}
|
|
}
|
|
|
|
type stringTestScenario struct {
|
|
input models.Scene
|
|
expected string
|
|
err bool
|
|
}
|
|
|
|
var getStudioScenarios = []stringTestScenario{
|
|
{
|
|
createStudioScene(studioID),
|
|
studioName,
|
|
false,
|
|
},
|
|
{
|
|
createStudioScene(missingStudioID),
|
|
"",
|
|
false,
|
|
},
|
|
{
|
|
createStudioScene(errStudioID),
|
|
"",
|
|
true,
|
|
},
|
|
}
|
|
|
|
func TestGetStudioName(t *testing.T) {
|
|
mockStudioReader := &mocks.StudioReaderWriter{}
|
|
|
|
studioErr := errors.New("error getting image")
|
|
|
|
mockStudioReader.On("Find", studioID).Return(&models.Studio{
|
|
Name: models.NullString(studioName),
|
|
}, nil).Once()
|
|
mockStudioReader.On("Find", missingStudioID).Return(nil, nil).Once()
|
|
mockStudioReader.On("Find", errStudioID).Return(nil, studioErr).Once()
|
|
|
|
for i, s := range getStudioScenarios {
|
|
scene := s.input
|
|
json, err := GetStudioName(mockStudioReader, &scene)
|
|
|
|
switch {
|
|
case !s.err && err != nil:
|
|
t.Errorf("[%d] unexpected error: %s", i, err.Error())
|
|
case s.err && err == nil:
|
|
t.Errorf("[%d] expected error not returned", i)
|
|
default:
|
|
assert.Equal(t, s.expected, json, "[%d]", i)
|
|
}
|
|
}
|
|
|
|
mockStudioReader.AssertExpectations(t)
|
|
}
|
|
|
|
type stringSliceTestScenario struct {
|
|
input models.Scene
|
|
expected []string
|
|
err bool
|
|
}
|
|
|
|
var getTagNamesScenarios = []stringSliceTestScenario{
|
|
{
|
|
createEmptyScene(sceneID),
|
|
names,
|
|
false,
|
|
},
|
|
{
|
|
createEmptyScene(noTagsID),
|
|
nil,
|
|
false,
|
|
},
|
|
{
|
|
createEmptyScene(errTagsID),
|
|
nil,
|
|
true,
|
|
},
|
|
}
|
|
|
|
func getTags(names []string) []*models.Tag {
|
|
var ret []*models.Tag
|
|
for _, n := range names {
|
|
ret = append(ret, &models.Tag{
|
|
Name: n,
|
|
})
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
func TestGetTagNames(t *testing.T) {
|
|
mockTagReader := &mocks.TagReaderWriter{}
|
|
|
|
tagErr := errors.New("error getting tag")
|
|
|
|
mockTagReader.On("FindBySceneID", sceneID).Return(getTags(names), nil).Once()
|
|
mockTagReader.On("FindBySceneID", noTagsID).Return(nil, nil).Once()
|
|
mockTagReader.On("FindBySceneID", errTagsID).Return(nil, tagErr).Once()
|
|
|
|
for i, s := range getTagNamesScenarios {
|
|
scene := s.input
|
|
json, err := GetTagNames(mockTagReader, &scene)
|
|
|
|
switch {
|
|
case !s.err && err != nil:
|
|
t.Errorf("[%d] unexpected error: %s", i, err.Error())
|
|
case s.err && err == nil:
|
|
t.Errorf("[%d] expected error not returned", i)
|
|
default:
|
|
assert.Equal(t, s.expected, json, "[%d]", i)
|
|
}
|
|
}
|
|
|
|
mockTagReader.AssertExpectations(t)
|
|
}
|
|
|
|
type sceneMoviesTestScenario struct {
|
|
input models.Scene
|
|
expected []jsonschema.SceneMovie
|
|
err bool
|
|
}
|
|
|
|
var getSceneMoviesJSONScenarios = []sceneMoviesTestScenario{
|
|
{
|
|
createEmptyScene(sceneID),
|
|
[]jsonschema.SceneMovie{
|
|
{
|
|
MovieName: movie1Name,
|
|
SceneIndex: movie1Scene,
|
|
},
|
|
{
|
|
MovieName: movie2Name,
|
|
SceneIndex: movie2Scene,
|
|
},
|
|
},
|
|
false,
|
|
},
|
|
{
|
|
createEmptyScene(noMoviesID),
|
|
nil,
|
|
false,
|
|
},
|
|
{
|
|
createEmptyScene(errMoviesID),
|
|
nil,
|
|
true,
|
|
},
|
|
{
|
|
createEmptyScene(errFindMovieID),
|
|
nil,
|
|
true,
|
|
},
|
|
}
|
|
|
|
var validMovies = []models.MoviesScenes{
|
|
{
|
|
MovieID: validMovie1,
|
|
SceneIndex: models.NullInt64(movie1Scene),
|
|
},
|
|
{
|
|
MovieID: validMovie2,
|
|
SceneIndex: models.NullInt64(movie2Scene),
|
|
},
|
|
}
|
|
|
|
var invalidMovies = []models.MoviesScenes{
|
|
{
|
|
MovieID: invalidMovie,
|
|
SceneIndex: models.NullInt64(movie1Scene),
|
|
},
|
|
}
|
|
|
|
func TestGetSceneMoviesJSON(t *testing.T) {
|
|
mockMovieReader := &mocks.MovieReaderWriter{}
|
|
mockSceneReader := &mocks.SceneReaderWriter{}
|
|
|
|
joinErr := errors.New("error getting scene movies")
|
|
movieErr := errors.New("error getting movie")
|
|
|
|
mockSceneReader.On("GetMovies", sceneID).Return(validMovies, nil).Once()
|
|
mockSceneReader.On("GetMovies", noMoviesID).Return(nil, nil).Once()
|
|
mockSceneReader.On("GetMovies", errMoviesID).Return(nil, joinErr).Once()
|
|
mockSceneReader.On("GetMovies", errFindMovieID).Return(invalidMovies, nil).Once()
|
|
|
|
mockMovieReader.On("Find", validMovie1).Return(&models.Movie{
|
|
Name: models.NullString(movie1Name),
|
|
}, nil).Once()
|
|
mockMovieReader.On("Find", validMovie2).Return(&models.Movie{
|
|
Name: models.NullString(movie2Name),
|
|
}, nil).Once()
|
|
mockMovieReader.On("Find", invalidMovie).Return(nil, movieErr).Once()
|
|
|
|
for i, s := range getSceneMoviesJSONScenarios {
|
|
scene := s.input
|
|
json, err := GetSceneMoviesJSON(mockMovieReader, mockSceneReader, &scene)
|
|
|
|
switch {
|
|
case !s.err && err != nil:
|
|
t.Errorf("[%d] unexpected error: %s", i, err.Error())
|
|
case s.err && err == nil:
|
|
t.Errorf("[%d] expected error not returned", i)
|
|
default:
|
|
assert.Equal(t, s.expected, json, "[%d]", i)
|
|
}
|
|
}
|
|
|
|
mockMovieReader.AssertExpectations(t)
|
|
}
|
|
|
|
const (
|
|
validMarkerID1 = 1
|
|
validMarkerID2 = 2
|
|
|
|
invalidMarkerID1 = 3
|
|
invalidMarkerID2 = 4
|
|
|
|
validTagID1 = 1
|
|
validTagID2 = 2
|
|
|
|
validTagName1 = "validTagName1"
|
|
validTagName2 = "validTagName2"
|
|
|
|
invalidTagID = 3
|
|
|
|
markerTitle1 = "markerTitle1"
|
|
markerTitle2 = "markerTitle2"
|
|
|
|
markerSeconds1 = 1.0
|
|
markerSeconds2 = 2.3
|
|
|
|
markerSeconds1Str = "1.0"
|
|
markerSeconds2Str = "2.3"
|
|
)
|
|
|
|
type sceneMarkersTestScenario struct {
|
|
input models.Scene
|
|
expected []jsonschema.SceneMarker
|
|
err bool
|
|
}
|
|
|
|
var getSceneMarkersJSONScenarios = []sceneMarkersTestScenario{
|
|
{
|
|
createEmptyScene(sceneID),
|
|
[]jsonschema.SceneMarker{
|
|
{
|
|
Title: markerTitle1,
|
|
PrimaryTag: validTagName1,
|
|
Seconds: markerSeconds1Str,
|
|
Tags: []string{
|
|
validTagName1,
|
|
validTagName2,
|
|
},
|
|
CreatedAt: models.JSONTime{
|
|
Time: createTime,
|
|
},
|
|
UpdatedAt: models.JSONTime{
|
|
Time: updateTime,
|
|
},
|
|
},
|
|
{
|
|
Title: markerTitle2,
|
|
PrimaryTag: validTagName2,
|
|
Seconds: markerSeconds2Str,
|
|
Tags: []string{
|
|
validTagName2,
|
|
},
|
|
CreatedAt: models.JSONTime{
|
|
Time: createTime,
|
|
},
|
|
UpdatedAt: models.JSONTime{
|
|
Time: updateTime,
|
|
},
|
|
},
|
|
},
|
|
false,
|
|
},
|
|
{
|
|
createEmptyScene(noMarkersID),
|
|
nil,
|
|
false,
|
|
},
|
|
{
|
|
createEmptyScene(errMarkersID),
|
|
nil,
|
|
true,
|
|
},
|
|
{
|
|
createEmptyScene(errFindPrimaryTagID),
|
|
nil,
|
|
true,
|
|
},
|
|
{
|
|
createEmptyScene(errFindByMarkerID),
|
|
nil,
|
|
true,
|
|
},
|
|
}
|
|
|
|
var validMarkers = []*models.SceneMarker{
|
|
{
|
|
ID: validMarkerID1,
|
|
Title: markerTitle1,
|
|
PrimaryTagID: validTagID1,
|
|
Seconds: markerSeconds1,
|
|
CreatedAt: models.SQLiteTimestamp{
|
|
Timestamp: createTime,
|
|
},
|
|
UpdatedAt: models.SQLiteTimestamp{
|
|
Timestamp: updateTime,
|
|
},
|
|
},
|
|
{
|
|
ID: validMarkerID2,
|
|
Title: markerTitle2,
|
|
PrimaryTagID: validTagID2,
|
|
Seconds: markerSeconds2,
|
|
CreatedAt: models.SQLiteTimestamp{
|
|
Timestamp: createTime,
|
|
},
|
|
UpdatedAt: models.SQLiteTimestamp{
|
|
Timestamp: updateTime,
|
|
},
|
|
},
|
|
}
|
|
|
|
var invalidMarkers1 = []*models.SceneMarker{
|
|
{
|
|
ID: invalidMarkerID1,
|
|
PrimaryTagID: invalidTagID,
|
|
},
|
|
}
|
|
|
|
var invalidMarkers2 = []*models.SceneMarker{
|
|
{
|
|
ID: invalidMarkerID2,
|
|
PrimaryTagID: validTagID1,
|
|
},
|
|
}
|
|
|
|
func TestGetSceneMarkersJSON(t *testing.T) {
|
|
mockTagReader := &mocks.TagReaderWriter{}
|
|
mockMarkerReader := &mocks.SceneMarkerReaderWriter{}
|
|
|
|
markersErr := errors.New("error getting scene markers")
|
|
tagErr := errors.New("error getting tags")
|
|
|
|
mockMarkerReader.On("FindBySceneID", sceneID).Return(validMarkers, nil).Once()
|
|
mockMarkerReader.On("FindBySceneID", noMarkersID).Return(nil, nil).Once()
|
|
mockMarkerReader.On("FindBySceneID", errMarkersID).Return(nil, markersErr).Once()
|
|
mockMarkerReader.On("FindBySceneID", errFindPrimaryTagID).Return(invalidMarkers1, nil).Once()
|
|
mockMarkerReader.On("FindBySceneID", errFindByMarkerID).Return(invalidMarkers2, nil).Once()
|
|
|
|
mockTagReader.On("Find", validTagID1).Return(&models.Tag{
|
|
Name: validTagName1,
|
|
}, nil)
|
|
mockTagReader.On("Find", validTagID2).Return(&models.Tag{
|
|
Name: validTagName2,
|
|
}, nil)
|
|
mockTagReader.On("Find", invalidTagID).Return(nil, tagErr)
|
|
|
|
mockTagReader.On("FindBySceneMarkerID", validMarkerID1).Return([]*models.Tag{
|
|
{
|
|
Name: validTagName1,
|
|
},
|
|
{
|
|
Name: validTagName2,
|
|
},
|
|
}, nil)
|
|
mockTagReader.On("FindBySceneMarkerID", validMarkerID2).Return([]*models.Tag{
|
|
{
|
|
Name: validTagName2,
|
|
},
|
|
}, nil)
|
|
mockTagReader.On("FindBySceneMarkerID", invalidMarkerID2).Return(nil, tagErr).Once()
|
|
|
|
for i, s := range getSceneMarkersJSONScenarios {
|
|
scene := s.input
|
|
json, err := GetSceneMarkersJSON(mockMarkerReader, mockTagReader, &scene)
|
|
|
|
switch {
|
|
case !s.err && err != nil:
|
|
t.Errorf("[%d] unexpected error: %s", i, err.Error())
|
|
case s.err && err == nil:
|
|
t.Errorf("[%d] expected error not returned", i)
|
|
default:
|
|
assert.Equal(t, s.expected, json, "[%d]", i)
|
|
}
|
|
}
|
|
|
|
mockTagReader.AssertExpectations(t)
|
|
}
|