Skip to content

Commit 017e249

Browse files
committed
Tests: Refine isolated test-folder cleanup and logging photoprism#5263
1 parent b6687b6 commit 017e249

2 files changed

Lines changed: 62 additions & 50 deletions

File tree

internal/config/test.go

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import (
1919
_ "github.com/jinzhu/gorm/dialects/sqlite"
2020

2121
"github.com/photoprism/photoprism/internal/config/customize"
22+
"github.com/photoprism/photoprism/internal/event"
2223
"github.com/photoprism/photoprism/internal/service/hub"
2324
"github.com/photoprism/photoprism/internal/thumb"
2425
"github.com/photoprism/photoprism/pkg/authn"
2526
"github.com/photoprism/photoprism/pkg/capture"
2627
"github.com/photoprism/photoprism/pkg/clean"
2728
"github.com/photoprism/photoprism/pkg/dsn"
2829
"github.com/photoprism/photoprism/pkg/fs"
30+
"github.com/photoprism/photoprism/pkg/log/status"
2931
"github.com/photoprism/photoprism/pkg/rnd"
3032
"github.com/photoprism/photoprism/pkg/txt/report"
3133
)
@@ -337,8 +339,9 @@ func NewTestConfig(dbName string) *Config {
337339

338340
var tp string
339341
var err error
342+
340343
if tp, err = os.MkdirTemp(storagePath, "test-photoprism-*"); err != nil {
341-
log.Fatalf("config: %s", err.Error())
344+
log.Panicf("config: %s", clean.Error(err))
342345
}
343346

344347
tp = filepath.Join(tp, fs.TestdataDir)
@@ -352,22 +355,22 @@ func NewTestConfig(dbName string) *Config {
352355

353356
s := customize.NewSettings(c.DefaultTheme(), c.DefaultLocale(), c.DefaultTimezone().String())
354357

355-
if err := fs.MkdirAll(c.ConfigPath()); err != nil {
356-
log.Panicf("config: %s", err.Error())
358+
if err = fs.MkdirAll(c.ConfigPath()); err != nil {
359+
log.Panicf("config: %s", clean.Error(err))
357360
}
358361

359362
// Save settings next to the test config path, reusing any existing
360363
// `.yaml`/`.yml` variant so the tests mirror production behavior.
361-
if err := s.Save(fs.ConfigFilePath(c.ConfigPath(), "settings", fs.ExtYml)); err != nil {
362-
log.Panicf("config: %s", err.Error())
364+
if err = s.Save(fs.ConfigFilePath(c.ConfigPath(), "settings", fs.ExtYml)); err != nil {
365+
log.Panicf("config: %s", clean.Error(err))
363366
}
364367

365-
if err := c.Init(); err != nil {
366-
log.Panicf("config: %s", err.Error())
368+
if err = c.Init(); err != nil {
369+
log.Panicf("config: %s", clean.Error(err))
367370
}
368371

369-
if err := c.InitializeTestData(); err != nil {
370-
log.Errorf("config: %s", err.Error())
372+
if err = c.InitializeTestData(); err != nil {
373+
log.Errorf("config: %s", clean.Error(err))
371374
}
372375

373376
c.RegisterDb()
@@ -635,20 +638,28 @@ func (c *Config) AssertTestData(t *testing.T) {
635638
}
636639
}
637640

638-
// CleanupTestFolder uses RemoveAll to remove the storage path above testdata.
641+
// CleanupTestFolder removes the isolated storage directory created by NewTestConfig.
642+
//
643+
// It only deletes paths matching the isolated layout "test-photoprism-*/testdata" so a
644+
// misconfigured StoragePath can never remove a real storage directory. A failed removal
645+
// is logged as a warning rather than aborting, so a teardown hiccup does not turn a
646+
// passing test run into a hard exit.
639647
func (c *Config) CleanupTestFolder() {
640648
if c.options == nil {
641-
log.Warn("config: c.options is nil in CleanupTestFolder")
649+
event.SystemWarn([]string{"config", "test", "c.options is nil in CleanupTestFolder"})
642650
return
643651
}
652+
644653
td := c.StoragePath()
645-
if strings.HasSuffix(td, "/testdata") && strings.Contains(td, "test-photoprism") {
646-
td = strings.TrimSuffix(td, "/testdata")
647-
if err := os.RemoveAll(td); err != nil {
648-
log.Fatalf("config: %s (cleantestfolder)", err.Error())
654+
parent := filepath.Dir(td)
655+
656+
if filepath.Base(td) == fs.TestdataDir && strings.HasPrefix(filepath.Base(parent), "test-photoprism") {
657+
if err := os.RemoveAll(parent); err != nil {
658+
event.SystemWarn([]string{"config", "test", "cleanup %s", "%s"}, parent, clean.Error(err))
659+
return
649660
}
650-
log.Debugf("config: cleaned up %s", td)
661+
event.SystemDebug([]string{"config", "test", "cleanup %s", status.Succeeded}, parent)
651662
} else {
652-
log.Warnf("config: %s not cleaned up", td)
663+
event.SystemWarn([]string{"config", "test", "cleanup %s", "failed"}, td)
653664
}
654665
}

internal/config/test_test.go

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ package config
22

33
import (
44
"bytes"
5-
"os"
65
"testing"
76

87
"github.com/jinzhu/gorm"
8+
"github.com/sirupsen/logrus"
99
"github.com/stretchr/testify/assert"
1010
"github.com/urfave/cli/v2"
1111

12+
"github.com/photoprism/photoprism/internal/event"
1213
"github.com/photoprism/photoprism/pkg/fs"
1314
)
1415

@@ -60,46 +61,46 @@ func TestNewTestErrorConfig(t *testing.T) {
6061
assert.IsType(t, &gorm.DB{}, db)
6162
}
6263

64+
// captureSystemLog swaps event.SystemLog for a buffer-backed logger, runs fn, and
65+
// returns what fn wrote to the system log. CleanupTestFolder logs via event.System*
66+
// (not the DB-hooked default logger), so tests must read the system log to see it.
67+
func captureSystemLog(t *testing.T, fn func()) string {
68+
t.Helper()
69+
var buf bytes.Buffer
70+
logger := logrus.New()
71+
logger.SetOutput(&buf)
72+
logger.SetLevel(logrus.DebugLevel)
73+
orig := event.SystemLog
74+
event.SystemLog = logger
75+
t.Cleanup(func() { event.SystemLog = orig })
76+
fn()
77+
return buf.String()
78+
}
79+
6380
func TestCleanupTestFolder(t *testing.T) {
6481
t.Run("OptionsNil", func(t *testing.T) {
65-
// Setup and capture log output
66-
buffer := bytes.Buffer{}
67-
log.SetOutput(&buffer)
68-
6982
var c Config
70-
c.CleanupTestFolder()
71-
72-
// Reset logger
73-
log.SetOutput(os.Stdout)
74-
75-
assert.Contains(t, buffer.String(), "config: c.options is nil in CleanupTestFolder")
83+
out := captureSystemLog(t, c.CleanupTestFolder)
84+
assert.Contains(t, out, "c.options is nil in CleanupTestFolder")
7685
})
77-
7886
t.Run("NotExpectedPath", func(t *testing.T) {
79-
// Setup and capture log output
80-
buffer := bytes.Buffer{}
81-
log.SetOutput(&buffer)
82-
8387
c := Config{options: &Options{StoragePath: "/tmp/photoprism/testdata"}}
84-
c.CleanupTestFolder()
85-
86-
// Reset logger
87-
log.SetOutput(os.Stdout)
88-
89-
assert.Contains(t, buffer.String(), "config: /tmp/photoprism/testdata not cleaned up")
88+
out := captureSystemLog(t, c.CleanupTestFolder)
89+
assert.Contains(t, out, "cleanup /tmp/photoprism/testdata")
90+
assert.Contains(t, out, "failed")
9091
})
91-
9292
t.Run("Success", func(t *testing.T) {
93-
// Setup and capture log output
94-
buffer := bytes.Buffer{}
95-
log.SetOutput(&buffer)
96-
9793
c := Config{options: &Options{StoragePath: "/tmp/photoprism/test-photoprism-1394931550/testdata"}}
98-
c.CleanupTestFolder()
99-
100-
// Reset logger
101-
log.SetOutput(os.Stdout)
102-
103-
assert.Contains(t, buffer.String(), "config: cleaned up /tmp/photoprism/test-photoprism-1394931550")
94+
out := captureSystemLog(t, c.CleanupTestFolder)
95+
assert.Contains(t, out, "cleanup /tmp/photoprism/test-photoprism-1394931550")
96+
assert.Contains(t, out, "succeeded")
97+
})
98+
t.Run("MarkerNotPrefix", func(t *testing.T) {
99+
// The isolated-folder marker must be the prefix of the parent directory, not merely
100+
// a substring, so a path like ".../my-test-photoprism-x/testdata" is refused.
101+
c := Config{options: &Options{StoragePath: "/tmp/photoprism/my-test-photoprism-x/testdata"}}
102+
out := captureSystemLog(t, c.CleanupTestFolder)
103+
assert.Contains(t, out, "cleanup /tmp/photoprism/my-test-photoprism-x/testdata")
104+
assert.Contains(t, out, "failed")
104105
})
105106
}

0 commit comments

Comments
 (0)