2019-05-06 23:18:10 +02:00
|
|
|
package config
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"os"
|
2020-05-31 02:09:52 +02:00
|
|
|
"path/filepath"
|
2021-01-02 18:56:15 +01:00
|
|
|
"strconv"
|
2020-01-06 02:14:17 +01:00
|
|
|
"sync"
|
2019-05-03 18:57:28 +02:00
|
|
|
"testing"
|
2020-04-30 14:32:48 +02:00
|
|
|
"time"
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
_ "github.com/jinzhu/gorm/dialects/mysql"
|
|
|
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
2020-01-06 14:32:15 +01:00
|
|
|
"github.com/photoprism/photoprism/internal/thumb"
|
2020-04-30 15:41:47 +02:00
|
|
|
"github.com/photoprism/photoprism/pkg/capture"
|
2020-01-13 11:07:09 +01:00
|
|
|
"github.com/photoprism/photoprism/pkg/fs"
|
2020-05-27 19:38:40 +02:00
|
|
|
"github.com/photoprism/photoprism/pkg/rnd"
|
2019-05-03 18:57:28 +02:00
|
|
|
"github.com/urfave/cli"
|
|
|
|
)
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// Download URL and ZIP hash for test files.
|
2019-05-03 18:57:28 +02:00
|
|
|
const (
|
|
|
|
TestDataZip = "/tmp/photoprism/testdata.zip"
|
2021-12-12 20:15:52 +01:00
|
|
|
TestDataURL = "https://dl.photoprism.app/qa/testdata.zip"
|
2020-01-26 10:22:27 +01:00
|
|
|
TestDataHash = "be394d5bee8a5634d415e9e0663eef20b5604510" // sha1sum
|
2019-05-03 18:57:28 +02:00
|
|
|
)
|
|
|
|
|
2019-05-06 23:18:10 +02:00
|
|
|
var testConfig *Config
|
2020-04-13 18:08:21 +02:00
|
|
|
var testConfigOnce sync.Once
|
2020-04-09 19:39:09 +02:00
|
|
|
var testConfigMutex sync.Mutex
|
2021-12-09 02:33:41 +01:00
|
|
|
var testDataMutex sync.Mutex
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
func testDataPath(assetsPath string) string {
|
|
|
|
return assetsPath + "/testdata"
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// NewTestOptions returns valid config options for tests.
|
2020-12-18 20:42:12 +01:00
|
|
|
func NewTestOptions() *Options {
|
2020-01-31 15:29:06 +01:00
|
|
|
assetsPath := fs.Abs("../../assets")
|
2020-05-31 02:09:52 +02:00
|
|
|
storagePath := fs.Abs("../../storage")
|
|
|
|
testDataPath := filepath.Join(storagePath, "testdata")
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2020-05-30 14:52:47 +02:00
|
|
|
dbDriver := os.Getenv("PHOTOPRISM_TEST_DRIVER")
|
|
|
|
dbDsn := os.Getenv("PHOTOPRISM_TEST_DSN")
|
|
|
|
|
|
|
|
// Config example for MySQL / MariaDB:
|
|
|
|
// dbDriver = MySQL,
|
2021-08-31 18:08:37 +02:00
|
|
|
// dbDsn = "photoprism:photoprism@tcp(mariadb:4001)/photoprism?parseTime=true",
|
2020-05-30 14:52:47 +02:00
|
|
|
|
2020-05-30 21:11:56 +02:00
|
|
|
if dbDriver == "test" || dbDriver == "sqlite" || dbDriver == "" || dbDsn == "" {
|
2021-12-09 07:47:23 +01:00
|
|
|
dbDriver = SQLite3
|
2020-05-30 14:52:47 +02:00
|
|
|
dbDsn = ".test.db"
|
|
|
|
}
|
|
|
|
|
2020-12-18 20:42:12 +01:00
|
|
|
c := &Options{
|
2020-05-27 19:38:40 +02:00
|
|
|
Name: "PhotoPrism",
|
|
|
|
Version: "0.0.0",
|
2022-01-03 13:48:44 +01:00
|
|
|
Copyright: "(c) 2018-2022 Michael Mayer",
|
2021-11-12 05:09:17 +01:00
|
|
|
Test: true,
|
2020-04-30 15:41:47 +02:00
|
|
|
Debug: true,
|
2019-11-12 05:49:10 +01:00
|
|
|
Public: true,
|
2021-08-12 12:05:10 +02:00
|
|
|
Experimental: true,
|
2019-11-12 05:49:10 +01:00
|
|
|
ReadOnly: false,
|
2020-01-13 16:48:32 +01:00
|
|
|
DetectNSFW: true,
|
2019-12-15 17:19:16 +01:00
|
|
|
UploadNSFW: false,
|
2019-05-03 18:57:28 +02:00
|
|
|
AssetsPath: assetsPath,
|
2021-01-02 18:56:15 +01:00
|
|
|
AutoIndex: -1,
|
|
|
|
AutoImport: 7200,
|
2020-05-31 02:09:52 +02:00
|
|
|
StoragePath: testDataPath,
|
2019-05-03 18:57:28 +02:00
|
|
|
CachePath: testDataPath + "/cache",
|
|
|
|
OriginalsPath: testDataPath + "/originals",
|
|
|
|
ImportPath: testDataPath + "/import",
|
2020-04-06 22:50:04 +02:00
|
|
|
TempPath: testDataPath + "/temp",
|
2020-12-18 20:42:12 +01:00
|
|
|
ConfigPath: testDataPath + "/config",
|
2020-12-11 19:17:07 +01:00
|
|
|
SidecarPath: testDataPath + "/sidecar",
|
2020-05-30 14:52:47 +02:00
|
|
|
DatabaseDriver: dbDriver,
|
|
|
|
DatabaseDsn: dbDsn,
|
2020-06-30 08:50:44 +02:00
|
|
|
AdminPassword: "photoprism",
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// NewTestOptionsError returns invalid config options for tests.
|
2020-12-18 20:42:12 +01:00
|
|
|
func NewTestOptionsError() *Options {
|
2020-01-31 15:29:06 +01:00
|
|
|
assetsPath := fs.Abs("../..")
|
2020-05-31 02:09:52 +02:00
|
|
|
testDataPath := fs.Abs("../../storage/testdata")
|
2019-07-17 12:00:15 +02:00
|
|
|
|
2020-12-18 20:42:12 +01:00
|
|
|
c := &Options{
|
2019-07-17 12:00:15 +02:00
|
|
|
DarktableBin: "/usr/bin/darktable-cli",
|
|
|
|
AssetsPath: assetsPath,
|
2020-05-31 02:09:52 +02:00
|
|
|
StoragePath: testDataPath,
|
2019-07-17 12:00:15 +02:00
|
|
|
CachePath: testDataPath + "/cache",
|
|
|
|
OriginalsPath: testDataPath + "/originals",
|
|
|
|
ImportPath: testDataPath + "/import",
|
2020-04-06 22:50:04 +02:00
|
|
|
TempPath: testDataPath + "/temp",
|
2021-12-09 07:47:23 +01:00
|
|
|
DatabaseDriver: SQLite3,
|
2020-07-13 20:41:16 +02:00
|
|
|
DatabaseDsn: ".test-error.db",
|
2019-07-17 12:00:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2020-04-13 18:08:21 +02:00
|
|
|
func SetNewTestConfig() {
|
|
|
|
testConfig = NewTestConfig()
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// TestConfig returns the existing test config instance or creates a new instance and returns it.
|
2019-05-06 23:18:10 +02:00
|
|
|
func TestConfig() *Config {
|
2020-04-13 18:08:21 +02:00
|
|
|
testConfigOnce.Do(SetNewTestConfig)
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2019-05-06 23:18:10 +02:00
|
|
|
return testConfig
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// NewTestConfig returns a valid test config.
|
2019-05-06 23:18:10 +02:00
|
|
|
func NewTestConfig() *Config {
|
2020-04-30 15:41:47 +02:00
|
|
|
defer log.Debug(capture.Time(time.Now(), "config: new test config created"))
|
|
|
|
|
2020-04-09 19:39:09 +02:00
|
|
|
testConfigMutex.Lock()
|
|
|
|
defer testConfigMutex.Unlock()
|
|
|
|
|
2020-05-27 19:38:40 +02:00
|
|
|
c := &Config{
|
2020-12-18 20:42:12 +01:00
|
|
|
options: NewTestOptions(),
|
|
|
|
token: rnd.Token(8),
|
2020-05-27 19:38:40 +02:00
|
|
|
}
|
|
|
|
|
2021-12-12 22:09:22 +01:00
|
|
|
s := NewSettings(c)
|
2020-05-31 02:09:52 +02:00
|
|
|
|
2020-12-17 18:24:55 +01:00
|
|
|
if err := os.MkdirAll(c.ConfigPath(), os.ModePerm); err != nil {
|
2020-05-31 02:09:52 +02:00
|
|
|
log.Fatalf("config: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
2020-12-17 18:24:55 +01:00
|
|
|
if err := s.Save(filepath.Join(c.ConfigPath(), "settings.yml")); err != nil {
|
2020-05-31 02:09:52 +02:00
|
|
|
log.Fatalf("config: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
2020-10-08 08:52:03 +02:00
|
|
|
if err := c.Init(); err != nil {
|
2020-04-30 15:41:47 +02:00
|
|
|
log.Fatalf("config: %s", err.Error())
|
2019-06-03 22:58:15 +02:00
|
|
|
}
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2020-05-08 19:34:29 +02:00
|
|
|
c.InitTestDb()
|
2020-01-06 02:14:17 +01:00
|
|
|
|
2021-09-05 12:32:08 +02:00
|
|
|
thumb.SizePrecached = c.ThumbSizePrecached()
|
2020-07-18 17:33:02 +02:00
|
|
|
thumb.SizeUncached = c.ThumbSizeUncached()
|
2020-05-05 17:17:19 +02:00
|
|
|
thumb.Filter = c.ThumbFilter()
|
2020-05-05 17:04:13 +02:00
|
|
|
thumb.JpegQuality = c.JpegQuality()
|
2020-01-06 14:32:15 +01:00
|
|
|
|
2019-05-03 18:57:28 +02:00
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// NewTestErrorConfig returns an invalid test config.
|
2019-07-17 12:00:15 +02:00
|
|
|
func NewTestErrorConfig() *Config {
|
2020-12-18 20:42:12 +01:00
|
|
|
c := &Config{options: NewTestOptionsError()}
|
2020-07-04 12:54:35 +02:00
|
|
|
|
2019-07-17 12:00:15 +02:00
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// CliTestContext returns a CLI context for testing.
|
2019-05-03 18:57:28 +02:00
|
|
|
func CliTestContext() *cli.Context {
|
2020-12-18 20:42:12 +01:00
|
|
|
config := NewTestOptions()
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
globalSet := flag.NewFlagSet("test", 0)
|
|
|
|
globalSet.Bool("debug", false, "doc")
|
2020-05-31 02:09:52 +02:00
|
|
|
globalSet.String("storage-path", config.StoragePath, "doc")
|
2020-12-04 11:02:19 +01:00
|
|
|
globalSet.String("backup-path", config.StoragePath, "doc")
|
2020-07-13 20:25:47 +02:00
|
|
|
globalSet.String("sidecar-path", config.SidecarPath, "doc")
|
2019-05-03 18:57:28 +02:00
|
|
|
globalSet.String("config-file", config.ConfigFile, "doc")
|
|
|
|
globalSet.String("assets-path", config.AssetsPath, "doc")
|
|
|
|
globalSet.String("originals-path", config.OriginalsPath, "doc")
|
2020-01-31 15:29:06 +01:00
|
|
|
globalSet.String("import-path", config.OriginalsPath, "doc")
|
2020-04-06 22:50:04 +02:00
|
|
|
globalSet.String("temp-path", config.OriginalsPath, "doc")
|
2020-01-31 15:29:06 +01:00
|
|
|
globalSet.String("cache-path", config.OriginalsPath, "doc")
|
2019-06-06 14:44:29 +02:00
|
|
|
globalSet.String("darktable-cli", config.DarktableBin, "doc")
|
2021-09-21 15:33:46 +02:00
|
|
|
globalSet.String("darktable-blacklist", config.DarktableBlacklist, "doc")
|
2020-06-30 08:50:44 +02:00
|
|
|
globalSet.String("admin-password", config.DarktableBin, "doc")
|
2020-01-13 16:48:32 +01:00
|
|
|
globalSet.Bool("detect-nsfw", config.DetectNSFW, "doc")
|
2021-01-02 18:56:15 +01:00
|
|
|
globalSet.Int("auto-index", config.AutoIndex, "doc")
|
|
|
|
globalSet.Int("auto-import", config.AutoImport, "doc")
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
app := cli.NewApp()
|
2020-11-16 19:39:40 +01:00
|
|
|
app.Version = "0.0.0"
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
c := cli.NewContext(app, globalSet, nil)
|
|
|
|
|
2020-05-31 02:09:52 +02:00
|
|
|
LogError(c.Set("storage-path", config.StoragePath))
|
2020-12-04 11:02:19 +01:00
|
|
|
LogError(c.Set("backup-path", config.BackupPath))
|
2020-07-13 20:25:47 +02:00
|
|
|
LogError(c.Set("sidecar-path", config.SidecarPath))
|
2020-04-30 15:41:47 +02:00
|
|
|
LogError(c.Set("config-file", config.ConfigFile))
|
|
|
|
LogError(c.Set("assets-path", config.AssetsPath))
|
|
|
|
LogError(c.Set("originals-path", config.OriginalsPath))
|
|
|
|
LogError(c.Set("import-path", config.ImportPath))
|
|
|
|
LogError(c.Set("temp-path", config.TempPath))
|
|
|
|
LogError(c.Set("cache-path", config.CachePath))
|
|
|
|
LogError(c.Set("darktable-cli", config.DarktableBin))
|
2021-09-21 15:33:46 +02:00
|
|
|
LogError(c.Set("darktable-blacklist", "raf,cr3"))
|
2020-06-30 08:50:44 +02:00
|
|
|
LogError(c.Set("admin-password", config.AdminPassword))
|
2020-04-30 15:41:47 +02:00
|
|
|
LogError(c.Set("detect-nsfw", "true"))
|
2021-01-02 18:56:15 +01:00
|
|
|
LogError(c.Set("auto-index", strconv.Itoa(config.AutoIndex)))
|
|
|
|
LogError(c.Set("auto-import", strconv.Itoa(config.AutoImport)))
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// RemoveTestData deletes files in import, export, originals, and cache folders.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) RemoveTestData(t *testing.T) {
|
2020-04-30 16:44:04 +02:00
|
|
|
if err := os.RemoveAll(c.ImportPath()); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.RemoveAll(c.TempPath()); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.RemoveAll(c.OriginalsPath()); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.RemoveAll(c.CachePath()); err != nil {
|
2022-02-23 15:16:45 +01:00
|
|
|
t.Logf("test: %s (remove cache)", err)
|
2020-04-30 16:44:04 +02:00
|
|
|
}
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// DownloadTestData downloads the test files from the file server.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) DownloadTestData(t *testing.T) {
|
2020-01-12 14:00:56 +01:00
|
|
|
if fs.FileExists(TestDataZip) {
|
|
|
|
hash := fs.Hash(TestDataZip)
|
2019-05-03 18:57:28 +02:00
|
|
|
|
|
|
|
if hash != TestDataHash {
|
2020-04-30 16:44:04 +02:00
|
|
|
if err := os.Remove(TestDataZip); err != nil {
|
|
|
|
t.Fatalf("config: %s", err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Logf("config: removed outdated test data zip file (fingerprint %s)", hash)
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 14:00:56 +01:00
|
|
|
if !fs.FileExists(TestDataZip) {
|
2020-04-30 16:44:04 +02:00
|
|
|
t.Logf("config: downloading latest test data zip file from %s", TestDataURL)
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2020-01-12 14:00:56 +01:00
|
|
|
if err := fs.Download(TestDataZip, TestDataURL); err != nil {
|
2020-04-30 16:44:04 +02:00
|
|
|
t.Fatalf("config: test data download failed: %s", err.Error())
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// UnzipTestData extracts tests files from the zip archive.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) UnzipTestData(t *testing.T) {
|
2020-05-31 02:09:52 +02:00
|
|
|
if _, err := fs.Unzip(TestDataZip, c.StoragePath()); err != nil {
|
2020-04-30 16:44:04 +02:00
|
|
|
t.Fatalf("config: could not unzip test data: %s", err.Error())
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
// InitializeTestData resets the test file directory.
|
2019-05-06 23:18:10 +02:00
|
|
|
func (c *Config) InitializeTestData(t *testing.T) {
|
2021-12-09 02:33:41 +01:00
|
|
|
testDataMutex.Lock()
|
|
|
|
defer testDataMutex.Unlock()
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
start := time.Now()
|
2019-05-03 18:57:28 +02:00
|
|
|
|
2021-12-09 02:33:41 +01:00
|
|
|
c.RemoveTestData(t)
|
2019-05-03 18:57:28 +02:00
|
|
|
c.DownloadTestData(t)
|
|
|
|
c.UnzipTestData(t)
|
2021-12-09 02:33:41 +01:00
|
|
|
|
|
|
|
t.Logf("config: initialized test data [%s]", time.Since(start))
|
2019-05-03 18:57:28 +02:00
|
|
|
}
|