github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/process/upgrade_kyma/manager_test.go (about)

     1  package upgrade_kyma
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/kyma-project/kyma-environment-broker/internal"
    12  	"github.com/kyma-project/kyma-environment-broker/internal/event"
    13  	"github.com/kyma-project/kyma-environment-broker/internal/fixture"
    14  	"github.com/kyma-project/kyma-environment-broker/internal/process"
    15  	"github.com/kyma-project/kyma-environment-broker/internal/storage"
    16  	"github.com/pivotal-cf/brokerapi/v8/domain"
    17  	"github.com/sirupsen/logrus"
    18  	"github.com/stretchr/testify/assert"
    19  	"k8s.io/apimachinery/pkg/util/wait"
    20  )
    21  
    22  const (
    23  	operationIDSuccess = "5b954fa8-fc34-4164-96e9-49e3b6741278"
    24  	operationIDFailed  = "69b8ee2b-5c21-4997-9070-4fd356b24c46"
    25  	operationIDRepeat  = "ca317a1e-ddab-44d2-b2ba-7bbd9df9066f"
    26  	operationIDPanic   = "8ffadf20-5fe6-410b-93ce-9d00088e1e17"
    27  )
    28  
    29  func TestManager_Execute(t *testing.T) {
    30  	for name, tc := range map[string]struct {
    31  		operationID            string
    32  		expectedError          bool
    33  		expectedRepeat         time.Duration
    34  		expectedDesc           string
    35  		expectedNumberOfEvents int
    36  	}{
    37  		"operation successful": {
    38  			operationID:            operationIDSuccess,
    39  			expectedError:          false,
    40  			expectedRepeat:         time.Duration(0),
    41  			expectedDesc:           "init one two final",
    42  			expectedNumberOfEvents: 4,
    43  		},
    44  		"operation failed": {
    45  			operationID:            operationIDFailed,
    46  			expectedError:          true,
    47  			expectedNumberOfEvents: 1,
    48  		},
    49  		"operation panicked": {
    50  			operationID:            operationIDPanic,
    51  			expectedError:          true,
    52  			expectedNumberOfEvents: 0,
    53  		},
    54  		"operation repeated": {
    55  			operationID:            operationIDRepeat,
    56  			expectedError:          false,
    57  			expectedRepeat:         time.Duration(10),
    58  			expectedDesc:           "init",
    59  			expectedNumberOfEvents: 1,
    60  		},
    61  	} {
    62  		t.Run(name, func(t *testing.T) {
    63  			// given
    64  			log := logrus.New()
    65  			memoryStorage := storage.NewMemoryStorage()
    66  			operations := memoryStorage.Operations()
    67  			err := operations.InsertUpgradeKymaOperation(fixOperation(tc.operationID))
    68  			assert.NoError(t, err)
    69  
    70  			sInit := testStep{t: t, name: "init", storage: operations}
    71  			s1 := testStep{t: t, name: "one", storage: operations}
    72  			s2 := testStep{t: t, name: "two", storage: operations}
    73  			sFinal := testStep{t: t, name: "final", storage: operations}
    74  
    75  			eventBroker := event.NewPubSub(logrus.New())
    76  			eventCollector := &collectingEventHandler{}
    77  			eventBroker.Subscribe(process.UpgradeKymaStepProcessed{}, eventCollector.OnEvent)
    78  
    79  			manager := NewManager(operations, eventBroker, log)
    80  			manager.InitStep(&sInit)
    81  
    82  			manager.AddStep(2, &sFinal, nil)
    83  			manager.AddStep(1, &s1, nil)
    84  			manager.AddStep(1, &s2, nil)
    85  
    86  			// when
    87  			repeat, err := manager.Execute(tc.operationID)
    88  
    89  			// then
    90  			if tc.expectedError {
    91  				assert.Error(t, err)
    92  			} else {
    93  				assert.NoError(t, err)
    94  				assert.Equal(t, tc.expectedRepeat, repeat)
    95  
    96  				operation, err := operations.GetOperationByID(tc.operationID)
    97  				assert.NoError(t, err)
    98  				assert.Equal(t, tc.expectedDesc, strings.Trim(operation.Description, " "))
    99  			}
   100  			assert.NoError(t, wait.PollImmediate(20*time.Millisecond, 2*time.Second, func() (bool, error) {
   101  				return len(eventCollector.Events) == tc.expectedNumberOfEvents, nil
   102  			}))
   103  		})
   104  	}
   105  }
   106  
   107  func fixOperation(ID string) internal.UpgradeKymaOperation {
   108  	upgradeOperation := fixture.FixUpgradeKymaOperation(ID, "fea2c1a1-139d-43f6-910a-a618828a79d5")
   109  	upgradeOperation.State = domain.InProgress
   110  	upgradeOperation.Description = ""
   111  
   112  	return upgradeOperation
   113  }
   114  
   115  type testStep struct {
   116  	t       *testing.T
   117  	name    string
   118  	storage storage.Operations
   119  }
   120  
   121  func (ts *testStep) Name() string {
   122  	return ts.name
   123  }
   124  
   125  func (ts *testStep) Run(operation internal.UpgradeKymaOperation, logger logrus.FieldLogger) (internal.UpgradeKymaOperation, time.Duration, error) {
   126  	logger.Infof("inside %s step", ts.name)
   127  
   128  	operation.Description = fmt.Sprintf("%s %s", operation.Description, ts.name)
   129  	updated, err := ts.storage.UpdateUpgradeKymaOperation(operation)
   130  	if err != nil {
   131  		ts.t.Error(err)
   132  	}
   133  
   134  	switch operation.Operation.ID {
   135  	case operationIDFailed:
   136  		return *updated, 0, fmt.Errorf("operation %s failed", operation.Operation.ID)
   137  	case operationIDRepeat:
   138  		return *updated, time.Duration(10), nil
   139  	case operationIDPanic:
   140  		panic("panic during operation")
   141  	default:
   142  		return *updated, 0, nil
   143  	}
   144  }
   145  
   146  type collectingEventHandler struct {
   147  	mu     sync.Mutex
   148  	Events []interface{}
   149  }
   150  
   151  func (h *collectingEventHandler) OnEvent(ctx context.Context, ev interface{}) error {
   152  	h.mu.Lock()
   153  	defer h.mu.Unlock()
   154  
   155  	h.Events = append(h.Events, ev)
   156  	return nil
   157  }