github.com/akamai/AkamaiOPEN-edgegrid-golang/v2@v2.17.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/v2/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": {
    27  			request: GetStreamRequest{
    28  				StreamID: 1,
    29  			},
    30  			responseStatus: http.StatusOK,
    31  			responseBody: `
    32  {
    33      "streamId":1,
    34      "streamVersionId":2,
    35      "streamName":"ds2-sample-name",
    36      "datasets":[
    37          {
    38              "datasetGroupName":"group_name_1",
    39              "datasetGroupDescription":"group_desc_1",
    40              "datasetFields":[
    41                  {
    42                      "datasetFieldId":1000,
    43                      "datasetFieldName":"dataset_field_name_1",
    44                      "datasetFieldDescription":"dataset_field_desc_1",
    45                      "order":0
    46                  },
    47                  {
    48                      "datasetFieldId":1002,
    49                      "datasetFieldName":"dataset_field_name_2",
    50                      "datasetFieldDescription":"dataset_field_desc_2",
    51                      "order":1
    52                  }
    53              ]
    54          },
    55          {
    56              "datasetGroupName":"group_name_2",
    57              "datasetFields":[
    58                  {
    59                      "datasetFieldId":1082,
    60                      "datasetFieldName":"dataset_field_name_3",
    61                      "datasetFieldDescription":"dataset_field_desc_3",
    62                      "order":32
    63                  }
    64              ]
    65          }
    66      ],
    67      "connectors":[
    68          {
    69              "connectorType":"S3",
    70              "connectorId":13174,
    71              "bucket":"amzdemods2",
    72              "path":"/sample_path",
    73              "compressLogs":true,
    74              "connectorName":"aws_ds2_amz_demo",
    75              "region":"us-east-1"
    76          }
    77      ],
    78      "productName":"Adaptive Media Delivery",
    79      "productId":"Adaptive_Media_Delivery",
    80      "templateName":"EDGE_LOGS",
    81      "config":{
    82          "delimiter":"SPACE",
    83          "uploadFilePrefix":"ak",
    84          "uploadFileSuffix":"ds",
    85          "frequency":{
    86              "timeInSec":30
    87          },
    88          "useStaticPublicIP":false,
    89          "format":"STRUCTURED"
    90      },
    91      "groupId":171647,
    92      "groupName":"Akamai Data Delivery-P-132NZF456",
    93      "contractId":"P-132NZF456",
    94      "properties":[
    95          {
    96              "propertyId":678154,
    97              "propertyName":"amz.demo.com"
    98          }
    99      ],
   100      "streamType":"RAW_LOGS",
   101      "activationStatus":"ACTIVATED",
   102      "createdBy":"sample_username",
   103      "createdDate":"08-07-2021 06:00:27 GMT",
   104      "modifiedBy":"sample_username2",
   105      "modifiedDate":"08-07-2021 16:00:27 GMT",
   106      "emailIds":"sample_username@akamai.com"
   107  }
   108  `,
   109  			expectedPath: "/datastream-config-api/v1/log/streams/1",
   110  			expectedResponse: &DetailedStreamVersion{
   111  				ActivationStatus: ActivationStatusActivated,
   112  				Config: Config{
   113  					Delimiter: DelimiterTypePtr(DelimiterTypeSpace),
   114  					Format:    FormatTypeStructured,
   115  					Frequency: Frequency{
   116  						TimeInSec: TimeInSec30,
   117  					},
   118  					UploadFilePrefix: "ak",
   119  					UploadFileSuffix: "ds",
   120  				},
   121  				Connectors: []ConnectorDetails{
   122  					{
   123  						ConnectorID:   13174,
   124  						CompressLogs:  true,
   125  						ConnectorName: "aws_ds2_amz_demo",
   126  						ConnectorType: ConnectorTypeS3,
   127  						Path:          "/sample_path",
   128  						Bucket:        "amzdemods2",
   129  						Region:        "us-east-1",
   130  					},
   131  				},
   132  				ContractID:  "P-132NZF456",
   133  				CreatedBy:   "sample_username",
   134  				CreatedDate: "08-07-2021 06:00:27 GMT",
   135  				Datasets: []DataSets{
   136  					{
   137  						DatasetGroupName:        "group_name_1",
   138  						DatasetGroupDescription: "group_desc_1",
   139  						DatasetFields: []DatasetFields{
   140  							{
   141  								DatasetFieldID:          1000,
   142  								DatasetFieldName:        "dataset_field_name_1",
   143  								DatasetFieldDescription: "dataset_field_desc_1",
   144  								Order:                   0,
   145  							},
   146  							{
   147  								DatasetFieldID:          1002,
   148  								DatasetFieldName:        "dataset_field_name_2",
   149  								DatasetFieldDescription: "dataset_field_desc_2",
   150  								Order:                   1,
   151  							},
   152  						},
   153  					},
   154  					{
   155  						DatasetGroupName: "group_name_2",
   156  						DatasetFields: []DatasetFields{
   157  							{
   158  								DatasetFieldID:          1082,
   159  								DatasetFieldName:        "dataset_field_name_3",
   160  								DatasetFieldDescription: "dataset_field_desc_3",
   161  								Order:                   32,
   162  							},
   163  						},
   164  					},
   165  				},
   166  				EmailIDs:     "sample_username@akamai.com",
   167  				GroupID:      171647,
   168  				GroupName:    "Akamai Data Delivery-P-132NZF456",
   169  				ModifiedBy:   "sample_username2",
   170  				ModifiedDate: "08-07-2021 16:00:27 GMT",
   171  				ProductID:    "Adaptive_Media_Delivery",
   172  				ProductName:  "Adaptive Media Delivery",
   173  				Properties: []Property{
   174  					{
   175  						PropertyID:   678154,
   176  						PropertyName: "amz.demo.com",
   177  					},
   178  				},
   179  				StreamID:        1,
   180  				StreamName:      "ds2-sample-name",
   181  				StreamType:      StreamTypeRawLogs,
   182  				StreamVersionID: 2,
   183  				TemplateName:    TemplateNameEdgeLogs,
   184  			},
   185  		},
   186  		"validation error": {
   187  			request: GetStreamRequest{},
   188  			withError: func(t *testing.T, err error) {
   189  				want := ErrStructValidation
   190  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   191  			},
   192  		},
   193  		"400 bad request": {
   194  			request:        GetStreamRequest{StreamID: 12},
   195  			responseStatus: http.StatusBadRequest,
   196  			expectedPath:   "/datastream-config-api/v1/log/streams/12",
   197  			responseBody: `
   198  {
   199  	"type": "bad-request",
   200  	"title": "Bad Request",
   201  	"detail": "bad request",
   202  	"instance": "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82",
   203  	"statusCode": 400,
   204  	"errors": [
   205  		{
   206  			"type": "bad-request",
   207  			"title": "Bad Request",
   208  			"detail": "Stream does not exist. Please provide valid stream."
   209  		}
   210  	]
   211  }
   212  `,
   213  			withError: func(t *testing.T, err error) {
   214  				want := &Error{
   215  					Type:       "bad-request",
   216  					Title:      "Bad Request",
   217  					Detail:     "bad request",
   218  					Instance:   "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82",
   219  					StatusCode: http.StatusBadRequest,
   220  					Errors: []RequestErrors{
   221  						{
   222  							Type:   "bad-request",
   223  							Title:  "Bad Request",
   224  							Detail: "Stream does not exist. Please provide valid stream.",
   225  						},
   226  					},
   227  				}
   228  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   229  			},
   230  		},
   231  	}
   232  
   233  	for name, test := range tests {
   234  		t.Run(name, func(t *testing.T) {
   235  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   236  				assert.Equal(t, test.expectedPath, r.URL.String())
   237  				assert.Equal(t, http.MethodGet, r.Method)
   238  				w.WriteHeader(test.responseStatus)
   239  				_, err := w.Write([]byte(test.responseBody))
   240  				assert.NoError(t, err)
   241  			}))
   242  			client := mockAPIClient(t, mockServer)
   243  			result, err := client.GetStream(context.Background(), test.request)
   244  			if test.withError != nil {
   245  				test.withError(t, err)
   246  				return
   247  			}
   248  			require.NoError(t, err)
   249  			assert.Equal(t, test.expectedResponse, result)
   250  		})
   251  	}
   252  }
   253  
   254  func TestDs_CreateStream(t *testing.T) {
   255  	createStreamRequest := CreateStreamRequest{
   256  		StreamConfiguration: StreamConfiguration{
   257  			ActivateNow: true,
   258  			Config: Config{
   259  				Delimiter:        DelimiterTypePtr(DelimiterTypeSpace),
   260  				Format:           FormatTypeStructured,
   261  				Frequency:        Frequency{TimeInSec: TimeInSec30},
   262  				UploadFilePrefix: "logs",
   263  				UploadFileSuffix: "ak",
   264  			},
   265  			Connectors: []AbstractConnector{
   266  				&S3Connector{
   267  					Path:            "log/edgelogs/{ %Y/%m/%d }",
   268  					ConnectorName:   "S3Destination",
   269  					Bucket:          "datastream.akamai.com",
   270  					Region:          "ap-south-1",
   271  					AccessKey:       "AKIA6DK7TDQLVGZ3TYP1",
   272  					SecretAccessKey: "1T2ll1H4dXWx5itGhpc7FlSbvvOvky1098nTtEMg",
   273  				},
   274  			},
   275  			ContractID: "2-FGHIJ",
   276  			DatasetFieldIDs: []int{
   277  				1002, 1005, 1006, 1008, 1009, 1011, 1012,
   278  				1013, 1014, 1015, 1016, 1017, 1101,
   279  			},
   280  			EmailIDs:     "useremail@akamai.com",
   281  			GroupID:      tools.IntPtr(21484),
   282  			PropertyIDs:  []int{123123, 123123},
   283  			StreamName:   "TestStream",
   284  			StreamType:   StreamTypeRawLogs,
   285  			TemplateName: TemplateNameEdgeLogs,
   286  		},
   287  	}
   288  
   289  	modifyRequest := func(r CreateStreamRequest, opt func(r *CreateStreamRequest)) CreateStreamRequest {
   290  		opt(&r)
   291  		return r
   292  	}
   293  
   294  	tests := map[string]struct {
   295  		request          CreateStreamRequest
   296  		responseStatus   int
   297  		responseBody     string
   298  		expectedPath     string
   299  		expectedBody     string
   300  		expectedResponse *StreamUpdate
   301  		withError        error
   302  	}{
   303  		"202 Accepted": {
   304  			request:        createStreamRequest,
   305  			responseStatus: http.StatusAccepted,
   306  			responseBody: `
   307  {
   308      "streamVersionKey": {
   309          "streamId": 7050,
   310          "streamVersionId": 1
   311      }
   312  }`,
   313  			expectedPath: "/datastream-config-api/v1/log/streams",
   314  			expectedResponse: &StreamUpdate{
   315  				StreamVersionKey: StreamVersionKey{
   316  					StreamID:        7050,
   317  					StreamVersionID: 1,
   318  				},
   319  			},
   320  			expectedBody: `
   321  {
   322      "streamName": "TestStream",
   323      "activateNow": true,
   324      "streamType": "RAW_LOGS",
   325      "templateName": "EDGE_LOGS",
   326      "groupId": 21484,
   327      "contractId": "2-FGHIJ",
   328      "emailIds": "useremail@akamai.com",
   329      "propertyIds": [
   330          123123,
   331  		123123
   332      ],
   333      "datasetFieldIds": [
   334          1002,
   335          1005,
   336          1006,
   337          1008,
   338          1009,
   339          1011,
   340          1012,
   341          1013,
   342          1014,
   343          1015,
   344          1016,
   345          1017,
   346          1101
   347      ],
   348      "config": {
   349          "uploadFilePrefix": "logs",
   350          "uploadFileSuffix": "ak",
   351          "delimiter": "SPACE",
   352          "format": "STRUCTURED",
   353          "frequency": {
   354              "timeInSec": 30
   355          }
   356      },
   357      "connectors": [
   358          {
   359              "path": "log/edgelogs/{ %Y/%m/%d }",
   360              "connectorName": "S3Destination",
   361              "bucket": "datastream.akamai.com",
   362              "region": "ap-south-1",
   363              "accessKey": "AKIA6DK7TDQLVGZ3TYP1",
   364              "secretAccessKey": "1T2ll1H4dXWx5itGhpc7FlSbvvOvky1098nTtEMg",
   365              "connectorType": "S3"
   366          }
   367      ]
   368  }`,
   369  		},
   370  		"validation error - empty request": {
   371  			request:   CreateStreamRequest{},
   372  			withError: ErrStructValidation,
   373  		},
   374  		"validation error - empty connectors list": {
   375  			request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) {
   376  				r.StreamConfiguration.Connectors = []AbstractConnector{}
   377  			}),
   378  			withError: ErrStructValidation,
   379  		},
   380  		"validation error - delimiter with JSON format": {
   381  			request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) {
   382  				r.StreamConfiguration.Config = Config{
   383  					Delimiter:        DelimiterTypePtr(DelimiterTypeSpace),
   384  					Format:           FormatTypeJson,
   385  					Frequency:        Frequency{TimeInSec: TimeInSec30},
   386  					UploadFilePrefix: "logs",
   387  					UploadFileSuffix: "ak",
   388  				}
   389  			}),
   390  			withError: ErrStructValidation,
   391  		},
   392  		"validation error - no delimiter with STRUCTURED format": {
   393  			request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) {
   394  				r.StreamConfiguration.Config = Config{
   395  					Format:           FormatTypeStructured,
   396  					Frequency:        Frequency{TimeInSec: TimeInSec30},
   397  					UploadFilePrefix: "logs",
   398  					UploadFileSuffix: "ak",
   399  				}
   400  			}),
   401  			withError: ErrStructValidation,
   402  		},
   403  		"validation error - missing connector configuration fields": {
   404  			request: modifyRequest(createStreamRequest, func(r *CreateStreamRequest) {
   405  				r.StreamConfiguration.Connectors = []AbstractConnector{
   406  					&S3Connector{
   407  						Path:          "log/edgelogs/{ %Y/%m/%d }",
   408  						ConnectorName: "S3Destination",
   409  						Bucket:        "datastream.akamai.com",
   410  						Region:        "ap-south-1",
   411  					},
   412  				}
   413  			}),
   414  			withError: ErrStructValidation,
   415  		},
   416  		"403 forbidden": {
   417  			request:        createStreamRequest,
   418  			responseStatus: http.StatusForbidden,
   419  			responseBody: `
   420  {
   421  	"type": "forbidden",
   422  	"title": "Forbidden",
   423  	"detail": "forbidden",
   424  	"instance": "72a7654e-3f95-454f-a174-104bc946be52",
   425  	"statusCode": 403,
   426  	"errors": [
   427  		{
   428  			"type": "forbidden",
   429  			"title": "Forbidden",
   430  			"detail": "User is not having access for the group. Access denied, please contact support."
   431  		}
   432  	]
   433  }
   434  `,
   435  			expectedPath: "/datastream-config-api/v1/log/streams",
   436  			withError: &Error{
   437  				Type:       "forbidden",
   438  				Title:      "Forbidden",
   439  				Detail:     "forbidden",
   440  				Instance:   "72a7654e-3f95-454f-a174-104bc946be52",
   441  				StatusCode: http.StatusForbidden,
   442  				Errors: []RequestErrors{
   443  					{
   444  						Type:   "forbidden",
   445  						Title:  "Forbidden",
   446  						Detail: "User is not having access for the group. Access denied, please contact support.",
   447  					},
   448  				},
   449  			},
   450  		},
   451  		"400 bad request": {
   452  			request:        createStreamRequest,
   453  			responseStatus: http.StatusBadRequest,
   454  			responseBody: `
   455  {
   456  	"type": "bad-request",
   457  	"title": "Bad Request",
   458  	"detail": "bad-request",
   459  	"instance": "d0d2497e-ed93-4685-b44c-93a8eb8f3dea",
   460  	"statusCode": 400,
   461  	"errors": [
   462  		{
   463  			"type": "bad-request",
   464  			"title": "Bad Request",
   465  			"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."
   466  		}
   467  	]
   468  }
   469  `,
   470  			expectedPath: "/datastream-config-api/v1/log/streams",
   471  			withError: &Error{
   472  				Type:       "bad-request",
   473  				Title:      "Bad Request",
   474  				Detail:     "bad-request",
   475  				Instance:   "d0d2497e-ed93-4685-b44c-93a8eb8f3dea",
   476  				StatusCode: http.StatusBadRequest,
   477  				Errors: []RequestErrors{
   478  					{
   479  						Type:   "bad-request",
   480  						Title:  "Bad Request",
   481  						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.",
   482  					},
   483  				},
   484  			},
   485  		},
   486  	}
   487  
   488  	for name, test := range tests {
   489  		t.Run(name, func(t *testing.T) {
   490  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   491  				assert.Equal(t, test.expectedPath, r.URL.String())
   492  				assert.Equal(t, http.MethodPost, r.Method)
   493  				w.WriteHeader(test.responseStatus)
   494  				_, err := w.Write([]byte(test.responseBody))
   495  				assert.NoError(t, err)
   496  
   497  				//check request body only if we aren't testing errors
   498  				if test.withError == nil {
   499  					var reqBody interface{}
   500  					err = json.NewDecoder(r.Body).Decode(&reqBody)
   501  					require.NoError(t, err, "Error while decoding request body")
   502  
   503  					var expectedBody interface{}
   504  					err = json.Unmarshal([]byte(test.expectedBody), &expectedBody)
   505  					require.NoError(t, err, "Error while parsing expected body to JSON")
   506  
   507  					assert.Equal(t, expectedBody, reqBody)
   508  				}
   509  			}))
   510  			client := mockAPIClient(t, mockServer)
   511  			result, err := client.CreateStream(context.Background(), test.request)
   512  			if test.withError != nil {
   513  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   514  				return
   515  			}
   516  			require.NoError(t, err)
   517  			assert.Equal(t, test.expectedResponse, result)
   518  		})
   519  	}
   520  }
   521  
   522  func TestDs_UpdateStream(t *testing.T) {
   523  	updateRequest := UpdateStreamRequest{
   524  		StreamID: 7050,
   525  		StreamConfiguration: StreamConfiguration{
   526  			ActivateNow: true,
   527  			Config: Config{
   528  				Delimiter:        DelimiterTypePtr(DelimiterTypeSpace),
   529  				Format:           "STRUCTURED",
   530  				Frequency:        Frequency{TimeInSec: TimeInSec30},
   531  				UploadFilePrefix: "logs",
   532  				UploadFileSuffix: "ak",
   533  			},
   534  			Connectors:      []AbstractConnector{},
   535  			ContractID:      "P-132NZF456",
   536  			DatasetFieldIDs: []int{1, 2, 3},
   537  			EmailIDs:        "test@aka.mai",
   538  			PropertyIDs:     []int{123123, 123123},
   539  			StreamName:      "TestStream",
   540  			StreamType:      "RAW_LOGS",
   541  			TemplateName:    "EDGE_LOGS",
   542  		},
   543  	}
   544  
   545  	modifyRequest := func(r UpdateStreamRequest, opt func(r *UpdateStreamRequest)) UpdateStreamRequest {
   546  		opt(&r)
   547  		return r
   548  	}
   549  
   550  	tests := map[string]struct {
   551  		request          UpdateStreamRequest
   552  		responseStatus   int
   553  		responseBody     string
   554  		expectedPath     string
   555  		expectedResponse *StreamUpdate
   556  		withError        error
   557  	}{
   558  		"202 Accepted": {
   559  			request:        updateRequest,
   560  			responseStatus: http.StatusAccepted,
   561  			responseBody: `
   562  {
   563      "streamVersionKey": {
   564          "streamId": 7050,
   565          "streamVersionId": 2
   566      }
   567  }
   568  `,
   569  			expectedPath: "/datastream-config-api/v1/log/streams/7050",
   570  			expectedResponse: &StreamUpdate{
   571  				StreamVersionKey: StreamVersionKey{
   572  					StreamID:        7050,
   573  					StreamVersionID: 2,
   574  				},
   575  			},
   576  		},
   577  		"validation error - empty request": {
   578  			request:   UpdateStreamRequest{},
   579  			withError: ErrStructValidation,
   580  		},
   581  		"validation error - delimiter with JSON format": {
   582  			request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) {
   583  				r.StreamConfiguration.Config = Config{
   584  					Delimiter:        DelimiterTypePtr(DelimiterTypeSpace),
   585  					Format:           FormatTypeJson,
   586  					Frequency:        Frequency{TimeInSec: TimeInSec30},
   587  					UploadFilePrefix: "logs",
   588  					UploadFileSuffix: "ak",
   589  				}
   590  			}),
   591  			withError: ErrStructValidation,
   592  		},
   593  		"validation error - no delimiter with STRUCTURED format": {
   594  			request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) {
   595  				r.StreamConfiguration.Config = Config{
   596  					Format:           FormatTypeStructured,
   597  					Frequency:        Frequency{TimeInSec: TimeInSec60},
   598  					UploadFilePrefix: "logs",
   599  					UploadFileSuffix: "ak",
   600  				}
   601  			}),
   602  			withError: ErrStructValidation,
   603  		},
   604  		"validation error - groupId modification": {
   605  			request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) {
   606  				r.StreamConfiguration.GroupID = tools.IntPtr(1337)
   607  			}),
   608  			withError: ErrStructValidation,
   609  		},
   610  		"validation error - missing contractId": {
   611  			request: modifyRequest(updateRequest, func(r *UpdateStreamRequest) {
   612  				r.StreamConfiguration.ContractID = ""
   613  			}),
   614  			withError: ErrStructValidation,
   615  		},
   616  		"400 bad request": {
   617  			request:        updateRequest,
   618  			responseStatus: http.StatusBadRequest,
   619  			responseBody: `
   620  {
   621  	"type": "bad-request",
   622  	"title": "Bad Request",
   623  	"detail": "bad request",
   624  	"instance": "a42cc1e6-fea4-4e3a-91ce-9da9819e089a",
   625  	"statusCode": 400,
   626  	"errors": [
   627  		{
   628  			"type": "bad-request",
   629  			"title": "Bad Request",
   630  			"detail": "Stream does not exist. Please provide valid stream."
   631  		}
   632  	]
   633  }
   634  `,
   635  			expectedPath: "/datastream-config-api/v1/log/streams/7050",
   636  			withError: &Error{
   637  				Type:       "bad-request",
   638  				Title:      "Bad Request",
   639  				Detail:     "bad request",
   640  				Instance:   "a42cc1e6-fea4-4e3a-91ce-9da9819e089a",
   641  				StatusCode: http.StatusBadRequest,
   642  				Errors: []RequestErrors{
   643  					{
   644  						Type:   "bad-request",
   645  						Title:  "Bad Request",
   646  						Detail: "Stream does not exist. Please provide valid stream.",
   647  					},
   648  				},
   649  			},
   650  		},
   651  	}
   652  
   653  	for name, test := range tests {
   654  		t.Run(name, func(t *testing.T) {
   655  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   656  				assert.Equal(t, test.expectedPath, r.URL.String())
   657  				assert.Equal(t, http.MethodPut, r.Method)
   658  				w.WriteHeader(test.responseStatus)
   659  				_, err := w.Write([]byte(test.responseBody))
   660  				assert.NoError(t, err)
   661  			}))
   662  			client := mockAPIClient(t, mockServer)
   663  			result, err := client.UpdateStream(context.Background(), test.request)
   664  			if test.withError != nil {
   665  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   666  				return
   667  			}
   668  			require.NoError(t, err)
   669  			assert.Equal(t, test.expectedResponse, result)
   670  		})
   671  	}
   672  }
   673  
   674  func TestDs_DeleteStream(t *testing.T) {
   675  	tests := map[string]struct {
   676  		request          DeleteStreamRequest
   677  		responseStatus   int
   678  		responseBody     string
   679  		expectedPath     string
   680  		expectedResponse *DeleteStreamResponse
   681  		withError        func(*testing.T, error)
   682  	}{
   683  		"200 OK": {
   684  			request: DeleteStreamRequest{
   685  				StreamID: 1,
   686  			},
   687  			responseStatus: http.StatusOK,
   688  			responseBody: `
   689  {
   690      "message": "Success"
   691  }
   692  `,
   693  			expectedPath: "/datastream-config-api/v1/log/streams/1",
   694  			expectedResponse: &DeleteStreamResponse{
   695  				Message: "Success",
   696  			},
   697  		},
   698  		"validation error": {
   699  			request: DeleteStreamRequest{},
   700  			withError: func(t *testing.T, err error) {
   701  				want := ErrStructValidation
   702  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   703  			},
   704  		},
   705  		"400 bad request": {
   706  			request:        DeleteStreamRequest{StreamID: 12},
   707  			responseStatus: http.StatusBadRequest,
   708  			expectedPath:   "/datastream-config-api/v1/log/streams/12",
   709  			responseBody: `
   710  {
   711  	"type": "bad-request",
   712  	"title": "Bad Request",
   713  	"detail": "bad request",
   714  	"instance": "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82",
   715  	"statusCode": 400,
   716  	"errors": [
   717  		{
   718  			"type": "bad-request",
   719  			"title": "Bad Request",
   720  			"detail": "Stream does not exist. Please provide valid stream."
   721  		}
   722  	]
   723  }
   724  `,
   725  			withError: func(t *testing.T, err error) {
   726  				want := &Error{
   727  					Type:       "bad-request",
   728  					Title:      "Bad Request",
   729  					Detail:     "bad request",
   730  					Instance:   "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82",
   731  					StatusCode: 400,
   732  					Errors: []RequestErrors{
   733  						{
   734  							Type:   "bad-request",
   735  							Title:  "Bad Request",
   736  							Detail: "Stream does not exist. Please provide valid stream.",
   737  						},
   738  					},
   739  				}
   740  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
   741  			},
   742  		},
   743  	}
   744  
   745  	for name, test := range tests {
   746  		t.Run(name, func(t *testing.T) {
   747  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   748  				assert.Equal(t, test.expectedPath, r.URL.String())
   749  				assert.Equal(t, http.MethodDelete, r.Method)
   750  				w.WriteHeader(test.responseStatus)
   751  				_, err := w.Write([]byte(test.responseBody))
   752  				assert.NoError(t, err)
   753  			}))
   754  			client := mockAPIClient(t, mockServer)
   755  			result, err := client.DeleteStream(context.Background(), test.request)
   756  			if test.withError != nil {
   757  				test.withError(t, err)
   758  				return
   759  			}
   760  			require.NoError(t, err)
   761  			assert.Equal(t, test.expectedResponse, result)
   762  		})
   763  	}
   764  }
   765  
   766  func TestDs_Connectors(t *testing.T) {
   767  	tests := map[string]struct {
   768  		connector    AbstractConnector
   769  		expectedJSON string
   770  	}{
   771  		"S3Connector": {
   772  			connector: &S3Connector{
   773  				Path:            "testPath",
   774  				ConnectorName:   "testConnectorName",
   775  				Bucket:          "testBucket",
   776  				Region:          "testRegion",
   777  				AccessKey:       "testAccessKey",
   778  				SecretAccessKey: "testSecretKey",
   779  			},
   780  			expectedJSON: `
   781  [{
   782  	"path": "testPath",
   783  	"connectorName": "testConnectorName",
   784  	"bucket": "testBucket",
   785  	"region": "testRegion",
   786  	"accessKey": "testAccessKey",
   787  	"secretAccessKey": "testSecretKey",
   788  	"connectorType": "S3"
   789  }]
   790  `,
   791  		},
   792  		"AzureConnector": {
   793  			connector: &AzureConnector{
   794  				AccountName:   "testAccountName",
   795  				AccessKey:     "testAccessKey",
   796  				ConnectorName: "testConnectorName",
   797  				ContainerName: "testContainerName",
   798  				Path:          "testPath",
   799  			},
   800  			expectedJSON: `
   801  [{
   802      "accountName": "testAccountName",
   803      "accessKey": "testAccessKey",
   804      "connectorName": "testConnectorName",
   805      "containerName": "testContainerName",
   806      "path": "testPath",
   807      "connectorType": "AZURE"
   808  }]
   809  `,
   810  		},
   811  		"DatadogConnector": {
   812  			connector: &DatadogConnector{
   813  				Service:       "testService",
   814  				AuthToken:     "testAuthToken",
   815  				ConnectorName: "testConnectorName",
   816  				URL:           "testURL",
   817  				Source:        "testSource",
   818  				Tags:          "testTags",
   819  				CompressLogs:  false,
   820  			},
   821  			expectedJSON: `
   822  [{
   823      "service": "testService",
   824      "authToken": "testAuthToken",
   825      "connectorName": "testConnectorName",
   826      "url": "testURL",
   827      "source": "testSource",
   828      "tags": "testTags",
   829      "connectorType": "DATADOG",
   830      "compressLogs": false
   831  }]
   832  `,
   833  		},
   834  		"SplunkConnector": {
   835  			connector: &SplunkConnector{
   836  				ConnectorName:       "testConnectorName",
   837  				URL:                 "testURL",
   838  				EventCollectorToken: "testEventCollector",
   839  				CompressLogs:        true,
   840  				CustomHeaderName:    "custom-header",
   841  				CustomHeaderValue:   "custom-header-value",
   842  			},
   843  			expectedJSON: `
   844  [{
   845      "connectorName": "testConnectorName",
   846      "url": "testURL",
   847      "eventCollectorToken": "testEventCollector",
   848      "connectorType": "SPLUNK",
   849      "compressLogs": true,
   850  	"customHeaderName": "custom-header",
   851  	"customHeaderValue": "custom-header-value"
   852  }]
   853  `,
   854  		},
   855  		"GCSConnector": {
   856  			connector: &GCSConnector{
   857  				ConnectorName:      "testConnectorName",
   858  				Bucket:             "testBucket",
   859  				Path:               "testPath",
   860  				ProjectID:          "testProjectID",
   861  				ServiceAccountName: "testServiceAccountName",
   862  				PrivateKey:         "testPrivateKey",
   863  			},
   864  			expectedJSON: `
   865  [{
   866      "connectorType": "GCS",
   867      "connectorName": "testConnectorName",
   868      "bucket": "testBucket",
   869      "path": "testPath",
   870      "projectId": "testProjectID",
   871      "serviceAccountName": "testServiceAccountName",
   872  	"privateKey": "testPrivateKey"
   873  }]
   874  `,
   875  		},
   876  		"CustomHTTPSConnector": {
   877  			connector: &CustomHTTPSConnector{
   878  				AuthenticationType: AuthenticationTypeBasic,
   879  				ConnectorName:      "testConnectorName",
   880  				URL:                "testURL",
   881  				UserName:           "testUserName",
   882  				Password:           "testPassword",
   883  				CompressLogs:       true,
   884  				CustomHeaderName:   "custom-header",
   885  				CustomHeaderValue:  "custom-header-value",
   886  				ContentType:        "application/json",
   887  			},
   888  			expectedJSON: `
   889  [{
   890      "authenticationType": "BASIC",
   891      "connectorName": "testConnectorName",
   892      "url": "testURL",
   893      "userName": "testUserName",
   894      "password": "testPassword",
   895      "connectorType": "HTTPS",
   896      "compressLogs": true,
   897  	"customHeaderName": "custom-header",
   898  	"customHeaderValue": "custom-header-value",
   899  	"contentType": "application/json"
   900  }]
   901  `,
   902  		},
   903  		"SumoLogicConnector": {
   904  			connector: &SumoLogicConnector{
   905  				ConnectorName:     "testConnectorName",
   906  				Endpoint:          "testEndpoint",
   907  				CollectorCode:     "testCollectorCode",
   908  				CompressLogs:      true,
   909  				CustomHeaderName:  "custom-header",
   910  				CustomHeaderValue: "custom-header-value",
   911  				ContentType:       "application/json",
   912  			},
   913  			expectedJSON: `
   914  [{
   915      "connectorType": "SUMO_LOGIC",
   916      "connectorName": "testConnectorName",
   917      "endpoint": "testEndpoint",
   918      "collectorCode": "testCollectorCode",
   919      "compressLogs": true,
   920  	"customHeaderName": "custom-header",
   921  	"customHeaderValue": "custom-header-value",
   922  	"contentType": "application/json"
   923  }]
   924  `,
   925  		},
   926  		"OracleCloudStorageConnector": {
   927  			connector: &OracleCloudStorageConnector{
   928  				AccessKey:       "testAccessKey",
   929  				ConnectorName:   "testConnectorName",
   930  				Path:            "testPath",
   931  				Bucket:          "testBucket",
   932  				Region:          "testRegion",
   933  				SecretAccessKey: "testSecretAccessKey",
   934  				Namespace:       "testNamespace",
   935  			},
   936  			expectedJSON: `
   937  [{
   938      "accessKey": "testAccessKey",
   939      "connectorName": "testConnectorName",
   940      "path": "testPath",
   941      "bucket": "testBucket",
   942      "region": "testRegion",
   943      "secretAccessKey": "testSecretAccessKey",
   944      "connectorType": "Oracle_Cloud_Storage",
   945      "namespace": "testNamespace"
   946  }]
   947  `,
   948  		},
   949  		"LogglyConnector": {
   950  			connector: &LogglyConnector{
   951  				ConnectorName:     "testConnectorName",
   952  				Endpoint:          "testEndpoint",
   953  				AuthToken:         "testAuthToken",
   954  				Tags:              "testTags",
   955  				ContentType:       "testContentType",
   956  				CustomHeaderName:  "testCustomHeaderName",
   957  				CustomHeaderValue: "testCustomHeaderValue",
   958  			},
   959  			expectedJSON: `
   960  [{
   961  	"connectorType": "LOGGLY",
   962  	"connectorName": "testConnectorName",
   963  	"endpoint": "testEndpoint",
   964  	"authToken": "testAuthToken",
   965  	"tags": "testTags",
   966  	"contentType": "testContentType",
   967  	"customHeaderName": "testCustomHeaderName",
   968  	"customHeaderValue": "testCustomHeaderValue"
   969  }]
   970      `,
   971  		},
   972  		"NewRelicConnector": {
   973  			connector: &NewRelicConnector{
   974  				ConnectorName:     "testConnectorName",
   975  				Endpoint:          "testEndpoint",
   976  				AuthToken:         "testAuthToken",
   977  				ContentType:       "testContentType",
   978  				CustomHeaderName:  "testCustomHeaderName",
   979  				CustomHeaderValue: "testCustomHeaderValue",
   980  			},
   981  			expectedJSON: `
   982  [{
   983  	"connectorType": "NEWRELIC",
   984  	"connectorName": "testConnectorName",
   985  	"endpoint": "testEndpoint",
   986  	"authToken": "testAuthToken",
   987  	"contentType": "testContentType",
   988  	"customHeaderName": "testCustomHeaderName",
   989  	"customHeaderValue": "testCustomHeaderValue"
   990  }]
   991      `,
   992  		},
   993  		"ElasticsearchConnector": {
   994  			connector: &ElasticsearchConnector{
   995  				ConnectorName:     "testConnectorName",
   996  				Endpoint:          "testEndpoint",
   997  				IndexName:         "testIndexName",
   998  				UserName:          "testUserName",
   999  				Password:          "testPassword",
  1000  				ContentType:       "testContentType",
  1001  				CustomHeaderName:  "testCustomHeaderName",
  1002  				CustomHeaderValue: "testCustomHeaderValue",
  1003  				TLSHostname:       "testTLSHostname",
  1004  				CACert:            "testCACert",
  1005  				ClientCert:        "testClientCert",
  1006  				ClientKey:         "testClientKey",
  1007  			},
  1008  			expectedJSON: `
  1009  [{
  1010  	"connectorType": "ELASTICSEARCH",
  1011  	"connectorName": "testConnectorName",
  1012  	"endpoint": "testEndpoint",
  1013  	"indexName": "testIndexName",
  1014  	"userName": "testUserName",
  1015  	"password": "testPassword",
  1016  	"contentType": "testContentType",
  1017  	"customHeaderName": "testCustomHeaderName",
  1018  	"customHeaderValue": "testCustomHeaderValue",
  1019  	"tlsHostname": "testTLSHostname",
  1020  	"caCert": "testCACert",
  1021  	"clientCert": "testClientCert",
  1022  	"clientKey": "testClientKey"
  1023  }]
  1024      `,
  1025  		},
  1026  	}
  1027  
  1028  	request := CreateStreamRequest{
  1029  		StreamConfiguration: StreamConfiguration{
  1030  			ActivateNow: true,
  1031  			Config: Config{
  1032  				Delimiter:        DelimiterTypePtr(DelimiterTypeSpace),
  1033  				Format:           FormatTypeStructured,
  1034  				Frequency:        Frequency{TimeInSec: TimeInSec30},
  1035  				UploadFilePrefix: "logs",
  1036  				UploadFileSuffix: "ak",
  1037  			},
  1038  			Connectors:      nil,
  1039  			ContractID:      "P-132NZF456",
  1040  			DatasetFieldIDs: []int{1, 2, 3},
  1041  			EmailIDs:        "test@aka.mai",
  1042  			GroupID:         tools.IntPtr(123231),
  1043  			PropertyIDs:     []int{123123, 123123},
  1044  			StreamName:      "TestStream",
  1045  			StreamType:      StreamTypeRawLogs,
  1046  			TemplateName:    TemplateNameEdgeLogs,
  1047  		},
  1048  	}
  1049  
  1050  	for name, test := range tests {
  1051  		t.Run(name, func(t *testing.T) {
  1052  			request.StreamConfiguration.Connectors = []AbstractConnector{test.connector}
  1053  
  1054  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1055  				var connectorMap map[string]interface{}
  1056  				err := json.NewDecoder(r.Body).Decode(&connectorMap)
  1057  				require.NoError(t, err)
  1058  
  1059  				var expectedMap interface{}
  1060  				err = json.Unmarshal([]byte(test.expectedJSON), &expectedMap)
  1061  				require.NoError(t, err)
  1062  
  1063  				res := reflect.DeepEqual(expectedMap, connectorMap["connectors"])
  1064  				assert.True(t, res)
  1065  			}))
  1066  
  1067  			client := mockAPIClient(t, mockServer)
  1068  			_, _ = client.CreateStream(context.Background(), request)
  1069  		})
  1070  	}
  1071  }
  1072  
  1073  type mockConnector struct {
  1074  	Called bool
  1075  }
  1076  
  1077  func (c *mockConnector) SetConnectorType() {
  1078  	c.Called = true
  1079  }
  1080  
  1081  func (c *mockConnector) Validate() error {
  1082  	return nil
  1083  }
  1084  
  1085  func TestDs_setConnectorTypes(t *testing.T) {
  1086  	mockConnector := mockConnector{Called: false}
  1087  
  1088  	request := CreateStreamRequest{
  1089  		StreamConfiguration: StreamConfiguration{
  1090  			ActivateNow: true,
  1091  			Config: Config{
  1092  				Delimiter:        DelimiterTypePtr(DelimiterTypeSpace),
  1093  				Format:           FormatTypeStructured,
  1094  				Frequency:        Frequency{TimeInSec: TimeInSec30},
  1095  				UploadFilePrefix: "logs",
  1096  				UploadFileSuffix: "ak",
  1097  			},
  1098  			Connectors: []AbstractConnector{
  1099  				&mockConnector,
  1100  			},
  1101  			ContractID:      "P-132NZF456",
  1102  			DatasetFieldIDs: []int{1, 2, 3},
  1103  			EmailIDs:        "test@aka.mai",
  1104  			GroupID:         tools.IntPtr(123231),
  1105  			PropertyIDs:     []int{123123, 123123},
  1106  			StreamName:      "TestStream",
  1107  			StreamType:      StreamTypeRawLogs,
  1108  			TemplateName:    TemplateNameEdgeLogs,
  1109  		},
  1110  	}
  1111  
  1112  	mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1113  		w.WriteHeader(http.StatusAccepted)
  1114  		_, err := w.Write([]byte("{}"))
  1115  		require.NoError(t, err)
  1116  	}))
  1117  	client := mockAPIClient(t, mockServer)
  1118  	_, err := client.CreateStream(context.Background(), request)
  1119  	require.NoError(t, err)
  1120  
  1121  	assert.True(t, mockConnector.Called)
  1122  }
  1123  
  1124  func TestDs_ListStreams(t *testing.T) {
  1125  	tests := map[string]struct {
  1126  		request          ListStreamsRequest
  1127  		responseStatus   int
  1128  		responseBody     string
  1129  		expectedPath     string
  1130  		expectedResponse []StreamDetails
  1131  		withError        func(*testing.T, error)
  1132  	}{
  1133  		"200 OK": {
  1134  			request:        ListStreamsRequest{},
  1135  			responseStatus: http.StatusOK,
  1136  			responseBody: `
  1137  [
  1138    {
  1139      "streamId": 1,
  1140      "streamName": "Stream1",
  1141      "streamVersionId": 2,
  1142      "createdBy": "user1",
  1143      "createdDate": "14-07-2020 07:07:40 GMT",
  1144      "currentVersionId": 2,
  1145      "archived": false,
  1146      "activationStatus": "DEACTIVATED",
  1147      "groupId": 1234,
  1148      "groupName": "Default Group",
  1149      "contractId": "1-ABCDE",
  1150      "connectors": "S3-S1",
  1151      "streamTypeName": "Logs - Raw",
  1152      "properties": [
  1153        {
  1154          "propertyId": 13371337,
  1155          "propertyName": "property_name_1"
  1156        }
  1157      ],
  1158  	"errors": [
  1159        {
  1160          "type": "ACTIVATION_ERROR",
  1161          "title": "Activation/Deactivation Error",
  1162          "detail": "Contact technical support."
  1163        }
  1164  	]
  1165    },
  1166    {
  1167      "streamId": 2,
  1168      "streamName": "Stream2",
  1169      "streamVersionId": 3,
  1170      "createdBy": "user2",
  1171      "createdDate": "24-07-2020 07:07:40 GMT",
  1172      "currentVersionId": 3,
  1173      "archived": true,
  1174      "activationStatus": "ACTIVATED",
  1175      "groupId": 4321,
  1176      "groupName": "Default Group",
  1177      "contractId": "2-ABCDE",
  1178      "connectors": "S3-S2",
  1179      "streamTypeName": "Logs - Raw",
  1180      "properties": [
  1181        {
  1182          "propertyId": 23372337,
  1183          "propertyName": "property_name_2"
  1184        },
  1185        {
  1186          "propertyId": 33373337,
  1187          "propertyName": "property_name_3"
  1188        }
  1189      ]
  1190    }
  1191  ]
  1192  `,
  1193  			expectedPath: "/datastream-config-api/v1/log/streams",
  1194  			expectedResponse: []StreamDetails{
  1195  				{
  1196  					ActivationStatus: ActivationStatusDeactivated,
  1197  					Archived:         false,
  1198  					Connectors:       "S3-S1",
  1199  					ContractID:       "1-ABCDE",
  1200  					CreatedBy:        "user1",
  1201  					CreatedDate:      "14-07-2020 07:07:40 GMT",
  1202  					CurrentVersionID: 2,
  1203  					Errors: []Errors{
  1204  						{
  1205  							Detail: "Contact technical support.",
  1206  							Title:  "Activation/Deactivation Error",
  1207  							Type:   "ACTIVATION_ERROR",
  1208  						},
  1209  					},
  1210  					GroupID:   1234,
  1211  					GroupName: "Default Group",
  1212  					Properties: []Property{
  1213  						{
  1214  							PropertyID:   13371337,
  1215  							PropertyName: "property_name_1",
  1216  						},
  1217  					},
  1218  					StreamID:        1,
  1219  					StreamName:      "Stream1",
  1220  					StreamTypeName:  "Logs - Raw",
  1221  					StreamVersionID: 2,
  1222  				},
  1223  				{
  1224  					ActivationStatus: ActivationStatusActivated,
  1225  					Archived:         true,
  1226  					Connectors:       "S3-S2",
  1227  					ContractID:       "2-ABCDE",
  1228  					CreatedBy:        "user2",
  1229  					CreatedDate:      "24-07-2020 07:07:40 GMT",
  1230  					CurrentVersionID: 3,
  1231  					Errors:           nil,
  1232  					GroupID:          4321,
  1233  					GroupName:        "Default Group",
  1234  					Properties: []Property{
  1235  						{
  1236  							PropertyID:   23372337,
  1237  							PropertyName: "property_name_2",
  1238  						},
  1239  						{
  1240  							PropertyID:   33373337,
  1241  							PropertyName: "property_name_3",
  1242  						},
  1243  					},
  1244  					StreamID:        2,
  1245  					StreamName:      "Stream2",
  1246  					StreamTypeName:  "Logs - Raw",
  1247  					StreamVersionID: 3,
  1248  				},
  1249  			},
  1250  		},
  1251  		"200 OK - with groupId": {
  1252  			request: ListStreamsRequest{
  1253  				GroupID: tools.IntPtr(1234),
  1254  			},
  1255  			responseStatus: http.StatusOK,
  1256  			responseBody: `
  1257  [
  1258    {
  1259      "streamId": 2,
  1260      "streamName": "Stream2",
  1261      "streamVersionId": 3,
  1262      "createdBy": "user2",
  1263      "createdDate": "24-07-2020 07:07:40 GMT",
  1264      "currentVersionId": 3,
  1265      "archived": true,
  1266      "activationStatus": "ACTIVATED",
  1267      "groupId": 1234,
  1268      "groupName": "Default Group",
  1269      "contractId": "2-ABCDE",
  1270      "connectors": "S3-S2",
  1271      "streamTypeName": "Logs - Raw",
  1272      "properties": [
  1273        {
  1274          "propertyId": 23372337,
  1275          "propertyName": "property_name_2"
  1276        },
  1277        {
  1278          "propertyId": 33373337,
  1279          "propertyName": "property_name_3"
  1280        }
  1281      ]
  1282    }
  1283  ]
  1284  `,
  1285  			expectedPath: "/datastream-config-api/v1/log/streams?groupId=1234",
  1286  			expectedResponse: []StreamDetails{
  1287  				{
  1288  					ActivationStatus: ActivationStatusActivated,
  1289  					Archived:         true,
  1290  					Connectors:       "S3-S2",
  1291  					ContractID:       "2-ABCDE",
  1292  					CreatedBy:        "user2",
  1293  					CreatedDate:      "24-07-2020 07:07:40 GMT",
  1294  					CurrentVersionID: 3,
  1295  					Errors:           nil,
  1296  					GroupID:          1234,
  1297  					GroupName:        "Default Group",
  1298  					Properties: []Property{
  1299  						{
  1300  							PropertyID:   23372337,
  1301  							PropertyName: "property_name_2",
  1302  						},
  1303  						{
  1304  							PropertyID:   33373337,
  1305  							PropertyName: "property_name_3",
  1306  						},
  1307  					},
  1308  					StreamID:        2,
  1309  					StreamName:      "Stream2",
  1310  					StreamTypeName:  "Logs - Raw",
  1311  					StreamVersionID: 3,
  1312  				},
  1313  			},
  1314  		},
  1315  		"400 bad request": {
  1316  			request:        ListStreamsRequest{},
  1317  			responseStatus: http.StatusBadRequest,
  1318  			expectedPath:   "/datastream-config-api/v1/log/streams",
  1319  			responseBody: `
  1320  {
  1321  	"type": "bad-request",
  1322  	"title": "Bad Request",
  1323  	"detail": "bad request",
  1324  	"instance": "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82",
  1325  	"statusCode": 400,
  1326  	"errors": [
  1327  		{
  1328  			"type": "bad-request",
  1329  			"title": "Bad Request",
  1330  			"detail": "Stream does not exist. Please provide valid stream."
  1331  		}
  1332  	]
  1333  }
  1334  `,
  1335  			withError: func(t *testing.T, err error) {
  1336  				want := &Error{
  1337  					Type:       "bad-request",
  1338  					Title:      "Bad Request",
  1339  					Detail:     "bad request",
  1340  					Instance:   "82b67b97-d98d-4bee-ac1e-ef6eaf7cac82",
  1341  					StatusCode: http.StatusBadRequest,
  1342  					Errors: []RequestErrors{
  1343  						{
  1344  							Type:   "bad-request",
  1345  							Title:  "Bad Request",
  1346  							Detail: "Stream does not exist. Please provide valid stream.",
  1347  						},
  1348  					},
  1349  				}
  1350  				assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err)
  1351  			},
  1352  		},
  1353  	}
  1354  
  1355  	for name, test := range tests {
  1356  		t.Run(name, func(t *testing.T) {
  1357  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1358  				assert.Equal(t, test.expectedPath, r.URL.String())
  1359  				assert.Equal(t, http.MethodGet, r.Method)
  1360  				w.WriteHeader(test.responseStatus)
  1361  				_, err := w.Write([]byte(test.responseBody))
  1362  				assert.NoError(t, err)
  1363  			}))
  1364  			client := mockAPIClient(t, mockServer)
  1365  			result, err := client.ListStreams(context.Background(), test.request)
  1366  			if test.withError != nil {
  1367  				test.withError(t, err)
  1368  				return
  1369  			}
  1370  			require.NoError(t, err)
  1371  			assert.Equal(t, test.expectedResponse, result)
  1372  		})
  1373  	}
  1374  }