// Licensed to the LF AI & Data foundation under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package rootcoord import ( "context" "testing" "github.com/stretchr/testify/assert" ) func newTestUndoTask() *baseUndoTask { stepExecutor := newMockStepExecutor() stepExecutor.AddStepsFunc = func(s *stepStack) { // no schedule, execute directly. s.Execute(context.Background()) } undoTask := newBaseUndoTask(stepExecutor) return undoTask } func Test_baseUndoTask_Execute(t *testing.T) { t.Run("should not happen", func(t *testing.T) { undoTask := newTestUndoTask() undoTask.todoStep = append(undoTask.todoStep, newMockNormalStep()) err := undoTask.Execute(context.Background()) assert.Error(t, err) }) t.Run("normal case, no undo step will be called", func(t *testing.T) { undoTask := newTestUndoTask() n := 10 todoSteps, undoSteps := make([]nestedStep, 0, n), make([]nestedStep, 0, n) for i := 0; i < n; i++ { normalTodoStep := newMockNormalStep() normalUndoStep := newMockNormalStep() todoSteps = append(todoSteps, normalTodoStep) undoSteps = append(undoSteps, normalUndoStep) } for i := 0; i < n; i++ { undoTask.AddStep(todoSteps[i], undoSteps[i]) } err := undoTask.Execute(context.Background()) assert.NoError(t, err) // make sure no undo steps will be called. for _, step := range undoSteps { assert.False(t, step.(*mockNormalStep).called) } }) t.Run("partial error, undo from last finished", func(t *testing.T) { undoTask := newTestUndoTask() todoSteps := []nestedStep{ newMockNormalStep(), newMockFailStep(), newMockNormalStep(), } undoSteps := []nestedStep{ newMockNormalStep(), newMockNormalStep(), newMockNormalStep(), } l := len(todoSteps) for i := 0; i < l; i++ { undoTask.AddStep(todoSteps[i], undoSteps[i]) } err := undoTask.Execute(context.Background()) assert.Error(t, err) assert.True(t, todoSteps[0].(*mockNormalStep).called) assert.True(t, todoSteps[1].(*mockFailStep).called) assert.False(t, todoSteps[2].(*mockNormalStep).called) <-undoSteps[0].(*mockNormalStep).calledChan assert.True(t, undoSteps[0].(*mockNormalStep).called) assert.False(t, undoSteps[1].(*mockNormalStep).called) assert.False(t, undoSteps[2].(*mockNormalStep).called) }) t.Run("partial error, undo meet error also", func(t *testing.T) { undoTask := newTestUndoTask() todoSteps := []nestedStep{ newMockNormalStep(), newMockNormalStep(), newMockFailStep(), } undoSteps := []nestedStep{ newMockNormalStep(), newMockFailStep(), newMockNormalStep(), } l := len(todoSteps) for i := 0; i < l; i++ { undoTask.AddStep(todoSteps[i], undoSteps[i]) } err := undoTask.Execute(context.Background()) assert.Error(t, err) assert.True(t, todoSteps[0].(*mockNormalStep).called) assert.True(t, todoSteps[1].(*mockNormalStep).called) assert.True(t, todoSteps[2].(*mockFailStep).called) assert.False(t, undoSteps[0].(*mockNormalStep).called) <-undoSteps[1].(*mockFailStep).calledChan assert.True(t, undoSteps[1].(*mockFailStep).called) assert.False(t, undoSteps[2].(*mockNormalStep).called) }) }