github.com/SAP/jenkins-library@v1.362.0/pkg/contrast/contrast_test.go (about) 1 package contrast 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 type contrastHttpClientMock struct { 11 page *int 12 } 13 14 func (c *contrastHttpClientMock) ExecuteRequest(url string, params map[string]string, dest interface{}) error { 15 switch url { 16 case appUrl: 17 app, ok := dest.(*ApplicationResponse) 18 if !ok { 19 return fmt.Errorf("wrong destination type") 20 } 21 app.Id = "1" 22 app.Name = "application" 23 case vulnsUrl: 24 vulns, ok := dest.(*VulnerabilitiesResponse) 25 if !ok { 26 return fmt.Errorf("wrong destination type") 27 } 28 vulns.Size = 6 29 vulns.TotalElements = 6 30 vulns.TotalPages = 1 31 vulns.Empty = false 32 vulns.First = true 33 vulns.Last = true 34 vulns.Vulnerabilities = []Vulnerability{ 35 {Severity: "HIGH", Status: "FIXED"}, 36 {Severity: "MEDIUM", Status: "REMEDIATED"}, 37 {Severity: "HIGH", Status: "REPORTED"}, 38 {Severity: "MEDIUM", Status: "REPORTED"}, 39 {Severity: "HIGH", Status: "CONFIRMED"}, 40 {Severity: "NOTE", Status: "SUSPICIOUS"}, 41 } 42 case vulnsUrlPaginated: 43 vulns, ok := dest.(*VulnerabilitiesResponse) 44 if !ok { 45 return fmt.Errorf("wrong destination type") 46 } 47 vulns.Size = 100 48 vulns.TotalElements = 300 49 vulns.TotalPages = 3 50 vulns.Empty = false 51 vulns.Last = false 52 if *c.page == 3 { 53 vulns.Last = true 54 return nil 55 } 56 for i := 0; i < 20; i++ { 57 vulns.Vulnerabilities = append(vulns.Vulnerabilities, Vulnerability{Severity: "HIGH", Status: "FIXED"}) 58 vulns.Vulnerabilities = append(vulns.Vulnerabilities, Vulnerability{Severity: "NOTE", Status: "FIXED"}) 59 vulns.Vulnerabilities = append(vulns.Vulnerabilities, Vulnerability{Severity: "MEDIUM", Status: "REPORTED"}) 60 vulns.Vulnerabilities = append(vulns.Vulnerabilities, Vulnerability{Severity: "LOW", Status: "REPORTED"}) 61 vulns.Vulnerabilities = append(vulns.Vulnerabilities, Vulnerability{Severity: "CRITICAL", Status: "NOT_A_PROBLEM"}) 62 } 63 *c.page++ 64 case vulnsUrlEmpty: 65 vulns, ok := dest.(*VulnerabilitiesResponse) 66 if !ok { 67 return fmt.Errorf("wrong destination type") 68 } 69 vulns.Empty = true 70 vulns.Last = true 71 default: 72 return fmt.Errorf("error") 73 } 74 return nil 75 } 76 77 const ( 78 appUrl = "https://server.com/applications" 79 errorUrl = "https://server.com/error" 80 vulnsUrl = "https://server.com/vulnerabilities" 81 vulnsUrlPaginated = "https://server.com/vulnerabilities/pagination" 82 vulnsUrlEmpty = "https://server.com/vulnerabilities/empty" 83 ) 84 85 func TestGetApplicationFromClient(t *testing.T) { 86 t.Parallel() 87 t.Run("Success", func(t *testing.T) { 88 contrastClient := &contrastHttpClientMock{} 89 app, err := getApplicationFromClient(contrastClient, appUrl) 90 assert.NoError(t, err) 91 assert.NotEmpty(t, app) 92 assert.Equal(t, "1", app.Id) 93 assert.Equal(t, "application", app.Name) 94 assert.Equal(t, "", app.Url) 95 assert.Equal(t, "", app.Server) 96 }) 97 98 t.Run("Error", func(t *testing.T) { 99 contrastClient := &contrastHttpClientMock{} 100 _, err := getApplicationFromClient(contrastClient, errorUrl) 101 assert.Error(t, err) 102 }) 103 } 104 105 func TestGetVulnerabilitiesFromClient(t *testing.T) { 106 t.Parallel() 107 t.Run("Success", func(t *testing.T) { 108 contrastClient := &contrastHttpClientMock{} 109 findings, err := getVulnerabilitiesFromClient(contrastClient, vulnsUrl, 0) 110 assert.NoError(t, err) 111 assert.NotEmpty(t, findings) 112 assert.Equal(t, 2, len(findings)) 113 for _, f := range findings { 114 assert.True(t, f.ClassificationName == AuditAll || f.ClassificationName == Optional) 115 if f.ClassificationName == AuditAll { 116 assert.Equal(t, 5, f.Total) 117 assert.Equal(t, 3, f.Audited) 118 } 119 if f.ClassificationName == Optional { 120 assert.Equal(t, 1, f.Total) 121 assert.Equal(t, 1, f.Audited) 122 } 123 } 124 }) 125 126 t.Run("Success with pagination results", func(t *testing.T) { 127 page := 0 128 contrastClient := &contrastHttpClientMock{page: &page} 129 findings, err := getVulnerabilitiesFromClient(contrastClient, vulnsUrlPaginated, 0) 130 assert.NoError(t, err) 131 assert.NotEmpty(t, findings) 132 assert.Equal(t, 2, len(findings)) 133 for _, f := range findings { 134 assert.True(t, f.ClassificationName == AuditAll || f.ClassificationName == Optional) 135 if f.ClassificationName == AuditAll { 136 assert.Equal(t, 180, f.Total) 137 assert.Equal(t, 120, f.Audited) 138 } 139 if f.ClassificationName == Optional { 140 assert.Equal(t, 120, f.Total) 141 assert.Equal(t, 60, f.Audited) 142 } 143 } 144 }) 145 146 t.Run("Empty response", func(t *testing.T) { 147 contrastClient := &contrastHttpClientMock{} 148 findings, err := getVulnerabilitiesFromClient(contrastClient, vulnsUrlEmpty, 0) 149 assert.NoError(t, err) 150 assert.Empty(t, findings) 151 assert.Equal(t, 0, len(findings)) 152 }) 153 154 t.Run("Error", func(t *testing.T) { 155 contrastClient := &contrastHttpClientMock{} 156 _, err := getVulnerabilitiesFromClient(contrastClient, errorUrl, 0) 157 assert.Error(t, err) 158 }) 159 } 160 161 func TestGetFindings(t *testing.T) { 162 t.Parallel() 163 t.Run("Critical severity", func(t *testing.T) { 164 vulns := []Vulnerability{ 165 {Severity: "CRITICAL", Status: "FIXED"}, 166 {Severity: "CRITICAL", Status: "REMEDIATED"}, 167 {Severity: "CRITICAL", Status: "REPORTED"}, 168 {Severity: "CRITICAL", Status: "CONFIRMED"}, 169 {Severity: "CRITICAL", Status: "NOT_A_PROBLEM"}, 170 {Severity: "CRITICAL", Status: "SUSPICIOUS"}, 171 } 172 auditAll, optional := getFindings(vulns) 173 assert.Equal(t, 6, auditAll.Total) 174 assert.Equal(t, 5, auditAll.Audited) 175 assert.Equal(t, 0, optional.Total) 176 assert.Equal(t, 0, optional.Audited) 177 }) 178 t.Run("High severity", func(t *testing.T) { 179 vulns := []Vulnerability{ 180 {Severity: "HIGH", Status: "FIXED"}, 181 {Severity: "HIGH", Status: "REMEDIATED"}, 182 {Severity: "HIGH", Status: "REPORTED"}, 183 {Severity: "HIGH", Status: "CONFIRMED"}, 184 {Severity: "HIGH", Status: "NOT_A_PROBLEM"}, 185 {Severity: "HIGH", Status: "SUSPICIOUS"}, 186 } 187 auditAll, optional := getFindings(vulns) 188 assert.Equal(t, 6, auditAll.Total) 189 assert.Equal(t, 5, auditAll.Audited) 190 assert.Equal(t, 0, optional.Total) 191 assert.Equal(t, 0, optional.Audited) 192 }) 193 t.Run("Medium severity", func(t *testing.T) { 194 vulns := []Vulnerability{ 195 {Severity: "MEDIUM", Status: "FIXED"}, 196 {Severity: "MEDIUM", Status: "REMEDIATED"}, 197 {Severity: "MEDIUM", Status: "REPORTED"}, 198 {Severity: "MEDIUM", Status: "CONFIRMED"}, 199 {Severity: "MEDIUM", Status: "NOT_A_PROBLEM"}, 200 {Severity: "MEDIUM", Status: "SUSPICIOUS"}, 201 } 202 auditAll, optional := getFindings(vulns) 203 assert.Equal(t, 6, auditAll.Total) 204 assert.Equal(t, 5, auditAll.Audited) 205 assert.Equal(t, 0, optional.Total) 206 assert.Equal(t, 0, optional.Audited) 207 }) 208 t.Run("Low severity", func(t *testing.T) { 209 vulns := []Vulnerability{ 210 {Severity: "LOW", Status: "FIXED"}, 211 {Severity: "LOW", Status: "REMEDIATED"}, 212 {Severity: "LOW", Status: "REPORTED"}, 213 {Severity: "LOW", Status: "CONFIRMED"}, 214 {Severity: "LOW", Status: "NOT_A_PROBLEM"}, 215 {Severity: "LOW", Status: "SUSPICIOUS"}, 216 } 217 auditAll, optional := getFindings(vulns) 218 assert.Equal(t, 0, auditAll.Total) 219 assert.Equal(t, 0, auditAll.Audited) 220 assert.Equal(t, 6, optional.Total) 221 assert.Equal(t, 5, optional.Audited) 222 }) 223 t.Run("Note severity", func(t *testing.T) { 224 vulns := []Vulnerability{ 225 {Severity: "NOTE", Status: "FIXED"}, 226 {Severity: "NOTE", Status: "REMEDIATED"}, 227 {Severity: "NOTE", Status: "REPORTED"}, 228 {Severity: "NOTE", Status: "CONFIRMED"}, 229 {Severity: "NOTE", Status: "NOT_A_PROBLEM"}, 230 {Severity: "NOTE", Status: "SUSPICIOUS"}, 231 } 232 auditAll, optional := getFindings(vulns) 233 assert.Equal(t, 0, auditAll.Total) 234 assert.Equal(t, 0, auditAll.Audited) 235 assert.Equal(t, 6, optional.Total) 236 assert.Equal(t, 5, optional.Audited) 237 }) 238 239 t.Run("Mixed severity", func(t *testing.T) { 240 vulns := []Vulnerability{ 241 {Severity: "CRITICAL", Status: "FIXED"}, 242 {Severity: "HIGH", Status: "REMEDIATED"}, 243 {Severity: "MEDIUM", Status: "REPORTED"}, 244 {Severity: "LOW", Status: "CONFIRMED"}, 245 {Severity: "NOTE", Status: "NOT_A_PROBLEM"}, 246 } 247 auditAll, optional := getFindings(vulns) 248 assert.Equal(t, 3, auditAll.Total) 249 assert.Equal(t, 2, auditAll.Audited) 250 assert.Equal(t, 2, optional.Total) 251 assert.Equal(t, 2, optional.Audited) 252 }) 253 } 254 255 func TestAccumulateFindings(t *testing.T) { 256 t.Parallel() 257 t.Run("Add Audit All to empty findings", func(t *testing.T) { 258 findings := []ContrastFindings{ 259 {ClassificationName: AuditAll}, 260 {ClassificationName: Optional}, 261 } 262 auditAll := ContrastFindings{ 263 ClassificationName: AuditAll, 264 Total: 100, 265 Audited: 50, 266 } 267 accumulateFindings(auditAll, ContrastFindings{}, findings) 268 assert.Equal(t, 100, findings[0].Total) 269 assert.Equal(t, 50, findings[0].Audited) 270 assert.Equal(t, 0, findings[1].Total) 271 assert.Equal(t, 0, findings[1].Audited) 272 }) 273 t.Run("Add Optional to empty findings", func(t *testing.T) { 274 findings := []ContrastFindings{ 275 {ClassificationName: AuditAll}, 276 {ClassificationName: Optional}, 277 } 278 optional := ContrastFindings{ 279 ClassificationName: Optional, 280 Total: 100, 281 Audited: 50, 282 } 283 accumulateFindings(ContrastFindings{}, optional, findings) 284 assert.Equal(t, 100, findings[1].Total) 285 assert.Equal(t, 50, findings[1].Audited) 286 assert.Equal(t, 0, findings[0].Total) 287 assert.Equal(t, 0, findings[0].Audited) 288 }) 289 t.Run("Add all to empty findings", func(t *testing.T) { 290 findings := []ContrastFindings{ 291 {ClassificationName: AuditAll}, 292 {ClassificationName: Optional}, 293 } 294 auditAll := ContrastFindings{ 295 ClassificationName: AuditAll, 296 Total: 10, 297 Audited: 5, 298 } 299 optional := ContrastFindings{ 300 ClassificationName: Optional, 301 Total: 100, 302 Audited: 50, 303 } 304 accumulateFindings(auditAll, optional, findings) 305 assert.Equal(t, 10, findings[0].Total) 306 assert.Equal(t, 5, findings[0].Audited) 307 assert.Equal(t, 100, findings[1].Total) 308 assert.Equal(t, 50, findings[1].Audited) 309 }) 310 t.Run("Add to non-empty findings", func(t *testing.T) { 311 findings := []ContrastFindings{ 312 { 313 ClassificationName: AuditAll, 314 Total: 100, 315 Audited: 50, 316 }, 317 { 318 ClassificationName: Optional, 319 Total: 100, 320 Audited: 50, 321 }, 322 } 323 auditAll := ContrastFindings{ 324 ClassificationName: AuditAll, 325 Total: 10, 326 Audited: 5, 327 } 328 optional := ContrastFindings{ 329 ClassificationName: Optional, 330 Total: 100, 331 Audited: 50, 332 } 333 accumulateFindings(auditAll, optional, findings) 334 assert.Equal(t, 110, findings[0].Total) 335 assert.Equal(t, 55, findings[0].Audited) 336 assert.Equal(t, 200, findings[1].Total) 337 assert.Equal(t, 100, findings[1].Audited) 338 }) 339 }