mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
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
This commit is contained in:
@@ -1,225 +1,165 @@
|
||||
package image
|
||||
|
||||
import (
|
||||
"errors"
|
||||
// import (
|
||||
// "errors"
|
||||
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/models/json"
|
||||
"github.com/stashapp/stash/pkg/models/jsonschema"
|
||||
"github.com/stashapp/stash/pkg/models/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
// "github.com/stashapp/stash/pkg/file"
|
||||
// "github.com/stashapp/stash/pkg/models"
|
||||
// "github.com/stashapp/stash/pkg/models/json"
|
||||
// "github.com/stashapp/stash/pkg/models/jsonschema"
|
||||
// "github.com/stashapp/stash/pkg/models/mocks"
|
||||
// "github.com/stretchr/testify/assert"
|
||||
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
// "testing"
|
||||
// "time"
|
||||
// )
|
||||
|
||||
const (
|
||||
imageID = 1
|
||||
// noImageID = 2
|
||||
errImageID = 3
|
||||
// const (
|
||||
// imageID = 1
|
||||
// errImageID = 3
|
||||
|
||||
studioID = 4
|
||||
missingStudioID = 5
|
||||
errStudioID = 6
|
||||
// studioID = 4
|
||||
// missingStudioID = 5
|
||||
// errStudioID = 6
|
||||
// )
|
||||
|
||||
// noGalleryID = 7
|
||||
// errGalleryID = 8
|
||||
// var (
|
||||
// checksum = "checksum"
|
||||
// title = "title"
|
||||
// rating = 5
|
||||
// organized = true
|
||||
// ocounter = 2
|
||||
// size int64 = 123
|
||||
// width = 100
|
||||
// height = 100
|
||||
// )
|
||||
|
||||
// noTagsID = 11
|
||||
errTagsID = 12
|
||||
// const (
|
||||
// studioName = "studioName"
|
||||
// )
|
||||
|
||||
// noMoviesID = 13
|
||||
// errMoviesID = 14
|
||||
// errFindMovieID = 15
|
||||
// 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)
|
||||
// )
|
||||
|
||||
// noMarkersID = 16
|
||||
// errMarkersID = 17
|
||||
// errFindPrimaryTagID = 18
|
||||
// errFindByMarkerID = 19
|
||||
)
|
||||
// func createFullImage(id int) models.Image {
|
||||
// return models.Image{
|
||||
// ID: id,
|
||||
// Title: title,
|
||||
// Files: []*file.ImageFile{
|
||||
// {
|
||||
// BaseFile: &file.BaseFile{
|
||||
// Size: size,
|
||||
// },
|
||||
// Height: height,
|
||||
// Width: width,
|
||||
// },
|
||||
// },
|
||||
// OCounter: ocounter,
|
||||
// Rating: &rating,
|
||||
// Organized: organized,
|
||||
// CreatedAt: createTime,
|
||||
// UpdatedAt: updateTime,
|
||||
// }
|
||||
// }
|
||||
|
||||
const (
|
||||
checksum = "checksum"
|
||||
title = "title"
|
||||
rating = 5
|
||||
organized = true
|
||||
ocounter = 2
|
||||
size = 123
|
||||
width = 100
|
||||
height = 100
|
||||
)
|
||||
// func createFullJSONImage() *jsonschema.Image {
|
||||
// return &jsonschema.Image{
|
||||
// Title: title,
|
||||
// Checksum: checksum,
|
||||
// OCounter: ocounter,
|
||||
// Rating: rating,
|
||||
// Organized: organized,
|
||||
// File: &jsonschema.ImageFile{
|
||||
// Height: height,
|
||||
// Size: size,
|
||||
// Width: width,
|
||||
// },
|
||||
// CreatedAt: json.JSONTime{
|
||||
// Time: createTime,
|
||||
// },
|
||||
// UpdatedAt: json.JSONTime{
|
||||
// Time: updateTime,
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
|
||||
const (
|
||||
studioName = "studioName"
|
||||
// galleryChecksum = "galleryChecksum"
|
||||
)
|
||||
// type basicTestScenario struct {
|
||||
// input models.Image
|
||||
// expected *jsonschema.Image
|
||||
// }
|
||||
|
||||
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 createFullImage(id int) models.Image {
|
||||
return models.Image{
|
||||
ID: id,
|
||||
Title: models.NullString(title),
|
||||
Checksum: checksum,
|
||||
Height: models.NullInt64(height),
|
||||
OCounter: ocounter,
|
||||
Rating: models.NullInt64(rating),
|
||||
Size: models.NullInt64(int64(size)),
|
||||
Organized: organized,
|
||||
Width: models.NullInt64(width),
|
||||
CreatedAt: models.SQLiteTimestamp{
|
||||
Timestamp: createTime,
|
||||
},
|
||||
UpdatedAt: models.SQLiteTimestamp{
|
||||
Timestamp: updateTime,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func createFullJSONImage() *jsonschema.Image {
|
||||
return &jsonschema.Image{
|
||||
Title: title,
|
||||
Checksum: checksum,
|
||||
OCounter: ocounter,
|
||||
Rating: rating,
|
||||
Organized: organized,
|
||||
File: &jsonschema.ImageFile{
|
||||
Height: height,
|
||||
Size: size,
|
||||
Width: width,
|
||||
},
|
||||
CreatedAt: json.JSONTime{
|
||||
Time: createTime,
|
||||
},
|
||||
UpdatedAt: json.JSONTime{
|
||||
Time: updateTime,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type basicTestScenario struct {
|
||||
input models.Image
|
||||
expected *jsonschema.Image
|
||||
}
|
||||
|
||||
var scenarios = []basicTestScenario{
|
||||
{
|
||||
createFullImage(imageID),
|
||||
createFullJSONImage(),
|
||||
},
|
||||
}
|
||||
|
||||
func TestToJSON(t *testing.T) {
|
||||
for i, s := range scenarios {
|
||||
image := s.input
|
||||
json := ToBasicJSON(&image)
|
||||
|
||||
assert.Equal(t, s.expected, json, "[%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func createStudioImage(studioID int) models.Image {
|
||||
return models.Image{
|
||||
StudioID: models.NullInt64(int64(studioID)),
|
||||
}
|
||||
}
|
||||
|
||||
type stringTestScenario struct {
|
||||
input models.Image
|
||||
expected string
|
||||
err bool
|
||||
}
|
||||
|
||||
var getStudioScenarios = []stringTestScenario{
|
||||
{
|
||||
createStudioImage(studioID),
|
||||
studioName,
|
||||
false,
|
||||
},
|
||||
{
|
||||
createStudioImage(missingStudioID),
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
createStudioImage(errStudioID),
|
||||
"",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
func TestGetStudioName(t *testing.T) {
|
||||
mockStudioReader := &mocks.StudioReaderWriter{}
|
||||
|
||||
studioErr := errors.New("error getting image")
|
||||
|
||||
mockStudioReader.On("Find", testCtx, studioID).Return(&models.Studio{
|
||||
Name: models.NullString(studioName),
|
||||
}, nil).Once()
|
||||
mockStudioReader.On("Find", testCtx, missingStudioID).Return(nil, nil).Once()
|
||||
mockStudioReader.On("Find", testCtx, errStudioID).Return(nil, studioErr).Once()
|
||||
|
||||
for i, s := range getStudioScenarios {
|
||||
image := s.input
|
||||
json, err := GetStudioName(testCtx, mockStudioReader, &image)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// var getGalleryChecksumScenarios = []stringTestScenario{
|
||||
// var scenarios = []basicTestScenario{
|
||||
// {
|
||||
// createEmptyImage(imageID),
|
||||
// galleryChecksum,
|
||||
// createFullImage(imageID),
|
||||
// createFullJSONImage(),
|
||||
// },
|
||||
// }
|
||||
|
||||
// func TestToJSON(t *testing.T) {
|
||||
// for i, s := range scenarios {
|
||||
// image := s.input
|
||||
// json := ToBasicJSON(&image)
|
||||
|
||||
// assert.Equal(t, s.expected, json, "[%d]", i)
|
||||
// }
|
||||
// }
|
||||
|
||||
// func createStudioImage(studioID int) models.Image {
|
||||
// return models.Image{
|
||||
// StudioID: &studioID,
|
||||
// }
|
||||
// }
|
||||
|
||||
// type stringTestScenario struct {
|
||||
// input models.Image
|
||||
// expected string
|
||||
// err bool
|
||||
// }
|
||||
|
||||
// var getStudioScenarios = []stringTestScenario{
|
||||
// {
|
||||
// createStudioImage(studioID),
|
||||
// studioName,
|
||||
// false,
|
||||
// },
|
||||
// {
|
||||
// createEmptyImage(noGalleryID),
|
||||
// createStudioImage(missingStudioID),
|
||||
// "",
|
||||
// false,
|
||||
// },
|
||||
// {
|
||||
// createEmptyImage(errGalleryID),
|
||||
// createStudioImage(errStudioID),
|
||||
// "",
|
||||
// true,
|
||||
// },
|
||||
// }
|
||||
|
||||
// func TestGetGalleryChecksum(t *testing.T) {
|
||||
// mockGalleryReader := &mocks.GalleryReaderWriter{}
|
||||
// func TestGetStudioName(t *testing.T) {
|
||||
// mockStudioReader := &mocks.StudioReaderWriter{}
|
||||
|
||||
// galleryErr := errors.New("error getting gallery")
|
||||
// studioErr := errors.New("error getting image")
|
||||
|
||||
// mockGalleryReader.On("FindByImageID", imageID).Return(&models.Gallery{
|
||||
// Checksum: galleryChecksum,
|
||||
// mockStudioReader.On("Find", testCtx, studioID).Return(&models.Studio{
|
||||
// Name: models.NullString(studioName),
|
||||
// }, nil).Once()
|
||||
// mockGalleryReader.On("FindByImageID", noGalleryID).Return(nil, nil).Once()
|
||||
// mockGalleryReader.On("FindByImageID", errGalleryID).Return(nil, galleryErr).Once()
|
||||
// mockStudioReader.On("Find", testCtx, missingStudioID).Return(nil, nil).Once()
|
||||
// mockStudioReader.On("Find", testCtx, errStudioID).Return(nil, studioErr).Once()
|
||||
|
||||
// for i, s := range getGalleryChecksumScenarios {
|
||||
// for i, s := range getStudioScenarios {
|
||||
// image := s.input
|
||||
// json, err := GetGalleryChecksum(mockGalleryReader, &image)
|
||||
// json, err := GetStudioName(testCtx, mockStudioReader, &image)
|
||||
|
||||
// if !s.err && err != nil {
|
||||
// switch {
|
||||
// case !s.err && err != nil:
|
||||
// t.Errorf("[%d] unexpected error: %s", i, err.Error())
|
||||
// } else if s.err && err == nil {
|
||||
// case s.err && err == nil:
|
||||
// t.Errorf("[%d] expected error not returned", i)
|
||||
// } else {
|
||||
// default:
|
||||
// assert.Equal(t, s.expected, json, "[%d]", i)
|
||||
// }
|
||||
// }
|
||||
|
||||
// mockGalleryReader.AssertExpectations(t)
|
||||
// mockStudioReader.AssertExpectations(t)
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user