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  }