github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/whitesource/whitesource_test.go (about) 1 //go:build unit 2 // +build unit 3 4 package whitesource 5 6 import ( 7 "bytes" 8 "fmt" 9 "io" 10 "net/http" 11 "testing" 12 "time" 13 14 piperhttp "github.com/SAP/jenkins-library/pkg/http" 15 "github.com/package-url/packageurl-go" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 type whitesourceMockClient struct { 21 httpMethod string 22 httpStatusCode int 23 urlsCalled string 24 requestBody io.Reader 25 responseBody string 26 requestError error 27 } 28 29 func (c *whitesourceMockClient) SetOptions(opts piperhttp.ClientOptions) { 30 //noop 31 } 32 33 func (c *whitesourceMockClient) SendRequest(method, url string, body io.Reader, header http.Header, cookies []*http.Cookie) (*http.Response, error) { 34 c.httpMethod = method 35 c.urlsCalled = url 36 c.requestBody = body 37 if c.requestError != nil { 38 return &http.Response{}, c.requestError 39 } 40 return &http.Response{StatusCode: c.httpStatusCode, Body: io.NopCloser(bytes.NewReader([]byte(c.responseBody)))}, nil 41 } 42 43 func TestGetProductsMetaInfo(t *testing.T) { 44 myTestClient := whitesourceMockClient{ 45 responseBody: `{ 46 "productVitals":[ 47 { 48 "name": "Test Product", 49 "token": "test_product_token", 50 "creationDate": "2020-01-01 00:00:00", 51 "lastUpdatedDate": "2020-01-01 01:00:00" 52 } 53 ] 54 }`, 55 } 56 57 expectedRequestBody := `{"requestType":"getOrganizationProductVitals","userKey":"test_user_token","orgToken":"test_org_token"}` 58 59 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 60 products, err := sys.GetProductsMetaInfo() 61 assert.NoError(t, err) 62 63 requestBody, err := io.ReadAll(myTestClient.requestBody) 64 assert.NoError(t, err) 65 assert.Equal(t, expectedRequestBody, string(requestBody)) 66 67 assert.NoError(t, err) 68 assert.Equal(t, []Product{{Name: "Test Product", Token: "test_product_token", CreationDate: "2020-01-01 00:00:00", LastUpdateDate: "2020-01-01 01:00:00"}}, products) 69 } 70 71 func TestCreateProduct(t *testing.T) { 72 t.Parallel() 73 t.Run("retryable error", func(t *testing.T) { 74 // init 75 myTestClient := whitesourceMockClient{ 76 responseBody: `{"errorCode":3000,"errorMessage":"WhiteSource backend has a hickup"}`, 77 } 78 expectedRequestBody := `{"requestType":"createProduct","userKey":"test_user_token","productName":"test_product_name","orgToken":"test_org_token"}` 79 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 80 sys.maxRetries = 3 81 sys.retryInterval = 1 * time.Microsecond 82 // test 83 productToken, err := sys.CreateProduct("test_product_name") 84 // assert 85 assert.EqualError(t, err, "WhiteSource request failed after 3 retries: invalid request, error code 3000, message 'WhiteSource backend has a hickup'") 86 requestBody, err := io.ReadAll(myTestClient.requestBody) 87 require.NoError(t, err) 88 assert.Equal(t, "", productToken) 89 assert.Equal(t, expectedRequestBody, string(requestBody)) 90 }) 91 t.Run("not allowed error", func(t *testing.T) { 92 // init 93 myTestClient := whitesourceMockClient{ 94 responseBody: `{"errorCode":5001,"errorMessage":"User is not allowed to perform this action"}`, 95 } 96 expectedRequestBody := `{"requestType":"createProduct","userKey":"test_user_token","productName":"test_product_name","orgToken":"test_org_token"}` 97 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 98 // test 99 productToken, err := sys.CreateProduct("test_product_name") 100 // assert 101 assert.EqualError(t, err, "invalid request, error code 5001, message 'User is not allowed to perform this action'") 102 requestBody, err := io.ReadAll(myTestClient.requestBody) 103 require.NoError(t, err) 104 assert.Equal(t, "", productToken) 105 assert.Equal(t, expectedRequestBody, string(requestBody)) 106 }) 107 t.Run("happy path", func(t *testing.T) { 108 // init 109 myTestClient := whitesourceMockClient{ 110 responseBody: `{"productToken":"test_product_token"}`, 111 } 112 expectedRequestBody := `{"requestType":"createProduct","userKey":"test_user_token","productName":"test_product_name","orgToken":"test_org_token"}` 113 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 114 // test 115 productToken, err := sys.CreateProduct("test_product_name") 116 // assert 117 assert.NoError(t, err) 118 requestBody, err := io.ReadAll(myTestClient.requestBody) 119 require.NoError(t, err) 120 assert.Equal(t, "test_product_token", productToken) 121 assert.Equal(t, expectedRequestBody, string(requestBody)) 122 }) 123 } 124 125 func TestGetMetaInfoForProduct(t *testing.T) { 126 myTestClient := whitesourceMockClient{ 127 responseBody: `{ 128 "productVitals":[ 129 { 130 "name": "Test Product 1", 131 "token": "test_product_token1", 132 "creationDate": "2020-01-01 00:00:00", 133 "lastUpdatedDate": "2020-01-01 01:00:00" 134 }, 135 { 136 "name": "Test Product 2", 137 "token": "test_product_token2", 138 "creationDate": "2020-02-01 00:00:00", 139 "lastUpdatedDate": "2020-02-01 01:00:00" 140 } 141 ] 142 }`, 143 } 144 145 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 146 product, err := sys.GetProductByName("Test Product 2") 147 148 assert.NoError(t, err) 149 assert.Equal(t, product.Name, "Test Product 2") 150 assert.Equal(t, product.Token, "test_product_token2") 151 152 } 153 154 func TestGetProjectsMetaInfo(t *testing.T) { 155 myTestClient := whitesourceMockClient{ 156 responseBody: `{ 157 "projectVitals":[ 158 { 159 "pluginName":"test-plugin", 160 "name": "Test Project", 161 "token": "test_project_token", 162 "uploadedBy": "test_upload_user", 163 "creationDate": "2020-01-01 00:00:00", 164 "lastUpdatedDate": "2020-01-01 01:00:00" 165 } 166 ] 167 }`, 168 } 169 170 expectedRequestBody := `{"requestType":"getProductProjectVitals","userKey":"test_user_token","productToken":"test_product_token","orgToken":"test_org_token"}` 171 172 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 173 projects, err := sys.GetProjectsMetaInfo("test_product_token") 174 assert.NoError(t, err) 175 176 requestBody, err := io.ReadAll(myTestClient.requestBody) 177 assert.NoError(t, err) 178 assert.Equal(t, expectedRequestBody, string(requestBody)) 179 180 assert.NoError(t, err) 181 assert.Equal(t, "Test Project", projects[0].Name) 182 assert.Equal(t, "test_project_token", projects[0].Token) 183 assert.Equal(t, "test-plugin", projects[0].PluginName) 184 assert.Equal(t, "test_upload_user", projects[0].UploadedBy) 185 assert.Equal(t, "2020-01-01 00:00:00", projects[0].CreationDate) 186 assert.Equal(t, "2020-01-01 01:00:00", projects[0].LastUpdateDate) 187 188 } 189 190 func TestGetProjectToken(t *testing.T) { 191 myTestClient := whitesourceMockClient{ 192 responseBody: `{ 193 "projectVitals":[ 194 { 195 "pluginName":"test-plugin", 196 "name": "Test Project1", 197 "token": "test_project_token1", 198 "uploadedBy": "test_upload_user", 199 "creationDate": "2020-01-01 00:00:00", 200 "lastUpdatedDate": "2020-01-01 01:00:00" 201 }, 202 { 203 "pluginName":"test-plugin", 204 "name": "Test Project2", 205 "token": "test_project_token2", 206 "uploadedBy": "test_upload_user", 207 "creationDate": "2020-01-01 00:00:00", 208 "lastUpdatedDate": "2020-01-01 01:00:00" 209 } 210 ] 211 }`, 212 } 213 214 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 215 216 t.Parallel() 217 218 t.Run("find project 1", func(t *testing.T) { 219 projectToken, err := sys.GetProjectToken("test_product_token", "Test Project1") 220 assert.NoError(t, err) 221 assert.Equal(t, "test_project_token1", projectToken) 222 }) 223 224 t.Run("find project 2", func(t *testing.T) { 225 projectToken, err := sys.GetProjectToken("test_product_token", "Test Project2") 226 assert.NoError(t, err) 227 assert.Equal(t, "test_project_token2", projectToken) 228 }) 229 230 t.Run("not finding project 3 is an error", func(t *testing.T) { 231 projectToken, err := sys.GetProjectToken("test_product_token", "Test Project3") 232 assert.NoError(t, err) 233 assert.Equal(t, "", projectToken) 234 }) 235 } 236 237 func TestGetProjectTokens(t *testing.T) { 238 myTestClient := whitesourceMockClient{ 239 responseBody: `{ 240 "projectVitals":[ 241 { 242 "pluginName":"test-plugin", 243 "name": "Test Project1", 244 "token": "test_project_token1", 245 "uploadedBy": "test_upload_user", 246 "creationDate": "2020-01-01 00:00:00", 247 "lastUpdatedDate": "2020-01-01 01:00:00" 248 }, 249 { 250 "pluginName":"test-plugin", 251 "name": "Test Project2", 252 "token": "test_project_token2", 253 "uploadedBy": "test_upload_user", 254 "creationDate": "2020-01-01 00:00:00", 255 "lastUpdatedDate": "2020-01-01 01:00:00" 256 } 257 ] 258 }`, 259 } 260 261 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 262 263 t.Run("success case", func(t *testing.T) { 264 projectTokens, err := sys.GetProjectTokens("test_product_token", []string{"Test Project1", "Test Project2"}) 265 assert.NoError(t, err) 266 assert.Equal(t, []string{"test_project_token1", "test_project_token2"}, projectTokens) 267 }) 268 269 t.Run("no tokens found", func(t *testing.T) { 270 projectTokens, err := sys.GetProjectTokens("test_product_token", []string{"Test Project3"}) 271 assert.Contains(t, fmt.Sprint(err), "no project token(s) found for provided projects") 272 assert.Equal(t, []string{}, projectTokens) 273 }) 274 275 t.Run("not all tokens found", func(t *testing.T) { 276 projectTokens, err := sys.GetProjectTokens("test_product_token", []string{"Test Project1", "Test Project3"}) 277 assert.Contains(t, fmt.Sprint(err), "not all project token(s) found for provided projects") 278 assert.Equal(t, []string{"test_project_token1"}, projectTokens) 279 }) 280 } 281 282 func TestGetProductName(t *testing.T) { 283 myTestClient := whitesourceMockClient{ 284 responseBody: `{ 285 "productTags":[ 286 { 287 "name": "Test Product", 288 "token": "test_product_token" 289 } 290 ] 291 }`, 292 } 293 294 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 295 296 productName, err := sys.GetProductName("test_product_token") 297 assert.NoError(t, err) 298 assert.Equal(t, "Test Product", productName) 299 } 300 301 func TestTransformLibToPurlType(t *testing.T) { 302 tt := []struct { 303 libType string 304 expected string 305 }{ 306 {libType: "Java", expected: packageurl.TypeMaven}, 307 {libType: "MAVEN_ARTIFACT", expected: packageurl.TypeMaven}, 308 {libType: "javascript/Node.js", expected: packageurl.TypeNPM}, 309 {libType: "node_packaged_module", expected: packageurl.TypeNPM}, 310 {libType: "javascript/bower", expected: "bower"}, 311 {libType: "go", expected: packageurl.TypeGolang}, 312 {libType: "go_package", expected: packageurl.TypeGolang}, 313 {libType: "python", expected: packageurl.TypePyPi}, 314 {libType: "python_package", expected: packageurl.TypePyPi}, 315 {libType: "debian", expected: packageurl.TypeDebian}, 316 {libType: "debian_package", expected: packageurl.TypeDebian}, 317 {libType: "docker", expected: packageurl.TypeDocker}, 318 {libType: ".net", expected: packageurl.TypeNuget}, 319 {libType: "dot_net_resource", expected: packageurl.TypeNuget}, 320 } 321 322 for i, test := range tt { 323 assert.Equalf(t, test.expected, transformLibToPurlType(test.libType), "run %v failed", i) 324 } 325 } 326 327 func TestGetProjectHierarchy(t *testing.T) { 328 myTestClient := whitesourceMockClient{ 329 responseBody: `{ 330 "libraries": [ 331 { 332 "keyUuid": "1f9ee6ec-eded-45d3-8fdb-2d0d735e5b14", 333 "keyId": 43, 334 "filename": "log4j-1.2.17.jar", 335 "name": "log4j", 336 "groupId": "log4j", 337 "artifactId": "log4j", 338 "version": "1.2.17", 339 "sha1": "5af35056b4d257e4b64b9e8069c0746e8b08629f", 340 "type": "UNKNOWN_ARTIFACT", 341 "coordinates": "log4j:log4j:1.2.17" 342 }, 343 { 344 "keyUuid": "f362c53f-ce25-4d0c-b53b-ee2768b32d1a", 345 "keyId": 45, 346 "filename": "akka-actor_2.11-2.5.2.jar", 347 "name": "akka-actor", 348 "groupId": "com.typesafe.akka", 349 "artifactId": "akka-actor_2.11", 350 "version": "2.5.2", 351 "sha1": "183ccaed9002bfa10628a5df48e7bac6f1c03f7b", 352 "type": "MAVEN_ARTIFACT", 353 "coordinates": "com.typesafe.akka:akka-actor_2.11:2.5.2", 354 "dependencies": [ 355 { 356 "keyUuid": "49c6840d-bf96-470f-8892-6c2a536c91eb", 357 "keyId": 44, 358 "filename": "scala-library-2.11.11.jar", 359 "name": "Scala Library", 360 "groupId": "org.scala-lang", 361 "artifactId": "scala-library", 362 "version": "2.11.11", 363 "sha1": "e283d2b7fde6504f6a86458b1f6af465353907cc", 364 "type": "MAVEN_ARTIFACT", 365 "coordinates": "org.scala-lang:scala-library:2.11.11" 366 }, 367 { 368 "keyUuid": "e5e730d1-8b41-4d2d-a8c5-610a374b6501", 369 "keyId": 46, 370 "filename": "scala-java8-compat_2.11-0.7.0.jar", 371 "name": "scala-java8-compat_2.11", 372 "groupId": "org.scala-lang.modules", 373 "artifactId": "scala-java8-compat_2.11", 374 "version": "0.7.0", 375 "sha1": "a31b1b36bcf0d53657733b5d40c78d5f090a5dea", 376 "type": "UNKNOWN_ARTIFACT", 377 "coordinates": "org.scala-lang.modules:scala-java8-compat_2.11:0.7.0" 378 }, 379 { 380 "keyUuid": "426c0056-f180-4cac-a9dd-c266a76b32c9", 381 "keyId": 47, 382 "filename": "config-1.3.1.jar", 383 "name": "config", 384 "groupId": "com.typesafe", 385 "artifactId": "config", 386 "version": "1.3.1", 387 "sha1": "2cf7a6cc79732e3bdf1647d7404279900ca63eb0", 388 "type": "UNKNOWN_ARTIFACT", 389 "coordinates": "com.typesafe:config:1.3.1" 390 } 391 ] 392 }, 393 { 394 "keyUuid": "25a8ceaa-4548-4fe4-9819-8658b8cbe9aa", 395 "keyId": 48, 396 "filename": "kafka-clients-0.10.2.1.jar", 397 "name": "Apache Kafka", 398 "groupId": "org.apache.kafka", 399 "artifactId": "kafka-clients", 400 "version": "0.10.2.1", 401 "sha1": "3dd2aa4c9f87ac54175d017bcb63b4bb5dca63dd", 402 "type": "MAVEN_ARTIFACT", 403 "coordinates": "org.apache.kafka:kafka-clients:0.10.2.1", 404 "dependencies": [ 405 { 406 "keyUuid": "71065ffb-e509-4e2d-88bc-9184bc50888d", 407 "keyId": 49, 408 "filename": "lz4-1.3.0.jar", 409 "name": "LZ4 and xxHash", 410 "groupId": "net.jpountz.lz4", 411 "artifactId": "lz4", 412 "version": "1.3.0", 413 "sha1": "c708bb2590c0652a642236ef45d9f99ff842a2ce", 414 "type": "MAVEN_ARTIFACT", 415 "coordinates": "net.jpountz.lz4:lz4:1.3.0" 416 }, 417 { 418 "keyUuid": "e44ab569-de95-4562-8efa-a2ebfe808471", 419 "keyId": 50, 420 "filename": "slf4j-api-1.7.21.jar", 421 "name": "SLF4J API Module", 422 "groupId": "org.slf4j", 423 "artifactId": "slf4j-api", 424 "version": "1.7.21", 425 "sha1": "139535a69a4239db087de9bab0bee568bf8e0b70", 426 "type": "MAVEN_ARTIFACT", 427 "coordinates": "org.slf4j:slf4j-api:1.7.21" 428 }, 429 { 430 "keyUuid": "72ecad5e-9f35-466c-9ed8-0974e7ce4e29", 431 "keyId": 51, 432 "filename": "snappy-java-1.1.2.6.jar", 433 "name": "snappy-java", 434 "groupId": "org.xerial.snappy", 435 "artifactId": "snappy-java", 436 "version": "1.1.2.6", 437 "sha1": "48d92871ca286a47f230feb375f0bbffa83b85f6", 438 "type": "UNKNOWN_ARTIFACT", 439 "coordinates": "org.xerial.snappy:snappy-java:1.1.2.6" 440 } 441 ] 442 } 443 ], 444 "warningMessages":[ 445 "Invalid input: orgToken" 446 ] 447 }`, 448 } 449 450 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 451 452 libraries, err := sys.GetProjectHierarchy("test_project_token", true) 453 assert.NoError(t, err) 454 assert.Equal(t, 3, len(libraries)) 455 assert.Nil(t, libraries[0].Dependencies) 456 assert.NotNil(t, libraries[1].Dependencies) 457 assert.Equal(t, 3, len(libraries[1].Dependencies)) 458 assert.NotNil(t, libraries[2].Dependencies) 459 assert.Equal(t, 3, len(libraries[2].Dependencies)) 460 } 461 462 func TestGetProjectsByIDs(t *testing.T) { 463 responseBody := 464 `{ 465 "projectVitals":[ 466 { 467 "id":1, 468 "name":"prj-1" 469 }, 470 { 471 "id":2, 472 "name":"prj-2" 473 }, 474 { 475 "id":3, 476 "name":"prj-3" 477 }, 478 { 479 "id":4, 480 "name":"prj-4" 481 } 482 ] 483 }` 484 485 t.Parallel() 486 487 t.Run("find projects by ids", func(t *testing.T) { 488 myTestClient := whitesourceMockClient{responseBody: responseBody} 489 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 490 491 projects, err := sys.GetProjectsByIDs("test_product_token", []int64{4, 2}) 492 493 assert.NoError(t, err) 494 assert.Equal(t, []Project{{ID: 2, Name: "prj-2"}, {ID: 4, Name: "prj-4"}}, projects) 495 }) 496 497 t.Run("find no projects by ids", func(t *testing.T) { 498 myTestClient := whitesourceMockClient{responseBody: responseBody} 499 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 500 501 projects, err := sys.GetProjectsByIDs("test_product_token", []int64{5}) 502 503 assert.NoError(t, err) 504 assert.Equal(t, []Project(nil), projects) 505 }) 506 } 507 508 func TestGetProjectAlertsByType(t *testing.T) { 509 t.Parallel() 510 511 t.Run("success case", func(t *testing.T) { 512 responseBody := `{"alerts":[{"type":"SECURITY_VULNERABILITY", "vulnerability":{"name":"testVulnerability1"}}]}` 513 myTestClient := whitesourceMockClient{responseBody: responseBody} 514 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 515 516 alerts, err := sys.GetProjectAlertsByType("test_project_token", "SECURITY_VULNERABILITY") 517 518 assert.NoError(t, err) 519 requestBody, err := io.ReadAll(myTestClient.requestBody) 520 assert.NoError(t, err) 521 assert.Contains(t, string(requestBody), `"requestType":"getProjectAlertsByType"`) 522 assert.Equal(t, []Alert{{Vulnerability: Vulnerability{Name: "testVulnerability1"}, Type: "SECURITY_VULNERABILITY"}}, alerts) 523 }) 524 525 t.Run("error case", func(t *testing.T) { 526 myTestClient := whitesourceMockClient{requestError: fmt.Errorf("request failed")} 527 sys := System{serverURL: "https://my.test.server", httpClient: &myTestClient, orgToken: "test_org_token", userToken: "test_user_token"} 528 529 _, err := sys.GetProjectAlertsByType("test_project_token", "SECURITY_VULNERABILITY") 530 assert.EqualError(t, err, "sending whiteSource request failed: failed to send request to WhiteSource: request failed") 531 532 }) 533 }