97 lines
2.8 KiB
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")
|
|
}
|
|
}
|