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