github.com/jaylevin/jenkins-library@v1.230.4/pkg/blackduck/blackduck_test.go (about) 1 package blackduck 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "net/http" 9 "testing" 10 "time" 11 12 piperhttp "github.com/SAP/jenkins-library/pkg/http" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 type httpMockClient struct { 17 responseBodyForURL map[string]string 18 errorMessageForURL map[string]string 19 header map[string]http.Header 20 } 21 22 func (c *httpMockClient) SetOptions(opts piperhttp.ClientOptions) {} 23 func (c *httpMockClient) SendRequest(method, url string, body io.Reader, header http.Header, cookies []*http.Cookie) (*http.Response, error) { 24 c.header[url] = header 25 response := http.Response{ 26 StatusCode: 200, 27 Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), 28 } 29 30 if c.errorMessageForURL[url] != "" { 31 response.StatusCode = 400 32 return &response, fmt.Errorf(c.errorMessageForURL[url]) 33 } 34 35 if c.responseBodyForURL[url] != "" { 36 response.Body = ioutil.NopCloser(bytes.NewReader([]byte(c.responseBodyForURL[url]))) 37 return &response, nil 38 } 39 40 return &response, nil 41 } 42 43 const ( 44 authContent = `{ 45 "bearerToken":"bearerTestToken", 46 "expiresInMilliseconds":7199997 47 }` 48 projectContent = `{ 49 "totalCount": 1, 50 "items": [ 51 { 52 "name": "SHC-PiperTest", 53 "_meta": { 54 "href": "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf", 55 "links": [ 56 { 57 "rel": "versions", 58 "href": "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions" 59 } 60 ] 61 } 62 } 63 ] 64 }` 65 projectVersionContent = `{ 66 "totalCount": 1, 67 "items": [ 68 { 69 "versionName": "1.0", 70 "_meta": { 71 "href": "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36", 72 "links": [ 73 { 74 "rel": "components", 75 "href": "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/components" 76 }, 77 { 78 "rel": "vulnerable-components", 79 "href": "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/vunlerable-bom-components" 80 }, 81 { 82 "rel": "policy-status", 83 "href": "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/policy-status" 84 } 85 ] 86 } 87 } 88 ] 89 }` 90 ) 91 92 func TestGetProject(t *testing.T) { 93 t.Run("success", func(t *testing.T) { 94 myTestClient := httpMockClient{ 95 responseBodyForURL: map[string]string{ 96 "https://my.blackduck.system/api/tokens/authenticate": authContent, 97 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 98 }, 99 header: map[string]http.Header{}, 100 } 101 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 102 project, err := bdClient.GetProject("SHC-PiperTest") 103 assert.NoError(t, err) 104 assert.Equal(t, "SHC-PiperTest", project.Name) 105 assert.Equal(t, "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions", project.Metadata.Links[0].Href) 106 headerExpected := http.Header{"Authorization": []string{"Bearer bearerTestToken"}, "Accept": {"application/vnd.blackducksoftware.project-detail-4+json"}} 107 assert.Equal(t, headerExpected, myTestClient.header["https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest"]) 108 }) 109 110 t.Run("failure - not found", func(t *testing.T) { 111 myTestClient := httpMockClient{ 112 responseBodyForURL: map[string]string{ 113 "https://my.blackduck.system/api/tokens/authenticate": authContent, 114 }, 115 errorMessageForURL: map[string]string{ 116 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": "not found", 117 }, 118 header: map[string]http.Header{}, 119 } 120 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 121 _, err := bdClient.GetProject("SHC-PiperTest") 122 assert.Contains(t, fmt.Sprint(err), "failed to get project 'SHC-PiperTest'") 123 }) 124 125 t.Run("failure - 0 results", func(t *testing.T) { 126 myTestClient := httpMockClient{ 127 responseBodyForURL: map[string]string{ 128 "https://my.blackduck.system/api/tokens/authenticate": authContent, 129 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": `{ 130 "totalCount": 0, 131 "items": [] 132 }`, 133 }, 134 header: map[string]http.Header{}, 135 } 136 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 137 _, err := bdClient.GetProject("SHC-PiperTest") 138 assert.Contains(t, fmt.Sprint(err), "project 'SHC-PiperTest' not found") 139 }) 140 141 t.Run("failure - unmarshalling", func(t *testing.T) { 142 myTestClient := httpMockClient{ 143 responseBodyForURL: map[string]string{ 144 "https://my.blackduck.system/api/tokens/authenticate": authContent, 145 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": "", 146 }, 147 header: map[string]http.Header{}, 148 } 149 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 150 _, err := bdClient.GetProject("SHC-PiperTest") 151 assert.Contains(t, fmt.Sprint(err), "failed to retrieve details for project 'SHC-PiperTest'") 152 }) 153 } 154 155 func TestGetProjectVersion(t *testing.T) { 156 t.Run("success", func(t *testing.T) { 157 myTestClient := httpMockClient{ 158 responseBodyForURL: map[string]string{ 159 "https://my.blackduck.system/api/tokens/authenticate": authContent, 160 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 161 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 162 }, 163 header: map[string]http.Header{}, 164 } 165 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 166 projectVersion, err := bdClient.GetProjectVersion("SHC-PiperTest", "1.0") 167 assert.NoError(t, err) 168 assert.Equal(t, "1.0", projectVersion.Name) 169 assert.Equal(t, "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36", projectVersion.Metadata.Href) 170 headerExpected := http.Header{"Authorization": []string{"Bearer bearerTestToken"}, "Accept": {"application/vnd.blackducksoftware.project-detail-4+json"}} 171 assert.Equal(t, headerExpected, myTestClient.header["https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0"]) 172 }) 173 174 t.Run("failure - project not found", func(t *testing.T) { 175 myTestClient := httpMockClient{ 176 responseBodyForURL: map[string]string{ 177 "https://my.blackduck.system/api/tokens/authenticate": authContent, 178 }, 179 errorMessageForURL: map[string]string{ 180 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": "not found", 181 }, 182 header: map[string]http.Header{}, 183 } 184 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 185 _, err := bdClient.GetProjectVersion("SHC-PiperTest", "1.0") 186 assert.Contains(t, fmt.Sprint(err), "failed to get project 'SHC-PiperTest'") 187 }) 188 189 t.Run("failure - version not found", func(t *testing.T) { 190 myTestClient := httpMockClient{ 191 responseBodyForURL: map[string]string{ 192 "https://my.blackduck.system/api/tokens/authenticate": authContent, 193 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 194 }, 195 errorMessageForURL: map[string]string{ 196 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": "not found", 197 }, 198 header: map[string]http.Header{}, 199 } 200 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 201 _, err := bdClient.GetProjectVersion("SHC-PiperTest", "1.0") 202 assert.Contains(t, fmt.Sprint(err), "failed to get project version 'SHC-PiperTest:1.0'") 203 }) 204 205 t.Run("failure - 0 results", func(t *testing.T) { 206 myTestClient := httpMockClient{ 207 responseBodyForURL: map[string]string{ 208 "https://my.blackduck.system/api/tokens/authenticate": authContent, 209 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 210 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": `{ 211 "totalCount": 0, 212 "items": [] 213 }`, 214 }, 215 header: map[string]http.Header{}, 216 } 217 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 218 _, err := bdClient.GetProjectVersion("SHC-PiperTest", "1.0") 219 assert.Contains(t, fmt.Sprint(err), "project version 'SHC-PiperTest:1.0' not found") 220 }) 221 222 t.Run("failure - unmarshalling", func(t *testing.T) { 223 myTestClient := httpMockClient{ 224 responseBodyForURL: map[string]string{ 225 "https://my.blackduck.system/api/tokens/authenticate": authContent, 226 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 227 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": "", 228 }, 229 header: map[string]http.Header{}, 230 } 231 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 232 _, err := bdClient.GetProjectVersion("SHC-PiperTest", "1.0") 233 assert.Contains(t, fmt.Sprint(err), "failed to retrieve details for project version 'SHC-PiperTest:1.0'") 234 }) 235 } 236 237 func TestGetVulnerabilities(t *testing.T) { 238 t.Run("success", func(t *testing.T) { 239 myTestClient := httpMockClient{ 240 responseBodyForURL: map[string]string{ 241 "https://my.blackduck.system/api/tokens/authenticate": authContent, 242 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 243 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 244 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/vunlerable-bom-components?limit=999&offset=0": `{ 245 "totalCount": 1, 246 "items": [ 247 { 248 "componentName": "Spring Framework", 249 "componentVersionName": "5.3.2", 250 "vulnerabilityWithRemediation" : { 251 "vulnerabilityName" : "BDSA-2019-2021", 252 "baseScore" : 1.0, 253 "overallScore" : 1.0, 254 "severity" : "HIGH", 255 "remediationStatus" : "IGNORED", 256 "description" : "description" 257 } 258 } 259 ] 260 }`, 261 }, 262 header: map[string]http.Header{}, 263 } 264 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 265 vulns, err := bdClient.GetVulnerabilities("SHC-PiperTest", "1.0") 266 assert.NoError(t, err) 267 assert.GreaterOrEqual(t, vulns.TotalCount, 1) 268 }) 269 270 t.Run("Success - 0 vulns", func(t *testing.T) { 271 myTestClient := httpMockClient{ 272 responseBodyForURL: map[string]string{ 273 "https://my.blackduck.system/api/tokens/authenticate": authContent, 274 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 275 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 276 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/vunlerable-bom-components?limit=999&offset=0": `{"totalCount":0,"items":[]}`, 277 }, 278 header: map[string]http.Header{}, 279 } 280 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 281 vulns, err := bdClient.GetVulnerabilities("SHC-PiperTest", "1.0") 282 assert.NoError(t, err) 283 assert.Equal(t, vulns.TotalCount, 0) 284 }) 285 286 t.Run("Failure - unmarshalling", func(t *testing.T) { 287 myTestClient := httpMockClient{ 288 responseBodyForURL: map[string]string{ 289 "https://my.blackduck.system/api/tokens/authenticate": authContent, 290 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 291 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 292 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/vunlerable-bom-components?limit=999&offset=0": "", 293 }, 294 header: map[string]http.Header{}, 295 } 296 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 297 _, err := bdClient.GetVulnerabilities("SHC-PiperTest", "1.0") 298 assert.Contains(t, fmt.Sprint(err), "failed to retrieve Vulnerability details for project version 'SHC-PiperTest:1.0'") 299 }) 300 } 301 302 func TestGetComponents(t *testing.T) { 303 t.Run("success", func(t *testing.T) { 304 myTestClient := httpMockClient{ 305 responseBodyForURL: map[string]string{ 306 "https://my.blackduck.system/api/tokens/authenticate": authContent, 307 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 308 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 309 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/components?limit=999&offset=0": `{ 310 "totalCount": 2, 311 "items" : [ 312 { 313 "componentName": "Spring Framework", 314 "componentVersionName": "5.3.9" 315 }, { 316 "componentName": "Apache Tomcat", 317 "componentVersionName": "9.0.52" 318 } 319 ] 320 }`, 321 }, 322 header: map[string]http.Header{}, 323 } 324 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 325 components, err := bdClient.GetComponents("SHC-PiperTest", "1.0") 326 assert.NoError(t, err) 327 assert.GreaterOrEqual(t, components.TotalCount, 2) 328 }) 329 330 t.Run("Failure - 0 components", func(t *testing.T) { 331 myTestClient := httpMockClient{ 332 responseBodyForURL: map[string]string{ 333 "https://my.blackduck.system/api/tokens/authenticate": authContent, 334 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 335 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 336 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/components?limit=999&offset=0": `{ 337 "totalCount": 0, 338 "items" : []}`, 339 }, 340 header: map[string]http.Header{}, 341 } 342 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 343 components, err := bdClient.GetComponents("SHC-PiperTest", "1.0") 344 assert.Contains(t, fmt.Sprint(err), "No Components found for project version 'SHC-PiperTest:1.0'") 345 assert.Nilf(t, components, "Expected Components to be nil") 346 }) 347 348 t.Run("Failure - unmarshalling", func(t *testing.T) { 349 myTestClient := httpMockClient{ 350 responseBodyForURL: map[string]string{ 351 "https://my.blackduck.system/api/tokens/authenticate": authContent, 352 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 353 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 354 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/components?limit=999&offset=0": "", 355 }, 356 header: map[string]http.Header{}, 357 } 358 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 359 components, err := bdClient.GetComponents("SHC-PiperTest", "1.0") 360 assert.Contains(t, fmt.Sprint(err), "failed to retrieve component details for project version 'SHC-PiperTest:1.0'") 361 assert.Nilf(t, components, "Expected Components to be nil") 362 }) 363 } 364 365 func TestGetComponentsWithLicensePolicyRule(t *testing.T) { 366 t.Run("success", func(t *testing.T) { 367 myTestClient := httpMockClient{ 368 responseBodyForURL: map[string]string{ 369 "https://my.blackduck.system/api/tokens/authenticate": authContent, 370 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 371 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 372 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/components?filter=policyCategory%3Alicense&limit=999&offset=0": `{ 373 "totalCount": 2, 374 "items" : [ 375 { 376 "componentName": "Spring Framework", 377 "componentVersionName": "5.3.9", 378 "policyStatus": "IN_VIOLATION" 379 }, { 380 "componentName": "Apache Tomcat", 381 "componentVersionName": "9.0.52", 382 "policyStatus": "NOT_IN_VIOLATION" 383 } 384 ] 385 }`, 386 }, 387 header: map[string]http.Header{}, 388 } 389 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 390 components, err := bdClient.GetComponentsWithLicensePolicyRule("SHC-PiperTest", "1.0") 391 assert.NoError(t, err) 392 assert.GreaterOrEqual(t, components.TotalCount, 2) 393 assert.Equal(t, components.Items[0].PolicyStatus, "IN_VIOLATION") 394 }) 395 396 t.Run("Failure - 0 components", func(t *testing.T) { 397 myTestClient := httpMockClient{ 398 responseBodyForURL: map[string]string{ 399 "https://my.blackduck.system/api/tokens/authenticate": authContent, 400 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 401 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 402 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/components?filter=policyCategory%3Alicense&limit=999&offset=0": `{ 403 "totalCount": 0, 404 "items" : []}`, 405 }, 406 header: map[string]http.Header{}, 407 } 408 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 409 components, err := bdClient.GetComponentsWithLicensePolicyRule("SHC-PiperTest", "1.0") 410 assert.NoError(t, err) 411 assert.NotNil(t, components) 412 assert.Equal(t, components.TotalCount, 0) 413 }) 414 415 t.Run("Failure - unmarshalling", func(t *testing.T) { 416 myTestClient := httpMockClient{ 417 responseBodyForURL: map[string]string{ 418 "https://my.blackduck.system/api/tokens/authenticate": authContent, 419 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 420 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 421 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/components?filter=policyCategory%3Alicense&limit=999&offset=0": "", 422 }, 423 header: map[string]http.Header{}, 424 } 425 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 426 components, err := bdClient.GetComponentsWithLicensePolicyRule("SHC-PiperTest", "1.0") 427 assert.Contains(t, fmt.Sprint(err), "failed to retrieve component details for project version 'SHC-PiperTest:1.0'") 428 assert.Nilf(t, components, "Expected Components to be nil") 429 }) 430 } 431 432 func TestGetPolicyStatus(t *testing.T) { 433 t.Run("success", func(t *testing.T) { 434 myTestClient := httpMockClient{ 435 responseBodyForURL: map[string]string{ 436 "https://my.blackduck.system/api/tokens/authenticate": authContent, 437 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 438 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 439 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/policy-status": `{ 440 "overallStatus": "IN_VIOLATION", 441 "componentVersionPolicyViolationDetails": { 442 "name": "IN_VIOLATION", 443 "severityLevels": [ 444 { "name": "BLOCKER", "value": 16 }, 445 { "name": "CRITICAL", "value": 1 }, 446 { "name": "MAJOR", "value": 0 }, 447 { "name": "MINOR", "value": 0 }, 448 { "name": "TRIVIAL", "value": 0 }, 449 { "name": "UNSPECIFIED", "value": 0 }, 450 { "name": "OK", "value": 0} 451 ] 452 } 453 }`, 454 }, 455 header: map[string]http.Header{}, 456 } 457 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 458 policyStatus, err := bdClient.GetPolicyStatus("SHC-PiperTest", "1.0") 459 assert.NoError(t, err) 460 assert.Equal(t, policyStatus.OverallStatus, "IN_VIOLATION") 461 assert.Equal(t, len(policyStatus.PolicyVersionDetails.SeverityLevels), 7) 462 assert.Equal(t, policyStatus.PolicyVersionDetails.Name, "IN_VIOLATION") 463 }) 464 465 t.Run("Failure - unmarshalling", func(t *testing.T) { 466 myTestClient := httpMockClient{ 467 responseBodyForURL: map[string]string{ 468 "https://my.blackduck.system/api/tokens/authenticate": authContent, 469 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 470 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 471 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36/policy-status": "", 472 }, 473 header: map[string]http.Header{}, 474 } 475 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 476 policyStatus, err := bdClient.GetPolicyStatus("SHC-PiperTest", "1.0") 477 assert.Contains(t, fmt.Sprint(err), "failed to retrieve Policy violation details for project version 'SHC-PiperTest:1.0'") 478 assert.Nilf(t, policyStatus, "Expected Components to be nil") 479 }) 480 } 481 482 func TestGetProjectVersionLink(t *testing.T) { 483 t.Run("Success Case", func(t *testing.T) { 484 myTestClient := httpMockClient{ 485 responseBodyForURL: map[string]string{ 486 "https://my.blackduck.system/api/tokens/authenticate": authContent, 487 "https://my.blackduck.system/api/projects?q=name%3ASHC-PiperTest": projectContent, 488 "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions?limit=100&offset=0": projectVersionContent, 489 }, 490 header: map[string]http.Header{}, 491 } 492 bdClient := NewClient("token", "https://my.blackduck.system", &myTestClient) 493 link, err := bdClient.GetProjectVersionLink("SHC-PiperTest", "1.0") 494 assert.NoError(t, err) 495 assert.Equal(t, link, "https://my.blackduck.system/api/projects/5ca86e11-1983-4e7b-97d4-eb1a0aeffbbf/versions/a6c94786-0ee6-414f-9054-90d549c69c36") 496 }) 497 } 498 499 func TestAuthenticate(t *testing.T) { 500 t.Run("success", func(t *testing.T) { 501 myTestClient := httpMockClient{ 502 responseBodyForURL: map[string]string{ 503 "https://my.blackduck.system/api/tokens/authenticate": authContent, 504 }, 505 header: map[string]http.Header{}, 506 } 507 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 508 err := bdClient.authenticate() 509 assert.NoError(t, err) 510 headerExpected := http.Header{"Authorization": {"token myTestToken"}, "Accept": {"application/vnd.blackducksoftware.user-4+json"}} 511 assert.Equal(t, headerExpected, myTestClient.header["https://my.blackduck.system/api/tokens/authenticate"]) 512 }) 513 514 t.Run("authentication failure", func(t *testing.T) { 515 myTestClient := httpMockClient{ 516 errorMessageForURL: map[string]string{ 517 "https://my.blackduck.system/api/tokens/authenticate": "not authorized", 518 }, 519 header: map[string]http.Header{}, 520 } 521 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 522 err := bdClient.authenticate() 523 assert.EqualError(t, err, "authentication to BlackDuck API failed: request to BlackDuck API failed: not authorized") 524 }) 525 526 t.Run("parse failure", func(t *testing.T) { 527 myTestClient := httpMockClient{ 528 responseBodyForURL: map[string]string{ 529 "https://my.blackduck.system/api/tokens/authenticate": "", 530 }, 531 header: map[string]http.Header{}, 532 } 533 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 534 err := bdClient.authenticate() 535 assert.Contains(t, fmt.Sprint(err), "failed to parse BlackDuck response") 536 }) 537 } 538 539 func TestSendRequest(t *testing.T) { 540 myTestClient := httpMockClient{ 541 responseBodyForURL: map[string]string{ 542 "https://my.blackduck.system/api/endpoint": "testContent", 543 "https://my.blackduck.system/api/endpoint?q=test": "testContentQuery", 544 }, 545 header: map[string]http.Header{}, 546 } 547 bdClient := NewClient("myTestToken", "https://my.blackduck.system", &myTestClient) 548 549 t.Run("simple", func(t *testing.T) { 550 responseBody, err := bdClient.sendRequest(http.MethodGet, "api/endpoint", map[string]string{}, nil, http.Header{}) 551 assert.NoError(t, err) 552 assert.Equal(t, "testContent", string(responseBody)) 553 }) 554 555 t.Run("with query params and bearer", func(t *testing.T) { 556 bdClient.BearerToken = "testBearer" 557 responseBody, err := bdClient.sendRequest(http.MethodGet, "api/endpoint", map[string]string{"q": "test"}, nil, http.Header{}) 558 assert.NoError(t, err) 559 assert.Equal(t, "testContentQuery", string(responseBody)) 560 assert.Equal(t, http.Header{"Authorization": {"Bearer testBearer"}}, myTestClient.header["https://my.blackduck.system/api/endpoint?q=test"]) 561 }) 562 } 563 564 func TestApiURL(t *testing.T) { 565 tt := []struct { 566 description string 567 apiEndpoint string 568 client Client 569 expected string 570 }{ 571 { 572 description: "trailing / in path", 573 apiEndpoint: "/my/path/", 574 client: Client{serverURL: "https://my.test.server"}, 575 expected: "https://my.test.server/my/path", 576 }, 577 { 578 description: "trailing / in server", 579 apiEndpoint: "/my/path", 580 client: Client{serverURL: "https://my.test.server/"}, 581 expected: "https://my.test.server/my/path", 582 }, 583 } 584 585 for _, test := range tt { 586 res, err := test.client.apiURL(test.apiEndpoint) 587 assert.NoError(t, err) 588 assert.Equalf(t, test.expected, res.String(), test.description) 589 } 590 } 591 592 func TestAuthenticationValid(t *testing.T) { 593 tt := []struct { 594 description string 595 now time.Time 596 client Client 597 expected bool 598 }{ 599 { 600 description: "login still valid", 601 now: time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC), 602 client: Client{BearerExpiresInMilliseconds: 120000, lastAuthentication: time.Date(2020, time.January, 01, 11, 59, 0, 0, time.UTC)}, 603 expected: true, 604 }, 605 { 606 description: "login still valid - edge", 607 now: time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC), 608 client: Client{BearerExpiresInMilliseconds: 120000, lastAuthentication: time.Date(2020, time.January, 01, 11, 58, 1, 0, time.UTC)}, 609 expected: true, 610 }, 611 { 612 description: "login expired", 613 now: time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC), 614 client: Client{BearerExpiresInMilliseconds: 120000, lastAuthentication: time.Date(2020, time.January, 01, 11, 57, 0, 0, time.UTC)}, 615 expected: false, 616 }, 617 { 618 description: "login expired - edge", 619 now: time.Date(2020, time.January, 1, 12, 0, 0, 0, time.UTC), 620 client: Client{BearerExpiresInMilliseconds: 120000, lastAuthentication: time.Date(2020, time.January, 01, 11, 58, 0, 0, time.UTC)}, 621 expected: false, 622 }, 623 } 624 625 for _, test := range tt { 626 assert.Equalf(t, test.expected, test.client.authenticationValid(test.now), test.description) 627 } 628 } 629 630 func TestUrlPath(t *testing.T) { 631 assert.Equal(t, "/this/is/the/path", urlPath("https://the.server.domain:8080/this/is/the/path")) 632 }