github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/formationconstraint/service_test.go (about) 1 package formationconstraint_test 2 3 import ( 4 "context" 5 "errors" 6 "reflect" 7 "testing" 8 9 "github.com/kyma-incubator/compass/components/director/internal/domain/formationconstraint" 10 "github.com/kyma-incubator/compass/components/director/internal/domain/formationconstraint/automock" 11 tnt "github.com/kyma-incubator/compass/components/director/internal/domain/tenant" 12 "github.com/kyma-incubator/compass/components/director/internal/model" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/mock" 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestService_Create(t *testing.T) { 19 // GIVEN 20 ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID) 21 22 testErr := errors.New("test error") 23 24 uidSvcFn := func() *automock.UidService { 25 uidSvc := &automock.UidService{} 26 uidSvc.On("Generate").Return(testID) 27 return uidSvc 28 } 29 30 testCases := []struct { 31 Name string 32 Context context.Context 33 Input *model.FormationConstraintInput 34 FormationConstraintRepository func() *automock.FormationConstraintRepository 35 FormationConstraintConverter func() *automock.FormationConstraintConverter 36 ExpectedOutput string 37 ExpectedError error 38 }{ 39 { 40 Name: "Success", 41 Context: ctx, 42 Input: formationConstraintModelInput, 43 FormationConstraintConverter: func() *automock.FormationConstraintConverter { 44 converter := &automock.FormationConstraintConverter{} 45 converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once() 46 return converter 47 }, 48 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 49 repo := &automock.FormationConstraintRepository{} 50 repo.On("Create", ctx, formationConstraintModel).Return(nil).Once() 51 return repo 52 }, 53 ExpectedOutput: testID, 54 ExpectedError: nil, 55 }, 56 { 57 Name: "Error when creating formation constraint", 58 Context: ctx, 59 Input: formationConstraintModelInput, 60 FormationConstraintConverter: func() *automock.FormationConstraintConverter { 61 converter := &automock.FormationConstraintConverter{} 62 converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once() 63 return converter 64 }, 65 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 66 repo := &automock.FormationConstraintRepository{} 67 repo.On("Create", ctx, formationConstraintModel).Return(testErr).Once() 68 return repo 69 }, 70 ExpectedOutput: "", 71 ExpectedError: testErr, 72 }, 73 } 74 75 for _, testCase := range testCases { 76 t.Run(testCase.Name, func(t *testing.T) { 77 formationConstraintRepo := testCase.FormationConstraintRepository() 78 formationConstraintConv := testCase.FormationConstraintConverter() 79 idSvc := uidSvcFn() 80 81 svc := formationconstraint.NewService(formationConstraintRepo, nil, idSvc, formationConstraintConv) 82 83 // WHEN 84 result, err := svc.Create(testCase.Context, testCase.Input) 85 86 // THEN 87 if testCase.ExpectedError != nil { 88 require.Error(t, err) 89 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 90 } else { 91 assert.NoError(t, err) 92 } 93 assert.Equal(t, testCase.ExpectedOutput, result) 94 95 mock.AssertExpectationsForObjects(t, formationConstraintRepo, idSvc, formationConstraintConv) 96 }) 97 } 98 } 99 100 func TestService_Get(t *testing.T) { 101 // GIVEN 102 ctx := context.TODO() 103 104 testErr := errors.New("test error") 105 106 testCases := []struct { 107 Name string 108 Input string 109 FormationConstraintRepository func() *automock.FormationConstraintRepository 110 ExpectedOutput *model.FormationConstraint 111 ExpectedError error 112 }{ 113 { 114 Name: "Success", 115 Input: testID, 116 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 117 repo := &automock.FormationConstraintRepository{} 118 repo.On("Get", ctx, testID).Return(formationConstraintModel, nil).Once() 119 return repo 120 }, 121 ExpectedOutput: formationConstraintModel, 122 ExpectedError: nil, 123 }, 124 { 125 Name: "Error when getting formation template", 126 Input: testID, 127 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 128 repo := &automock.FormationConstraintRepository{} 129 repo.On("Get", ctx, testID).Return(nil, testErr).Once() 130 return repo 131 }, 132 ExpectedOutput: nil, 133 ExpectedError: testErr, 134 }, 135 } 136 137 for _, testCase := range testCases { 138 t.Run(testCase.Name, func(t *testing.T) { 139 formationConstraintRepo := testCase.FormationConstraintRepository() 140 141 svc := formationconstraint.NewService(formationConstraintRepo, nil, nil, nil) 142 143 // WHEN 144 result, err := svc.Get(ctx, testCase.Input) 145 146 // THEN 147 if testCase.ExpectedError != nil { 148 require.Error(t, err) 149 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 150 } else { 151 assert.NoError(t, err) 152 } 153 assert.Equal(t, testCase.ExpectedOutput, result) 154 155 mock.AssertExpectationsForObjects(t, formationConstraintRepo) 156 }) 157 } 158 } 159 160 func TestService_List(t *testing.T) { 161 // GIVEN 162 ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID) 163 164 testErr := errors.New("test error") 165 166 testCases := []struct { 167 Name string 168 Context context.Context 169 FormationConstraintRepository func() *automock.FormationConstraintRepository 170 ExpectedOutput []*model.FormationConstraint 171 ExpectedError error 172 }{ 173 { 174 Name: "Success", 175 Context: ctx, 176 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 177 repo := &automock.FormationConstraintRepository{} 178 repo.On("ListAll", ctx).Return([]*model.FormationConstraint{formationConstraintModel}, nil).Once() 179 return repo 180 }, 181 ExpectedOutput: []*model.FormationConstraint{formationConstraintModel}, 182 ExpectedError: nil, 183 }, 184 { 185 Name: "Error when listing formation constraints", 186 Context: ctx, 187 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 188 repo := &automock.FormationConstraintRepository{} 189 repo.On("ListAll", ctx).Return(nil, testErr).Once() 190 return repo 191 }, 192 ExpectedOutput: nil, 193 ExpectedError: testErr, 194 }, 195 } 196 197 for _, testCase := range testCases { 198 t.Run(testCase.Name, func(t *testing.T) { 199 formationConstraintRepo := testCase.FormationConstraintRepository() 200 201 svc := formationconstraint.NewService(formationConstraintRepo, nil, nil, nil) 202 203 // WHEN 204 result, err := svc.List(testCase.Context) 205 206 // THEN 207 if testCase.ExpectedError != nil { 208 require.Error(t, err) 209 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 210 } else { 211 assert.NoError(t, err) 212 } 213 assert.Equal(t, testCase.ExpectedOutput, result) 214 215 mock.AssertExpectationsForObjects(t, formationConstraintRepo) 216 }) 217 } 218 } 219 220 func TestService_ListByFormationTemplateID(t *testing.T) { 221 // GIVEN 222 ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID) 223 224 testErr := errors.New("test error") 225 226 testCases := []struct { 227 Name string 228 Context context.Context 229 FormationConstraintRepository func() *automock.FormationConstraintRepository 230 FormationConstraintReferenceRepository func() *automock.FormationTemplateConstraintReferenceRepository 231 ExpectedOutput []*model.FormationConstraint 232 ExpectedError error 233 }{ 234 { 235 Name: "Success", 236 Context: ctx, 237 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 238 repo := &automock.FormationConstraintRepository{} 239 repo.On("ListByIDs", ctx, []string{testID}).Return([]*model.FormationConstraint{formationConstraintModel}, nil).Once() 240 return repo 241 }, 242 FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository { 243 repo := &automock.FormationTemplateConstraintReferenceRepository{} 244 repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once() 245 return repo 246 }, 247 ExpectedOutput: []*model.FormationConstraint{formationConstraintModel}, 248 ExpectedError: nil, 249 }, 250 { 251 Name: "Error when listing formation constraints", 252 Context: ctx, 253 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 254 repo := &automock.FormationConstraintRepository{} 255 repo.On("ListByIDs", ctx, []string{testID}).Return(nil, testErr).Once() 256 return repo 257 }, 258 FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository { 259 repo := &automock.FormationTemplateConstraintReferenceRepository{} 260 repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once() 261 return repo 262 }, 263 ExpectedOutput: nil, 264 ExpectedError: testErr, 265 }, 266 { 267 Name: "Error when listing constraint references", 268 Context: ctx, 269 FormationConstraintRepository: UnusedFormationConstraintRepository, 270 FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository { 271 repo := &automock.FormationTemplateConstraintReferenceRepository{} 272 repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return(nil, testErr).Once() 273 return repo 274 }, 275 ExpectedOutput: nil, 276 ExpectedError: testErr, 277 }, 278 } 279 280 for _, testCase := range testCases { 281 t.Run(testCase.Name, func(t *testing.T) { 282 formationConstraintRepo := testCase.FormationConstraintRepository() 283 formationConstraintReferenceRepo := testCase.FormationConstraintReferenceRepository() 284 svc := formationconstraint.NewService(formationConstraintRepo, formationConstraintReferenceRepo, nil, nil) 285 286 // WHEN 287 result, err := svc.ListByFormationTemplateID(testCase.Context, formationTemplateID) 288 289 // THEN 290 if testCase.ExpectedError != nil { 291 require.Error(t, err) 292 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 293 } else { 294 assert.NoError(t, err) 295 } 296 assert.Equal(t, testCase.ExpectedOutput, result) 297 298 mock.AssertExpectationsForObjects(t, formationConstraintRepo, formationConstraintReferenceRepo) 299 }) 300 } 301 } 302 303 func TestService_Delete(t *testing.T) { 304 // GIVEN 305 ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID) 306 testErr := errors.New("test error") 307 308 testCases := []struct { 309 Name string 310 Context context.Context 311 Input string 312 FormationConstraintRepository func() *automock.FormationConstraintRepository 313 ExpectedError error 314 }{ 315 { 316 Name: "Success", 317 Context: ctx, 318 Input: testID, 319 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 320 repo := &automock.FormationConstraintRepository{} 321 repo.On("Delete", ctx, testID).Return(nil).Once() 322 return repo 323 }, 324 ExpectedError: nil, 325 }, 326 { 327 Name: "Error when deleting formation constraint", 328 Context: ctx, 329 Input: testID, 330 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 331 repo := &automock.FormationConstraintRepository{} 332 repo.On("Delete", ctx, testID).Return(testErr).Once() 333 return repo 334 }, 335 ExpectedError: testErr, 336 }, 337 } 338 339 for _, testCase := range testCases { 340 t.Run(testCase.Name, func(t *testing.T) { 341 formationConstraintRepo := testCase.FormationConstraintRepository() 342 343 svc := formationconstraint.NewService(formationConstraintRepo, nil, nil, nil) 344 345 // WHEN 346 err := svc.Delete(testCase.Context, testCase.Input) 347 348 // THEN 349 if testCase.ExpectedError != nil { 350 require.Error(t, err) 351 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 352 } else { 353 assert.NoError(t, err) 354 } 355 356 mock.AssertExpectationsForObjects(t, formationConstraintRepo) 357 }) 358 } 359 } 360 361 func TestService_ListMatchingConstraints(t *testing.T) { 362 // GIVEN 363 ctx := tnt.SaveToContext(context.TODO(), testTenantID, testTenantID) 364 365 testErr := errors.New("test error") 366 367 testCases := []struct { 368 Name string 369 Context context.Context 370 FormationConstraintRepository func() *automock.FormationConstraintRepository 371 FormationConstraintReferenceRepository func() *automock.FormationTemplateConstraintReferenceRepository 372 ExpectedOutput []*model.FormationConstraint 373 ExpectedError error 374 }{ 375 { 376 Name: "Success", 377 Context: ctx, 378 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 379 repo := &automock.FormationConstraintRepository{} 380 repo.On("ListMatchingFormationConstraints", ctx, []string{testID}, location, matchingDetails).Return([]*model.FormationConstraint{formationConstraintModel}, nil).Once() 381 return repo 382 }, 383 FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository { 384 repo := &automock.FormationTemplateConstraintReferenceRepository{} 385 repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once() 386 return repo 387 }, 388 ExpectedOutput: []*model.FormationConstraint{formationConstraintModel}, 389 ExpectedError: nil, 390 }, 391 { 392 Name: "Error when listing formation constraints", 393 Context: ctx, 394 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 395 repo := &automock.FormationConstraintRepository{} 396 repo.On("ListMatchingFormationConstraints", ctx, []string{testID}, location, matchingDetails).Return(nil, testErr).Once() 397 return repo 398 }, 399 FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository { 400 repo := &automock.FormationTemplateConstraintReferenceRepository{} 401 repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return([]*model.FormationTemplateConstraintReference{formationConstraintReference}, nil).Once() 402 return repo 403 }, 404 ExpectedOutput: nil, 405 ExpectedError: testErr, 406 }, 407 { 408 Name: "Error when listing constraint references", 409 Context: ctx, 410 FormationConstraintRepository: UnusedFormationConstraintRepository, 411 FormationConstraintReferenceRepository: func() *automock.FormationTemplateConstraintReferenceRepository { 412 repo := &automock.FormationTemplateConstraintReferenceRepository{} 413 repo.On("ListByFormationTemplateID", ctx, formationTemplateID).Return(nil, testErr).Once() 414 return repo 415 }, 416 ExpectedOutput: nil, 417 ExpectedError: testErr, 418 }, 419 } 420 421 for _, testCase := range testCases { 422 t.Run(testCase.Name, func(t *testing.T) { 423 formationConstraintRepo := testCase.FormationConstraintRepository() 424 formationConstraintReferenceRepo := testCase.FormationConstraintReferenceRepository() 425 svc := formationconstraint.NewService(formationConstraintRepo, formationConstraintReferenceRepo, nil, nil) 426 427 // WHEN 428 result, err := svc.ListMatchingConstraints(testCase.Context, formationTemplateID, location, matchingDetails) 429 430 // THEN 431 if testCase.ExpectedError != nil { 432 require.Error(t, err) 433 assert.Contains(t, err.Error(), testCase.ExpectedError.Error()) 434 } else { 435 assert.NoError(t, err) 436 } 437 assert.Equal(t, testCase.ExpectedOutput, result) 438 439 mock.AssertExpectationsForObjects(t, formationConstraintRepo, formationConstraintReferenceRepo) 440 }) 441 } 442 } 443 444 func TestService_Update(t *testing.T) { 445 // GIVEN 446 ctx := context.TODO() 447 448 testErr := errors.New("test error") 449 450 testCases := []struct { 451 Name string 452 Context context.Context 453 InputConstraintTemplate *model.FormationConstraintInput 454 FormationConstraintRepository func() *automock.FormationConstraintRepository 455 FormationConstraintConverter func() *automock.FormationConstraintConverter 456 ExpectedErrorMessage string 457 }{ 458 { 459 Name: "Success", 460 Context: ctx, 461 InputConstraintTemplate: formationConstraintModelInput, 462 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 463 repo := &automock.FormationConstraintRepository{} 464 repo.On("Update", ctx, formationConstraintModel).Return(nil).Once() 465 return repo 466 }, 467 FormationConstraintConverter: func() *automock.FormationConstraintConverter { 468 converter := &automock.FormationConstraintConverter{} 469 converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once() 470 471 return converter 472 }, 473 ExpectedErrorMessage: "", 474 }, 475 { 476 Name: "Error when updating fails", 477 Context: ctx, 478 InputConstraintTemplate: formationConstraintModelInput, 479 FormationConstraintRepository: func() *automock.FormationConstraintRepository { 480 repo := &automock.FormationConstraintRepository{} 481 repo.On("Update", ctx, formationConstraintModel).Return(testErr).Once() 482 return repo 483 }, 484 FormationConstraintConverter: func() *automock.FormationConstraintConverter { 485 converter := &automock.FormationConstraintConverter{} 486 converter.On("FromModelInputToModel", formationConstraintModelInput, testID).Return(formationConstraintModel).Once() 487 488 return converter 489 }, 490 ExpectedErrorMessage: "while updating Formation Constraint with ID", 491 }, 492 } 493 494 for _, testCase := range testCases { 495 t.Run(testCase.Name, func(t *testing.T) { 496 repo := UnusedFormationConstraintRepository() 497 if testCase.FormationConstraintRepository != nil { 498 repo = testCase.FormationConstraintRepository() 499 } 500 conv := UnusedFormationConstraintConverter() 501 if testCase.FormationConstraintConverter != nil { 502 conv = testCase.FormationConstraintConverter() 503 } 504 svc := formationconstraint.NewService(repo, nil, nil, conv) 505 506 // WHEN 507 err := svc.Update(testCase.Context, testID, testCase.InputConstraintTemplate) 508 509 // THEN 510 if testCase.ExpectedErrorMessage != "" { 511 require.Error(t, err) 512 assert.Contains(t, err.Error(), testCase.ExpectedErrorMessage) 513 } else { 514 assert.NoError(t, err) 515 } 516 517 mock.AssertExpectationsForObjects(t, repo, conv) 518 }) 519 } 520 } 521 522 func TestService_ListByFormationTemplateIDs(t *testing.T) { 523 ctx := context.TODO() 524 525 testErr := errors.New("test err") 526 formationTemplateIDs := []string{formationTemplateID1, formationTemplateID2, formationTemplateID3} 527 constraintIDs := []string{constraintID1, constraintID2} 528 529 constraintRefs := []*model.FormationTemplateConstraintReference{ 530 { 531 ConstraintID: constraintIDs[0], 532 FormationTemplateID: formationTemplateIDs[0], 533 }, 534 { 535 ConstraintID: constraintIDs[1], 536 FormationTemplateID: formationTemplateIDs[1], 537 }, 538 { 539 ConstraintID: constraintIDs[1], 540 FormationTemplateID: formationTemplateIDs[2], 541 }, 542 } 543 544 constraints := []*model.FormationConstraint{formationConstraint1, formationConstraint2, globalConstraint} 545 546 constraintsPerFormationTemplate := [][]*model.FormationConstraint{ 547 { 548 formationConstraint1, 549 formationConstraint2, 550 globalConstraint, 551 }, 552 { 553 formationConstraint1, 554 globalConstraint, 555 }, 556 } 557 558 testCases := []struct { 559 Name string 560 FormationTemplateConstraintReferenceRepo func() *automock.FormationTemplateConstraintReferenceRepository 561 FormationConstraintRepo func() *automock.FormationConstraintRepository 562 Input []string 563 ExpectedConstraints [][]*model.FormationConstraint 564 ExpectedError error 565 }{ 566 { 567 Name: "Success", 568 FormationTemplateConstraintReferenceRepo: func() *automock.FormationTemplateConstraintReferenceRepository { 569 refRepo := &automock.FormationTemplateConstraintReferenceRepository{} 570 refRepo.On("ListByFormationTemplateIDs", ctx, formationTemplateIDs).Return(constraintRefs, nil).Once() 571 return refRepo 572 }, 573 FormationConstraintRepo: func() *automock.FormationConstraintRepository { 574 constraintRepo := &automock.FormationConstraintRepository{} 575 constraintRepo.On("ListByIDsAndGlobal", ctx, append(constraintIDs, constraintIDs[1])).Return(constraints, nil).Once() 576 return constraintRepo 577 }, 578 Input: formationTemplateIDs, 579 ExpectedConstraints: constraintsPerFormationTemplate, 580 ExpectedError: nil, 581 }, 582 { 583 Name: "Returns error when listing constraints fails", 584 FormationTemplateConstraintReferenceRepo: func() *automock.FormationTemplateConstraintReferenceRepository { 585 refRepo := &automock.FormationTemplateConstraintReferenceRepository{} 586 refRepo.On("ListByFormationTemplateIDs", ctx, formationTemplateIDs).Return(constraintRefs, nil).Once() 587 return refRepo 588 }, 589 FormationConstraintRepo: func() *automock.FormationConstraintRepository { 590 constraintRepo := &automock.FormationConstraintRepository{} 591 constraintRepo.On("ListByIDsAndGlobal", ctx, append(constraintIDs, constraintIDs[1])).Return(nil, testErr).Once() 592 return constraintRepo 593 }, 594 Input: formationTemplateIDs, 595 ExpectedConstraints: nil, 596 ExpectedError: testErr, 597 }, 598 { 599 Name: "Returns error when listing constraints refs fails", 600 FormationTemplateConstraintReferenceRepo: func() *automock.FormationTemplateConstraintReferenceRepository { 601 refRepo := &automock.FormationTemplateConstraintReferenceRepository{} 602 refRepo.On("ListByFormationTemplateIDs", ctx, formationTemplateIDs).Return(nil, testErr).Once() 603 return refRepo 604 }, 605 Input: formationTemplateIDs, 606 ExpectedConstraints: nil, 607 ExpectedError: testErr, 608 }, 609 } 610 611 for _, testCase := range testCases { 612 t.Run(testCase.Name, func(t *testing.T) { 613 constraintRefRepo := testCase.FormationTemplateConstraintReferenceRepo() 614 constraintRepo := UnusedFormationConstraintRepository() 615 if testCase.FormationConstraintRepo != nil { 616 constraintRepo = testCase.FormationConstraintRepo() 617 } 618 svc := formationconstraint.NewService(constraintRepo, constraintRefRepo, nil, nil) 619 620 res, err := svc.ListByFormationTemplateIDs(ctx, testCase.Input) 621 622 if testCase.ExpectedError != nil { 623 require.Error(t, err) 624 require.Nil(t, res) 625 } else { 626 require.Nil(t, err) 627 reflect.DeepEqual(res, testCase.ExpectedConstraints) 628 } 629 630 mock.AssertExpectationsForObjects(t, constraintRefRepo, constraintRepo) 631 }) 632 } 633 }