stash/pkg/sqlite/movies_test.go

333 lines
7.9 KiB
Go

//go:build integration
// +build integration
package sqlite_test
import (
"context"
"fmt"
"strconv"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stashapp/stash/pkg/models"
)
func TestMovieFindByName(t *testing.T) {
withTxn(func(ctx context.Context) error {
mqb := db.Movie
name := movieNames[movieIdxWithScene] // find a movie by name
movie, err := mqb.FindByName(ctx, name, false)
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
}
assert.Equal(t, movieNames[movieIdxWithScene], movie.Name)
name = movieNames[movieIdxWithDupName] // find a movie by name nocase
movie, err = mqb.FindByName(ctx, name, true)
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
}
// movieIdxWithDupName and movieIdxWithScene should have similar names ( only diff should be Name vs NaMe)
//movie.Name should match with movieIdxWithScene since its ID is before moveIdxWithDupName
assert.Equal(t, movieNames[movieIdxWithScene], movie.Name)
//movie.Name should match with movieIdxWithDupName if the check is not case sensitive
assert.Equal(t, strings.ToLower(movieNames[movieIdxWithDupName]), strings.ToLower(movie.Name))
return nil
})
}
func TestMovieFindByNames(t *testing.T) {
withTxn(func(ctx context.Context) error {
var names []string
mqb := db.Movie
names = append(names, movieNames[movieIdxWithScene]) // find movies by names
movies, err := mqb.FindByNames(ctx, names, false)
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
}
assert.Len(t, movies, 1)
assert.Equal(t, movieNames[movieIdxWithScene], movies[0].Name)
movies, err = mqb.FindByNames(ctx, names, true) // find movies by names nocase
if err != nil {
t.Errorf("Error finding movies: %s", err.Error())
}
assert.Len(t, movies, 2) // movieIdxWithScene and movieIdxWithDupName
assert.Equal(t, strings.ToLower(movieNames[movieIdxWithScene]), strings.ToLower(movies[0].Name))
assert.Equal(t, strings.ToLower(movieNames[movieIdxWithScene]), strings.ToLower(movies[1].Name))
return nil
})
}
func moviesToIDs(i []*models.Movie) []int {
ret := make([]int, len(i))
for i, v := range i {
ret[i] = v.ID
}
return ret
}
func TestMovieQuery(t *testing.T) {
var (
frontImage = "front_image"
backImage = "back_image"
)
tests := []struct {
name string
findFilter *models.FindFilterType
filter *models.MovieFilterType
includeIdxs []int
excludeIdxs []int
wantErr bool
}{
{
"is missing front image",
nil,
&models.MovieFilterType{
IsMissing: &frontImage,
},
// just ensure that it doesn't error
nil,
nil,
false,
},
{
"is missing back image",
nil,
&models.MovieFilterType{
IsMissing: &backImage,
},
// just ensure that it doesn't error
nil,
nil,
false,
},
}
for _, tt := range tests {
runWithRollbackTxn(t, tt.name, func(t *testing.T, ctx context.Context) {
assert := assert.New(t)
results, _, err := db.Movie.Query(ctx, tt.filter, tt.findFilter)
if (err != nil) != tt.wantErr {
t.Errorf("MovieQueryBuilder.Query() error = %v, wantErr %v", err, tt.wantErr)
return
}
ids := moviesToIDs(results)
include := indexesToIDs(performerIDs, tt.includeIdxs)
exclude := indexesToIDs(performerIDs, tt.excludeIdxs)
for _, i := range include {
assert.Contains(ids, i)
}
for _, e := range exclude {
assert.NotContains(ids, e)
}
})
}
}
func TestMovieQueryStudio(t *testing.T) {
withTxn(func(ctx context.Context) error {
mqb := db.Movie
studioCriterion := models.HierarchicalMultiCriterionInput{
Value: []string{
strconv.Itoa(studioIDs[studioIdxWithMovie]),
},
Modifier: models.CriterionModifierIncludes,
}
movieFilter := models.MovieFilterType{
Studios: &studioCriterion,
}
movies, _, err := mqb.Query(ctx, &movieFilter, nil)
if err != nil {
t.Errorf("Error querying movie: %s", err.Error())
}
assert.Len(t, movies, 1)
// ensure id is correct
assert.Equal(t, movieIDs[movieIdxWithStudio], movies[0].ID)
studioCriterion = models.HierarchicalMultiCriterionInput{
Value: []string{
strconv.Itoa(studioIDs[studioIdxWithMovie]),
},
Modifier: models.CriterionModifierExcludes,
}
q := getMovieStringValue(movieIdxWithStudio, titleField)
findFilter := models.FindFilterType{
Q: &q,
}
movies, _, err = mqb.Query(ctx, &movieFilter, &findFilter)
if err != nil {
t.Errorf("Error querying movie: %s", err.Error())
}
assert.Len(t, movies, 0)
return nil
})
}
func TestMovieQueryURL(t *testing.T) {
const sceneIdx = 1
movieURL := getMovieStringValue(sceneIdx, urlField)
urlCriterion := models.StringCriterionInput{
Value: movieURL,
Modifier: models.CriterionModifierEquals,
}
filter := models.MovieFilterType{
URL: &urlCriterion,
}
verifyFn := func(n *models.Movie) {
t.Helper()
verifyString(t, n.URL, urlCriterion)
}
verifyMovieQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierNotEquals
verifyMovieQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierMatchesRegex
urlCriterion.Value = "movie_.*1_URL"
verifyMovieQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierNotMatchesRegex
verifyMovieQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierIsNull
urlCriterion.Value = ""
verifyMovieQuery(t, filter, verifyFn)
urlCriterion.Modifier = models.CriterionModifierNotNull
verifyMovieQuery(t, filter, verifyFn)
}
func verifyMovieQuery(t *testing.T, filter models.MovieFilterType, verifyFn func(s *models.Movie)) {
withTxn(func(ctx context.Context) error {
t.Helper()
sqb := db.Movie
movies := queryMovie(ctx, t, sqb, &filter, nil)
// assume it should find at least one
assert.Greater(t, len(movies), 0)
for _, m := range movies {
verifyFn(m)
}
return nil
})
}
func queryMovie(ctx context.Context, t *testing.T, sqb models.MovieReader, movieFilter *models.MovieFilterType, findFilter *models.FindFilterType) []*models.Movie {
movies, _, err := sqb.Query(ctx, movieFilter, findFilter)
if err != nil {
t.Errorf("Error querying movie: %s", err.Error())
}
return movies
}
func TestMovieQuerySorting(t *testing.T) {
sort := "scenes_count"
direction := models.SortDirectionEnumDesc
findFilter := models.FindFilterType{
Sort: &sort,
Direction: &direction,
}
withTxn(func(ctx context.Context) error {
sqb := db.Movie
movies := queryMovie(ctx, t, sqb, nil, &findFilter)
// scenes should be in same order as indexes
firstMovie := movies[0]
assert.Equal(t, movieIDs[movieIdxWithScene], firstMovie.ID)
// sort in descending order
direction = models.SortDirectionEnumAsc
movies = queryMovie(ctx, t, sqb, nil, &findFilter)
lastMovie := movies[len(movies)-1]
assert.Equal(t, movieIDs[movieIdxWithScene], lastMovie.ID)
return nil
})
}
func TestMovieUpdateFrontImage(t *testing.T) {
if err := withRollbackTxn(func(ctx context.Context) error {
qb := db.Movie
// create movie to test against
const name = "TestMovieUpdateMovieImages"
movie := models.Movie{
Name: name,
}
err := qb.Create(ctx, &movie)
if err != nil {
return fmt.Errorf("Error creating movie: %s", err.Error())
}
return testUpdateImage(t, ctx, movie.ID, qb.UpdateFrontImage, qb.GetFrontImage)
}); err != nil {
t.Error(err.Error())
}
}
func TestMovieUpdateBackImage(t *testing.T) {
if err := withRollbackTxn(func(ctx context.Context) error {
qb := db.Movie
// create movie to test against
const name = "TestMovieUpdateMovieImages"
movie := models.Movie{
Name: name,
}
err := qb.Create(ctx, &movie)
if err != nil {
return fmt.Errorf("Error creating movie: %s", err.Error())
}
return testUpdateImage(t, ctx, movie.ID, qb.UpdateBackImage, qb.GetBackImage)
}); err != nil {
t.Error(err.Error())
}
}
// TODO Update
// TODO Destroy - ensure image is destroyed
// TODO Find
// TODO Count
// TODO All
// TODO Query