stash/pkg/sqlite/scene_marker_test.go

412 lines
9.6 KiB
Go
Raw Normal View History

//go:build integration
// +build integration
package sqlite_test
import (
"context"
"slices"
"strconv"
"testing"
"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
"github.com/stretchr/testify/assert"
)
func TestMarkerFindBySceneID(t *testing.T) {
withTxn(func(ctx context.Context) error {
mqb := db.SceneMarker
sceneID := sceneIDs[sceneIdxWithMarkers]
markers, err := mqb.FindBySceneID(ctx, sceneID)
if err != nil {
t.Errorf("Error finding markers: %s", err.Error())
}
assert.Greater(t, len(markers), 0)
for _, marker := range markers {
assert.Equal(t, sceneIDs[sceneIdxWithMarkers], marker.SceneID)
}
markers, err = mqb.FindBySceneID(ctx, 0)
if err != nil {
t.Errorf("Error finding marker: %s", err.Error())
}
assert.Len(t, markers, 0)
return nil
})
}
func TestMarkerCountByTagID(t *testing.T) {
withTxn(func(ctx context.Context) error {
mqb := db.SceneMarker
markerCount, err := mqb.CountByTagID(ctx, tagIDs[tagIdxWithPrimaryMarkers])
if err != nil {
t.Errorf("error calling CountByTagID: %s", err.Error())
}
2023-06-23 01:04:54 +00:00
assert.Equal(t, 6, markerCount)
markerCount, err = mqb.CountByTagID(ctx, tagIDs[tagIdxWithMarkers])
if err != nil {
t.Errorf("error calling CountByTagID: %s", err.Error())
}
2023-06-23 01:04:54 +00:00
assert.Equal(t, 2, markerCount)
markerCount, err = mqb.CountByTagID(ctx, 0)
if err != nil {
t.Errorf("error calling CountByTagID: %s", err.Error())
}
assert.Equal(t, 0, markerCount)
return nil
})
}
2024-06-24 06:02:46 +00:00
func TestMarkerQueryQ(t *testing.T) {
withTxn(func(ctx context.Context) error {
q := getSceneTitle(sceneIdxWithMarkers)
m, _, err := db.SceneMarker.Query(ctx, nil, &models.FindFilterType{
Q: &q,
})
if err != nil {
t.Errorf("Error querying scene markers: %s", err.Error())
}
if !assert.Greater(t, len(m), 0) {
return nil
}
assert.Equal(t, sceneIDs[sceneIdxWithMarkers], m[0].SceneID)
return nil
})
}
func TestMarkerQuerySortBySceneUpdated(t *testing.T) {
withTxn(func(ctx context.Context) error {
sort := "scenes_updated_at"
_, _, err := db.SceneMarker.Query(ctx, nil, &models.FindFilterType{
Sort: &sort,
})
if err != nil {
t.Errorf("Error querying scene markers: %s", err.Error())
}
return nil
})
}
2023-06-23 01:04:54 +00:00
func verifyIDs(t *testing.T, modifier models.CriterionModifier, values []int, results []int) {
t.Helper()
switch modifier {
case models.CriterionModifierIsNull:
assert.Len(t, results, 0)
case models.CriterionModifierNotNull:
assert.NotEqual(t, 0, len(results))
case models.CriterionModifierIncludes:
for _, v := range values {
assert.Contains(t, results, v)
}
case models.CriterionModifierExcludes:
for _, v := range values {
assert.NotContains(t, results, v)
}
case models.CriterionModifierEquals:
for _, v := range values {
assert.Contains(t, results, v)
}
assert.Len(t, results, len(values))
case models.CriterionModifierNotEquals:
foundAll := true
for _, v := range values {
if !slices.Contains(results, v) {
2023-06-23 01:04:54 +00:00
foundAll = false
break
}
}
if foundAll && len(results) == len(values) {
t.Errorf("expected ids not equal to %v - found %v", values, results)
}
}
}
func TestMarkerQueryTags(t *testing.T) {
type test struct {
name string
markerFilter *models.SceneMarkerFilterType
findFilter *models.FindFilterType
}
withTxn(func(ctx context.Context) error {
2023-06-23 01:04:54 +00:00
testTags := func(t *testing.T, m *models.SceneMarker, markerFilter *models.SceneMarkerFilterType) {
tagIDs, err := db.SceneMarker.GetTagIDs(ctx, m.ID)
if err != nil {
t.Errorf("error getting marker tag ids: %v", err)
}
2023-06-23 01:04:54 +00:00
// HACK - if modifier isn't null/not null, then add the primary tag id
if markerFilter.Tags.Modifier != models.CriterionModifierIsNull && markerFilter.Tags.Modifier != models.CriterionModifierNotNull {
tagIDs = append(tagIDs, m.PrimaryTagID)
}
2023-06-23 01:04:54 +00:00
values, _ := stringslice.StringSliceToIntSlice(markerFilter.Tags.Value)
verifyIDs(t, markerFilter.Tags.Modifier, values, tagIDs)
}
cases := []test{
{
"is null",
&models.SceneMarkerFilterType{
Tags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIsNull,
},
},
nil,
},
{
"not null",
&models.SceneMarkerFilterType{
Tags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierNotNull,
},
},
nil,
},
2023-06-23 01:04:54 +00:00
{
"includes",
&models.SceneMarkerFilterType{
Tags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIncludes,
Value: []string{
strconv.Itoa(tagIDs[tagIdxWithMarkers]),
},
},
},
nil,
},
{
"includes all",
&models.SceneMarkerFilterType{
Tags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIncludesAll,
Value: []string{
strconv.Itoa(tagIDs[tagIdxWithMarkers]),
strconv.Itoa(tagIDs[tagIdx2WithMarkers]),
},
},
},
nil,
},
{
"equals",
&models.SceneMarkerFilterType{
Tags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierEquals,
Value: []string{
strconv.Itoa(tagIDs[tagIdxWithPrimaryMarkers]),
strconv.Itoa(tagIDs[tagIdxWithMarkers]),
strconv.Itoa(tagIDs[tagIdx2WithMarkers]),
},
},
},
nil,
},
// not equals not supported
// {
// "not equals",
// &models.SceneMarkerFilterType{
// Tags: &models.HierarchicalMultiCriterionInput{
// Modifier: models.CriterionModifierNotEquals,
// Value: []string{
// strconv.Itoa(tagIDs[tagIdx2WithScene]),
// strconv.Itoa(tagIDs[tagIdx3WithScene]),
// },
// },
// },
// nil,
// },
{
"excludes",
&models.SceneMarkerFilterType{
Tags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIncludes,
Value: []string{
strconv.Itoa(tagIDs[tagIdx2WithMarkers]),
},
},
},
nil,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
markers := queryMarkers(ctx, t, db.SceneMarker, tc.markerFilter, tc.findFilter)
assert.Greater(t, len(markers), 0)
for _, m := range markers {
2023-06-23 01:04:54 +00:00
testTags(t, m, tc.markerFilter)
}
})
}
return nil
})
}
func TestMarkerQuerySceneTags(t *testing.T) {
type test struct {
name string
markerFilter *models.SceneMarkerFilterType
findFilter *models.FindFilterType
}
withTxn(func(ctx context.Context) error {
testTags := func(t *testing.T, m *models.SceneMarker, markerFilter *models.SceneMarkerFilterType) {
s, err := db.Scene.Find(ctx, m.SceneID)
if err != nil {
t.Errorf("error getting marker tag ids: %v", err)
File storage rewrite (#2676) * Restructure data layer part 2 (#2599) * Refactor and separate image model * Refactor image query builder * Handle relationships in image query builder * Remove relationship management methods * Refactor gallery model/query builder * Add scenes to gallery model * Convert scene model * Refactor scene models * Remove unused methods * Add unit tests for gallery * Add image tests * Add scene tests * Convert unnecessary scene value pointers to values * Convert unnecessary pointer values to values * Refactor scene partial * Add scene partial tests * Refactor ImagePartial * Add image partial tests * Refactor gallery partial update * Add partial gallery update tests * Use zero/null package for null values * Add files and scan system * Add sqlite implementation for files/folders * Add unit tests for files/folders * Image refactors * Update image data layer * Refactor gallery model and creation * Refactor scene model * Refactor scenes * Don't set title from filename * Allow galleries to freely add/remove images * Add multiple scene file support to graphql and UI * Add multiple file support for images in graphql/UI * Add multiple file for galleries in graphql/UI * Remove use of some deprecated fields * Remove scene path usage * Remove gallery path usage * Remove path from image * Move funscript to video file * Refactor caption detection * Migrate existing data * Add post commit/rollback hook system * Lint. Comment out import/export tests * Add WithDatabase read only wrapper * Prepend tasks to list * Add 32 pre-migration * Add warnings in release and migration notes
2022-07-13 06:30:54 +00:00
return
}
if err := s.LoadTagIDs(ctx, db.Scene); err != nil {
t.Errorf("error getting marker tag ids: %v", err)
return
}
tagIDs := s.TagIDs.List()
values, _ := stringslice.StringSliceToIntSlice(markerFilter.SceneTags.Value)
2023-06-23 01:04:54 +00:00
verifyIDs(t, markerFilter.SceneTags.Modifier, values, tagIDs)
}
cases := []test{
{
"is null",
&models.SceneMarkerFilterType{
SceneTags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIsNull,
},
},
nil,
},
{
"not null",
&models.SceneMarkerFilterType{
SceneTags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierNotNull,
},
},
nil,
},
{
"includes",
&models.SceneMarkerFilterType{
SceneTags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIncludes,
Value: []string{
strconv.Itoa(tagIDs[tagIdx3WithScene]),
},
},
},
nil,
},
{
"includes all",
&models.SceneMarkerFilterType{
SceneTags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIncludesAll,
Value: []string{
strconv.Itoa(tagIDs[tagIdx2WithScene]),
strconv.Itoa(tagIDs[tagIdx3WithScene]),
},
},
},
nil,
},
{
"equals",
&models.SceneMarkerFilterType{
SceneTags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierEquals,
Value: []string{
strconv.Itoa(tagIDs[tagIdx2WithScene]),
strconv.Itoa(tagIDs[tagIdx3WithScene]),
},
},
},
nil,
},
// not equals not supported
// {
// "not equals",
// &models.SceneMarkerFilterType{
// SceneTags: &models.HierarchicalMultiCriterionInput{
// Modifier: models.CriterionModifierNotEquals,
// Value: []string{
// strconv.Itoa(tagIDs[tagIdx2WithScene]),
// strconv.Itoa(tagIDs[tagIdx3WithScene]),
// },
// },
// },
// nil,
// },
{
"excludes",
&models.SceneMarkerFilterType{
SceneTags: &models.HierarchicalMultiCriterionInput{
Modifier: models.CriterionModifierIncludes,
Value: []string{
strconv.Itoa(tagIDs[tagIdx2WithScene]),
},
},
},
nil,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
markers := queryMarkers(ctx, t, db.SceneMarker, tc.markerFilter, tc.findFilter)
assert.Greater(t, len(markers), 0)
for _, m := range markers {
testTags(t, m, tc.markerFilter)
}
})
}
return nil
})
}
func queryMarkers(ctx context.Context, t *testing.T, sqb models.SceneMarkerReader, markerFilter *models.SceneMarkerFilterType, findFilter *models.FindFilterType) []*models.SceneMarker {
t.Helper()
result, _, err := sqb.Query(ctx, markerFilter, findFilter)
if err != nil {
t.Errorf("Error querying markers: %v", err)
}
return result
}
// TODO Update
// TODO Destroy
// TODO Find
// TODO GetMarkerStrings
// TODO Wall
// TODO Count
// TODO All
// TODO Query