// +build integration package sqlite_test import ( "strconv" "testing" "github.com/stretchr/testify/assert" "github.com/stashapp/stash/pkg/models" ) func TestGalleryFind(t *testing.T) { withTxn(func(r models.Repository) error { gqb := r.Gallery() const galleryIdx = 0 gallery, err := gqb.Find(galleryIDs[galleryIdx]) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Equal(t, getGalleryStringValue(galleryIdx, "Path"), gallery.Path.String) gallery, err = gqb.Find(0) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Nil(t, gallery) return nil }) } func TestGalleryFindByChecksum(t *testing.T) { withTxn(func(r models.Repository) error { gqb := r.Gallery() const galleryIdx = 0 galleryChecksum := getGalleryStringValue(galleryIdx, "Checksum") gallery, err := gqb.FindByChecksum(galleryChecksum) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Equal(t, getGalleryStringValue(galleryIdx, "Path"), gallery.Path.String) galleryChecksum = "not exist" gallery, err = gqb.FindByChecksum(galleryChecksum) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Nil(t, gallery) return nil }) } func TestGalleryFindByPath(t *testing.T) { withTxn(func(r models.Repository) error { gqb := r.Gallery() const galleryIdx = 0 galleryPath := getGalleryStringValue(galleryIdx, "Path") gallery, err := gqb.FindByPath(galleryPath) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Equal(t, galleryPath, gallery.Path.String) galleryPath = "not exist" gallery, err = gqb.FindByPath(galleryPath) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Nil(t, gallery) return nil }) } func TestGalleryFindBySceneID(t *testing.T) { withTxn(func(r models.Repository) error { gqb := r.Gallery() sceneID := sceneIDs[sceneIdxWithGallery] galleries, err := gqb.FindBySceneID(sceneID) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Equal(t, getGalleryStringValue(galleryIdxWithScene, "Path"), galleries[0].Path.String) galleries, err = gqb.FindBySceneID(0) if err != nil { t.Errorf("Error finding gallery: %s", err.Error()) } assert.Nil(t, galleries) return nil }) } func TestGalleryQueryQ(t *testing.T) { withTxn(func(r models.Repository) error { const galleryIdx = 0 q := getGalleryStringValue(galleryIdx, pathField) sqb := r.Gallery() galleryQueryQ(t, sqb, q, galleryIdx) return nil }) } func galleryQueryQ(t *testing.T, qb models.GalleryReader, q string, expectedGalleryIdx int) { filter := models.FindFilterType{ Q: &q, } galleries, _, err := qb.Query(nil, &filter) if err != nil { t.Errorf("Error querying gallery: %s", err.Error()) } assert.Len(t, galleries, 1) gallery := galleries[0] assert.Equal(t, galleryIDs[expectedGalleryIdx], gallery.ID) // no Q should return all results filter.Q = nil galleries, _, err = qb.Query(nil, &filter) if err != nil { t.Errorf("Error querying gallery: %s", err.Error()) } assert.Len(t, galleries, totalGalleries) } func TestGalleryQueryPath(t *testing.T) { withTxn(func(r models.Repository) error { const galleryIdx = 1 galleryPath := getGalleryStringValue(galleryIdx, "Path") pathCriterion := models.StringCriterionInput{ Value: galleryPath, Modifier: models.CriterionModifierEquals, } verifyGalleriesPath(t, r.Gallery(), pathCriterion) pathCriterion.Modifier = models.CriterionModifierNotEquals verifyGalleriesPath(t, r.Gallery(), pathCriterion) pathCriterion.Modifier = models.CriterionModifierMatchesRegex pathCriterion.Value = "gallery.*1_Path" verifyGalleriesPath(t, r.Gallery(), pathCriterion) pathCriterion.Modifier = models.CriterionModifierNotMatchesRegex verifyGalleriesPath(t, r.Gallery(), pathCriterion) return nil }) } func verifyGalleriesPath(t *testing.T, sqb models.GalleryReader, pathCriterion models.StringCriterionInput) { galleryFilter := models.GalleryFilterType{ Path: &pathCriterion, } galleries, _, err := sqb.Query(&galleryFilter, nil) if err != nil { t.Errorf("Error querying gallery: %s", err.Error()) } for _, gallery := range galleries { verifyNullString(t, gallery.Path, pathCriterion) } } func TestGalleryQueryURL(t *testing.T) { const sceneIdx = 1 galleryURL := getGalleryStringValue(sceneIdx, urlField) urlCriterion := models.StringCriterionInput{ Value: galleryURL, Modifier: models.CriterionModifierEquals, } filter := models.GalleryFilterType{ URL: &urlCriterion, } verifyFn := func(g *models.Gallery) { t.Helper() verifyNullString(t, g.URL, urlCriterion) } verifyGalleryQuery(t, filter, verifyFn) urlCriterion.Modifier = models.CriterionModifierNotEquals verifyGalleryQuery(t, filter, verifyFn) urlCriterion.Modifier = models.CriterionModifierMatchesRegex urlCriterion.Value = "gallery_.*1_URL" verifyGalleryQuery(t, filter, verifyFn) urlCriterion.Modifier = models.CriterionModifierNotMatchesRegex verifyGalleryQuery(t, filter, verifyFn) urlCriterion.Modifier = models.CriterionModifierIsNull urlCriterion.Value = "" verifyGalleryQuery(t, filter, verifyFn) urlCriterion.Modifier = models.CriterionModifierNotNull verifyGalleryQuery(t, filter, verifyFn) } func verifyGalleryQuery(t *testing.T, filter models.GalleryFilterType, verifyFn func(s *models.Gallery)) { withTxn(func(r models.Repository) error { t.Helper() sqb := r.Gallery() galleries := queryGallery(t, sqb, &filter, nil) // assume it should find at least one assert.Greater(t, len(galleries), 0) for _, gallery := range galleries { verifyFn(gallery) } return nil }) } func TestGalleryQueryRating(t *testing.T) { const rating = 3 ratingCriterion := models.IntCriterionInput{ Value: rating, Modifier: models.CriterionModifierEquals, } verifyGalleriesRating(t, ratingCriterion) ratingCriterion.Modifier = models.CriterionModifierNotEquals verifyGalleriesRating(t, ratingCriterion) ratingCriterion.Modifier = models.CriterionModifierGreaterThan verifyGalleriesRating(t, ratingCriterion) ratingCriterion.Modifier = models.CriterionModifierLessThan verifyGalleriesRating(t, ratingCriterion) ratingCriterion.Modifier = models.CriterionModifierIsNull verifyGalleriesRating(t, ratingCriterion) ratingCriterion.Modifier = models.CriterionModifierNotNull verifyGalleriesRating(t, ratingCriterion) } func verifyGalleriesRating(t *testing.T, ratingCriterion models.IntCriterionInput) { withTxn(func(r models.Repository) error { sqb := r.Gallery() galleryFilter := models.GalleryFilterType{ Rating: &ratingCriterion, } galleries, _, err := sqb.Query(&galleryFilter, nil) if err != nil { t.Errorf("Error querying gallery: %s", err.Error()) } for _, gallery := range galleries { verifyInt64(t, gallery.Rating, ratingCriterion) } return nil }) } func TestGalleryQueryIsMissingScene(t *testing.T) { withTxn(func(r models.Repository) error { qb := r.Gallery() isMissing := "scenes" galleryFilter := models.GalleryFilterType{ IsMissing: &isMissing, } q := getGalleryStringValue(galleryIdxWithScene, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries, _, err := qb.Query(&galleryFilter, &findFilter) if err != nil { t.Errorf("Error querying gallery: %s", err.Error()) } assert.Len(t, galleries, 0) findFilter.Q = nil galleries, _, err = qb.Query(&galleryFilter, &findFilter) if err != nil { t.Errorf("Error querying gallery: %s", err.Error()) } // ensure non of the ids equal the one with gallery for _, gallery := range galleries { assert.NotEqual(t, galleryIDs[galleryIdxWithScene], gallery.ID) } return nil }) } func queryGallery(t *testing.T, sqb models.GalleryReader, galleryFilter *models.GalleryFilterType, findFilter *models.FindFilterType) []*models.Gallery { galleries, _, err := sqb.Query(galleryFilter, findFilter) if err != nil { t.Errorf("Error querying gallery: %s", err.Error()) } return galleries } func TestGalleryQueryIsMissingStudio(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() isMissing := "studio" galleryFilter := models.GalleryFilterType{ IsMissing: &isMissing, } q := getGalleryStringValue(galleryIdxWithStudio, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries := queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) findFilter.Q = nil galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) // ensure non of the ids equal the one with studio for _, gallery := range galleries { assert.NotEqual(t, galleryIDs[galleryIdxWithStudio], gallery.ID) } return nil }) } func TestGalleryQueryIsMissingPerformers(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() isMissing := "performers" galleryFilter := models.GalleryFilterType{ IsMissing: &isMissing, } q := getGalleryStringValue(galleryIdxWithPerformer, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries := queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) findFilter.Q = nil galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.True(t, len(galleries) > 0) // ensure non of the ids equal the one with movies for _, gallery := range galleries { assert.NotEqual(t, galleryIDs[galleryIdxWithPerformer], gallery.ID) } return nil }) } func TestGalleryQueryIsMissingTags(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() isMissing := "tags" galleryFilter := models.GalleryFilterType{ IsMissing: &isMissing, } q := getGalleryStringValue(galleryIdxWithTwoTags, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries := queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) findFilter.Q = nil galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.True(t, len(galleries) > 0) return nil }) } func TestGalleryQueryPerformers(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() performerCriterion := models.MultiCriterionInput{ Value: []string{ strconv.Itoa(performerIDs[performerIdxWithGallery]), strconv.Itoa(performerIDs[performerIdx1WithGallery]), }, Modifier: models.CriterionModifierIncludes, } galleryFilter := models.GalleryFilterType{ Performers: &performerCriterion, } galleries := queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 2) // ensure ids are correct for _, gallery := range galleries { assert.True(t, gallery.ID == galleryIDs[galleryIdxWithPerformer] || gallery.ID == galleryIDs[galleryIdxWithTwoPerformers]) } performerCriterion = models.MultiCriterionInput{ Value: []string{ strconv.Itoa(performerIDs[performerIdx1WithGallery]), strconv.Itoa(performerIDs[performerIdx2WithGallery]), }, Modifier: models.CriterionModifierIncludesAll, } galleries = queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 1) assert.Equal(t, galleryIDs[galleryIdxWithTwoPerformers], galleries[0].ID) performerCriterion = models.MultiCriterionInput{ Value: []string{ strconv.Itoa(performerIDs[performerIdx1WithGallery]), }, Modifier: models.CriterionModifierExcludes, } q := getGalleryStringValue(galleryIdxWithTwoPerformers, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) return nil }) } func TestGalleryQueryTags(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() tagCriterion := models.MultiCriterionInput{ Value: []string{ strconv.Itoa(tagIDs[tagIdxWithGallery]), strconv.Itoa(tagIDs[tagIdx1WithGallery]), }, Modifier: models.CriterionModifierIncludes, } galleryFilter := models.GalleryFilterType{ Tags: &tagCriterion, } galleries := queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 2) // ensure ids are correct for _, gallery := range galleries { assert.True(t, gallery.ID == galleryIDs[galleryIdxWithTag] || gallery.ID == galleryIDs[galleryIdxWithTwoTags]) } tagCriterion = models.MultiCriterionInput{ Value: []string{ strconv.Itoa(tagIDs[tagIdx1WithGallery]), strconv.Itoa(tagIDs[tagIdx2WithGallery]), }, Modifier: models.CriterionModifierIncludesAll, } galleries = queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 1) assert.Equal(t, galleryIDs[galleryIdxWithTwoTags], galleries[0].ID) tagCriterion = models.MultiCriterionInput{ Value: []string{ strconv.Itoa(tagIDs[tagIdx1WithGallery]), }, Modifier: models.CriterionModifierExcludes, } q := getGalleryStringValue(galleryIdxWithTwoTags, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) return nil }) } func TestGalleryQueryStudio(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() studioCriterion := models.MultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGallery]), }, Modifier: models.CriterionModifierIncludes, } galleryFilter := models.GalleryFilterType{ Studios: &studioCriterion, } galleries := queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 1) // ensure id is correct assert.Equal(t, galleryIDs[galleryIdxWithStudio], galleries[0].ID) studioCriterion = models.MultiCriterionInput{ Value: []string{ strconv.Itoa(studioIDs[studioIdxWithGallery]), }, Modifier: models.CriterionModifierExcludes, } q := getGalleryStringValue(galleryIdxWithStudio, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) return nil }) } func TestGalleryQueryPerformerTags(t *testing.T) { withTxn(func(r models.Repository) error { sqb := r.Gallery() tagCriterion := models.MultiCriterionInput{ Value: []string{ strconv.Itoa(tagIDs[tagIdxWithPerformer]), strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierIncludes, } galleryFilter := models.GalleryFilterType{ PerformerTags: &tagCriterion, } galleries := queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 2) // ensure ids are correct for _, gallery := range galleries { assert.True(t, gallery.ID == galleryIDs[galleryIdxWithPerformerTag] || gallery.ID == galleryIDs[galleryIdxWithPerformerTwoTags]) } tagCriterion = models.MultiCriterionInput{ Value: []string{ strconv.Itoa(tagIDs[tagIdx1WithPerformer]), strconv.Itoa(tagIDs[tagIdx2WithPerformer]), }, Modifier: models.CriterionModifierIncludesAll, } galleries = queryGallery(t, sqb, &galleryFilter, nil) assert.Len(t, galleries, 1) assert.Equal(t, galleryIDs[galleryIdxWithPerformerTwoTags], galleries[0].ID) tagCriterion = models.MultiCriterionInput{ Value: []string{ strconv.Itoa(tagIDs[tagIdx1WithPerformer]), }, Modifier: models.CriterionModifierExcludes, } q := getGalleryStringValue(galleryIdxWithPerformerTwoTags, titleField) findFilter := models.FindFilterType{ Q: &q, } galleries = queryGallery(t, sqb, &galleryFilter, &findFilter) assert.Len(t, galleries, 0) return nil }) } // TODO Count // TODO All // TODO Query // TODO Update // TODO Destroy