github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/telemetry/telemetry_test.go (about) 1 //go:build unit 2 // +build unit 3 4 package telemetry 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "github.com/SAP/jenkins-library/pkg/log" 10 "github.com/SAP/jenkins-library/pkg/orchestrator" 11 "github.com/jarcoal/httpmock" 12 "github.com/sirupsen/logrus" 13 "github.com/sirupsen/logrus/hooks/test" 14 "net/http" 15 "reflect" 16 "regexp" 17 "testing" 18 "time" 19 20 piperhttp "github.com/SAP/jenkins-library/pkg/http" 21 "github.com/stretchr/testify/assert" 22 ) 23 24 func TestTelemetry_Initialize(t *testing.T) { 25 type fields struct { 26 baseData BaseData 27 baseMetaData BaseMetaData 28 data Data 29 provider orchestrator.OrchestratorSpecificConfigProviding 30 disabled bool 31 client *piperhttp.Client 32 CustomReportingDsn string 33 CustomReportingToken string 34 customClient *piperhttp.Client 35 BaseURL string 36 Endpoint string 37 SiteID string 38 } 39 type args struct { 40 telemetryDisabled bool 41 stepName string 42 } 43 tests := []struct { 44 name string 45 fields fields 46 args args 47 want *piperhttp.Client 48 }{ 49 { 50 name: "telemetry disabled", 51 fields: fields{}, 52 args: args{ 53 telemetryDisabled: true, 54 stepName: "test", 55 }, 56 want: nil, 57 }, 58 { 59 name: "telemetry enabled", 60 fields: fields{}, 61 args: args{ 62 telemetryDisabled: false, 63 stepName: "test", 64 }, 65 want: &piperhttp.Client{}, 66 }, 67 } 68 for _, tt := range tests { 69 t.Run(tt.name, func(t *testing.T) { 70 telemetryClient := &Telemetry{} 71 telemetryClient.Initialize(tt.args.telemetryDisabled, tt.args.stepName) 72 // assert 73 assert.NotEqual(t, tt.want, telemetryClient.client) 74 assert.Equal(t, tt.args.stepName, telemetryClient.baseData.StepName) 75 }) 76 } 77 } 78 79 func TestTelemetry_Send(t *testing.T) { 80 type fields struct { 81 baseData BaseData 82 baseMetaData BaseMetaData 83 data Data 84 provider orchestrator.OrchestratorSpecificConfigProviding 85 disabled bool 86 client *piperhttp.Client 87 CustomReportingDsn string 88 CustomReportingToken string 89 BaseURL string 90 Endpoint string 91 SiteID string 92 } 93 tests := []struct { 94 name string 95 fields fields 96 swaCalls int 97 }{ 98 { 99 name: "Telemetry disabled, reporting disabled", 100 fields: fields{ 101 disabled: true, 102 }, 103 swaCalls: 0, 104 }, 105 { 106 name: "Telemetry enabled", 107 fields: fields{ 108 disabled: false, 109 }, 110 swaCalls: 1, 111 }, 112 { 113 name: "Telemetry disabled", 114 fields: fields{ 115 disabled: true, 116 }, 117 swaCalls: 0, 118 }, 119 } 120 121 httpmock.Activate() 122 defer httpmock.DeactivateAndReset() 123 for _, tt := range tests { 124 t.Run(tt.name, func(t *testing.T) { 125 httpmock.Reset() 126 telemetryClient := &Telemetry{disabled: tt.fields.disabled} 127 telemetryClient.Initialize(tt.fields.disabled, tt.name) 128 telemetryClient.CustomReportingDsn = tt.fields.CustomReportingDsn 129 if telemetryClient.client == nil { 130 telemetryClient.client = &piperhttp.Client{} 131 } 132 133 url := telemetryClient.BaseURL + telemetryClient.Endpoint 134 135 telemetryClient.client.SetOptions(piperhttp.ClientOptions{ 136 MaxRequestDuration: 5 * time.Second, 137 Token: "TOKEN", 138 TransportSkipVerification: true, 139 UseDefaultTransport: true, 140 MaxRetries: -1, 141 }) 142 143 if tt.fields.CustomReportingDsn != "" { 144 telemetryClient.customClient = &piperhttp.Client{} 145 telemetryClient.customClient.SetOptions(piperhttp.ClientOptions{ 146 MaxRequestDuration: 5 * time.Second, 147 Token: "TOKEN", 148 TransportSkipVerification: true, 149 UseDefaultTransport: true, // Needed for mocking 150 MaxRetries: -1, 151 }) 152 } 153 154 httpmock.RegisterResponder(http.MethodGet, url, 155 func(req *http.Request) (*http.Response, error) { 156 return httpmock.NewStringResponse(200, "Ok"), nil 157 }, 158 ) 159 httpmock.RegisterResponder(http.MethodPost, telemetryClient.CustomReportingDsn, 160 func(req *http.Request) (*http.Response, error) { 161 return httpmock.NewStringResponse(200, "Ok"), nil 162 }, 163 ) 164 165 // test 166 telemetryClient.SetData(&CustomData{}) 167 telemetryClient.Send() 168 169 // assert 170 info := httpmock.GetCallCountInfo() 171 172 if got := info["GET "+url]; !assert.Equal(t, got, tt.swaCalls) { 173 t.Errorf("Send() = swa calls %v, wanted %v", got, tt.swaCalls) 174 } 175 176 }) 177 } 178 defer httpmock.DeactivateAndReset() 179 } 180 181 func TestSetData(t *testing.T) { 182 type args struct { 183 customData *CustomData 184 } 185 tests := []struct { 186 name string 187 args args 188 want Data 189 }{ 190 { 191 name: "Test", 192 args: args{customData: &CustomData{ 193 Duration: "100", 194 ErrorCode: "0", 195 ErrorCategory: "Undefined", 196 PiperCommitHash: "abcd12345", 197 }, 198 }, 199 want: Data{ 200 BaseData: BaseData{ 201 URL: "", 202 ActionName: "", 203 EventType: "", 204 StepName: "TestCreateDataObject", 205 SiteID: "", 206 PipelineURLHash: "", 207 BuildURLHash: "", 208 Orchestrator: "Unknown", 209 }, 210 BaseMetaData: BaseMetaData{ 211 StepNameLabel: "stepName", 212 StageNameLabel: "stageName", 213 PipelineURLHashLabel: "pipelineUrlHash", 214 BuildURLHashLabel: "buildUrlHash", 215 DurationLabel: "duration", 216 ExitCodeLabel: "exitCode", 217 ErrorCategoryLabel: "errorCategory", 218 OrchestratorLabel: "orchestrator", 219 PiperCommitHashLabel: "piperCommitHash", 220 }, 221 CustomData: CustomData{ 222 Duration: "100", 223 ErrorCode: "0", 224 ErrorCategory: "Undefined", 225 PiperCommitHash: "abcd12345", 226 Custom1Label: "", 227 Custom2Label: "", 228 Custom3Label: "", 229 Custom4Label: "", 230 Custom5Label: "", 231 Custom1: "", 232 Custom2: "", 233 Custom3: "", 234 Custom4: "", 235 Custom5: "", 236 }, 237 }, 238 }, 239 } 240 for _, tt := range tests { 241 t.Run(tt.name, func(t *testing.T) { 242 telemetryClient := Telemetry{} 243 telemetryClient.Initialize(false, "TestCreateDataObject") 244 telemetryClient.baseData = BaseData{ 245 URL: "", 246 ActionName: "", 247 EventType: "", 248 StepName: "TestCreateDataObject", 249 SiteID: "", 250 PipelineURLHash: "", 251 BuildURLHash: "", 252 Orchestrator: "Unknown", 253 } 254 telemetryClient.baseMetaData = baseMetaData 255 telemetryClient.SetData(tt.args.customData) 256 fmt.Println(telemetryClient.data) 257 fmt.Println(tt.want) 258 if !reflect.DeepEqual(telemetryClient.data, tt.want) { 259 t.Errorf("CreateDataObject() t.data= %v, want %v", telemetryClient.data, tt.want) 260 } 261 }) 262 } 263 } 264 265 func TestTelemetry_logStepTelemetryData(t *testing.T) { 266 267 provider := &orchestrator.UnknownOrchestratorConfigProvider{} 268 269 type fields struct { 270 data Data 271 provider orchestrator.OrchestratorSpecificConfigProviding 272 } 273 tests := []struct { 274 name string 275 fields fields 276 fatalError logrus.Fields 277 logOutput string 278 }{ 279 { 280 name: "logging with error, no fatalError set", 281 fields: fields{ 282 data: Data{ 283 BaseData: BaseData{}, 284 BaseMetaData: BaseMetaData{}, 285 CustomData: CustomData{ 286 ErrorCode: "1", 287 Duration: "200", 288 PiperCommitHash: "n/a", 289 }, 290 }, 291 provider: provider, 292 }, 293 }, 294 { 295 name: "logging with error, fatal error set", 296 fields: fields{ 297 data: Data{ 298 BaseData: BaseData{}, 299 BaseMetaData: BaseMetaData{}, 300 CustomData: CustomData{ 301 ErrorCode: "1", 302 Duration: "200", 303 PiperCommitHash: "n/a", 304 }, 305 }, 306 provider: provider, 307 }, 308 fatalError: logrus.Fields{ 309 "message": "Some error happened", 310 "error": "Oh snap!", 311 "category": "undefined", 312 "result": "failure", 313 "correlationId": "test", 314 "time": "0000-00-00 00:00:00.000", 315 }, 316 }, 317 { 318 name: "logging without error", 319 fields: fields{ 320 data: Data{ 321 CustomData: CustomData{ 322 ErrorCode: "0", 323 Duration: "200", 324 PiperCommitHash: "n/a", 325 }, 326 }, 327 provider: provider, 328 }, 329 }, 330 } 331 for _, tt := range tests { 332 t.Run(tt.name, func(t *testing.T) { 333 _, hook := test.NewNullLogger() 334 log.RegisterHook(hook) 335 telemetry := &Telemetry{ 336 data: tt.fields.data, 337 provider: tt.fields.provider, 338 } 339 var re *regexp.Regexp 340 if tt.fatalError != nil { 341 errDetails, _ := json.Marshal(&tt.fatalError) 342 log.SetFatalErrorDetail(errDetails) 343 re = regexp.MustCompile(`Step telemetry data:{"StepStartTime":".*?","PipelineURLHash":"","BuildURLHash":"","StageName":"","StepName":"","ErrorCode":"\d","StepDuration":"\d+","ErrorCategory":"","CorrelationID":"n/a","PiperCommitHash":"n/a","ErrorDetail":{"category":"undefined","correlationId":"test","error":"Oh snap!","message":"Some error happened","result":"failure","time":"0000-00-00 00:00:00.000"}}`) 344 345 } else { 346 re = regexp.MustCompile(`Step telemetry data:{"StepStartTime":".*?","PipelineURLHash":"","BuildURLHash":"","StageName":"","StepName":"","ErrorCode":"\d","StepDuration":"\d+","ErrorCategory":"","CorrelationID":"n/a","PiperCommitHash":"n/a","ErrorDetail":null}`) 347 } 348 telemetry.logStepTelemetryData() 349 assert.Regexp(t, re, hook.LastEntry().Message) 350 hook.Reset() 351 }) 352 } 353 }