Files
orbit/internal/retention/runtime_test.go

97 lines
2.8 KiB
Go

package retention
import (
"context"
"os"
"path/filepath"
"testing"
core "git.yuntuo.hk/k2safe/orbit/model"
)
type idleArchiveStore struct {
RuntimeStore
scheduled int
}
func (s *idleArchiveStore) ScheduleArchive(context.Context, core.ID) error { s.scheduled++; return nil }
func (s *idleArchiveStore) ClaimArchive(context.Context, core.ID) (*ManagedJob, error) {
return nil, nil
}
func TestArchiveVolumeIdentityLockAndInitializationRecovery(t *testing.T) {
store := &idleArchiveStore{}
id, _ := core.NewID()
runtime := &ArchiveRuntime{Directory: filepath.Join(t.TempDir(), "volume"), StorageID: id, MaxBytes: 8 << 20, Store: store}
if err := runtime.Init(); err != nil {
t.Fatal(err)
}
root, lock, err := openJob(runtime.Directory, false)
if err != nil {
t.Fatal(err)
}
// 其他节点正在执行时,新节点仍可读取不可变卷身份并正常启动。
if err = runtime.Init(); err != nil {
t.Fatal("another node could not initialize", err)
}
other := *runtime
other.StorageID, _ = core.NewID()
if err = other.Init(); err == nil {
t.Fatal("wrong volume accepted while busy")
}
if err = runtime.Tick(context.Background()); err != nil || store.scheduled != 0 {
t.Fatal("busy volume scheduled work", err)
}
lock.Close()
root.Close()
if err = runtime.Tick(context.Background()); err != nil || store.scheduled != 1 {
t.Fatal("unlocked volume did not schedule", err)
}
if err = other.Init(); err == nil {
t.Fatal("wrong volume accepted")
}
// 首次身份文件原子发布前崩溃,只允许丢弃本工具的安全临时文件。
fresh := *runtime
fresh.Directory = filepath.Join(t.TempDir(), "interrupted")
if err = os.Mkdir(fresh.Directory, 0700); err != nil {
t.Fatal(err)
}
if err = os.WriteFile(filepath.Join(fresh.Directory, ".write.tmp"), []byte(id), 0600); err != nil {
t.Fatal(err)
}
if err = fresh.Init(); err != nil {
t.Fatal("volume init did not recover", err)
}
}
func TestArchiveVolumeScanCountsAllJobsAndRejectsLinks(t *testing.T) {
dir := t.TempDir()
job := "job"
if err := os.Mkdir(filepath.Join(dir, job), 0700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "other"), []byte("volume"), 0600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, job, "batch"), []byte("job"), 0600); err != nil {
t.Fatal(err)
}
root, err := os.OpenRoot(dir)
if err != nil {
t.Fatal(err)
}
defer root.Close()
count := 0
total, current, err := archiveVolumeUsage(context.Background(), root, ".", job, &count)
if err != nil || total != 9 || current != 3 || count != 3 {
t.Fatal(total, current, count, err)
}
if err = os.Symlink("other", filepath.Join(dir, "unexpected")); err != nil {
t.Fatal(err)
}
count = 0
if _, _, err = archiveVolumeUsage(context.Background(), root, ".", job, &count); err == nil {
t.Fatal("volume symlink accepted")
}
}