feat: support explicit instance data deletion
This commit is contained in:
@@ -136,6 +136,111 @@ func TestShellDeletesOnlyAfterConfirmation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellDeletesInstanceDataBeforeRemovingConfiguration(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[3]
|
||||
deletions := 0
|
||||
shell.OnDeleteInstanceData(func(_ context.Context, row InstanceRow) error {
|
||||
deletions++
|
||||
if row.ID != target.ID || row.UserDataDir != target.UserDataDir {
|
||||
t.Fatalf("delete snapshot = %#v", row)
|
||||
}
|
||||
return nil
|
||||
}, nil)
|
||||
|
||||
shell.requestDelete(target.ID)
|
||||
shell.deleteData.Value = true
|
||||
shell.confirmDelete()
|
||||
if !shell.deleteDataRunning || len(shell.rows) != 4 {
|
||||
t.Fatalf("data deletion started=%v rows=%d", shell.deleteDataRunning, len(shell.rows))
|
||||
}
|
||||
var result instanceDataDeleteResult
|
||||
select {
|
||||
case result = <-shell.deleteDataResults:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("data deletion did not produce a result")
|
||||
}
|
||||
if deletions != 1 {
|
||||
t.Fatalf("deletions = %d", deletions)
|
||||
}
|
||||
shell.deleteDataResults <- result
|
||||
shell.consumeInstanceDataDeleteResults()
|
||||
if shell.pendingDeleteID != "" || shell.deleteDataRunning || len(shell.rows) != 3 {
|
||||
t.Fatalf("data deletion state = pending %q running=%v rows=%d", shell.pendingDeleteID, shell.deleteDataRunning, len(shell.rows))
|
||||
}
|
||||
if _, exists := shell.instanceRow(target.ID); exists || !strings.Contains(shell.instanceFeedback, "及其 User Data Dir 数据") {
|
||||
t.Fatalf("data deletion did not remove target: rows=%#v feedback=%q", shell.rows, shell.instanceFeedback)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellKeepsInstanceWhenDataDeletionFails(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[3]
|
||||
shell.OnDeleteInstanceData(func(context.Context, InstanceRow) error {
|
||||
return errors.New("permission denied")
|
||||
}, nil)
|
||||
|
||||
shell.requestDelete(target.ID)
|
||||
shell.deleteData.Value = true
|
||||
shell.confirmDelete()
|
||||
var result instanceDataDeleteResult
|
||||
select {
|
||||
case result = <-shell.deleteDataResults:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("data deletion did not produce a result")
|
||||
}
|
||||
shell.deleteDataResults <- result
|
||||
shell.consumeInstanceDataDeleteResults()
|
||||
if !shell.deleteData.Value || shell.pendingDeleteID != target.ID || shell.deleteDataRunning || len(shell.rows) != 4 {
|
||||
t.Fatalf("failed deletion state = data=%v pending=%q running=%v rows=%d", shell.deleteData.Value, shell.pendingDeleteID, shell.deleteDataRunning, len(shell.rows))
|
||||
}
|
||||
if !strings.Contains(shell.deleteDataFeedback, "未删除实例配置或 User Data Dir") {
|
||||
t.Fatalf("failure feedback = %q", shell.deleteDataFeedback)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellRejectsInstanceDataDeletionWhenStatusIsActive(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
called := false
|
||||
shell.OnDeleteInstanceData(func(context.Context, InstanceRow) error {
|
||||
called = true
|
||||
return nil
|
||||
}, nil)
|
||||
|
||||
shell.requestDelete(target.ID)
|
||||
shell.deleteData.Value = true
|
||||
shell.confirmDelete()
|
||||
if called || shell.deleteDataRunning || len(shell.rows) != 4 {
|
||||
t.Fatalf("active data deletion called=%v running=%v rows=%d", called, shell.deleteDataRunning, len(shell.rows))
|
||||
}
|
||||
if !strings.Contains(shell.deleteDataFeedback, "当前状态不能删除") {
|
||||
t.Fatalf("active deletion feedback = %q", shell.deleteDataFeedback)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellDiscardsStaleInstanceDataDeletionResult(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[3]
|
||||
shell.OnDeleteInstanceData(func(context.Context, InstanceRow) error { return nil }, nil)
|
||||
|
||||
shell.requestDelete(target.ID)
|
||||
shell.deleteData.Value = true
|
||||
shell.confirmDelete()
|
||||
var result instanceDataDeleteResult
|
||||
select {
|
||||
case result = <-shell.deleteDataResults:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("data deletion did not produce a result")
|
||||
}
|
||||
shell.rows[3].UserDataDir = "C:\\profiles\\changed"
|
||||
shell.deleteDataResults <- result
|
||||
shell.consumeInstanceDataDeleteResults()
|
||||
if shell.pendingDeleteID != target.ID || len(shell.rows) != 4 || !strings.Contains(shell.deleteDataFeedback, "配置已变化") {
|
||||
t.Fatalf("stale deletion state = pending=%q rows=%d feedback=%q", shell.pendingDeleteID, len(shell.rows), shell.deleteDataFeedback)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShellStartsInstanceAsynchronouslyAndAppliesResult(t *testing.T) {
|
||||
shell := NewShell(material.NewTheme())
|
||||
target := shell.rows[0]
|
||||
|
||||
Reference in New Issue
Block a user