github.com/jaylevin/jenkins-library@v1.230.4/cmd/checkmarxExecuteScan_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"archive/zip"
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"strconv"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/bmatcuk/doublestar"
    17  
    18  	"github.com/SAP/jenkins-library/pkg/checkmarx"
    19  	piperGithub "github.com/SAP/jenkins-library/pkg/github"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  type fileInfo struct {
    24  	nam     string      // base name of the file
    25  	siz     int64       // length in bytes for regular files; system-dependent for others
    26  	mod     os.FileMode // file mode bits
    27  	modtime time.Time   // modification time
    28  	dir     bool        // abbreviation for Mode().IsDir()
    29  	syss    interface{} // underlying data source (can return nil)
    30  }
    31  
    32  func (fi fileInfo) IsDir() bool {
    33  	return fi.dir
    34  }
    35  func (fi fileInfo) Name() string {
    36  	return fi.nam
    37  }
    38  func (fi fileInfo) Size() int64 {
    39  	return fi.siz
    40  }
    41  func (fi fileInfo) ModTime() time.Time {
    42  	return fi.modtime
    43  }
    44  func (fi fileInfo) Mode() os.FileMode {
    45  	return fi.mod
    46  }
    47  func (fi fileInfo) Sys() interface{} {
    48  	return fi.syss
    49  }
    50  
    51  type systemMock struct {
    52  	response                         interface{}
    53  	isIncremental                    bool
    54  	isPublic                         bool
    55  	forceScan                        bool
    56  	createProject                    bool
    57  	previousPName                    string
    58  	getPresetsCalled                 bool
    59  	updateProjectConfigurationCalled bool
    60  }
    61  
    62  func (sys *systemMock) FilterPresetByName(_ []checkmarx.Preset, presetName string) checkmarx.Preset {
    63  	if presetName == "CX_Default" {
    64  		return checkmarx.Preset{ID: 16, Name: "CX_Default", OwnerName: "16"}
    65  	}
    66  	return checkmarx.Preset{ID: 10050, Name: "SAP_JS_Default", OwnerName: "16"}
    67  }
    68  func (sys *systemMock) FilterPresetByID([]checkmarx.Preset, int) checkmarx.Preset {
    69  	return checkmarx.Preset{ID: 10048, Name: "SAP_Default", OwnerName: "16"}
    70  }
    71  func (sys *systemMock) FilterProjectByName([]checkmarx.Project, string) checkmarx.Project {
    72  	return checkmarx.Project{ID: 1, Name: "Test", TeamID: "16", IsPublic: true}
    73  }
    74  func (sys *systemMock) GetProjectByID(projectID int) (checkmarx.Project, error) {
    75  	if projectID == 17 {
    76  		return checkmarx.Project{ID: 17, Name: "Test_PR-17", TeamID: "16", IsPublic: true}, nil
    77  	}
    78  	return checkmarx.Project{ID: 19, Name: "Test_PR-19", TeamID: "16", IsPublic: true}, nil
    79  }
    80  
    81  func (sys *systemMock) GetProjectsByNameAndTeam(projectName, teamID string) ([]checkmarx.Project, error) {
    82  	if !sys.createProject || sys.previousPName == projectName {
    83  		if strings.Contains(projectName, "PR-17") {
    84  			return []checkmarx.Project{{ID: 17, Name: projectName, TeamID: teamID, IsPublic: true}}, nil
    85  		}
    86  		return []checkmarx.Project{{ID: 19, Name: projectName, TeamID: teamID, IsPublic: true}}, nil
    87  	}
    88  	if projectName == "Test" {
    89  		return []checkmarx.Project{{ID: 1, Name: projectName, TeamID: teamID, IsPublic: true}}, nil
    90  	}
    91  	sys.previousPName = projectName
    92  	return []checkmarx.Project{}, fmt.Errorf("no project error")
    93  }
    94  func (sys *systemMock) FilterTeamByName(_ []checkmarx.Team, teamName string) (checkmarx.Team, error) {
    95  	if teamName == "OpenSource/Cracks/16" {
    96  		return checkmarx.Team{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, nil
    97  	}
    98  	return checkmarx.Team{ID: json.RawMessage(`15`), FullName: "OpenSource/Cracks/15"}, nil
    99  }
   100  func (sys *systemMock) FilterTeamByID(_ []checkmarx.Team, teamID json.RawMessage) checkmarx.Team {
   101  	teamIDBytes, _ := teamID.MarshalJSON()
   102  	if bytes.Compare(teamIDBytes, []byte(`"16"`)) == 0 {
   103  		return checkmarx.Team{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}
   104  	}
   105  	return checkmarx.Team{ID: json.RawMessage(`15`), FullName: "OpenSource/Cracks/15"}
   106  }
   107  func (sys *systemMock) DownloadReport(int) ([]byte, error) {
   108  	return sys.response.([]byte), nil
   109  }
   110  func (sys *systemMock) GetReportStatus(int) (checkmarx.ReportStatusResponse, error) {
   111  	return checkmarx.ReportStatusResponse{Status: checkmarx.ReportStatus{ID: 2, Value: "Created"}}, nil
   112  }
   113  func (sys *systemMock) RequestNewReport(int, string) (checkmarx.Report, error) {
   114  	return checkmarx.Report{ReportID: 17}, nil
   115  }
   116  func (sys *systemMock) GetResults(int) checkmarx.ResultsStatistics {
   117  	return checkmarx.ResultsStatistics{}
   118  }
   119  func (sys *systemMock) GetScans(int) ([]checkmarx.ScanStatus, error) {
   120  	return []checkmarx.ScanStatus{{IsIncremental: true}, {IsIncremental: true}, {IsIncremental: true}, {IsIncremental: false}}, nil
   121  }
   122  func (sys *systemMock) GetScanStatusAndDetail(int) (string, checkmarx.ScanStatusDetail) {
   123  	return "Finished", checkmarx.ScanStatusDetail{Stage: "Step 1 of 25", Step: "Scan something"}
   124  }
   125  func (sys *systemMock) ScanProject(_ int, isIncrementalV, isPublicV, forceScanV bool) (checkmarx.Scan, error) {
   126  	sys.isIncremental = isIncrementalV
   127  	sys.isPublic = isPublicV
   128  	sys.forceScan = forceScanV
   129  	return checkmarx.Scan{ID: 16}, nil
   130  }
   131  func (sys *systemMock) UpdateProjectConfiguration(int, int, string) error {
   132  	sys.updateProjectConfigurationCalled = true
   133  	return nil
   134  }
   135  func (sys *systemMock) UpdateProjectExcludeSettings(int, string, string) error {
   136  	return nil
   137  }
   138  func (sys *systemMock) UploadProjectSourceCode(int, string) error {
   139  	return nil
   140  }
   141  func (sys *systemMock) CreateProject(string, string) (checkmarx.ProjectCreateResult, error) {
   142  	return checkmarx.ProjectCreateResult{ID: 20}, nil
   143  }
   144  func (sys *systemMock) CreateBranch(int, string) int {
   145  	return 18
   146  }
   147  func (sys *systemMock) GetShortDescription(int, int) (checkmarx.ShortDescription, error) {
   148  	return checkmarx.ShortDescription{Text: "dummyText"}, nil
   149  }
   150  func (sys *systemMock) GetPresets() []checkmarx.Preset {
   151  	sys.getPresetsCalled = true
   152  	return []checkmarx.Preset{{ID: 10078, Name: "SAP Java Default", OwnerName: "16"}, {ID: 10048, Name: "SAP JS Default", OwnerName: "16"}, {ID: 16, Name: "CX_Default", OwnerName: "16"}}
   153  }
   154  func (sys *systemMock) GetProjects() ([]checkmarx.Project, error) {
   155  	return []checkmarx.Project{{ID: 15, Name: "OtherTest", TeamID: "16"}, {ID: 1, Name: "Test", TeamID: "16"}}, nil
   156  }
   157  func (sys *systemMock) GetTeams() []checkmarx.Team {
   158  	return []checkmarx.Team{{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, {ID: json.RawMessage(`15`), FullName: "OpenSource/Cracks/15"}}
   159  }
   160  
   161  type systemMockForExistingProject struct {
   162  	response          interface{}
   163  	isIncremental     bool
   164  	isPublic          bool
   165  	forceScan         bool
   166  	scanProjectCalled bool
   167  }
   168  
   169  func (sys *systemMockForExistingProject) FilterPresetByName([]checkmarx.Preset, string) checkmarx.Preset {
   170  	return checkmarx.Preset{ID: 10050, Name: "SAP_JS_Default", OwnerName: "16"}
   171  }
   172  func (sys *systemMockForExistingProject) FilterPresetByID([]checkmarx.Preset, int) checkmarx.Preset {
   173  	return checkmarx.Preset{ID: 10048, Name: "SAP_Default", OwnerName: "16"}
   174  }
   175  func (sys *systemMockForExistingProject) FilterProjectByName([]checkmarx.Project, string) checkmarx.Project {
   176  	return checkmarx.Project{ID: 1, Name: "TestExisting", TeamID: "16", IsPublic: true}
   177  }
   178  func (sys *systemMockForExistingProject) GetProjectByID(int) (checkmarx.Project, error) {
   179  	return checkmarx.Project{}, nil
   180  }
   181  func (sys *systemMockForExistingProject) GetProjectsByNameAndTeam(projectName, teamID string) ([]checkmarx.Project, error) {
   182  	return []checkmarx.Project{{ID: 19, Name: projectName, TeamID: teamID, IsPublic: true}}, nil
   183  }
   184  func (sys *systemMockForExistingProject) FilterTeamByName([]checkmarx.Team, string) (checkmarx.Team, error) {
   185  	return checkmarx.Team{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, nil
   186  }
   187  func (sys *systemMockForExistingProject) FilterTeamByID([]checkmarx.Team, json.RawMessage) checkmarx.Team {
   188  	return checkmarx.Team{ID: json.RawMessage(`"15"`), FullName: "OpenSource/Cracks/15"}
   189  }
   190  func (sys *systemMockForExistingProject) DownloadReport(int) ([]byte, error) {
   191  	return sys.response.([]byte), nil
   192  }
   193  func (sys *systemMockForExistingProject) GetReportStatus(int) (checkmarx.ReportStatusResponse, error) {
   194  	return checkmarx.ReportStatusResponse{Status: checkmarx.ReportStatus{ID: 2, Value: "Created"}}, nil
   195  }
   196  func (sys *systemMockForExistingProject) RequestNewReport(int, string) (checkmarx.Report, error) {
   197  	return checkmarx.Report{ReportID: 17}, nil
   198  }
   199  func (sys *systemMockForExistingProject) GetResults(int) checkmarx.ResultsStatistics {
   200  	return checkmarx.ResultsStatistics{}
   201  }
   202  func (sys *systemMockForExistingProject) GetScans(int) ([]checkmarx.ScanStatus, error) {
   203  	return []checkmarx.ScanStatus{{IsIncremental: true}, {IsIncremental: true}, {IsIncremental: true}, {IsIncremental: false}}, nil
   204  }
   205  func (sys *systemMockForExistingProject) GetShortDescription(int, int) (checkmarx.ShortDescription, error) {
   206  	return checkmarx.ShortDescription{Text: "dummyText"}, nil
   207  }
   208  func (sys *systemMockForExistingProject) GetScanStatusAndDetail(int) (string, checkmarx.ScanStatusDetail) {
   209  	return "Finished", checkmarx.ScanStatusDetail{Stage: "", Step: ""}
   210  }
   211  func (sys *systemMockForExistingProject) ScanProject(_ int, isIncrementalV, isPublicV, forceScanV bool) (checkmarx.Scan, error) {
   212  	sys.scanProjectCalled = true
   213  	sys.isIncremental = isIncrementalV
   214  	sys.isPublic = isPublicV
   215  	sys.forceScan = forceScanV
   216  	return checkmarx.Scan{ID: 16}, nil
   217  }
   218  func (sys *systemMockForExistingProject) UpdateProjectConfiguration(int, int, string) error {
   219  	return nil
   220  }
   221  func (sys *systemMockForExistingProject) UpdateProjectExcludeSettings(int, string, string) error {
   222  	return nil
   223  }
   224  func (sys *systemMockForExistingProject) UploadProjectSourceCode(int, string) error {
   225  	return nil
   226  }
   227  func (sys *systemMockForExistingProject) CreateProject(string, string) (checkmarx.ProjectCreateResult, error) {
   228  	return checkmarx.ProjectCreateResult{}, fmt.Errorf("create project error")
   229  }
   230  func (sys *systemMockForExistingProject) CreateBranch(int, string) int {
   231  	return 0
   232  }
   233  func (sys *systemMockForExistingProject) GetPresets() []checkmarx.Preset {
   234  	return []checkmarx.Preset{{ID: 10078, Name: "SAP_Java_Default", OwnerName: "16"}, {ID: 10048, Name: "SAP_JS_Default", OwnerName: "16"}}
   235  }
   236  func (sys *systemMockForExistingProject) GetProjects() ([]checkmarx.Project, error) {
   237  	return []checkmarx.Project{{ID: 1, Name: "TestExisting", TeamID: "16"}}, nil
   238  }
   239  func (sys *systemMockForExistingProject) GetTeams() []checkmarx.Team {
   240  	return []checkmarx.Team{{ID: json.RawMessage(`"16"`), FullName: "OpenSource/Cracks/16"}, {ID: json.RawMessage(`"15"`), FullName: "OpenSource/Cracks/15"}}
   241  }
   242  
   243  type checkmarxExecuteScanUtilsMock struct {
   244  	errorOnFileInfoHeader bool
   245  	errorOnStat           bool
   246  	errorOnOpen           bool
   247  	errorOnWriteFile      bool
   248  	errorOnPathMatch      bool
   249  	workspace             string
   250  	ghCreateIssueOptions  *piperGithub.CreateIssueOptions
   251  	ghCreateIssueError    error
   252  }
   253  
   254  func newCheckmarxExecuteScanUtilsMock() checkmarxExecuteScanUtilsMock {
   255  	return checkmarxExecuteScanUtilsMock{}
   256  }
   257  
   258  func (c checkmarxExecuteScanUtilsMock) GetWorkspace() string {
   259  	return c.workspace
   260  }
   261  
   262  func (c checkmarxExecuteScanUtilsMock) PathMatch(pattern, name string) (bool, error) {
   263  	if c.errorOnPathMatch {
   264  		return false, fmt.Errorf("error on PathMatch")
   265  	}
   266  	return doublestar.PathMatch(pattern, name)
   267  }
   268  
   269  func (c checkmarxExecuteScanUtilsMock) WriteFile(filename string, data []byte, perm os.FileMode) error {
   270  	if c.errorOnWriteFile {
   271  		return fmt.Errorf("error on WriteFile")
   272  	}
   273  	return ioutil.WriteFile(filename, data, perm)
   274  }
   275  
   276  func (c checkmarxExecuteScanUtilsMock) FileInfoHeader(fi os.FileInfo) (*zip.FileHeader, error) {
   277  	if c.errorOnFileInfoHeader {
   278  		return nil, fmt.Errorf("error on FileInfoHeader")
   279  	}
   280  	return zip.FileInfoHeader(fi)
   281  }
   282  
   283  func (c checkmarxExecuteScanUtilsMock) Stat(name string) (os.FileInfo, error) {
   284  	if c.errorOnStat {
   285  		return nil, fmt.Errorf("error on Stat")
   286  	}
   287  	return os.Stat(name)
   288  }
   289  
   290  func (c checkmarxExecuteScanUtilsMock) Open(name string) (*os.File, error) {
   291  	if c.errorOnOpen {
   292  		return nil, fmt.Errorf("error on Open")
   293  	}
   294  	return os.Open(name)
   295  }
   296  
   297  func (c checkmarxExecuteScanUtilsMock) CreateIssue(ghCreateIssueOptions *piperGithub.CreateIssueOptions) error {
   298  	if c.ghCreateIssueError != nil {
   299  		return c.ghCreateIssueError
   300  	}
   301  	c.ghCreateIssueOptions = ghCreateIssueOptions
   302  	return nil
   303  }
   304  
   305  func TestFilterFileGlob(t *testing.T) {
   306  	t.Parallel()
   307  	tt := []struct {
   308  		input    string
   309  		fInfo    fileInfo
   310  		expected bool
   311  	}{
   312  		{input: filepath.Join("somepath", "node_modules", "someOther", "some.file"), fInfo: fileInfo{}, expected: true},
   313  		{input: filepath.Join("somepath", "non_modules", "someOther", "some.go"), fInfo: fileInfo{}, expected: false},
   314  		{input: filepath.Join(".xmake", "someOther", "some.go"), fInfo: fileInfo{}, expected: true},
   315  		{input: filepath.Join("another", "vendor", "some.html"), fInfo: fileInfo{}, expected: false},
   316  		{input: filepath.Join("another", "vendor", "some.pdf"), fInfo: fileInfo{}, expected: true},
   317  		{input: filepath.Join("another", "vendor", "some.test"), fInfo: fileInfo{}, expected: true},
   318  		{input: filepath.Join("some.test"), fInfo: fileInfo{}, expected: false},
   319  		{input: filepath.Join("a", "b", "c"), fInfo: fileInfo{dir: true}, expected: false},
   320  	}
   321  
   322  	for k, v := range tt {
   323  		result, err := isFileNotMatchingPattern([]string{"!**/node_modules/**", "!**/.xmake/**", "!**/*_test.go", "!**/vendor/**/*.go", "**/*.go", "**/*.html", "*.test"}, v.input, v.fInfo, newCheckmarxExecuteScanUtilsMock())
   324  		assert.Equal(t, v.expected, result, fmt.Sprintf("wrong result for run %v", k))
   325  		assert.NoError(t, err, "no error expected in run %v", k)
   326  	}
   327  }
   328  
   329  func TestFilterFileGlob_errorOnPathMatch(t *testing.T) {
   330  	t.Parallel()
   331  
   332  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   333  	utilsMock.errorOnPathMatch = true
   334  
   335  	result, err := isFileNotMatchingPattern([]string{"!**/node_modules/**", "!**/.xmake/**", "!**/*_test.go", "!**/vendor/**/*.go", "**/*.go", "**/*.html", "*.test"}, filepath.Join("a", "b", "c"), fileInfo{}, utilsMock)
   336  	assert.Equal(t, false, result, fmt.Sprintf("wrong result"))
   337  	assert.EqualError(t, err, "Pattern **/node_modules/** could not get executed: error on PathMatch")
   338  }
   339  
   340  func TestZipFolder(t *testing.T) {
   341  	t.Parallel()
   342  
   343  	t.Run("zip files successfully", func(t *testing.T) {
   344  		t.Parallel()
   345  		dir, err := ioutil.TempDir("", "test zip files")
   346  		if err != nil {
   347  			t.Fatal("Failed to create temporary directory")
   348  		}
   349  		// clean up tmp dir
   350  		defer os.RemoveAll(dir)
   351  
   352  		err = ioutil.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0700)
   353  		assert.NoError(t, err)
   354  		err = ioutil.WriteFile(filepath.Join(dir, "abcd.yaml"), []byte("abcd.yaml"), 0700)
   355  		assert.NoError(t, err)
   356  		err = os.Mkdir(filepath.Join(dir, "somepath"), 0700)
   357  		assert.NoError(t, err)
   358  		err = ioutil.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0700)
   359  		assert.NoError(t, err)
   360  		err = ioutil.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0700)
   361  		assert.NoError(t, err)
   362  		err = ioutil.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0700)
   363  		assert.NoError(t, err)
   364  
   365  		var zipFileMock bytes.Buffer
   366  		err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "!**/abcd.yaml", "**/abcd.*"}, newCheckmarxExecuteScanUtilsMock())
   367  		assert.NoError(t, err)
   368  
   369  		zipString := zipFileMock.String()
   370  
   371  		//assert.Equal(t, 724, zipFileMock.Len(), "Expected length of 724, but got %v", zipFileMock.Len())
   372  		assert.True(t, strings.Contains(zipString, "abcd.go"), "Expected 'abcd.go' contained")
   373  		assert.True(t, strings.Contains(zipString, filepath.Join("somepath", "abcd.txt")), "Expected 'somepath/abcd.txt' contained")
   374  		assert.False(t, strings.Contains(zipString, "abcd_test.go"), "Not expected 'abcd_test.go' contained")
   375  		assert.False(t, strings.Contains(zipString, "abcd.yaml"), "Not expected 'abcd.yaml' contained")
   376  		assert.False(t, strings.Contains(zipString, "abc_test.go"), "Not expected 'abc_test.go' contained")
   377  	})
   378  
   379  	t.Run("error on query file info header", func(t *testing.T) {
   380  		t.Parallel()
   381  		dir, err := ioutil.TempDir("", "test zip files")
   382  		if err != nil {
   383  			t.Fatal("Failed to create temporary directory")
   384  		}
   385  		// clean up tmp dir
   386  		defer os.RemoveAll(dir)
   387  
   388  		err = ioutil.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0700)
   389  		assert.NoError(t, err)
   390  		err = os.Mkdir(filepath.Join(dir, "somepath"), 0700)
   391  		assert.NoError(t, err)
   392  		err = ioutil.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0700)
   393  		assert.NoError(t, err)
   394  		err = ioutil.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0700)
   395  		assert.NoError(t, err)
   396  		err = ioutil.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0700)
   397  		assert.NoError(t, err)
   398  
   399  		var zipFileMock bytes.Buffer
   400  		mock := newCheckmarxExecuteScanUtilsMock()
   401  		mock.errorOnFileInfoHeader = true
   402  		err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "**/abcd.*"}, mock)
   403  
   404  		assert.EqualError(t, err, "error on FileInfoHeader")
   405  	})
   406  
   407  	t.Run("error on os stat", func(t *testing.T) {
   408  		t.Parallel()
   409  		dir, err := ioutil.TempDir("", "test zip files")
   410  		if err != nil {
   411  			t.Fatal("Failed to create temporary directory")
   412  		}
   413  		// clean up tmp dir
   414  		defer os.RemoveAll(dir)
   415  
   416  		err = ioutil.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0700)
   417  		assert.NoError(t, err)
   418  		err = os.Mkdir(filepath.Join(dir, "somepath"), 0700)
   419  		assert.NoError(t, err)
   420  		err = ioutil.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0700)
   421  		assert.NoError(t, err)
   422  		err = ioutil.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0700)
   423  		assert.NoError(t, err)
   424  		err = ioutil.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0700)
   425  		assert.NoError(t, err)
   426  
   427  		var zipFileMock bytes.Buffer
   428  		mock := newCheckmarxExecuteScanUtilsMock()
   429  		mock.errorOnStat = true
   430  		err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "**/abcd.*"}, mock)
   431  
   432  		assert.NoError(t, err)
   433  	})
   434  
   435  	t.Run("error on os Open", func(t *testing.T) {
   436  		t.Parallel()
   437  		dir, err := ioutil.TempDir("", "test zip files")
   438  		if err != nil {
   439  			t.Fatal("Failed to create temporary directory")
   440  		}
   441  		// clean up tmp dir
   442  		defer os.RemoveAll(dir)
   443  
   444  		err = ioutil.WriteFile(filepath.Join(dir, "abcd.go"), []byte("abcd.go"), 0700)
   445  		assert.NoError(t, err)
   446  		err = os.Mkdir(filepath.Join(dir, "somepath"), 0700)
   447  		assert.NoError(t, err)
   448  		err = ioutil.WriteFile(filepath.Join(dir, "somepath", "abcd.txt"), []byte("somepath/abcd.txt"), 0700)
   449  		assert.NoError(t, err)
   450  		err = ioutil.WriteFile(filepath.Join(dir, "abcd_test.go"), []byte("abcd_test.go"), 0700)
   451  		assert.NoError(t, err)
   452  		err = ioutil.WriteFile(filepath.Join(dir, "abc_test.go"), []byte("abc_test.go"), 0700)
   453  		assert.NoError(t, err)
   454  
   455  		var zipFileMock bytes.Buffer
   456  		mock := newCheckmarxExecuteScanUtilsMock()
   457  		mock.errorOnOpen = true
   458  		err = zipFolder(dir, &zipFileMock, []string{"!**/abc_test.txt", "**/abcd.*"}, mock)
   459  
   460  		assert.EqualError(t, err, "error on Open")
   461  	})
   462  }
   463  
   464  func TestGetDetailedResults(t *testing.T) {
   465  	t.Parallel()
   466  
   467  	t.Run("success case", func(t *testing.T) {
   468  		t.Parallel()
   469  		sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?>
   470  		<CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public">
   471  		<Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430">
   472  			<Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   473  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   474  			</Result>
   475  			<Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="False" Severity="High" AssignToUser="" state="1" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   476  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   477  			</Result>
   478  			<Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="2" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   479  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   480  			</Result>
   481  			<Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="3" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   482  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   483  			</Result>
   484  			<Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="4" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   485  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   486  			</Result>
   487  		</Query>
   488  		</CxXMLResults>`)}
   489  		dir, err := ioutil.TempDir("", "test detailed results")
   490  		if err != nil {
   491  			t.Fatal("Failed to create temporary directory")
   492  		}
   493  		// clean up tmp dir
   494  		defer os.RemoveAll(dir)
   495  		result, err := getDetailedResults(sys, filepath.Join(dir, "abc.xml"), 2635, newCheckmarxExecuteScanUtilsMock())
   496  		assert.NoError(t, err, "error occurred but none expected")
   497  		assert.Equal(t, "2", result["ProjectId"], "Project ID incorrect")
   498  		assert.Equal(t, "Project 1", result["ProjectName"], "Project name incorrect")
   499  		assert.Equal(t, 2, result["High"].(map[string]int)["Issues"], "Number of High issues incorrect")
   500  		assert.Equal(t, 2, result["High"].(map[string]int)["NotFalsePositive"], "Number of High NotFalsePositive issues incorrect")
   501  		assert.Equal(t, 1, result["Medium"].(map[string]int)["Issues"], "Number of Medium issues incorrect")
   502  		assert.Equal(t, 0, result["Medium"].(map[string]int)["NotFalsePositive"], "Number of Medium NotFalsePositive issues incorrect")
   503  	})
   504  
   505  	t.Run("error on write file", func(t *testing.T) {
   506  		t.Parallel()
   507  		sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?>
   508  		<CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public">
   509  		<Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430">
   510  			<Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   511  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   512  			</Result>
   513  			<Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="False" Severity="High" AssignToUser="" state="1" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   514  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   515  			</Result>
   516  			<Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="2" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   517  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   518  			</Result>
   519  			<Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="3" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   520  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   521  			</Result>
   522  			<Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="4" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   523  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   524  			</Result>
   525  		</Query>
   526  		</CxXMLResults>`)}
   527  		dir, err := ioutil.TempDir("", "test detailed results")
   528  		if err != nil {
   529  			t.Fatal("Failed to create temporary directory")
   530  		}
   531  		// clean up tmp dir
   532  		defer os.RemoveAll(dir)
   533  		utils := newCheckmarxExecuteScanUtilsMock()
   534  		utils.errorOnWriteFile = true
   535  		_, err = getDetailedResults(sys, filepath.Join(dir, "abc.xml"), 2635, utils)
   536  		assert.EqualError(t, err, "failed to write file: error on WriteFile")
   537  	})
   538  }
   539  
   540  func TestRunScan(t *testing.T) {
   541  	t.Parallel()
   542  
   543  	sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)}
   544  	options := checkmarxExecuteScanOptions{ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   545  	workspace, err := ioutil.TempDir("", "workspace1")
   546  	if err != nil {
   547  		t.Fatal("Failed to create temporary workspace directory")
   548  	}
   549  	// clean up tmp dir
   550  	defer os.RemoveAll(workspace)
   551  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   552  	assert.NoError(t, err)
   553  	options.FilterPattern = "**/abcd.go"
   554  
   555  	influx := checkmarxExecuteScanInflux{}
   556  
   557  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   558  	utilsMock.workspace = workspace
   559  
   560  	err = runScan(options, sys, &influx, utilsMock)
   561  	assert.NoError(t, err, "error occurred but none expected")
   562  	assert.Equal(t, false, sys.isIncremental, "isIncremental has wrong value")
   563  	assert.Equal(t, true, sys.isPublic, "isPublic has wrong value")
   564  	assert.Equal(t, true, sys.forceScan, "forceScan has wrong value")
   565  	assert.Equal(t, true, sys.scanProjectCalled, "ScanProject was not invoked")
   566  }
   567  
   568  func TestRunScan_nonNumeralPreset(t *testing.T) {
   569  	t.Parallel()
   570  
   571  	sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)}
   572  	options := checkmarxExecuteScanOptions{ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "SAP_JS_Default", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   573  	workspace, err := ioutil.TempDir("", "workspace1")
   574  	if err != nil {
   575  		t.Fatal("Failed to create temporary workspace directory")
   576  	}
   577  	// clean up tmp dir
   578  	defer os.RemoveAll(workspace)
   579  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   580  	assert.NoError(t, err)
   581  	options.FilterPattern = "**/abcd.go"
   582  
   583  	influx := checkmarxExecuteScanInflux{}
   584  
   585  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   586  	utilsMock.workspace = workspace
   587  
   588  	err = runScan(options, sys, &influx, utilsMock)
   589  	assert.NoError(t, err, "error occurred but none expected")
   590  }
   591  
   592  func TestRunOptimizedScan(t *testing.T) {
   593  	t.Parallel()
   594  
   595  	sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)}
   596  	options := checkmarxExecuteScanOptions{IsOptimizedAndScheduled: true, ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "1", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   597  	workspace, err := ioutil.TempDir("", "workspace1")
   598  	if err != nil {
   599  		t.Fatal("Failed to create temporary workspace directory")
   600  	}
   601  	// clean up tmp dir
   602  	defer os.RemoveAll(workspace)
   603  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   604  	assert.NoError(t, err)
   605  	options.FilterPattern = "**/abcd.go"
   606  
   607  	influx := checkmarxExecuteScanInflux{}
   608  
   609  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   610  	utilsMock.workspace = workspace
   611  
   612  	err = runScan(options, sys, &influx, utilsMock)
   613  	assert.NoError(t, err, "error occurred but none expected")
   614  	assert.Equal(t, false, sys.isIncremental, "isIncremental has wrong value")
   615  	assert.Equal(t, true, sys.isPublic, "isPublic has wrong value")
   616  	assert.Equal(t, true, sys.forceScan, "forceScan has wrong value")
   617  	assert.Equal(t, true, sys.scanProjectCalled, "ScanProject was not invoked")
   618  }
   619  
   620  func TestSetPresetForProjectWithIDProvided(t *testing.T) {
   621  	t.Parallel()
   622  
   623  	sys := &systemMock{}
   624  	err := setPresetForProject(sys, 12345, 16, "testProject", "CX_Default", "")
   625  	assert.NoError(t, err, "error occurred but none expected")
   626  	assert.Equal(t, false, sys.getPresetsCalled, "GetPresets was called")
   627  	assert.Equal(t, true, sys.updateProjectConfigurationCalled, "UpdateProjectConfiguration was not called")
   628  }
   629  
   630  func TestSetPresetForProjectWithNameProvided(t *testing.T) {
   631  	t.Parallel()
   632  
   633  	sys := &systemMock{}
   634  	presetID, _ := strconv.Atoi("CX_Default")
   635  	err := setPresetForProject(sys, 12345, presetID, "testProject", "CX_Default", "")
   636  	assert.NoError(t, err, "error occurred but none expected")
   637  	assert.Equal(t, true, sys.getPresetsCalled, "GetPresets was not called")
   638  	assert.Equal(t, true, sys.updateProjectConfigurationCalled, "UpdateProjectConfiguration was not called")
   639  }
   640  
   641  func TestVerifyOnly(t *testing.T) {
   642  	t.Parallel()
   643  
   644  	sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)}
   645  	options := checkmarxExecuteScanOptions{VerifyOnly: true, ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   646  	workspace, err := ioutil.TempDir("", "workspace1")
   647  	if err != nil {
   648  		t.Fatal("Failed to create temporary workspace directory")
   649  	}
   650  	// clean up tmp dir
   651  	defer os.RemoveAll(workspace)
   652  
   653  	influx := checkmarxExecuteScanInflux{}
   654  
   655  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   656  	utilsMock.workspace = workspace
   657  
   658  	err = runScan(options, sys, &influx, utilsMock)
   659  	assert.NoError(t, err, "error occurred but none expected")
   660  	assert.Equal(t, false, sys.scanProjectCalled, "ScanProject was invoked but shouldn't")
   661  }
   662  
   663  func TestVerifyOnly_errorOnWriteFileDoesNotBlock(t *testing.T) {
   664  	t.Parallel()
   665  
   666  	sys := &systemMockForExistingProject{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)}
   667  	options := checkmarxExecuteScanOptions{VerifyOnly: true, ProjectName: "TestExisting", VulnerabilityThresholdUnit: "absolute", FullScanCycle: "2", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   668  	workspace, err := ioutil.TempDir("", "workspace1")
   669  	if err != nil {
   670  		t.Fatal("Failed to create temporary workspace directory")
   671  	}
   672  	// clean up tmp dir
   673  	defer os.RemoveAll(workspace)
   674  
   675  	influx := checkmarxExecuteScanInflux{}
   676  
   677  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   678  	utilsMock.workspace = workspace
   679  	utilsMock.errorOnWriteFile = true
   680  
   681  	err = runScan(options, sys, &influx, utilsMock)
   682  	assert.EqualError(t, err, "scan, upload, and result validation returned an error: project TestExisting not compliant: failed to get detailed results: failed to write file: error on WriteFile")
   683  }
   684  
   685  func TestRunScanWOtherCycle(t *testing.T) {
   686  	t.Parallel()
   687  
   688  	sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true}
   689  	options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "123", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   690  	workspace, err := ioutil.TempDir("", "workspace2")
   691  	if err != nil {
   692  		t.Fatal("Failed to create temporary workspace directory")
   693  	}
   694  	// clean up tmp dir
   695  	defer os.RemoveAll(workspace)
   696  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   697  	assert.NoError(t, err)
   698  	options.FilterPattern = "**/abcd.go"
   699  
   700  	influx := checkmarxExecuteScanInflux{}
   701  
   702  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   703  	utilsMock.workspace = workspace
   704  
   705  	err = runScan(options, sys, &influx, utilsMock)
   706  	assert.NoError(t, err, "error occurred but none expected")
   707  	assert.Equal(t, true, sys.isIncremental, "isIncremental has wrong value")
   708  	assert.Equal(t, true, sys.isPublic, "isPublic has wrong value")
   709  	assert.Equal(t, true, sys.forceScan, "forceScan has wrong value")
   710  }
   711  
   712  func TestRunScanErrorInZip(t *testing.T) {
   713  	t.Parallel()
   714  
   715  	sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true}
   716  	options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "123", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   717  	workspace, err := ioutil.TempDir("", "workspace2")
   718  	if err != nil {
   719  		t.Fatal("Failed to create temporary workspace directory")
   720  	}
   721  	// clean up tmp dir
   722  	defer os.RemoveAll(workspace)
   723  
   724  	influx := checkmarxExecuteScanInflux{}
   725  
   726  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   727  	utilsMock.workspace = workspace
   728  	utilsMock.errorOnFileInfoHeader = true
   729  
   730  	err = runScan(options, sys, &influx, utilsMock)
   731  	assert.EqualError(t, err, "scan, upload, and result validation returned an error: failed to zip workspace files: failed to compact folder: error on FileInfoHeader")
   732  }
   733  
   734  func TestRunScanForPullRequest(t *testing.T) {
   735  	t.Parallel()
   736  
   737  	sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`)}
   738  	options := checkmarxExecuteScanOptions{PullRequestName: "PR-19", ProjectName: "Test", VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "123", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true, AvoidDuplicateProjectScans: false}
   739  	workspace, err := ioutil.TempDir("", "workspace3")
   740  	if err != nil {
   741  		t.Fatal("Failed to create temporary workspace directory")
   742  	}
   743  	// clean up tmp dir
   744  	defer os.RemoveAll(workspace)
   745  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   746  	assert.NoError(t, err)
   747  	options.FilterPattern = "**/abcd.go"
   748  
   749  	influx := checkmarxExecuteScanInflux{}
   750  
   751  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   752  	utilsMock.workspace = workspace
   753  
   754  	err = runScan(options, sys, &influx, utilsMock)
   755  	assert.Equal(t, true, sys.isIncremental, "isIncremental has wrong value")
   756  	assert.Equal(t, true, sys.isPublic, "isPublic has wrong value")
   757  	assert.Equal(t, true, sys.forceScan, "forceScan has wrong value")
   758  }
   759  
   760  func TestRunScanForPullRequestProjectNew(t *testing.T) {
   761  	t.Parallel()
   762  
   763  	sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true}
   764  	options := checkmarxExecuteScanOptions{PullRequestName: "PR-17", ProjectName: "Test", AvoidDuplicateProjectScans: true, VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "10048", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   765  	workspace, err := ioutil.TempDir("", "workspace4")
   766  	if err != nil {
   767  		t.Fatal("Failed to create temporary workspace directory")
   768  	}
   769  	// clean up tmp dir
   770  	defer os.RemoveAll(workspace)
   771  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   772  	assert.NoError(t, err)
   773  	options.FilterPattern = "**/abcd.go"
   774  
   775  	influx := checkmarxExecuteScanInflux{}
   776  
   777  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   778  	utilsMock.workspace = workspace
   779  
   780  	err = runScan(options, sys, &influx, utilsMock)
   781  	assert.NoError(t, err, "Unexpected error caught")
   782  	assert.Equal(t, true, sys.isIncremental, "isIncremental has wrong value")
   783  	assert.Equal(t, true, sys.isPublic, "isPublic has wrong value")
   784  	assert.Equal(t, false, sys.forceScan, "forceScan has wrong value")
   785  }
   786  
   787  func TestRunScanForPullRequestProjectNew_nonNumeralPreset(t *testing.T) {
   788  	t.Parallel()
   789  
   790  	sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?><CxXMLResults />`), createProject: true}
   791  	options := checkmarxExecuteScanOptions{PullRequestName: "PR-17", ProjectName: "Test", AvoidDuplicateProjectScans: true, VulnerabilityThresholdUnit: "percentage", FullScanCycle: "3", Incremental: true, FullScansScheduled: true, Preset: "SAP_JS_Default", TeamName: "OpenSource/Cracks/15", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   792  	workspace, err := ioutil.TempDir("", "workspace4")
   793  	if err != nil {
   794  		t.Fatal("Failed to create temporary workspace directory")
   795  	}
   796  	// clean up tmp dir
   797  	defer os.RemoveAll(workspace)
   798  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   799  	assert.NoError(t, err)
   800  	options.FilterPattern = "**/abcd.go"
   801  
   802  	influx := checkmarxExecuteScanInflux{}
   803  
   804  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   805  	utilsMock.workspace = workspace
   806  
   807  	err = runScan(options, sys, &influx, utilsMock)
   808  	assert.NoError(t, err, "error occurred but none expected")
   809  }
   810  
   811  func TestRunScanHighViolationPercentage(t *testing.T) {
   812  	t.Parallel()
   813  
   814  	sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?>
   815  	<CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public">
   816  	<Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430">
   817  		<Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   818  			<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   819  		</Result>
   820  		<Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="False" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   821  			<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   822  		</Result>
   823  		<Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   824  			<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   825  		</Result>
   826  		<Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   827  			<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   828  		</Result>
   829  		<Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   830  			<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   831  		</Result>
   832  	</Query>
   833  	</CxXMLResults>`)}
   834  	options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdResult: "FAILURE", VulnerabilityThresholdHigh: 100, FullScanCycle: "10", FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   835  	workspace, err := ioutil.TempDir("", "workspace5")
   836  	if err != nil {
   837  		t.Fatal("Failed to create temporary workspace directory")
   838  	}
   839  	// clean up tmp dir
   840  	defer os.RemoveAll(workspace)
   841  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   842  	assert.NoError(t, err)
   843  	options.FilterPattern = "**/abcd.go"
   844  
   845  	influx := checkmarxExecuteScanInflux{}
   846  
   847  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   848  	utilsMock.workspace = workspace
   849  
   850  	err = runScan(options, sys, &influx, utilsMock)
   851  	assert.Contains(t, fmt.Sprint(err), "the project is not compliant", "Expected different error")
   852  }
   853  
   854  func TestRunScanHighViolationAbsolute(t *testing.T) {
   855  	t.Parallel()
   856  
   857  	sys := &systemMock{response: []byte(`<?xml version="1.0" encoding="utf-8"?>
   858  		<CxXMLResults InitiatorName="admin" Owner="admin" ScanId="1000005" ProjectId="2" ProjectName="Project 1" TeamFullPathOnReportDate="CxServer" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2" ScanStart="Sunday, December 3, 2017 4:50:34 PM" Preset="Checkmarx Default" ScanTime="00h:03m:18s" LinesOfCodeScanned="6838" FilesScanned="34" ReportCreationTime="Sunday, December 3, 2017 6:13:45 PM" Team="CxServer" CheckmarxVersion="8.6.0" ScanComments="" ScanType="Incremental" SourceOrigin="LocalPath" Visibility="Public">
   859  		<Query id="430" categories="PCI DSS v3.2;PCI DSS (3.2) - 6.5.1 - Injection flaws - particularly SQL injection,OWASP Top 10 2013;A1-Injection,FISMA 2014;System And Information Integrity,NIST SP 800-53;SI-10 Information Input Validation (P1),OWASP Top 10 2017;A1-Injection" cweId="89" name="SQL_Injection" group="CSharp_High_Risk" Severity="High" Language="CSharp" LanguageHash="1363215419077432" LanguageChangeDate="2017-12-03T00:00:00.0000000" SeverityIndex="3" QueryPath="CSharp\Cx\CSharp High Risk\SQL Injection Version:0" QueryVersionCode="430">
   860  			<Result NodeId="10000050002" FileName="bookstore/Login.cs" Status="Recurrent" Line="179" Column="103" FalsePositive="True" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   861  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   862  			</Result>
   863  			<Result NodeId="10000050003" FileName="bookstore/Login.cs" Status="Recurrent" Line="180" Column="10" FalsePositive="True" Severity="High" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="3">
   864  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   865  			</Result>
   866  			<Result NodeId="10000050004" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="True" Severity="Medium" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   867  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   868  			</Result>
   869  			<Result NodeId="10000050005" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="False" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   870  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   871  			</Result>
   872  			<Result NodeId="10000050006" FileName="bookstore/Login.cs" Status="Recurrent" Line="181" Column="190" FalsePositive="False" Severity="Low" AssignToUser="" state="0" Remark="" DeepLink="http://WIN2K12-TEMP/CxWebClient/ViewerMain.aspx?scanid=1000005&amp;projectid=2&amp;pathid=2" SeverityIndex="2">
   873  				<Path ResultId="1000005" PathId="2" SimilarityId="1765812516"/>
   874  			</Result>
   875  		</Query>
   876  		</CxXMLResults>`)}
   877  	options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdResult: "FAILURE", VulnerabilityThresholdLow: 1, FullScanCycle: "10", FullScansScheduled: true, Preset: "10048", TeamID: "16", VulnerabilityThresholdEnabled: true, GeneratePdfReport: true}
   878  	workspace, err := ioutil.TempDir("", "workspace6")
   879  	if err != nil {
   880  		t.Fatal("Failed to create temporary workspace directory")
   881  	}
   882  	// clean up tmp dir
   883  	defer os.RemoveAll(workspace)
   884  	err = ioutil.WriteFile(filepath.Join(workspace, "abcd.go"), []byte("abcd.go"), 0700)
   885  	assert.NoError(t, err)
   886  	options.FilterPattern = "**/abcd.go"
   887  
   888  	influx := checkmarxExecuteScanInflux{}
   889  
   890  	utilsMock := newCheckmarxExecuteScanUtilsMock()
   891  	utilsMock.workspace = workspace
   892  
   893  	err = runScan(options, sys, &influx, utilsMock)
   894  	assert.Contains(t, fmt.Sprint(err), "the project is not compliant", "Expected different error")
   895  }
   896  
   897  func TestEnforceThresholds(t *testing.T) {
   898  	t.Parallel()
   899  
   900  	results := map[string]interface{}{}
   901  	results["High"] = map[string]int{}
   902  	results["Medium"] = map[string]int{}
   903  	results["Low"] = map[string]int{}
   904  
   905  	results["High"].(map[string]int)["NotFalsePositive"] = 10
   906  	results["Medium"].(map[string]int)["NotFalsePositive"] = 10
   907  	results["Low"].(map[string]int)["NotFalsePositive"] = 10
   908  	results["Low"].(map[string]int)["NotExploitable"] = 0
   909  	results["Low"].(map[string]int)["Confirmed"] = 0
   910  
   911  	results["High"].(map[string]int)["Issues"] = 10
   912  	results["Medium"].(map[string]int)["Issues"] = 10
   913  	results["Low"].(map[string]int)["Issues"] = 10
   914  
   915  	t.Run("percentage high violation", func(t *testing.T) {
   916  		t.Parallel()
   917  
   918  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdHigh: 100, VulnerabilityThresholdEnabled: true}
   919  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   920  
   921  		assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
   922  		assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
   923  		assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
   924  	})
   925  
   926  	t.Run("absolute high violation", func(t *testing.T) {
   927  		t.Parallel()
   928  
   929  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdHigh: 5, VulnerabilityThresholdEnabled: true}
   930  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   931  
   932  		assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
   933  		assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
   934  		assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
   935  	})
   936  
   937  	t.Run("percentage medium violation", func(t *testing.T) {
   938  		t.Parallel()
   939  
   940  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdMedium: 100, VulnerabilityThresholdEnabled: true}
   941  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   942  
   943  		assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
   944  		assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
   945  		assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
   946  	})
   947  
   948  	t.Run("absolute medium violation", func(t *testing.T) {
   949  		t.Parallel()
   950  
   951  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdMedium: 5, VulnerabilityThresholdEnabled: true}
   952  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   953  
   954  		assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
   955  		assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
   956  		assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
   957  	})
   958  
   959  	t.Run("percentage low violation", func(t *testing.T) {
   960  		t.Parallel()
   961  
   962  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdLow: 100, VulnerabilityThresholdEnabled: true}
   963  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   964  
   965  		assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
   966  		assert.Equal(t, 1, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
   967  		assert.Equal(t, 2, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
   968  	})
   969  
   970  	t.Run("absolute low violation", func(t *testing.T) {
   971  		t.Parallel()
   972  
   973  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdLow: 5, VulnerabilityThresholdEnabled: true}
   974  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   975  
   976  		assert.Equal(t, true, insecure, "Expected results to be insecure but where not")
   977  		assert.Equal(t, 3, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
   978  		assert.Equal(t, 0, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
   979  	})
   980  
   981  	t.Run("percentage no violation", func(t *testing.T) {
   982  		t.Parallel()
   983  
   984  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "percentage", VulnerabilityThresholdLow: 0, VulnerabilityThresholdEnabled: true}
   985  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   986  
   987  		assert.Equal(t, false, insecure, "Expected results to be insecure but where not")
   988  		assert.Equal(t, 0, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
   989  		assert.Equal(t, 3, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
   990  	})
   991  
   992  	t.Run("absolute no violation", func(t *testing.T) {
   993  		t.Parallel()
   994  
   995  		options := checkmarxExecuteScanOptions{VulnerabilityThresholdUnit: "absolute", VulnerabilityThresholdLow: 15, VulnerabilityThresholdMedium: 15, VulnerabilityThresholdHigh: 15, VulnerabilityThresholdEnabled: true}
   996  		insecure, insecureResults, neutralResults := enforceThresholds(options, results)
   997  
   998  		assert.Equal(t, false, insecure, "Expected results to be insecure but where not")
   999  		assert.Equal(t, 0, len(insecureResults), fmt.Sprintf("Unexpected number of results: %v", insecureResults))
  1000  		assert.Equal(t, 3, len(neutralResults), fmt.Sprintf("Unexpected number of results: %v", neutralResults))
  1001  	})
  1002  }
  1003  
  1004  func TestLoadPreset(t *testing.T) {
  1005  	t.Parallel()
  1006  
  1007  	sys := &systemMock{}
  1008  
  1009  	t.Run("resolve via name", func(t *testing.T) {
  1010  		t.Parallel()
  1011  
  1012  		preset, err := loadPreset(sys, "SAP_JS_Default")
  1013  		assert.NoError(t, err, "Expected success but failed")
  1014  		assert.Equal(t, "SAP_JS_Default", preset.Name, "Expected result but got none")
  1015  	})
  1016  
  1017  	t.Run("error case", func(t *testing.T) {
  1018  		t.Parallel()
  1019  
  1020  		preset, err := loadPreset(sys, "")
  1021  		assert.Contains(t, fmt.Sprint(err), "preset SAP_JS_Default not found", "Expected different error")
  1022  		assert.Equal(t, 0, preset.ID, "Expected result but got none")
  1023  	})
  1024  }
  1025  
  1026  func TestPreventInfiniteLoop(t *testing.T) {
  1027  	t.Parallel()
  1028  
  1029  	utils := checkmarxExecuteScanUtilsBundle{
  1030  		workspace: "abc",
  1031  	}
  1032  
  1033  	assert.Equal(t, "abc", utils.GetWorkspace(), "Wrong workspace has been loaded")
  1034  }