github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/datastream/stream_test.go (about) 1 package datastream 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "net/http" 8 "net/http/httptest" 9 "reflect" 10 "testing" 11 12 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestDs_GetStream(t *testing.T) { 18 tests := map[string]struct { 19 request GetStreamRequest 20 responseStatus int 21 responseBody string 22 expectedPath string 23 expectedResponse *DetailedStreamVersion 24 withError func(*testing.T, error) 25 }{ 26 "200 OK Without midgress field": { 27 request: GetStreamRequest{ 28 StreamID: 1, 29 }, 30 responseStatus: http.StatusOK, 31 responseBody: ` 32 { 33 "contractId": "P-1324", 34 "createdBy": "sample_username", 35 "createdDate": "2022-11-04T00:49:45Z", 36 "datasetFields": [ 37 { 38 "datasetFieldId":1000, 39 "datasetFieldName":"dataset_field_name_1", 40 "datasetFieldJsonKey":"dataset_field_json_key_1" 41 }, 42 { 43 "datasetFieldId":1002, 44 "datasetFieldName":"dataset_field_name_2", 45 "datasetFieldJsonKey":"dataset_field_json_key_2" 46 }, 47 { 48 "datasetFieldId":1082, 49 "datasetFieldName":"dataset_field_name_3", 50 "datasetFieldJsonKey":"dataset_field_json_key_3" 51 } 52 ], 53 "deliveryConfiguration": { 54 "fieldDelimiter": "SPACE", 55 "format": "STRUCTURED", 56 "frequency": { 57 "intervalInSeconds": 30 58 }, 59 "uploadFilePrefix": "ak", 60 "uploadFileSuffix": "ds" 61 }, 62 "destination": { 63 "bucket": "sample_bucket", 64 "compressLogs": true, 65 "destinationType": "S3", 66 "displayName": "sample_display_name", 67 "path": "/sample_path", 68 "region": "us-east-1" 69 }, 70 "groupId": 1234, 71 "latestVersion": 2, 72 "modifiedBy": "sample_username2", 73 "modifiedDate": "2022-11-04T02:14:29Z", 74 "notificationEmails": [ 75 "sample_username@akamai.com" 76 ], 77 "productId": "Adaptive_Media_Delivery", 78 "properties": [ 79 { 80 "propertyId": 12345, 81 "propertyName": "example.com" 82 } 83 ], 84 "streamId": 1, 85 "streamName": "ds2-sample-name", 86 "streamStatus": "ACTIVATED", 87 "streamVersion": 2 88 } 89 `, 90 expectedPath: "/datastream-config-api/v2/log/streams/1", 91 expectedResponse: &DetailedStreamVersion{ 92 StreamStatus: StreamStatusActivated, 93 DeliveryConfiguration: DeliveryConfiguration{ 94 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 95 Format: FormatTypeStructured, 96 Frequency: Frequency{ 97 IntervalInSeconds: IntervalInSeconds30, 98 }, 99 UploadFilePrefix: "ak", 100 UploadFileSuffix: "ds", 101 }, 102 Destination: Destination{ 103 CompressLogs: true, 104 DisplayName: "sample_display_name", 105 DestinationType: DestinationTypeS3, 106 Path: "/sample_path", 107 Bucket: "sample_bucket", 108 Region: "us-east-1", 109 }, 110 ContractID: "P-1324", 111 CreatedBy: "sample_username", 112 CreatedDate: "2022-11-04T00:49:45Z", 113 DatasetFields: []DataSetField{ 114 { 115 DatasetFieldID: 1000, 116 DatasetFieldName: "dataset_field_name_1", 117 DatasetFieldJsonKey: "dataset_field_json_key_1", 118 }, 119 { 120 DatasetFieldID: 1002, 121 DatasetFieldName: "dataset_field_name_2", 122 DatasetFieldJsonKey: "dataset_field_json_key_2", 123 }, 124 { 125 DatasetFieldID: 1082, 126 DatasetFieldName: "dataset_field_name_3", 127 DatasetFieldJsonKey: "dataset_field_json_key_3", 128 }, 129 }, 130 NotificationEmails: []string{"sample_username@akamai.com"}, 131 GroupID: 1234, 132 ModifiedBy: "sample_username2", 133 ModifiedDate: "2022-11-04T02:14:29Z", 134 ProductID: "Adaptive_Media_Delivery", 135 Properties: []Property{ 136 { 137 PropertyID: 12345, 138 PropertyName: "example.com", 139 }, 140 }, 141 StreamID: 1, 142 StreamName: "ds2-sample-name", 143 StreamVersion: 2, 144 LatestVersion: 2, 145 }, 146 }, 147 148 "200 OK With midgress field": { 149 request: GetStreamRequest{ 150 StreamID: 1, 151 }, 152 responseStatus: http.StatusOK, 153 responseBody: ` 154 { 155 "contractId": "P-1324", 156 "createdBy": "sample_username", 157 "createdDate": "2022-11-04T00:49:45Z", 158 "collectMidgress": true, 159 "datasetFields": [ 160 { 161 "datasetFieldId":1000, 162 "datasetFieldName":"dataset_field_name_1", 163 "datasetFieldJsonKey":"dataset_field_json_key_1" 164 }, 165 { 166 "datasetFieldId":1002, 167 "datasetFieldName":"dataset_field_name_2", 168 "datasetFieldJsonKey":"dataset_field_json_key_2" 169 }, 170 { 171 "datasetFieldId":1082, 172 "datasetFieldName":"dataset_field_name_3", 173 "datasetFieldJsonKey":"dataset_field_json_key_3" 174 } 175 ], 176 "deliveryConfiguration": { 177 "fieldDelimiter": "SPACE", 178 "format": "STRUCTURED", 179 "frequency": { 180 "intervalInSeconds": 30 181 }, 182 "uploadFilePrefix": "ak", 183 "uploadFileSuffix": "ds" 184 }, 185 "destination": { 186 "bucket": "sample_bucket", 187 "compressLogs": true, 188 "destinationType": "S3", 189 "displayName": "sample_display_name", 190 "path": "/sample_path", 191 "region": "us-east-1" 192 }, 193 "groupId": 1234, 194 "latestVersion": 2, 195 "modifiedBy": "sample_username2", 196 "modifiedDate": "2022-11-04T02:14:29Z", 197 "notificationEmails": [ 198 "sample_username@akamai.com" 199 ], 200 "productId": "Adaptive_Media_Delivery", 201 "properties": [ 202 { 203 "propertyId": 1234, 204 "propertyName": "sample.com" 205 } 206 ], 207 "streamId": 1, 208 "streamName": "ds2-sample-name", 209 "streamStatus": "ACTIVATED", 210 "streamVersion": 2 211 } 212 `, 213 expectedPath: "/datastream-config-api/v2/log/streams/1", 214 expectedResponse: &DetailedStreamVersion{ 215 CollectMidgress: true, 216 StreamStatus: StreamStatusActivated, 217 DeliveryConfiguration: DeliveryConfiguration{ 218 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 219 Format: FormatTypeStructured, 220 Frequency: Frequency{ 221 IntervalInSeconds: IntervalInSeconds30, 222 }, 223 UploadFilePrefix: "ak", 224 UploadFileSuffix: "ds", 225 }, 226 Destination: Destination{ 227 CompressLogs: true, 228 DisplayName: "sample_display_name", 229 DestinationType: DestinationTypeS3, 230 Path: "/sample_path", 231 Bucket: "sample_bucket", 232 Region: "us-east-1", 233 }, 234 ContractID: "P-1324", 235 CreatedBy: "sample_username", 236 CreatedDate: "2022-11-04T00:49:45Z", 237 DatasetFields: []DataSetField{ 238 { 239 DatasetFieldID: 1000, 240 DatasetFieldName: "dataset_field_name_1", 241 DatasetFieldJsonKey: "dataset_field_json_key_1", 242 }, 243 { 244 DatasetFieldID: 1002, 245 DatasetFieldName: "dataset_field_name_2", 246 DatasetFieldJsonKey: "dataset_field_json_key_2", 247 }, 248 { 249 DatasetFieldID: 1082, 250 DatasetFieldName: "dataset_field_name_3", 251 DatasetFieldJsonKey: "dataset_field_json_key_3", 252 }, 253 }, 254 NotificationEmails: []string{"sample_username@akamai.com"}, 255 GroupID: 1234, 256 ModifiedBy: "sample_username2", 257 ModifiedDate: "2022-11-04T02:14:29Z", 258 ProductID: "Adaptive_Media_Delivery", 259 Properties: []Property{ 260 { 261 PropertyID: 1234, 262 PropertyName: "sample.com", 263 }, 264 }, 265 StreamID: 1, 266 StreamName: "ds2-sample-name", 267 StreamVersion: 2, 268 LatestVersion: 2, 269 }, 270 }, 271 272 "validation error": { 273 request: GetStreamRequest{}, 274 withError: func(t *testing.T, err error) { 275 want := ErrStructValidation 276 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 277 }, 278 }, 279 "400 bad request": { 280 request: GetStreamRequest{StreamID: 12}, 281 responseStatus: http.StatusBadRequest, 282 expectedPath: "/datastream-config-api/v2/log/streams/12", 283 responseBody: ` 284 { 285 "type": "bad-request", 286 "title": "Bad Request", 287 "detail": "bad request", 288 "instance": "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82", 289 "statusCode": 400, 290 "errors": [ 291 { 292 "type": "bad-request", 293 "title": "Bad Request", 294 "detail": "Stream does not exist. Please provide valid stream." 295 } 296 ] 297 } 298 `, 299 withError: func(t *testing.T, err error) { 300 want := &Error{ 301 Type: "bad-request", 302 Title: "Bad Request", 303 Detail: "bad request", 304 Instance: "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82", 305 StatusCode: http.StatusBadRequest, 306 Errors: []RequestErrors{ 307 { 308 Type: "bad-request", 309 Title: "Bad Request", 310 Detail: "Stream does not exist. Please provide valid stream.", 311 }, 312 }, 313 } 314 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 315 }, 316 }, 317 } 318 319 for name, test := range tests { 320 t.Run(name, func(t *testing.T) { 321 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 322 assert.Equal(t, test.expectedPath, r.URL.String()) 323 assert.Equal(t, http.MethodGet, r.Method) 324 w.WriteHeader(test.responseStatus) 325 _, err := w.Write([]byte(test.responseBody)) 326 assert.NoError(t, err) 327 })) 328 client := mockAPIClient(t, mockServer) 329 result, err := client.GetStream(context.Background(), test.request) 330 if test.withError != nil { 331 test.withError(t, err) 332 return 333 } 334 require.NoError(t, err) 335 assert.Equal(t, test.expectedResponse, result) 336 }) 337 } 338 } 339 340 func TestDs_CreateStream(t *testing.T) { 341 createStreamRequest := CreateStreamRequest{ 342 Activate: true, 343 StreamConfiguration: StreamConfiguration{ 344 DeliveryConfiguration: DeliveryConfiguration{ 345 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 346 Format: FormatTypeStructured, 347 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 348 UploadFilePrefix: "logs", 349 UploadFileSuffix: "ak", 350 }, 351 352 Destination: AbstractConnector( 353 &S3Connector{ 354 Path: "sample-path/{%Y/%m/%d}", 355 DisplayName: "sample-display-name", 356 Bucket: "datastream.com", 357 Region: "ap-south-1", 358 AccessKey: "1234ABCD", 359 SecretAccessKey: "1234ABCD", 360 }, 361 ), 362 ContractID: "2-AB1234", 363 DatasetFields: []DatasetFieldID{ 364 { 365 DatasetFieldID: 2020, 366 }, 367 }, 368 NotificationEmails: []string{"useremail1@akamai.com", "useremail2@akamai.com"}, 369 GroupID: 1234, 370 Properties: []PropertyID{ 371 { 372 PropertyID: 1234, 373 }, 374 { 375 PropertyID: 1234, 376 }, 377 }, 378 StreamName: "TestStream", 379 CollectMidgress: true, 380 }, 381 } 382 383 modifyRequest := func(r CreateStreamRequest, opt func(r *CreateStreamRequest)) CreateStreamRequest { 384 opt(&r) 385 return r 386 } 387 388 tests := map[string]struct { 389 request CreateStreamRequest 390 responseStatus int 391 responseBody string 392 expectedPath string 393 expectedBody string 394 expectedResponse *DetailedStreamVersion 395 withError error 396 }{ 397 "201 Created ActivateNow:true": { 398 request: createStreamRequest, 399 responseStatus: http.StatusCreated, 400 responseBody: ` 401 402 { 403 "contractId": "2-AB1234", 404 "createdBy": "sample_username", 405 "createdDate": "2022-11-04T00:49:45Z", 406 "collectMidgress": true, 407 "datasetFields": [ 408 { 409 "datasetFieldId":2020, 410 "datasetFieldName":"field_name_1", 411 "datasetFieldJsonKey":"field_json_key_1" 412 } 413 ], 414 "deliveryConfiguration": { 415 "fieldDelimiter": "SPACE", 416 "format": "STRUCTURED", 417 "frequency": { 418 "intervalInSeconds": 30 419 }, 420 "uploadFilePrefix": "logs", 421 "uploadFileSuffix": "ak" 422 }, 423 "destination": { 424 "bucket": "datastream.com", 425 "compressLogs": true, 426 "destinationType": "S3", 427 "displayName": "sample-display-name", 428 "path": "sample-path/{%Y/%m/%d}", 429 "region": "ap-south-1" 430 }, 431 "groupId": 1234, 432 "latestVersion": 1, 433 "modifiedBy": "sample_username2", 434 "modifiedDate": "2022-11-04T02:14:29Z", 435 "notificationEmails": [ 436 "useremail1@akamai.com", "useremail2@akamai.com" 437 ], 438 "productId": "Adaptive_Media_Delivery", 439 "properties": [ 440 { 441 "propertyId": 1234, 442 "propertyName": "abcd" 443 }, 444 { 445 "propertyId": 1234, 446 "propertyName": "abcd" 447 } 448 ], 449 "streamId": 7050, 450 "streamName": "TestStream", 451 "streamStatus": "ACTIVATED", 452 "streamVersion": 1 453 } 454 455 456 `, 457 expectedPath: "/datastream-config-api/v2/log/streams?activate=true", 458 expectedResponse: &DetailedStreamVersion{ 459 CollectMidgress: true, 460 ContractID: "2-AB1234", 461 CreatedBy: "sample_username", 462 CreatedDate: "2022-11-04T00:49:45Z", 463 DatasetFields: []DataSetField{ 464 { 465 DatasetFieldName: "field_name_1", 466 DatasetFieldID: 2020, 467 DatasetFieldJsonKey: "field_json_key_1", 468 }, 469 }, 470 DeliveryConfiguration: DeliveryConfiguration{ 471 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 472 Format: FormatTypeStructured, 473 Frequency: Frequency{ 474 IntervalInSeconds: IntervalInSeconds30, 475 }, 476 UploadFilePrefix: "logs", 477 UploadFileSuffix: "ak", 478 }, 479 Destination: Destination{ 480 CompressLogs: true, 481 DisplayName: "sample-display-name", 482 DestinationType: DestinationTypeS3, 483 Path: "sample-path/{%Y/%m/%d}", 484 Bucket: "datastream.com", 485 Region: "ap-south-1", 486 }, 487 GroupID: 1234, 488 LatestVersion: 1, 489 StreamID: 7050, 490 StreamVersion: 1, 491 StreamName: "TestStream", 492 StreamStatus: StreamStatusActivated, 493 ModifiedBy: "sample_username2", 494 ModifiedDate: "2022-11-04T02:14:29Z", 495 NotificationEmails: []string{"useremail1@akamai.com", "useremail2@akamai.com"}, 496 ProductID: "Adaptive_Media_Delivery", 497 Properties: []Property{ 498 { 499 PropertyID: 1234, 500 PropertyName: "abcd", 501 }, 502 { 503 PropertyID: 1234, 504 PropertyName: "abcd", 505 }, 506 }, 507 }, 508 509 expectedBody: ` 510 { 511 "streamName":"TestStream", 512 "groupId":1234, 513 "contractId":"2-AB1234", 514 "collectMidgress":true, 515 "notificationEmails":[ 516 "useremail1@akamai.com", 517 "useremail2@akamai.com" 518 ], 519 "properties":[ 520 { 521 "propertyId":1234 522 }, 523 { 524 "propertyId":1234 525 } 526 ], 527 "datasetFields":[ 528 { 529 "datasetFieldId":2020 530 } 531 ], 532 "deliveryConfiguration":{ 533 "uploadFilePrefix":"logs", 534 "uploadFileSuffix":"ak", 535 "fieldDelimiter":"SPACE", 536 "format":"STRUCTURED", 537 "frequency":{ 538 "intervalInSeconds":30 539 } 540 }, 541 "destination":{ 542 "path":"sample-path/{%Y/%m/%d}", 543 "displayName":"sample-display-name", 544 "bucket":"datastream.com", 545 "region":"ap-south-1", 546 "accessKey":"1234ABCD", 547 "secretAccessKey":"1234ABCD", 548 "destinationType":"S3" 549 } 550 } 551 `, 552 }, 553 554 "validation error - empty destination": { 555 request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) { 556 r.StreamConfiguration.Destination = AbstractConnector(&S3Connector{}) 557 }), 558 withError: ErrStructValidation, 559 }, 560 "validation error - delimiter with JSON format": { 561 request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) { 562 r.StreamConfiguration.DeliveryConfiguration = DeliveryConfiguration{ 563 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 564 Format: FormatTypeJson, 565 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 566 UploadFilePrefix: "logs", 567 UploadFileSuffix: "ak", 568 } 569 }), 570 withError: ErrStructValidation, 571 }, 572 "validation error - no delimiter with STRUCTURED format": { 573 request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) { 574 r.StreamConfiguration.DeliveryConfiguration = DeliveryConfiguration{ 575 Format: FormatTypeStructured, 576 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 577 UploadFilePrefix: "logs", 578 UploadFileSuffix: "ak", 579 } 580 }), 581 withError: ErrStructValidation, 582 }, 583 "validation error - missing destination configuration fields": { 584 request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) { 585 r.StreamConfiguration.Destination = AbstractConnector( 586 &S3Connector{ 587 Path: "log/edgelogs/{ %Y/%m/%d }", 588 DisplayName: "S3Destination", 589 Bucket: "datastream.akamai.com", 590 Region: "ap-south-1", 591 }, 592 ) 593 }), 594 withError: ErrStructValidation, 595 }, 596 "403 forbidden": { 597 request: createStreamRequest, 598 responseStatus: http.StatusForbidden, 599 responseBody: ` 600 { 601 "type": "forbidden", 602 "title": "Forbidden", 603 "detail": "forbidden", 604 "instance": "72a7654e-3f95-454f-a174-104bc946be52", 605 "statusCode": 403, 606 "errors": [ 607 { 608 "type": "forbidden", 609 "title": "Forbidden", 610 "detail": "User is not having access for the group. Access denied, please contact support." 611 } 612 ] 613 } 614 `, 615 expectedPath: "/datastream-config-api/v2/log/streams?activate=true", 616 withError: &Error{ 617 Type: "forbidden", 618 Title: "Forbidden", 619 Detail: "forbidden", 620 Instance: "72a7654e-3f95-454f-a174-104bc946be52", 621 StatusCode: http.StatusForbidden, 622 Errors: []RequestErrors{ 623 { 624 Type: "forbidden", 625 Title: "Forbidden", 626 Detail: "User is not having access for the group. Access denied, please contact support.", 627 }, 628 }, 629 }, 630 }, 631 "400 bad request": { 632 request: createStreamRequest, 633 responseStatus: http.StatusBadRequest, 634 responseBody: ` 635 { 636 "type": "bad-request", 637 "title": "Bad Request", 638 "detail": "bad-request", 639 "instance": "d0d2497e-ed93-4685-b44c-93a8eb8f3dea", 640 "statusCode": 400, 641 "errors": [ 642 { 643 "type": "bad-request", 644 "title": "Bad Request", 645 "detail": "The credentials provided don’t give you write access to the bucket. Check your AWS credentials or bucket permissions in the S3 account and try again." 646 } 647 ] 648 } 649 `, 650 expectedPath: "/datastream-config-api/v2/log/streams?activate=true", 651 withError: &Error{ 652 Type: "bad-request", 653 Title: "Bad Request", 654 Detail: "bad-request", 655 Instance: "d0d2497e-ed93-4685-b44c-93a8eb8f3dea", 656 StatusCode: http.StatusBadRequest, 657 Errors: []RequestErrors{ 658 { 659 Type: "bad-request", 660 Title: "Bad Request", 661 Detail: "The credentials provided don’t give you write access to the bucket. Check your AWS credentials or bucket permissions in the S3 account and try again.", 662 }, 663 }, 664 }, 665 }, 666 } 667 668 for name, test := range tests { 669 t.Run(name, func(t *testing.T) { 670 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 671 assert.Equal(t, test.expectedPath, r.URL.String()) 672 assert.Equal(t, http.MethodPost, r.Method) 673 w.WriteHeader(test.responseStatus) 674 _, err := w.Write([]byte(test.responseBody)) 675 assert.NoError(t, err) 676 677 //check request body only if we aren't testing errors 678 if test.withError == nil { 679 var reqBody interface{} 680 err = json.NewDecoder(r.Body).Decode(&reqBody) 681 require.NoError(t, err, "Error while decoding request body") 682 683 var expectedBody interface{} 684 err = json.Unmarshal([]byte(test.expectedBody), &expectedBody) 685 require.NoError(t, err, "Error while parsing expected body to JSON") 686 687 assert.Equal(t, expectedBody, reqBody) 688 } 689 })) 690 client := mockAPIClient(t, mockServer) 691 result, err := client.CreateStream(context.Background(), test.request) 692 if test.withError != nil { 693 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 694 return 695 } 696 require.NoError(t, err) 697 assert.Equal(t, test.expectedResponse, result) 698 }) 699 } 700 } 701 702 func TestDs_UpdateStream(t *testing.T) { 703 updateRequest := UpdateStreamRequest{ 704 StreamID: 7050, 705 Activate: true, 706 StreamConfiguration: StreamConfiguration{ 707 DeliveryConfiguration: DeliveryConfiguration{ 708 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 709 Format: "STRUCTURED", 710 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 711 UploadFilePrefix: "logs", 712 UploadFileSuffix: "ak", 713 }, 714 Destination: AbstractConnector(&S3Connector{ 715 DisplayName: "sample-display-name", 716 DestinationType: DestinationTypeS3, 717 Path: "sample-path/{%Y/%m/%d}", 718 Bucket: "datastream.com", 719 Region: "ap-south-1", 720 AccessKey: "ABC", 721 SecretAccessKey: "XYZ", 722 }), 723 ContractID: "P-1324", 724 DatasetFields: []DatasetFieldID{ 725 { 726 DatasetFieldID: 1, 727 }, 728 { 729 DatasetFieldID: 2, 730 }, 731 { 732 DatasetFieldID: 3, 733 }, 734 }, 735 NotificationEmails: []string{"test@aka.mai", "useremail2@akamai.com"}, 736 737 Properties: []PropertyID{ 738 { 739 PropertyID: 123123, 740 }, 741 { 742 PropertyID: 123123, 743 }, 744 }, 745 746 StreamName: "TestStream", 747 }, 748 } 749 750 modifyRequest := func(r UpdateStreamRequest, opt func(r *UpdateStreamRequest)) UpdateStreamRequest { 751 opt(&r) 752 return r 753 } 754 755 tests := map[string]struct { 756 request UpdateStreamRequest 757 responseStatus int 758 responseBody string 759 expectedPath string 760 expectedResponse *DetailedStreamVersion 761 withError error 762 }{ 763 "200 OK activate:true": { 764 request: updateRequest, 765 responseStatus: http.StatusOK, 766 responseBody: ` 767 { 768 "contractId": "2-AB1234", 769 "createdBy": "sample_username", 770 "createdDate": "2022-11-04T00:49:45Z", 771 "collectMidgress": true, 772 "datasetFields": [ 773 { 774 "datasetFieldId":2020, 775 "datasetFieldName":"field_name_1", 776 "datasetFieldJsonKey":"field_json_key_1" 777 } 778 ], 779 "deliveryConfiguration": { 780 "fieldDelimiter": "SPACE", 781 "format": "STRUCTURED", 782 "frequency": { 783 "intervalInSeconds": 30 784 }, 785 "uploadFilePrefix": "logs", 786 "uploadFileSuffix": "ak" 787 }, 788 "destination": { 789 "bucket": "datastream.com", 790 "compressLogs": true, 791 "destinationType": "S3", 792 "displayName": "sample-display-name", 793 "path": "sample-path/{%Y/%m/%d}", 794 "region": "ap-south-1" 795 }, 796 "groupId": 1234, 797 "latestVersion": 2, 798 "modifiedBy": "modified_by_user", 799 "modifiedDate": "2022-11-04T02:14:29Z", 800 "notificationEmails": [ 801 "useremail1@akamai.com", "useremail2@akamai.com" 802 ], 803 "productId": "Adaptive_Media_Delivery", 804 "properties": [ 805 { 806 "propertyId": 1234, 807 "propertyName": "sample1.com" 808 }, 809 { 810 "propertyId": 1234, 811 "propertyName": "sample2.com" 812 } 813 ], 814 "streamId": 7050, 815 "streamName": "TestStream", 816 "streamStatus": "ACTIVATED", 817 "streamVersion": 2 818 } 819 `, 820 expectedPath: "/datastream-config-api/v2/log/streams/7050?activate=true", 821 expectedResponse: &DetailedStreamVersion{ 822 CollectMidgress: true, 823 ContractID: "2-AB1234", 824 CreatedBy: "sample_username", 825 CreatedDate: "2022-11-04T00:49:45Z", 826 DatasetFields: []DataSetField{ 827 { 828 DatasetFieldName: "field_name_1", 829 DatasetFieldID: 2020, 830 DatasetFieldJsonKey: "field_json_key_1", 831 }, 832 }, 833 DeliveryConfiguration: DeliveryConfiguration{ 834 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 835 Format: FormatTypeStructured, 836 Frequency: Frequency{ 837 IntervalInSeconds: IntervalInSeconds30, 838 }, 839 UploadFilePrefix: "logs", 840 UploadFileSuffix: "ak", 841 }, 842 Destination: Destination{ 843 CompressLogs: true, 844 DisplayName: "sample-display-name", 845 DestinationType: DestinationTypeS3, 846 Path: "sample-path/{%Y/%m/%d}", 847 Bucket: "datastream.com", 848 Region: "ap-south-1", 849 }, 850 GroupID: 1234, 851 LatestVersion: 2, 852 StreamID: 7050, 853 StreamVersion: 2, 854 StreamName: "TestStream", 855 StreamStatus: StreamStatusActivated, 856 ModifiedBy: "modified_by_user", 857 ModifiedDate: "2022-11-04T02:14:29Z", 858 NotificationEmails: []string{"useremail1@akamai.com", "useremail2@akamai.com"}, 859 ProductID: "Adaptive_Media_Delivery", 860 Properties: []Property{ 861 { 862 PropertyID: 1234, 863 PropertyName: "sample1.com", 864 }, 865 { 866 PropertyID: 1234, 867 PropertyName: "sample2.com", 868 }, 869 }, 870 }, 871 }, 872 873 "validation error - delimiter with JSON format": { 874 request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) { 875 r.StreamConfiguration.DeliveryConfiguration = DeliveryConfiguration{ 876 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 877 Format: FormatTypeJson, 878 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 879 UploadFilePrefix: "logs", 880 UploadFileSuffix: "ak", 881 } 882 }), 883 withError: ErrStructValidation, 884 }, 885 "validation error - no delimiter with STRUCTURED format": { 886 request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) { 887 r.StreamConfiguration.DeliveryConfiguration = DeliveryConfiguration{ 888 Format: FormatTypeStructured, 889 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 890 UploadFilePrefix: "logs", 891 UploadFileSuffix: "ak", 892 } 893 }), 894 withError: ErrStructValidation, 895 }, 896 "validation error - groupId modification": { 897 request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) { 898 r.StreamConfiguration.GroupID = 1337 899 }), 900 withError: ErrStructValidation, 901 }, 902 "validation error - missing contractId": { 903 request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) { 904 r.StreamConfiguration.ContractID = "" 905 }), 906 withError: ErrStructValidation, 907 }, 908 "400 bad request": { 909 request: updateRequest, 910 responseStatus: http.StatusBadRequest, 911 responseBody: ` 912 { 913 "type": "bad-request", 914 "title": "Bad Request", 915 "detail": "bad request", 916 "instance": "a42cc1e6-fea4-4e3a-91ce-9da9819e089a", 917 "statusCode": 400, 918 "errors": [ 919 { 920 "type": "bad-request", 921 "title": "Bad Request", 922 "detail": "Stream does not exist. Please provide valid stream." 923 } 924 ] 925 } 926 `, 927 expectedPath: "/datastream-config-api/v2/log/streams/7050?activate=true", 928 withError: &Error{ 929 Type: "bad-request", 930 Title: "Bad Request", 931 Detail: "bad request", 932 Instance: "a42cc1e6-fea4-4e3a-91ce-9da9819e089a", 933 StatusCode: http.StatusBadRequest, 934 Errors: []RequestErrors{ 935 { 936 Type: "bad-request", 937 Title: "Bad Request", 938 Detail: "Stream does not exist. Please provide valid stream.", 939 }, 940 }, 941 }, 942 }, 943 } 944 945 for name, test := range tests { 946 t.Run(name, func(t *testing.T) { 947 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 948 assert.Equal(t, test.expectedPath, r.URL.String()) 949 assert.Equal(t, http.MethodPut, r.Method) 950 w.WriteHeader(test.responseStatus) 951 _, err := w.Write([]byte(test.responseBody)) 952 assert.NoError(t, err) 953 })) 954 client := mockAPIClient(t, mockServer) 955 result, err := client.UpdateStream(context.Background(), test.request) 956 if test.withError != nil { 957 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 958 return 959 } 960 require.NoError(t, err) 961 assert.Equal(t, test.expectedResponse, result) 962 }) 963 } 964 } 965 966 func TestDs_DeleteStream(t *testing.T) { 967 tests := map[string]struct { 968 request DeleteStreamRequest 969 responseStatus int 970 responseBody string 971 expectedPath string 972 withError func(*testing.T, error) 973 }{ 974 "200 OK": { 975 request: DeleteStreamRequest{ 976 StreamID: 1, 977 }, 978 responseStatus: http.StatusNoContent, 979 responseBody: ``, 980 expectedPath: "/datastream-config-api/v2/log/streams/1", 981 }, 982 "validation error": { 983 request: DeleteStreamRequest{}, 984 withError: func(t *testing.T, err error) { 985 want := ErrStructValidation 986 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 987 }, 988 }, 989 "400 bad request": { 990 request: DeleteStreamRequest{StreamID: 12}, 991 responseStatus: http.StatusBadRequest, 992 expectedPath: "/datastream-config-api/v2/log/streams/12", 993 responseBody: ` 994 { 995 "type": "bad-request", 996 "title": "Bad Request", 997 "detail": "bad request", 998 "instance": "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82", 999 "statusCode": 400, 1000 "errors": [ 1001 { 1002 "type": "bad-request", 1003 "title": "Bad Request", 1004 "detail": "Stream does not exist. Please provide valid stream." 1005 } 1006 ] 1007 } 1008 `, 1009 withError: func(t *testing.T, err error) { 1010 want := &Error{ 1011 Type: "bad-request", 1012 Title: "Bad Request", 1013 Detail: "bad request", 1014 Instance: "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82", 1015 StatusCode: 400, 1016 Errors: []RequestErrors{ 1017 { 1018 Type: "bad-request", 1019 Title: "Bad Request", 1020 Detail: "Stream does not exist. Please provide valid stream.", 1021 }, 1022 }, 1023 } 1024 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 1025 }, 1026 }, 1027 } 1028 1029 for name, test := range tests { 1030 t.Run(name, func(t *testing.T) { 1031 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1032 assert.Equal(t, test.expectedPath, r.URL.String()) 1033 assert.Equal(t, http.MethodDelete, r.Method) 1034 w.WriteHeader(test.responseStatus) 1035 _, err := w.Write([]byte(test.responseBody)) 1036 assert.NoError(t, err) 1037 })) 1038 client := mockAPIClient(t, mockServer) 1039 err := client.DeleteStream(context.Background(), test.request) 1040 if test.withError != nil { 1041 test.withError(t, err) 1042 return 1043 } 1044 require.NoError(t, err) 1045 }) 1046 } 1047 } 1048 1049 func TestDs_Destinations(t *testing.T) { 1050 tests := map[string]struct { 1051 destination AbstractConnector 1052 expectedJSON string 1053 }{ 1054 "S3Connector": { 1055 destination: &S3Connector{ 1056 Path: "testPath", 1057 DisplayName: "testDisplayName", 1058 Bucket: "testBucket", 1059 Region: "testRegion", 1060 AccessKey: "testAccessKey", 1061 SecretAccessKey: "testSecretKey", 1062 }, 1063 expectedJSON: ` 1064 { 1065 "path": "testPath", 1066 "displayName": "testDisplayName", 1067 "bucket": "testBucket", 1068 "region": "testRegion", 1069 "accessKey": "testAccessKey", 1070 "secretAccessKey": "testSecretKey", 1071 "destinationType": "S3" 1072 } 1073 `, 1074 }, 1075 "AzureConnector": { 1076 destination: &AzureConnector{ 1077 AccountName: "testAccountName", 1078 AccessKey: "testAccessKey", 1079 DisplayName: "testDisplayName", 1080 ContainerName: "testContainerName", 1081 Path: "testPath", 1082 }, 1083 expectedJSON: ` 1084 { 1085 "accountName": "testAccountName", 1086 "accessKey": "testAccessKey", 1087 "displayName": "testDisplayName", 1088 "containerName": "testContainerName", 1089 "path": "testPath", 1090 "destinationType": "AZURE" 1091 } 1092 `, 1093 }, 1094 "DatadogConnector": { 1095 destination: &DatadogConnector{ 1096 Service: "testService", 1097 AuthToken: "testAuthToken", 1098 DisplayName: "testDisplayName", 1099 Endpoint: "testURL", 1100 Source: "testSource", 1101 Tags: "testTags", 1102 CompressLogs: false, 1103 }, 1104 expectedJSON: ` 1105 { 1106 "service": "testService", 1107 "authToken": "testAuthToken", 1108 "displayName": "testDisplayName", 1109 "endpoint": "testURL", 1110 "source": "testSource", 1111 "tags": "testTags", 1112 "destinationType": "DATADOG", 1113 "compressLogs": false 1114 } 1115 `, 1116 }, 1117 "SplunkConnector": { 1118 destination: &SplunkConnector{ 1119 DisplayName: "testDisplayName", 1120 Endpoint: "testURL", 1121 EventCollectorToken: "testEventCollector", 1122 CompressLogs: true, 1123 CustomHeaderName: "custom-header", 1124 CustomHeaderValue: "custom-header-value", 1125 }, 1126 expectedJSON: ` 1127 { 1128 "displayName": "testDisplayName", 1129 "endpoint": "testURL", 1130 "eventCollectorToken": "testEventCollector", 1131 "destinationType": "SPLUNK", 1132 "compressLogs": true, 1133 "customHeaderName": "custom-header", 1134 "customHeaderValue": "custom-header-value" 1135 } 1136 `, 1137 }, 1138 "GCSConnector": { 1139 destination: &GCSConnector{ 1140 DisplayName: "testDisplayName", 1141 Bucket: "testBucket", 1142 Path: "testPath", 1143 ProjectID: "testProjectID", 1144 ServiceAccountName: "testServiceAccountName", 1145 PrivateKey: "testPrivateKey", 1146 }, 1147 expectedJSON: ` 1148 { 1149 "destinationType": "GCS", 1150 "displayName": "testDisplayName", 1151 "bucket": "testBucket", 1152 "path": "testPath", 1153 "projectId": "testProjectID", 1154 "serviceAccountName": "testServiceAccountName", 1155 "privateKey": "testPrivateKey" 1156 } 1157 `, 1158 }, 1159 "CustomHTTPSConnector": { 1160 destination: &CustomHTTPSConnector{ 1161 AuthenticationType: AuthenticationTypeBasic, 1162 DisplayName: "testDisplayName", 1163 Endpoint: "testURL", 1164 UserName: "testUserName", 1165 Password: "testPassword", 1166 CompressLogs: true, 1167 CustomHeaderName: "custom-header", 1168 CustomHeaderValue: "custom-header-value", 1169 ContentType: "application/json", 1170 }, 1171 expectedJSON: ` 1172 { 1173 "authenticationType": "BASIC", 1174 "displayName": "testDisplayName", 1175 "endpoint": "testURL", 1176 "userName": "testUserName", 1177 "password": "testPassword", 1178 "destinationType": "HTTPS", 1179 "compressLogs": true, 1180 "customHeaderName": "custom-header", 1181 "customHeaderValue": "custom-header-value", 1182 "contentType": "application/json" 1183 } 1184 `, 1185 }, 1186 "SumoLogicConnector": { 1187 destination: &SumoLogicConnector{ 1188 DisplayName: "testDisplayName", 1189 Endpoint: "testEndpoint", 1190 CollectorCode: "testCollectorCode", 1191 CompressLogs: true, 1192 CustomHeaderName: "custom-header", 1193 CustomHeaderValue: "custom-header-value", 1194 ContentType: "application/json", 1195 }, 1196 expectedJSON: ` 1197 { 1198 "destinationType": "SUMO_LOGIC", 1199 "displayName": "testDisplayName", 1200 "endpoint": "testEndpoint", 1201 "collectorCode": "testCollectorCode", 1202 "compressLogs": true, 1203 "customHeaderName": "custom-header", 1204 "customHeaderValue": "custom-header-value", 1205 "contentType": "application/json" 1206 } 1207 `, 1208 }, 1209 "OracleCloudStorageConnector": { 1210 destination: &OracleCloudStorageConnector{ 1211 AccessKey: "testAccessKey", 1212 DisplayName: "testDisplayName", 1213 Path: "testPath", 1214 Bucket: "testBucket", 1215 Region: "testRegion", 1216 SecretAccessKey: "testSecretAccessKey", 1217 Namespace: "testNamespace", 1218 }, 1219 expectedJSON: ` 1220 { 1221 "accessKey": "testAccessKey", 1222 "displayName": "testDisplayName", 1223 "path": "testPath", 1224 "bucket": "testBucket", 1225 "region": "testRegion", 1226 "secretAccessKey": "testSecretAccessKey", 1227 "destinationType": "Oracle_Cloud_Storage", 1228 "namespace": "testNamespace" 1229 } 1230 `, 1231 }, 1232 "LogglyConnector": { 1233 destination: &LogglyConnector{ 1234 DisplayName: "testDisplayName", 1235 Endpoint: "testEndpoint", 1236 AuthToken: "testAuthToken", 1237 Tags: "testTags", 1238 ContentType: "testContentType", 1239 CustomHeaderName: "testCustomHeaderName", 1240 CustomHeaderValue: "testCustomHeaderValue", 1241 }, 1242 expectedJSON: ` 1243 { 1244 "destinationType": "LOGGLY", 1245 "displayName": "testDisplayName", 1246 "endpoint": "testEndpoint", 1247 "authToken": "testAuthToken", 1248 "tags": "testTags", 1249 "contentType": "testContentType", 1250 "customHeaderName": "testCustomHeaderName", 1251 "customHeaderValue": "testCustomHeaderValue" 1252 } 1253 `, 1254 }, 1255 "NewRelicConnector": { 1256 destination: &NewRelicConnector{ 1257 DisplayName: "testDisplayName", 1258 Endpoint: "testEndpoint", 1259 AuthToken: "testAuthToken", 1260 ContentType: "testContentType", 1261 CustomHeaderName: "testCustomHeaderName", 1262 CustomHeaderValue: "testCustomHeaderValue", 1263 }, 1264 expectedJSON: ` 1265 { 1266 "destinationType": "NEWRELIC", 1267 "displayName": "testDisplayName", 1268 "endpoint": "testEndpoint", 1269 "authToken": "testAuthToken", 1270 "contentType": "testContentType", 1271 "customHeaderName": "testCustomHeaderName", 1272 "customHeaderValue": "testCustomHeaderValue" 1273 } 1274 `, 1275 }, 1276 "ElasticsearchConnector": { 1277 destination: &ElasticsearchConnector{ 1278 DisplayName: "testDisplayName", 1279 Endpoint: "testEndpoint", 1280 IndexName: "testIndexName", 1281 UserName: "testUserName", 1282 Password: "testPassword", 1283 ContentType: "testContentType", 1284 CustomHeaderName: "testCustomHeaderName", 1285 CustomHeaderValue: "testCustomHeaderValue", 1286 TLSHostname: "testTLSHostname", 1287 CACert: "testCACert", 1288 ClientCert: "testClientCert", 1289 ClientKey: "testClientKey", 1290 }, 1291 expectedJSON: ` 1292 { 1293 "destinationType": "ELASTICSEARCH", 1294 "displayName": "testDisplayName", 1295 "endpoint": "testEndpoint", 1296 "indexName": "testIndexName", 1297 "userName": "testUserName", 1298 "password": "testPassword", 1299 "contentType": "testContentType", 1300 "customHeaderName": "testCustomHeaderName", 1301 "customHeaderValue": "testCustomHeaderValue", 1302 "tlsHostname": "testTLSHostname", 1303 "caCert": "testCACert", 1304 "clientCert": "testClientCert", 1305 "clientKey": "testClientKey" 1306 } 1307 `, 1308 }, 1309 } 1310 1311 request := CreateStreamRequest{ 1312 Activate: true, 1313 StreamConfiguration: StreamConfiguration{ 1314 DeliveryConfiguration: DeliveryConfiguration{ 1315 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 1316 Format: FormatTypeStructured, 1317 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 1318 UploadFilePrefix: "logs", 1319 UploadFileSuffix: "ak", 1320 }, 1321 Destination: nil, 1322 ContractID: "P-1324", 1323 DatasetFields: []DatasetFieldID{ 1324 { 1325 DatasetFieldID: 1, 1326 }, 1327 { 1328 DatasetFieldID: 2, 1329 }, 1330 { 1331 DatasetFieldID: 3, 1332 }, 1333 }, 1334 1335 NotificationEmails: []string{"test@aka.mai"}, 1336 GroupID: 123231, 1337 Properties: []PropertyID{ 1338 { 1339 PropertyID: 123123, 1340 }, 1341 { 1342 PropertyID: 123123, 1343 }, 1344 }, 1345 StreamName: "TestStream", 1346 }, 1347 } 1348 1349 for name, test := range tests { 1350 t.Run(name, func(t *testing.T) { 1351 request.StreamConfiguration.Destination = test.destination 1352 1353 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1354 var destinationMap map[string]interface{} 1355 err := json.NewDecoder(r.Body).Decode(&destinationMap) 1356 require.NoError(t, err) 1357 1358 var expectedMap interface{} 1359 err = json.Unmarshal([]byte(test.expectedJSON), &expectedMap) 1360 require.NoError(t, err) 1361 1362 res := reflect.DeepEqual(expectedMap, destinationMap["destination"]) 1363 assert.True(t, res) 1364 })) 1365 1366 client := mockAPIClient(t, mockServer) 1367 _, _ = client.CreateStream(context.Background(), request) 1368 }) 1369 } 1370 } 1371 1372 type mockConnector struct { 1373 Called bool 1374 } 1375 1376 func (c *mockConnector) SetDestinationType() { 1377 c.Called = true 1378 } 1379 1380 func (c *mockConnector) Validate() error { 1381 return nil 1382 } 1383 1384 func TestDs_setDestinationTypes(t *testing.T) { 1385 mockConnector := mockConnector{Called: false} 1386 1387 request := CreateStreamRequest{ 1388 Activate: true, 1389 StreamConfiguration: StreamConfiguration{ 1390 DeliveryConfiguration: DeliveryConfiguration{ 1391 Delimiter: DelimiterTypePtr(DelimiterTypeSpace), 1392 Format: FormatTypeStructured, 1393 Frequency: Frequency{IntervalInSeconds: IntervalInSeconds30}, 1394 UploadFilePrefix: "logs", 1395 UploadFileSuffix: "ak", 1396 }, 1397 Destination: AbstractConnector( 1398 &mockConnector, 1399 ), 1400 ContractID: "P-1324", 1401 1402 DatasetFields: []DatasetFieldID{ 1403 { 1404 DatasetFieldID: 1, 1405 }, 1406 { 1407 DatasetFieldID: 2, 1408 }, 1409 { 1410 DatasetFieldID: 3, 1411 }, 1412 }, 1413 1414 NotificationEmails: []string{"test@aka.mai"}, 1415 GroupID: 123231, 1416 Properties: []PropertyID{ 1417 { 1418 PropertyID: 123123, 1419 }, 1420 { 1421 PropertyID: 123123, 1422 }, 1423 }, 1424 StreamName: "TestStream", 1425 }, 1426 } 1427 1428 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1429 w.WriteHeader(http.StatusCreated) 1430 _, err := w.Write([]byte("{}")) 1431 require.NoError(t, err) 1432 })) 1433 client := mockAPIClient(t, mockServer) 1434 _, err := client.CreateStream(context.Background(), request) 1435 require.NoError(t, err) 1436 1437 assert.True(t, mockConnector.Called) 1438 } 1439 1440 func TestDs_ListStreams(t *testing.T) { 1441 tests := map[string]struct { 1442 request ListStreamsRequest 1443 responseStatus int 1444 responseBody string 1445 expectedPath string 1446 expectedResponse []StreamDetails 1447 withError func(*testing.T, error) 1448 }{ 1449 "200 OK": { 1450 request: ListStreamsRequest{}, 1451 responseStatus: http.StatusOK, 1452 responseBody: ` 1453 [ 1454 { 1455 "contractId":"1-ABC", 1456 "createdBy":"abc", 1457 "createdDate":"2022-04-21T17:02:58Z", 1458 "groupId":123, 1459 "latestVersion":15, 1460 "modifiedBy":"abc", 1461 "modifiedDate":"2022-12-26T17:00:03Z", 1462 "productId":"API_Acceleration", 1463 "properties":[ 1464 { 1465 "propertyId":123, 1466 "propertyName":"example.com" 1467 }, 1468 { 1469 "propertyId":123, 1470 "propertyName":"abc.media" 1471 } 1472 ], 1473 "streamId":123, 1474 "streamName":"test-stream-1", 1475 "streamStatus":"ACTIVATED", 1476 "streamVersion":15 1477 }, 1478 { 1479 "contractId":"1-123", 1480 "createdBy":"abc", 1481 "createdDate":"2023-01-03T12:44:15Z", 1482 "groupId":123, 1483 "latestVersion":1, 1484 "modifiedBy":"abc", 1485 "modifiedDate":"2023-01-03T12:44:15Z", 1486 "productId":"Download_Delivery", 1487 "properties":[ 1488 { 1489 "propertyId":123, 1490 "propertyName":"abc" 1491 } 1492 ], 1493 "streamId":123, 1494 "streamName":"test-stream-2", 1495 "streamStatus":"INACTIVE", 1496 "streamVersion":1 1497 } 1498 ] 1499 `, 1500 expectedPath: "/datastream-config-api/v2/log/streams", 1501 expectedResponse: []StreamDetails{ 1502 { 1503 StreamStatus: StreamStatusActivated, 1504 ProductID: "API_Acceleration", 1505 ModifiedBy: "abc", 1506 ModifiedDate: "2022-12-26T17:00:03Z", 1507 ContractID: "1-ABC", 1508 CreatedBy: "abc", 1509 CreatedDate: "2022-04-21T17:02:58Z", 1510 LatestVersion: 15, 1511 GroupID: 123, 1512 Properties: []Property{ 1513 { 1514 PropertyID: 123, 1515 PropertyName: "example.com", 1516 }, 1517 { 1518 PropertyID: 123, 1519 PropertyName: "abc.media", 1520 }, 1521 }, 1522 StreamID: 123, 1523 StreamName: "test-stream-1", 1524 StreamVersion: 15, 1525 }, 1526 { 1527 StreamStatus: StreamStatusInactive, 1528 ProductID: "Download_Delivery", 1529 ModifiedBy: "abc", 1530 ModifiedDate: "2023-01-03T12:44:15Z", 1531 ContractID: "1-123", 1532 CreatedBy: "abc", 1533 CreatedDate: "2023-01-03T12:44:15Z", 1534 LatestVersion: 1, 1535 GroupID: 123, 1536 Properties: []Property{ 1537 { 1538 PropertyID: 123, 1539 PropertyName: "abc", 1540 }, 1541 }, 1542 StreamID: 123, 1543 StreamName: "test-stream-2", 1544 StreamVersion: 1, 1545 }, 1546 }, 1547 }, 1548 "200 OK - with groupId": { 1549 request: ListStreamsRequest{ 1550 GroupID: tools.IntPtr(1234), 1551 }, 1552 responseStatus: http.StatusOK, 1553 responseBody: ` 1554 [ 1555 { 1556 "contractId": "1-123", 1557 "createdBy": "abc", 1558 "createdDate": "2022-07-25T08:36:32Z", 1559 "groupId": 123, 1560 "latestVersion": 2, 1561 "modifiedBy": "abc", 1562 "modifiedDate": "2022-12-26T20:00:02Z", 1563 "productId": "Object_Delivery", 1564 "properties": [ 1565 { 1566 "propertyId": 123, 1567 "propertyName": "abc.net" 1568 } 1569 ], 1570 "streamId": 123, 1571 "streamName": "test-stream", 1572 "streamStatus": "ACTIVATED", 1573 "streamVersion": 2 1574 } 1575 ] 1576 `, 1577 expectedPath: "/datastream-config-api/v2/log/streams?groupId=1234", 1578 expectedResponse: []StreamDetails{ 1579 { 1580 StreamStatus: StreamStatusActivated, 1581 ProductID: "Object_Delivery", 1582 ModifiedBy: "abc", 1583 ModifiedDate: "2022-12-26T20:00:02Z", 1584 ContractID: "1-123", 1585 CreatedBy: "abc", 1586 CreatedDate: "2022-07-25T08:36:32Z", 1587 LatestVersion: 2, 1588 GroupID: 123, 1589 Properties: []Property{ 1590 { 1591 PropertyID: 123, 1592 PropertyName: "abc.net", 1593 }, 1594 }, 1595 StreamID: 123, 1596 StreamName: "test-stream", 1597 StreamVersion: 2, 1598 }, 1599 }, 1600 }, 1601 "400 bad request": { 1602 request: ListStreamsRequest{}, 1603 responseStatus: http.StatusBadRequest, 1604 expectedPath: "/datastream-config-api/v2/log/streams", 1605 responseBody: ` 1606 { 1607 "type": "bad-request", 1608 "title": "Bad Request", 1609 "detail": "bad request", 1610 "instance": "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82", 1611 "statusCode": 400, 1612 "errors": [ 1613 { 1614 "type": "bad-request", 1615 "title": "Bad Request", 1616 "detail": "Stream does not exist. Please provide valid stream." 1617 } 1618 ] 1619 } 1620 `, 1621 withError: func(t *testing.T, err error) { 1622 want := &Error{ 1623 Type: "bad-request", 1624 Title: "Bad Request", 1625 Detail: "bad request", 1626 Instance: "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82", 1627 StatusCode: http.StatusBadRequest, 1628 Errors: []RequestErrors{ 1629 { 1630 Type: "bad-request", 1631 Title: "Bad Request", 1632 Detail: "Stream does not exist. Please provide valid stream.", 1633 }, 1634 }, 1635 } 1636 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 1637 }, 1638 }, 1639 } 1640 1641 for name, test := range tests { 1642 t.Run(name, func(t *testing.T) { 1643 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1644 assert.Equal(t, test.expectedPath, r.URL.String()) 1645 assert.Equal(t, http.MethodGet, r.Method) 1646 w.WriteHeader(test.responseStatus) 1647 _, err := w.Write([]byte(test.responseBody)) 1648 assert.NoError(t, err) 1649 })) 1650 client := mockAPIClient(t, mockServer) 1651 result, err := client.ListStreams(context.Background(), test.request) 1652 if test.withError != nil { 1653 test.withError(t, err) 1654 return 1655 } 1656 require.NoError(t, err) 1657 assert.Equal(t, test.expectedResponse, result) 1658 }) 1659 } 1660 }