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  }