github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/formation/asa_engine_test.go (about)

     1  package formation_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/kyma-incubator/compass/components/director/internal/domain/formation"
     7  	"github.com/kyma-incubator/compass/components/director/internal/domain/formation/automock"
     8  	"github.com/kyma-incubator/compass/components/director/internal/model"
     9  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    10  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    11  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    12  	"github.com/pkg/errors"
    13  	"github.com/stretchr/testify/mock"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestService_EnsureScenarioAssigned(t *testing.T) {
    18  	ctx := fixCtxWithTenant()
    19  
    20  	testErr := errors.New("test err")
    21  
    22  	rtmIDs := []string{"123", "456", "789"}
    23  	rtmNames := []string{"first", "second", "third"}
    24  
    25  	runtimes := []*model.Runtime{
    26  		{
    27  			ID:   rtmIDs[0],
    28  			Name: rtmNames[0],
    29  		},
    30  		{
    31  			ID:   rtmIDs[1],
    32  			Name: rtmNames[1],
    33  		},
    34  		{
    35  			ID:   rtmIDs[2],
    36  			Name: rtmNames[2],
    37  		},
    38  	}
    39  
    40  	ownedRuntimes := []*model.Runtime{runtimes[0], runtimes[1]}
    41  
    42  	rtmContexts := []*model.RuntimeContext{
    43  		{
    44  			ID:        "1",
    45  			RuntimeID: rtmIDs[0],
    46  			Key:       "test",
    47  			Value:     "test",
    48  		},
    49  		{
    50  			ID:        "2",
    51  			RuntimeID: rtmIDs[2],
    52  			Key:       "test",
    53  			Value:     "test",
    54  		},
    55  	}
    56  
    57  	tnt := tenantID.String()
    58  	testFormation := fixModel(testFormationName)
    59  
    60  	testCases := []struct {
    61  		Name                          string
    62  		RuntimeRepoFN                 func() *automock.RuntimeRepository
    63  		RuntimeContextRepoFn          func() *automock.RuntimeContextRepository
    64  		FormationRepositoryFn         func() *automock.FormationRepository
    65  		FormationTemplateRepositoryFn func() *automock.FormationTemplateRepository
    66  		ProcessFunc                   func() *automock.ProcessFunc
    67  		InputASA                      model.AutomaticScenarioAssignment
    68  		ExpectedErrMessage            string
    69  	}{
    70  		{
    71  			Name: "Success",
    72  			RuntimeRepoFN: func() *automock.RuntimeRepository {
    73  				runtimeRepo := &automock.RuntimeRepository{}
    74  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
    75  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(runtimes, nil).Once()
    76  				return runtimeRepo
    77  			},
    78  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
    79  				runtimeContextRepo := &automock.RuntimeContextRepository{}
    80  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
    81  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
    82  
    83  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(rtmContexts[0], nil).Once()
    84  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(nil, apperrors.NewNotFoundError(resource.RuntimeContext, rtmContexts[0].ID)).Once()
    85  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[2]).Return(rtmContexts[1], nil).Once()
    86  
    87  				return runtimeContextRepo
    88  			},
    89  			FormationRepositoryFn: func() *automock.FormationRepository {
    90  				repo := &automock.FormationRepository{}
    91  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
    92  				return repo
    93  			},
    94  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
    95  				repo := &automock.FormationTemplateRepository{}
    96  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
    97  				return repo
    98  			},
    99  			ProcessFunc: func() *automock.ProcessFunc {
   100  				f := &automock.ProcessFunc{}
   101  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   102  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, rtmContexts[0].ID, graphql.FormationObjectTypeRuntimeContext, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   103  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, rtmContexts[1].ID, graphql.FormationObjectTypeRuntimeContext, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   104  				return f
   105  			},
   106  			InputASA:           fixModel(testFormationName),
   107  			ExpectedErrMessage: "",
   108  		},
   109  		{
   110  			Name:                 "Returns error getting formation by name fails",
   111  			RuntimeRepoFN:        unusedRuntimeRepo,
   112  			RuntimeContextRepoFn: unusedRuntimeContextRepo,
   113  			FormationRepositoryFn: func() *automock.FormationRepository {
   114  				repo := &automock.FormationRepository{}
   115  				repo.On("GetByName", ctx, testFormationName, tnt).Return(nil, testErr).Times(1)
   116  				return repo
   117  			},
   118  			FormationTemplateRepositoryFn: unusedFormationTemplateRepo,
   119  			InputASA:                      fixModel(testFormationName),
   120  			ExpectedErrMessage:            testErr.Error(),
   121  		},
   122  		{
   123  			Name:                 "Returns error getting formation template by ID fails",
   124  			RuntimeRepoFN:        unusedRuntimeRepo,
   125  			RuntimeContextRepoFn: unusedRuntimeContextRepo,
   126  			FormationRepositoryFn: func() *automock.FormationRepository {
   127  				repo := &automock.FormationRepository{}
   128  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Times(1)
   129  				return repo
   130  			},
   131  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   132  				repo := &automock.FormationTemplateRepository{}
   133  				repo.On("Get", ctx, FormationTemplateID).Return(nil, testErr).Once()
   134  				return repo
   135  			},
   136  			InputASA:           fixModel(testFormationName),
   137  			ExpectedErrMessage: testErr.Error(),
   138  		},
   139  		{
   140  			Name: "Returns error when listing owned runtimes fails",
   141  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   142  				runtimeRepo := &automock.RuntimeRepository{}
   143  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(nil, testErr).Once()
   144  				return runtimeRepo
   145  			},
   146  			RuntimeContextRepoFn: unusedRuntimeContextRepo,
   147  			FormationRepositoryFn: func() *automock.FormationRepository {
   148  				repo := &automock.FormationRepository{}
   149  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Times(1)
   150  				return repo
   151  			},
   152  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   153  				repo := &automock.FormationTemplateRepository{}
   154  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   155  				return repo
   156  			},
   157  			InputASA:           fixModel(testFormationName),
   158  			ExpectedErrMessage: testErr.Error(),
   159  		},
   160  		{
   161  			Name: "Returns error when checking if runtime exists by id fails",
   162  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   163  				runtimeRepo := &automock.RuntimeRepository{}
   164  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   165  				return runtimeRepo
   166  			},
   167  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   168  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   169  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, testErr).Once()
   170  				return runtimeContextRepo
   171  			},
   172  			FormationRepositoryFn: func() *automock.FormationRepository {
   173  				repo := &automock.FormationRepository{}
   174  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Times(1)
   175  				return repo
   176  			},
   177  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   178  				repo := &automock.FormationTemplateRepository{}
   179  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   180  				return repo
   181  			},
   182  			InputASA:           fixModel(testFormationName),
   183  			ExpectedErrMessage: testErr.Error(),
   184  		},
   185  		{
   186  			Name: "Returns error when assigning runtime to formation fails",
   187  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   188  				runtimeRepo := &automock.RuntimeRepository{}
   189  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   190  				return runtimeRepo
   191  			},
   192  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   193  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   194  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   195  				return runtimeContextRepo
   196  			},
   197  			FormationRepositoryFn: func() *automock.FormationRepository {
   198  				repo := &automock.FormationRepository{}
   199  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   200  				return repo
   201  			},
   202  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   203  				repo := &automock.FormationTemplateRepository{}
   204  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   205  				return repo
   206  			},
   207  			ProcessFunc: func() *automock.ProcessFunc {
   208  				f := &automock.ProcessFunc{}
   209  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, testErr).Once()
   210  				return f
   211  			},
   212  			InputASA:           fixModel(testFormationName),
   213  			ExpectedErrMessage: testErr.Error(),
   214  		},
   215  		{
   216  			Name: "Returns error when listing all runtimes fails",
   217  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   218  				runtimeRepo := &automock.RuntimeRepository{}
   219  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   220  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(nil, testErr).Once()
   221  				return runtimeRepo
   222  			},
   223  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   224  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   225  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   226  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
   227  
   228  				return runtimeContextRepo
   229  			},
   230  			FormationRepositoryFn: func() *automock.FormationRepository {
   231  				repo := &automock.FormationRepository{}
   232  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   233  				return repo
   234  			},
   235  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   236  				repo := &automock.FormationTemplateRepository{}
   237  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   238  				return repo
   239  			},
   240  			ProcessFunc: func() *automock.ProcessFunc {
   241  				f := &automock.ProcessFunc{}
   242  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   243  				return f
   244  			},
   245  			InputASA:           fixModel(testFormationName),
   246  			ExpectedErrMessage: testErr.Error(),
   247  		},
   248  		{
   249  			Name: "Returns error when listing runtime contexts for runtime fails",
   250  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   251  				runtimeRepo := &automock.RuntimeRepository{}
   252  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   253  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(runtimes, nil).Once()
   254  				return runtimeRepo
   255  			},
   256  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   257  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   258  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   259  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
   260  
   261  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(nil, testErr).Once()
   262  
   263  				return runtimeContextRepo
   264  			},
   265  			FormationRepositoryFn: func() *automock.FormationRepository {
   266  				repo := &automock.FormationRepository{}
   267  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   268  				return repo
   269  			},
   270  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   271  				repo := &automock.FormationTemplateRepository{}
   272  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   273  				return repo
   274  			},
   275  			ProcessFunc: func() *automock.ProcessFunc {
   276  				f := &automock.ProcessFunc{}
   277  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   278  				return f
   279  			},
   280  			InputASA:           fixModel(testFormationName),
   281  			ExpectedErrMessage: testErr.Error(),
   282  		},
   283  		{
   284  			Name: "Returns error when assigning runtime context to formation fails",
   285  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   286  				runtimeRepo := &automock.RuntimeRepository{}
   287  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   288  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(runtimes, nil).Once()
   289  				return runtimeRepo
   290  			},
   291  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   292  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   293  
   294  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   295  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
   296  
   297  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(rtmContexts[0], nil).Once()
   298  				return runtimeContextRepo
   299  			},
   300  			FormationRepositoryFn: func() *automock.FormationRepository {
   301  				repo := &automock.FormationRepository{}
   302  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   303  				return repo
   304  			},
   305  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   306  				repo := &automock.FormationTemplateRepository{}
   307  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   308  				return repo
   309  			},
   310  			ProcessFunc: func() *automock.ProcessFunc {
   311  				f := &automock.ProcessFunc{}
   312  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   313  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, rtmContexts[0].ID, graphql.FormationObjectTypeRuntimeContext, model.Formation{Name: testFormation.ScenarioName}).Return(nil, testErr).Once()
   314  				return f
   315  			},
   316  			InputASA:           fixModel(testFormationName),
   317  			ExpectedErrMessage: testErr.Error(),
   318  		},
   319  	}
   320  	for _, testCase := range testCases {
   321  		t.Run(testCase.Name, func(t *testing.T) {
   322  			// GIVEN
   323  			runtimeRepo := unusedRuntimeRepo()
   324  			if testCase.RuntimeRepoFN != nil {
   325  				runtimeRepo = testCase.RuntimeRepoFN()
   326  			}
   327  			runtimeContextRepo := unusedRuntimeContextRepo()
   328  			if testCase.RuntimeContextRepoFn != nil {
   329  				runtimeContextRepo = testCase.RuntimeContextRepoFn()
   330  			}
   331  			formationRepo := unusedFormationRepo()
   332  			if testCase.FormationRepositoryFn != nil {
   333  				formationRepo = testCase.FormationRepositoryFn()
   334  			}
   335  			formationTemplateRepo := unusedFormationTemplateRepo()
   336  			if testCase.FormationTemplateRepositoryFn != nil {
   337  				formationTemplateRepo = testCase.FormationTemplateRepositoryFn()
   338  			}
   339  			processFuncMock := unusedProcessFunc()
   340  			if testCase.ProcessFunc != nil {
   341  				processFuncMock = testCase.ProcessFunc()
   342  			}
   343  
   344  			svc := formation.NewASAEngine(nil, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo, runtimeType, applicationType)
   345  
   346  			// WHEN
   347  			err := svc.EnsureScenarioAssigned(ctx, testCase.InputASA, processFuncMock.ProcessScenarioFunc)
   348  
   349  			// THEN
   350  			if testCase.ExpectedErrMessage == "" {
   351  				require.NoError(t, err)
   352  			} else {
   353  				require.Error(t, err)
   354  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   355  			}
   356  
   357  			mock.AssertExpectationsForObjects(t, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo, processFuncMock)
   358  		})
   359  	}
   360  }
   361  
   362  func TestService_RemoveAssignedScenario(t *testing.T) {
   363  	ctx := fixCtxWithTenant()
   364  
   365  	testErr := errors.New("test err")
   366  
   367  	rtmIDs := []string{"123", "456", "789"}
   368  	rtmNames := []string{"first", "second", "third"}
   369  
   370  	runtimes := []*model.Runtime{
   371  		{
   372  			ID:   rtmIDs[0],
   373  			Name: rtmNames[0],
   374  		},
   375  		{
   376  			ID:   rtmIDs[1],
   377  			Name: rtmNames[1],
   378  		},
   379  		{
   380  			ID:   rtmIDs[2],
   381  			Name: rtmNames[2],
   382  		},
   383  	}
   384  	ownedRuntimes := []*model.Runtime{runtimes[0], runtimes[1]}
   385  
   386  	rtmContexts := []*model.RuntimeContext{
   387  		{
   388  			ID:        "1",
   389  			RuntimeID: rtmIDs[0],
   390  			Key:       "test",
   391  			Value:     "test",
   392  		},
   393  		{
   394  			ID:        "2",
   395  			RuntimeID: rtmIDs[2],
   396  			Key:       "test",
   397  			Value:     "test",
   398  		},
   399  	}
   400  
   401  	tnt := tenantID.String()
   402  	testFormation := fixModel(testFormationName)
   403  
   404  	testCases := []struct {
   405  		Name                          string
   406  		RuntimeRepoFN                 func() *automock.RuntimeRepository
   407  		RuntimeContextRepoFn          func() *automock.RuntimeContextRepository
   408  		FormationRepositoryFn         func() *automock.FormationRepository
   409  		FormationTemplateRepositoryFn func() *automock.FormationTemplateRepository
   410  		ProcessFunc                   func() *automock.ProcessFunc
   411  		InputASA                      model.AutomaticScenarioAssignment
   412  		ExpectedErrMessage            string
   413  	}{
   414  		{
   415  			Name: "Success",
   416  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   417  				runtimeRepo := &automock.RuntimeRepository{}
   418  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   419  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(runtimes, nil).Once()
   420  				return runtimeRepo
   421  			},
   422  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   423  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   424  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   425  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
   426  
   427  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(rtmContexts[0], nil).Once()
   428  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(nil, apperrors.NewNotFoundError(resource.RuntimeContext, rtmContexts[0].ID)).Once()
   429  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[2]).Return(rtmContexts[1], nil).Once()
   430  
   431  				return runtimeContextRepo
   432  			},
   433  			FormationRepositoryFn: func() *automock.FormationRepository {
   434  				repo := &automock.FormationRepository{}
   435  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   436  				return repo
   437  			},
   438  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   439  				repo := &automock.FormationTemplateRepository{}
   440  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   441  				return repo
   442  			},
   443  			ProcessFunc: func() *automock.ProcessFunc {
   444  				f := &automock.ProcessFunc{}
   445  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   446  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, rtmContexts[0].ID, graphql.FormationObjectTypeRuntimeContext, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   447  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, rtmContexts[1].ID, graphql.FormationObjectTypeRuntimeContext, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   448  				return f
   449  			},
   450  			InputASA:           fixModel(testFormationName),
   451  			ExpectedErrMessage: "",
   452  		},
   453  		{
   454  			Name: "Returns error when processing scenarios for runtime context fails",
   455  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   456  				runtimeRepo := &automock.RuntimeRepository{}
   457  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   458  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(runtimes, nil).Once()
   459  
   460  				return runtimeRepo
   461  			},
   462  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   463  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   464  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   465  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
   466  
   467  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(rtmContexts[0], nil).Once()
   468  
   469  				return runtimeContextRepo
   470  			},
   471  			FormationRepositoryFn: func() *automock.FormationRepository {
   472  				repo := &automock.FormationRepository{}
   473  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   474  				return repo
   475  			},
   476  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   477  				repo := &automock.FormationTemplateRepository{}
   478  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   479  				return repo
   480  			},
   481  			ProcessFunc: func() *automock.ProcessFunc {
   482  				f := &automock.ProcessFunc{}
   483  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   484  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, rtmContexts[0].ID, graphql.FormationObjectTypeRuntimeContext, model.Formation{Name: testFormation.ScenarioName}).Return(nil, testErr).Once()
   485  				return f
   486  			},
   487  			InputASA:           fixModel(testFormationName),
   488  			ExpectedErrMessage: testErr.Error(),
   489  		},
   490  		{
   491  			Name: "Returns error when getting runtime context for runtime fails",
   492  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   493  				runtimeRepo := &automock.RuntimeRepository{}
   494  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   495  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(runtimes, nil).Once()
   496  				return runtimeRepo
   497  			},
   498  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   499  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   500  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   501  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
   502  
   503  				runtimeContextRepo.On("GetByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(nil, testErr).Once()
   504  
   505  				return runtimeContextRepo
   506  			},
   507  			FormationRepositoryFn: func() *automock.FormationRepository {
   508  				repo := &automock.FormationRepository{}
   509  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   510  				return repo
   511  			},
   512  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   513  				repo := &automock.FormationTemplateRepository{}
   514  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   515  				return repo
   516  			},
   517  			ProcessFunc: func() *automock.ProcessFunc {
   518  				f := &automock.ProcessFunc{}
   519  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   520  				return f
   521  			},
   522  			InputASA:           fixModel(testFormationName),
   523  			ExpectedErrMessage: testErr.Error(),
   524  		},
   525  		{
   526  			Name: "Returns error when listing all runtimes fails",
   527  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   528  				runtimeRepo := &automock.RuntimeRepository{}
   529  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   530  				runtimeRepo.On("ListAllWithUnionSetCombination", ctx, TargetTenantID, runtimeLblFilters).Return(nil, testErr).Once()
   531  				return runtimeRepo
   532  			},
   533  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   534  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   535  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   536  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[1]).Return(true, nil).Once()
   537  
   538  				return runtimeContextRepo
   539  			},
   540  			FormationRepositoryFn: func() *automock.FormationRepository {
   541  				repo := &automock.FormationRepository{}
   542  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   543  				return repo
   544  			},
   545  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   546  				repo := &automock.FormationTemplateRepository{}
   547  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   548  				return repo
   549  			},
   550  			ProcessFunc: func() *automock.ProcessFunc {
   551  				f := &automock.ProcessFunc{}
   552  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, nil).Once()
   553  				return f
   554  			},
   555  			InputASA:           fixModel(testFormationName),
   556  			ExpectedErrMessage: testErr.Error(),
   557  		},
   558  		{
   559  			Name: "Returns error when processing scenarios for runtime fails",
   560  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   561  				runtimeRepo := &automock.RuntimeRepository{}
   562  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   563  				return runtimeRepo
   564  			},
   565  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   566  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   567  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, nil).Once()
   568  				return runtimeContextRepo
   569  			},
   570  			FormationRepositoryFn: func() *automock.FormationRepository {
   571  				repo := &automock.FormationRepository{}
   572  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   573  				return repo
   574  			},
   575  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   576  				repo := &automock.FormationTemplateRepository{}
   577  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   578  				return repo
   579  			},
   580  			ProcessFunc: func() *automock.ProcessFunc {
   581  				f := &automock.ProcessFunc{}
   582  				f.On("ProcessScenarioFunc", ctx, testFormation.Tenant, ownedRuntimes[0].ID, graphql.FormationObjectTypeRuntime, model.Formation{Name: testFormation.ScenarioName}).Return(nil, testErr).Once()
   583  				return f
   584  			},
   585  			InputASA:           fixModel(testFormationName),
   586  			ExpectedErrMessage: testErr.Error(),
   587  		},
   588  		{
   589  			Name: "Returns error when checking if runtime context exists by parent runtime id fails",
   590  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   591  				runtimeRepo := &automock.RuntimeRepository{}
   592  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(ownedRuntimes, nil).Once()
   593  				return runtimeRepo
   594  			},
   595  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   596  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   597  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, rtmIDs[0]).Return(false, testErr).Once()
   598  				return runtimeContextRepo
   599  			},
   600  			FormationRepositoryFn: func() *automock.FormationRepository {
   601  				repo := &automock.FormationRepository{}
   602  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   603  				return repo
   604  			},
   605  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   606  				repo := &automock.FormationTemplateRepository{}
   607  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   608  				return repo
   609  			},
   610  			InputASA:           fixModel(testFormationName),
   611  			ExpectedErrMessage: testErr.Error(),
   612  		},
   613  		{
   614  			Name: "Returns error when listing owned runtimes fails",
   615  			RuntimeRepoFN: func() *automock.RuntimeRepository {
   616  				runtimeRepo := &automock.RuntimeRepository{}
   617  				runtimeRepo.On("ListOwnedRuntimes", ctx, TargetTenantID, runtimeLblFilters).Return(nil, testErr).Once()
   618  				return runtimeRepo
   619  			},
   620  			FormationRepositoryFn: func() *automock.FormationRepository {
   621  				repo := &automock.FormationRepository{}
   622  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   623  				return repo
   624  			},
   625  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   626  				repo := &automock.FormationTemplateRepository{}
   627  				repo.On("Get", ctx, FormationTemplateID).Return(&formationTemplate, nil).Once()
   628  				return repo
   629  			},
   630  			InputASA:           fixModel(testFormationName),
   631  			ExpectedErrMessage: testErr.Error(),
   632  		},
   633  		{
   634  			Name: "Returns error when getting formation template by id fails",
   635  			FormationRepositoryFn: func() *automock.FormationRepository {
   636  				repo := &automock.FormationRepository{}
   637  				repo.On("GetByName", ctx, testFormationName, tnt).Return(&modelFormation, nil).Once()
   638  				return repo
   639  			},
   640  			FormationTemplateRepositoryFn: func() *automock.FormationTemplateRepository {
   641  				repo := &automock.FormationTemplateRepository{}
   642  				repo.On("Get", ctx, FormationTemplateID).Return(nil, testErr).Once()
   643  				return repo
   644  			},
   645  			InputASA:           fixModel(testFormationName),
   646  			ExpectedErrMessage: testErr.Error(),
   647  		},
   648  		{
   649  			Name: "Returns error when getting formation by name fails",
   650  			FormationRepositoryFn: func() *automock.FormationRepository {
   651  				repo := &automock.FormationRepository{}
   652  				repo.On("GetByName", ctx, testFormationName, tnt).Return(nil, testErr).Once()
   653  				return repo
   654  			},
   655  			InputASA:           fixModel(testFormationName),
   656  			ExpectedErrMessage: testErr.Error(),
   657  		},
   658  	}
   659  	for _, testCase := range testCases {
   660  		t.Run(testCase.Name, func(t *testing.T) {
   661  			// GIVEN
   662  			runtimeRepo := unusedRuntimeRepo()
   663  			if testCase.RuntimeRepoFN != nil {
   664  				runtimeRepo = testCase.RuntimeRepoFN()
   665  			}
   666  			runtimeContextRepo := unusedRuntimeContextRepo()
   667  			if testCase.RuntimeContextRepoFn != nil {
   668  				runtimeContextRepo = testCase.RuntimeContextRepoFn()
   669  			}
   670  			formationRepo := unusedFormationRepo()
   671  			if testCase.FormationRepositoryFn != nil {
   672  				formationRepo = testCase.FormationRepositoryFn()
   673  			}
   674  			formationTemplateRepo := unusedFormationTemplateRepo()
   675  			if testCase.FormationTemplateRepositoryFn != nil {
   676  				formationTemplateRepo = testCase.FormationTemplateRepositoryFn()
   677  			}
   678  			processFuncMock := unusedProcessFunc()
   679  			if testCase.ProcessFunc != nil {
   680  				processFuncMock = testCase.ProcessFunc()
   681  			}
   682  			svc := formation.NewASAEngine(nil, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo, runtimeType, applicationType)
   683  
   684  			// WHEN
   685  			err := svc.RemoveAssignedScenario(ctx, testCase.InputASA, processFuncMock.ProcessScenarioFunc)
   686  
   687  			// THEN
   688  			if testCase.ExpectedErrMessage == "" {
   689  				require.NoError(t, err)
   690  			} else {
   691  				require.Error(t, err)
   692  				require.Contains(t, err.Error(), testCase.ExpectedErrMessage)
   693  			}
   694  
   695  			mock.AssertExpectationsForObjects(t, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo, processFuncMock)
   696  		})
   697  	}
   698  }
   699  
   700  func TestService_GetScenariosFromMatchingASAs(t *testing.T) {
   701  	ctx := fixCtxWithTenant()
   702  	runtimeID := "runtimeID"
   703  	runtimeID2 := "runtimeID2"
   704  
   705  	testErr := errors.New(ErrMsg)
   706  	notFoudErr := apperrors.NewNotFoundError(resource.Runtime, runtimeID2)
   707  
   708  	testScenarios := []*model.AutomaticScenarioAssignment{
   709  		{
   710  			ScenarioName:   ScenarioName,
   711  			Tenant:         tenantID.String(),
   712  			TargetTenantID: TargetTenantID,
   713  		},
   714  		{
   715  			ScenarioName:   ScenarioName2,
   716  			Tenant:         TenantID2,
   717  			TargetTenantID: TargetTenantID2,
   718  		},
   719  	}
   720  
   721  	formations := []*model.Formation{
   722  		{
   723  			ID:                  FormationID,
   724  			TenantID:            tenantID.String(),
   725  			FormationTemplateID: FormationTemplateID,
   726  			Name:                ScenarioName,
   727  		},
   728  		{
   729  			ID:                  FormationID,
   730  			TenantID:            tenantID.String(),
   731  			FormationTemplateID: FormationTemplateID,
   732  			Name:                ScenarioName2,
   733  		},
   734  	}
   735  
   736  	rtmCtx := &model.RuntimeContext{
   737  		ID:        RuntimeContextID,
   738  		Key:       "subscription",
   739  		Value:     "subscriptionValue",
   740  		RuntimeID: runtimeID,
   741  	}
   742  
   743  	rtmCtx2 := &model.RuntimeContext{
   744  		ID:        RuntimeContextID,
   745  		Key:       "subscription",
   746  		Value:     "subscriptionValue",
   747  		RuntimeID: runtimeID2,
   748  	}
   749  
   750  	testCases := []struct {
   751  		Name                     string
   752  		ScenarioAssignmentRepoFn func() *automock.AutomaticFormationAssignmentRepository
   753  		RuntimeRepoFn            func() *automock.RuntimeRepository
   754  		RuntimeContextRepoFn     func() *automock.RuntimeContextRepository
   755  		FormationRepoFn          func() *automock.FormationRepository
   756  		FormationTemplateRepoFn  func() *automock.FormationTemplateRepository
   757  		ObjectID                 string
   758  		ObjectType               graphql.FormationObjectType
   759  		ExpectedErrorMessage     string
   760  		ExpectedScenarios        []string
   761  	}{
   762  		{
   763  			Name: "Success for runtime",
   764  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   765  				repo := &automock.AutomaticFormationAssignmentRepository{}
   766  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   767  				return repo
   768  			},
   769  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   770  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   771  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, RuntimeID).Return(false, nil).Once()
   772  				return runtimeContextRepo
   773  			},
   774  			RuntimeRepoFn: func() *automock.RuntimeRepository {
   775  				runtimeRepo := &automock.RuntimeRepository{}
   776  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[0].TargetTenantID, RuntimeID, runtimeLblFilters).Return(true, nil).Once()
   777  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[1].TargetTenantID, RuntimeID, runtimeLblFilters).Return(false, nil).Once()
   778  				return runtimeRepo
   779  			},
   780  			FormationRepoFn: func() *automock.FormationRepository {
   781  				formationRepo := &automock.FormationRepository{}
   782  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
   783  				formationRepo.On("GetByName", ctx, ScenarioName2, testScenarios[1].Tenant).Return(formations[1], nil).Once()
   784  				return formationRepo
   785  			},
   786  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   787  				formationTemplateRepo := &automock.FormationTemplateRepository{}
   788  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
   789  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
   790  				return formationTemplateRepo
   791  			},
   792  			ObjectID:             RuntimeID,
   793  			ObjectType:           graphql.FormationObjectTypeRuntime,
   794  			ExpectedErrorMessage: "",
   795  			ExpectedScenarios:    []string{ScenarioName},
   796  		},
   797  		{
   798  			Name: "Success for runtime context",
   799  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   800  				repo := &automock.AutomaticFormationAssignmentRepository{}
   801  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   802  				return repo
   803  			},
   804  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   805  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   806  				runtimeContextRepo.On("GetByID", ctx, testScenarios[0].TargetTenantID, RuntimeContextID).Return(rtmCtx, nil).Once()
   807  				runtimeContextRepo.On("GetByID", ctx, testScenarios[1].TargetTenantID, RuntimeContextID).Return(rtmCtx2, nil).Once()
   808  				return runtimeContextRepo
   809  			},
   810  			RuntimeRepoFn: func() *automock.RuntimeRepository {
   811  				runtimeRepo := &automock.RuntimeRepository{}
   812  				runtimeRepo.On("GetByFiltersAndIDUsingUnion", ctx, testScenarios[0].TargetTenantID, rtmCtx.RuntimeID, runtimeLblFilters).Return(&model.Runtime{}, nil).Once()
   813  				runtimeRepo.On("GetByFiltersAndIDUsingUnion", ctx, testScenarios[1].TargetTenantID, rtmCtx2.RuntimeID, runtimeLblFilters).Return(nil, notFoudErr).Once()
   814  				return runtimeRepo
   815  			},
   816  			FormationRepoFn: func() *automock.FormationRepository {
   817  				formationRepo := &automock.FormationRepository{}
   818  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
   819  				formationRepo.On("GetByName", ctx, ScenarioName2, testScenarios[1].Tenant).Return(formations[1], nil).Once()
   820  				return formationRepo
   821  			},
   822  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   823  				formationTemplateRepo := &automock.FormationTemplateRepository{}
   824  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
   825  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
   826  				return formationTemplateRepo
   827  			},
   828  			ObjectID:             RuntimeContextID,
   829  			ObjectType:           graphql.FormationObjectTypeRuntimeContext,
   830  			ExpectedErrorMessage: "",
   831  			ExpectedScenarios:    []string{ScenarioName},
   832  		},
   833  		{
   834  			Name: "Returns an error when getting runtime contexts",
   835  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   836  				repo := &automock.AutomaticFormationAssignmentRepository{}
   837  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   838  				return repo
   839  			},
   840  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   841  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   842  				runtimeContextRepo.On("GetByID", ctx, testScenarios[0].TargetTenantID, RuntimeContextID).Return(nil, testErr).Once()
   843  				return runtimeContextRepo
   844  			},
   845  			FormationRepoFn: func() *automock.FormationRepository {
   846  				formationRepo := &automock.FormationRepository{}
   847  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
   848  				return formationRepo
   849  			},
   850  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   851  				formationTemplateRepo := &automock.FormationTemplateRepository{}
   852  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
   853  				return formationTemplateRepo
   854  			},
   855  			ObjectID:             RuntimeContextID,
   856  			ObjectType:           graphql.FormationObjectTypeRuntimeContext,
   857  			ExpectedErrorMessage: "while getting runtime contexts with ID",
   858  			ExpectedScenarios:    nil,
   859  		},
   860  		{
   861  			Name: "Returns an not found error when getting runtime contexts",
   862  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   863  				repo := &automock.AutomaticFormationAssignmentRepository{}
   864  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   865  				return repo
   866  			},
   867  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   868  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   869  				runtimeContextRepo.On("GetByID", ctx, testScenarios[0].TargetTenantID, RuntimeContextID).Return(nil, notFoudErr).Once()
   870  				runtimeContextRepo.On("GetByID", ctx, testScenarios[1].TargetTenantID, RuntimeContextID).Return(nil, notFoudErr).Once()
   871  				return runtimeContextRepo
   872  			},
   873  			FormationRepoFn: func() *automock.FormationRepository {
   874  				formationRepo := &automock.FormationRepository{}
   875  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
   876  				formationRepo.On("GetByName", ctx, ScenarioName2, testScenarios[1].Tenant).Return(formations[1], nil).Once()
   877  				return formationRepo
   878  			},
   879  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   880  				formationTemplateRepo := &automock.FormationTemplateRepository{}
   881  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
   882  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
   883  				return formationTemplateRepo
   884  			},
   885  			ObjectID:             RuntimeContextID,
   886  			ObjectType:           graphql.FormationObjectTypeRuntimeContext,
   887  			ExpectedErrorMessage: "",
   888  			ExpectedScenarios:    nil,
   889  		},
   890  		{
   891  			Name: "Returns an error when getting runtime",
   892  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   893  				repo := &automock.AutomaticFormationAssignmentRepository{}
   894  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   895  				return repo
   896  			},
   897  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   898  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   899  				runtimeContextRepo.On("GetByID", ctx, testScenarios[0].TargetTenantID, RuntimeContextID).Return(rtmCtx, nil).Once()
   900  				return runtimeContextRepo
   901  			},
   902  			RuntimeRepoFn: func() *automock.RuntimeRepository {
   903  				runtimeRepo := &automock.RuntimeRepository{}
   904  				runtimeRepo.On("GetByFiltersAndIDUsingUnion", ctx, testScenarios[0].TargetTenantID, rtmCtx.RuntimeID, runtimeLblFilters).Return(nil, testErr).Once()
   905  				return runtimeRepo
   906  			},
   907  			FormationRepoFn: func() *automock.FormationRepository {
   908  				formationRepo := &automock.FormationRepository{}
   909  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
   910  				return formationRepo
   911  			},
   912  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   913  				formationTemplateRepo := &automock.FormationTemplateRepository{}
   914  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
   915  				return formationTemplateRepo
   916  			},
   917  			ObjectID:             RuntimeContextID,
   918  			ObjectType:           graphql.FormationObjectTypeRuntimeContext,
   919  			ExpectedErrorMessage: "while getting runtime with ID:",
   920  			ExpectedScenarios:    nil,
   921  		},
   922  		{
   923  			Name: "Returns an error when getting formations",
   924  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   925  				repo := &automock.AutomaticFormationAssignmentRepository{}
   926  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   927  				return repo
   928  			},
   929  			FormationRepoFn: func() *automock.FormationRepository {
   930  				formationRepo := &automock.FormationRepository{}
   931  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(nil, testErr).Once()
   932  				return formationRepo
   933  			},
   934  			ObjectID:             RuntimeContextID,
   935  			ObjectType:           graphql.FormationObjectTypeRuntimeContext,
   936  			ExpectedErrorMessage: "while getting formation by name",
   937  			ExpectedScenarios:    nil,
   938  		},
   939  		{
   940  			Name: "Returns error for runtime when checking if the runtime has context fails",
   941  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   942  				repo := &automock.AutomaticFormationAssignmentRepository{}
   943  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   944  				return repo
   945  			},
   946  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
   947  				runtimeContextRepo := &automock.RuntimeContextRepository{}
   948  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, RuntimeID).Return(false, testErr).Once()
   949  				return runtimeContextRepo
   950  			},
   951  			RuntimeRepoFn: func() *automock.RuntimeRepository {
   952  				runtimeRepo := &automock.RuntimeRepository{}
   953  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[0].TargetTenantID, RuntimeID, runtimeLblFilters).Return(true, nil).Once()
   954  				return runtimeRepo
   955  			},
   956  			FormationRepoFn: func() *automock.FormationRepository {
   957  				formationRepo := &automock.FormationRepository{}
   958  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
   959  				return formationRepo
   960  			},
   961  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   962  				formationTemplateRepo := &automock.FormationTemplateRepository{}
   963  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
   964  				return formationTemplateRepo
   965  			},
   966  			ObjectID:             RuntimeID,
   967  			ObjectType:           graphql.FormationObjectTypeRuntime,
   968  			ExpectedErrorMessage: "while cheking runtime context existence for runtime with ID",
   969  			ExpectedScenarios:    nil,
   970  		},
   971  		{
   972  			Name: "Returns error for runtime when checking if runtime exists by filters and ID and has owner=true fails",
   973  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
   974  				repo := &automock.AutomaticFormationAssignmentRepository{}
   975  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
   976  				return repo
   977  			},
   978  			RuntimeRepoFn: func() *automock.RuntimeRepository {
   979  				runtimeRepo := &automock.RuntimeRepository{}
   980  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[0].TargetTenantID, RuntimeID, runtimeLblFilters).Return(false, testErr).Once()
   981  				return runtimeRepo
   982  			},
   983  			FormationRepoFn: func() *automock.FormationRepository {
   984  				formationRepo := &automock.FormationRepository{}
   985  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
   986  				return formationRepo
   987  			},
   988  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
   989  				formationTemplateRepo := &automock.FormationTemplateRepository{}
   990  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
   991  				return formationTemplateRepo
   992  			},
   993  			ObjectID:             RuntimeID,
   994  			ObjectType:           graphql.FormationObjectTypeRuntime,
   995  			ExpectedErrorMessage: "while checking if asa matches runtime with ID rt-id: while checking if runtime with id \"rt-id\" have owner=true: some error",
   996  			ExpectedScenarios:    nil,
   997  		},
   998  		{
   999  			Name: "Returns error for runtime when getting formation template runtime type fails",
  1000  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  1001  				repo := &automock.AutomaticFormationAssignmentRepository{}
  1002  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
  1003  				return repo
  1004  			},
  1005  			FormationRepoFn: func() *automock.FormationRepository {
  1006  				formationRepo := &automock.FormationRepository{}
  1007  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
  1008  				return formationRepo
  1009  			},
  1010  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1011  				formationTemplateRepo := &automock.FormationTemplateRepository{}
  1012  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(nil, testErr).Once()
  1013  				return formationTemplateRepo
  1014  			},
  1015  			ObjectID:             RuntimeID,
  1016  			ObjectType:           graphql.FormationObjectTypeRuntime,
  1017  			ExpectedErrorMessage: "while checking if asa matches runtime with ID rt-id: while getting formation template by id \"bda5378d-caa1-4ee4-b8bf-f733e180fbf9\"",
  1018  			ExpectedScenarios:    nil,
  1019  		},
  1020  		{
  1021  			Name: "Returns error when listing ASAs fails",
  1022  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  1023  				repo := &automock.AutomaticFormationAssignmentRepository{}
  1024  				repo.On("ListAll", ctx, tenantID.String()).Return(nil, testErr)
  1025  				return repo
  1026  			},
  1027  			ObjectID:             RuntimeID,
  1028  			ObjectType:           graphql.FormationObjectTypeRuntime,
  1029  			ExpectedErrorMessage: "while listing Automatic Scenario Assignments in tenant",
  1030  			ExpectedScenarios:    nil,
  1031  		},
  1032  		{
  1033  			Name:                 "Returns error when can't find matching func",
  1034  			ObjectID:             "",
  1035  			ObjectType:           "test",
  1036  			ExpectedErrorMessage: "unexpected formation object type \"test\"",
  1037  			ExpectedScenarios:    nil,
  1038  		},
  1039  	}
  1040  	for _, testCase := range testCases {
  1041  		t.Run(testCase.Name, func(t *testing.T) {
  1042  			// GIVEN
  1043  			asaRepo := unusedASARepo()
  1044  			if testCase.ScenarioAssignmentRepoFn != nil {
  1045  				asaRepo = testCase.ScenarioAssignmentRepoFn()
  1046  			}
  1047  			runtimeRepo := unusedRuntimeRepo()
  1048  			if testCase.RuntimeRepoFn != nil {
  1049  				runtimeRepo = testCase.RuntimeRepoFn()
  1050  			}
  1051  			runtimeContextRepo := unusedRuntimeContextRepo()
  1052  			if testCase.RuntimeContextRepoFn != nil {
  1053  				runtimeContextRepo = testCase.RuntimeContextRepoFn()
  1054  			}
  1055  			formationRepo := unusedFormationRepo()
  1056  			if testCase.FormationRepoFn != nil {
  1057  				formationRepo = testCase.FormationRepoFn()
  1058  			}
  1059  			formationTemplateRepo := unusedFormationTemplateRepo()
  1060  			if testCase.FormationTemplateRepoFn != nil {
  1061  				formationTemplateRepo = testCase.FormationTemplateRepoFn()
  1062  			}
  1063  
  1064  			svc := formation.NewASAEngine(asaRepo, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo, runtimeType, applicationType)
  1065  
  1066  			// WHEN
  1067  			scenarios, err := svc.GetScenariosFromMatchingASAs(ctx, testCase.ObjectID, testCase.ObjectType)
  1068  
  1069  			// THEN
  1070  			if testCase.ExpectedErrorMessage == "" {
  1071  				require.NoError(t, err)
  1072  				require.ElementsMatch(t, scenarios, testCase.ExpectedScenarios)
  1073  			} else {
  1074  				require.Error(t, err)
  1075  				require.Contains(t, err.Error(), testCase.ExpectedErrorMessage)
  1076  				require.Nil(t, testCase.ExpectedScenarios)
  1077  			}
  1078  
  1079  			mock.AssertExpectationsForObjects(t, asaRepo, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo)
  1080  		})
  1081  	}
  1082  }
  1083  
  1084  func TestService_IsFormationComingFromASA(t *testing.T) {
  1085  	ctx := fixCtxWithTenant()
  1086  	testScenarios := []*model.AutomaticScenarioAssignment{
  1087  		{
  1088  			ScenarioName:   ScenarioName,
  1089  			Tenant:         tenantID.String(),
  1090  			TargetTenantID: TargetTenantID,
  1091  		},
  1092  		{
  1093  			ScenarioName:   ScenarioName2,
  1094  			Tenant:         TenantID2,
  1095  			TargetTenantID: TargetTenantID2,
  1096  		},
  1097  	}
  1098  
  1099  	formations := []*model.Formation{
  1100  		{
  1101  			ID:                  FormationID,
  1102  			TenantID:            tenantID.String(),
  1103  			FormationTemplateID: FormationTemplateID,
  1104  			Name:                ScenarioName,
  1105  		},
  1106  		{
  1107  			ID:                  FormationID,
  1108  			TenantID:            tenantID.String(),
  1109  			FormationTemplateID: FormationTemplateID,
  1110  			Name:                ScenarioName2,
  1111  		},
  1112  	}
  1113  
  1114  	testCases := []struct {
  1115  		Name                     string
  1116  		ScenarioAssignmentRepoFn func() *automock.AutomaticFormationAssignmentRepository
  1117  		RuntimeRepoFn            func() *automock.RuntimeRepository
  1118  		RuntimeContextRepoFn     func() *automock.RuntimeContextRepository
  1119  		FormationRepoFn          func() *automock.FormationRepository
  1120  		FormationTemplateRepoFn  func() *automock.FormationTemplateRepository
  1121  		FormationName            string
  1122  		ObjectID                 string
  1123  		ObjectType               graphql.FormationObjectType
  1124  		ExpectedErrorMessage     string
  1125  		ExpectedResult           bool
  1126  	}{
  1127  		{
  1128  			Name: "Success formation is coming from ASA",
  1129  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  1130  				repo := &automock.AutomaticFormationAssignmentRepository{}
  1131  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
  1132  				return repo
  1133  			},
  1134  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
  1135  				runtimeContextRepo := &automock.RuntimeContextRepository{}
  1136  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, RuntimeID).Return(false, nil).Once()
  1137  				return runtimeContextRepo
  1138  			},
  1139  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  1140  				runtimeRepo := &automock.RuntimeRepository{}
  1141  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[0].TargetTenantID, RuntimeID, runtimeLblFilters).Return(true, nil).Once()
  1142  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[1].TargetTenantID, RuntimeID, runtimeLblFilters).Return(false, nil).Once()
  1143  				return runtimeRepo
  1144  			},
  1145  			FormationRepoFn: func() *automock.FormationRepository {
  1146  				formationRepo := &automock.FormationRepository{}
  1147  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
  1148  				formationRepo.On("GetByName", ctx, ScenarioName2, testScenarios[1].Tenant).Return(formations[1], nil).Once()
  1149  				return formationRepo
  1150  			},
  1151  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1152  				formationTemplateRepo := &automock.FormationTemplateRepository{}
  1153  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  1154  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
  1155  				return formationTemplateRepo
  1156  			},
  1157  			FormationName:        ScenarioName,
  1158  			ObjectID:             RuntimeID,
  1159  			ObjectType:           graphql.FormationObjectTypeRuntime,
  1160  			ExpectedErrorMessage: "",
  1161  			ExpectedResult:       true,
  1162  		},
  1163  		{
  1164  			Name: "Success formation is not coming from ASA",
  1165  			ScenarioAssignmentRepoFn: func() *automock.AutomaticFormationAssignmentRepository {
  1166  				repo := &automock.AutomaticFormationAssignmentRepository{}
  1167  				repo.On("ListAll", ctx, tenantID.String()).Return(testScenarios, nil)
  1168  				return repo
  1169  			},
  1170  			RuntimeContextRepoFn: func() *automock.RuntimeContextRepository {
  1171  				runtimeContextRepo := &automock.RuntimeContextRepository{}
  1172  				runtimeContextRepo.On("ExistsByRuntimeID", ctx, TargetTenantID, RuntimeID).Return(false, nil).Once()
  1173  				return runtimeContextRepo
  1174  			},
  1175  			RuntimeRepoFn: func() *automock.RuntimeRepository {
  1176  				runtimeRepo := &automock.RuntimeRepository{}
  1177  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[0].TargetTenantID, RuntimeID, runtimeLblFilters).Return(true, nil).Once()
  1178  				runtimeRepo.On("OwnerExistsByFiltersAndID", ctx, testScenarios[1].TargetTenantID, RuntimeID, runtimeLblFilters).Return(false, nil).Once()
  1179  				return runtimeRepo
  1180  			},
  1181  			FormationRepoFn: func() *automock.FormationRepository {
  1182  				formationRepo := &automock.FormationRepository{}
  1183  				formationRepo.On("GetByName", ctx, ScenarioName, testScenarios[0].Tenant).Return(formations[0], nil).Once()
  1184  				formationRepo.On("GetByName", ctx, ScenarioName2, testScenarios[1].Tenant).Return(formations[1], nil).Once()
  1185  				return formationRepo
  1186  			},
  1187  			FormationTemplateRepoFn: func() *automock.FormationTemplateRepository {
  1188  				formationTemplateRepo := &automock.FormationTemplateRepository{}
  1189  				formationTemplateRepo.On("Get", ctx, formations[0].FormationTemplateID).Return(&formationTemplate, nil).Once()
  1190  				formationTemplateRepo.On("Get", ctx, formations[1].FormationTemplateID).Return(&formationTemplate, nil).Once()
  1191  				return formationTemplateRepo
  1192  			},
  1193  			FormationName:        ScenarioName2,
  1194  			ObjectID:             RuntimeID,
  1195  			ObjectType:           graphql.FormationObjectTypeRuntime,
  1196  			ExpectedErrorMessage: "",
  1197  			ExpectedResult:       false,
  1198  		},
  1199  		{
  1200  			Name:                 "Error when getting scenarios fails",
  1201  			ObjectID:             "",
  1202  			ObjectType:           "test",
  1203  			ExpectedErrorMessage: "unexpected formation object type \"test\"",
  1204  			ExpectedResult:       false,
  1205  		},
  1206  	}
  1207  	for _, testCase := range testCases {
  1208  		t.Run(testCase.Name, func(t *testing.T) {
  1209  			// GIVEN
  1210  			asaRepo := unusedASARepo()
  1211  			if testCase.ScenarioAssignmentRepoFn != nil {
  1212  				asaRepo = testCase.ScenarioAssignmentRepoFn()
  1213  			}
  1214  			runtimeRepo := unusedRuntimeRepo()
  1215  			if testCase.RuntimeRepoFn != nil {
  1216  				runtimeRepo = testCase.RuntimeRepoFn()
  1217  			}
  1218  			runtimeContextRepo := unusedRuntimeContextRepo()
  1219  			if testCase.RuntimeContextRepoFn != nil {
  1220  				runtimeContextRepo = testCase.RuntimeContextRepoFn()
  1221  			}
  1222  			formationRepo := unusedFormationRepo()
  1223  			if testCase.FormationRepoFn != nil {
  1224  				formationRepo = testCase.FormationRepoFn()
  1225  			}
  1226  			formationTemplateRepo := unusedFormationTemplateRepo()
  1227  			if testCase.FormationTemplateRepoFn != nil {
  1228  				formationTemplateRepo = testCase.FormationTemplateRepoFn()
  1229  			}
  1230  
  1231  			svc := formation.NewASAEngine(asaRepo, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo, runtimeType, applicationType)
  1232  
  1233  			// WHEN
  1234  			comesFromASA, err := svc.IsFormationComingFromASA(ctx, testCase.ObjectID, testCase.FormationName, testCase.ObjectType)
  1235  
  1236  			// THEN
  1237  			if testCase.ExpectedErrorMessage == "" {
  1238  				require.NoError(t, err)
  1239  				require.Equal(t, testCase.ExpectedResult, comesFromASA)
  1240  			} else {
  1241  				require.Error(t, err)
  1242  				require.Contains(t, err.Error(), testCase.ExpectedErrorMessage)
  1243  				require.False(t, comesFromASA)
  1244  			}
  1245  
  1246  			mock.AssertExpectationsForObjects(t, asaRepo, runtimeRepo, runtimeContextRepo, formationRepo, formationTemplateRepo)
  1247  		})
  1248  	}
  1249  }