github.com/SAP/jenkins-library@v1.362.0/cmd/codeqlExecuteScan_test.go (about)

     1  //go:build unit
     2  // +build unit
     3  
     4  package cmd
     5  
     6  import (
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/SAP/jenkins-library/pkg/codeql"
    12  	"github.com/SAP/jenkins-library/pkg/mock"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  type codeqlExecuteScanMockUtils struct {
    17  	*mock.ExecMockRunner
    18  	*mock.FilesMock
    19  	*mock.HttpClientMock
    20  }
    21  
    22  func newCodeqlExecuteScanTestsUtils() codeqlExecuteScanMockUtils {
    23  	utils := codeqlExecuteScanMockUtils{
    24  		ExecMockRunner: &mock.ExecMockRunner{},
    25  		FilesMock:      &mock.FilesMock{},
    26  		HttpClientMock: &mock.HttpClientMock{},
    27  	}
    28  	return utils
    29  }
    30  
    31  func TestGetMavenSettings(t *testing.T) {
    32  	t.Parallel()
    33  	t.Run("No maven", func(t *testing.T) {
    34  		config := codeqlExecuteScanOptions{BuildTool: "npm"}
    35  		buildCmd := "mvn clean install"
    36  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    37  		assert.Equal(t, "", params)
    38  	})
    39  
    40  	t.Run("No build command", func(t *testing.T) {
    41  		config := codeqlExecuteScanOptions{BuildTool: "maven"}
    42  		params := getMavenSettings("", &config, newCodeqlExecuteScanTestsUtils())
    43  		assert.Equal(t, "", params)
    44  	})
    45  
    46  	t.Run("Project Settings file", func(t *testing.T) {
    47  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "test.xml"}
    48  		buildCmd := "mvn clean install"
    49  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    50  		assert.Equal(t, " --settings=test.xml", params)
    51  	})
    52  
    53  	t.Run("Skip Project Settings file in case already used", func(t *testing.T) {
    54  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "test.xml"}
    55  		buildCmd := "mvn clean install --settings=project.xml"
    56  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    57  		assert.Equal(t, "", params)
    58  	})
    59  
    60  	t.Run("Global Settings file", func(t *testing.T) {
    61  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "global.xml"}
    62  		buildCmd := "mvn clean install"
    63  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    64  		assert.Equal(t, " --global-settings=global.xml", params)
    65  	})
    66  
    67  	t.Run("Project and Global Settings file", func(t *testing.T) {
    68  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "test.xml", GlobalSettingsFile: "global.xml"}
    69  		buildCmd := "mvn clean install"
    70  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    71  		assert.Equal(t, " --global-settings=global.xml --settings=test.xml", params)
    72  	})
    73  
    74  	t.Run("ProjectSettingsFile https url", func(t *testing.T) {
    75  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "https://jenkins-sap-test.com/test.xml"}
    76  		buildCmd := "mvn clean install"
    77  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    78  		assert.Equal(t, " --settings=.pipeline/mavenProjectSettings.xml", params)
    79  	})
    80  
    81  	t.Run("ProjectSettingsFile http url", func(t *testing.T) {
    82  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "http://jenkins-sap-test.com/test.xml"}
    83  		buildCmd := "mvn clean install"
    84  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    85  		assert.Equal(t, " --settings=.pipeline/mavenProjectSettings.xml", params)
    86  	})
    87  
    88  	t.Run("GlobalSettingsFile https url", func(t *testing.T) {
    89  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "https://jenkins-sap-test.com/test.xml"}
    90  		buildCmd := "mvn clean install"
    91  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    92  		assert.Equal(t, " --global-settings=.pipeline/mavenGlobalSettings.xml", params)
    93  	})
    94  
    95  	t.Run("GlobalSettingsFile http url", func(t *testing.T) {
    96  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "http://jenkins-sap-test.com/test.xml"}
    97  		buildCmd := "mvn clean install"
    98  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
    99  		assert.Equal(t, " --global-settings=.pipeline/mavenGlobalSettings.xml", params)
   100  	})
   101  
   102  	t.Run("ProjectSettingsFile and GlobalSettingsFile https url", func(t *testing.T) {
   103  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "https://jenkins-sap-test.com/test.xml", ProjectSettingsFile: "http://jenkins-sap-test.com/test.xml"}
   104  		buildCmd := "mvn clean install"
   105  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
   106  		assert.Equal(t, " --global-settings=.pipeline/mavenGlobalSettings.xml --settings=.pipeline/mavenProjectSettings.xml", params)
   107  	})
   108  
   109  	t.Run("ProjectSettingsFile and GlobalSettingsFile http url", func(t *testing.T) {
   110  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "http://jenkins-sap-test.com/test.xml", ProjectSettingsFile: "http://jenkins-sap-test.com/test.xml"}
   111  		buildCmd := "mvn clean install"
   112  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
   113  		assert.Equal(t, " --global-settings=.pipeline/mavenGlobalSettings.xml --settings=.pipeline/mavenProjectSettings.xml", params)
   114  	})
   115  
   116  	t.Run("ProjectSettingsFile file and GlobalSettingsFile https url", func(t *testing.T) {
   117  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "https://jenkins-sap-test.com/test.xml", ProjectSettingsFile: "test.xml"}
   118  		buildCmd := "mvn clean install"
   119  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
   120  		assert.Equal(t, " --global-settings=.pipeline/mavenGlobalSettings.xml --settings=test.xml", params)
   121  	})
   122  
   123  	t.Run("ProjectSettingsFile file and GlobalSettingsFile https url", func(t *testing.T) {
   124  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "http://jenkins-sap-test.com/test.xml", ProjectSettingsFile: "test.xml"}
   125  		buildCmd := "mvn clean install"
   126  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
   127  		assert.Equal(t, " --global-settings=.pipeline/mavenGlobalSettings.xml --settings=test.xml", params)
   128  	})
   129  
   130  	t.Run("ProjectSettingsFile https url and GlobalSettingsFile file", func(t *testing.T) {
   131  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "global.xml", ProjectSettingsFile: "http://jenkins-sap-test.com/test.xml"}
   132  		buildCmd := "mvn clean install"
   133  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
   134  		assert.Equal(t, " --global-settings=global.xml --settings=.pipeline/mavenProjectSettings.xml", params)
   135  	})
   136  
   137  	t.Run("ProjectSettingsFile http url and GlobalSettingsFile file", func(t *testing.T) {
   138  		config := codeqlExecuteScanOptions{BuildTool: "maven", GlobalSettingsFile: "global.xml", ProjectSettingsFile: "http://jenkins-sap-test.com/test.xml"}
   139  		buildCmd := "mvn clean install"
   140  		params := getMavenSettings(buildCmd, &config, newCodeqlExecuteScanTestsUtils())
   141  		assert.Equal(t, " --global-settings=global.xml --settings=.pipeline/mavenProjectSettings.xml", params)
   142  	})
   143  }
   144  
   145  func TestUpdateCmdFlag(t *testing.T) {
   146  	t.Parallel()
   147  
   148  	t.Run("No maven", func(t *testing.T) {
   149  		config := codeqlExecuteScanOptions{BuildTool: "npm"}
   150  		customFlags := map[string]string{
   151  			"--command": "mvn clean install",
   152  		}
   153  		updateCmdFlag(&config, customFlags, newCodeqlExecuteScanTestsUtils())
   154  		assert.Equal(t, "mvn clean install", customFlags["--command"])
   155  		assert.Equal(t, "", customFlags["-c"])
   156  	})
   157  
   158  	t.Run("No custom flags with build command provided", func(t *testing.T) {
   159  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "test.xml", GlobalSettingsFile: "global.xml"}
   160  		customFlags := map[string]string{}
   161  		updateCmdFlag(&config, customFlags, newCodeqlExecuteScanTestsUtils())
   162  		assert.Equal(t, "", customFlags["--command"])
   163  		assert.Equal(t, "", customFlags["-c"])
   164  	})
   165  
   166  	t.Run("Both --command and -c flags are set, no settings file provided", func(t *testing.T) {
   167  		config := codeqlExecuteScanOptions{BuildTool: "maven"}
   168  		customFlags := map[string]string{
   169  			"--command": "mvn clean install",
   170  			"-c":        "mvn clean install -DskipTests",
   171  		}
   172  		updateCmdFlag(&config, customFlags, newCodeqlExecuteScanTestsUtils())
   173  		assert.Equal(t, "mvn clean install", customFlags["--command"])
   174  		assert.Equal(t, "", customFlags["-c"])
   175  	})
   176  
   177  	t.Run("Only -c flag is set, no settings file provided", func(t *testing.T) {
   178  		config := codeqlExecuteScanOptions{BuildTool: "maven"}
   179  		customFlags := map[string]string{
   180  			"-c": "mvn clean install -DskipTests",
   181  		}
   182  		updateCmdFlag(&config, customFlags, newCodeqlExecuteScanTestsUtils())
   183  		assert.Equal(t, "mvn clean install -DskipTests", customFlags["--command"])
   184  		assert.Equal(t, "", customFlags["-c"])
   185  	})
   186  
   187  	t.Run("Update custom command with GlobalSettingsFile and ProjectSettingsFile", func(t *testing.T) {
   188  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "test.xml", GlobalSettingsFile: "global.xml"}
   189  		customFlags := map[string]string{
   190  			"--command": "mvn clean install",
   191  		}
   192  		updateCmdFlag(&config, customFlags, newCodeqlExecuteScanTestsUtils())
   193  		assert.Equal(t, "mvn clean install --global-settings=global.xml --settings=test.xml", customFlags["--command"])
   194  		assert.Equal(t, "", customFlags["-c"])
   195  	})
   196  
   197  	t.Run("Custom command has --global-settings and --settings", func(t *testing.T) {
   198  		config := codeqlExecuteScanOptions{BuildTool: "maven", ProjectSettingsFile: "test.xml", GlobalSettingsFile: "global.xml"}
   199  		customFlags := map[string]string{
   200  			"--command": "mvn clean install --settings=test1.xml --global-settings=global1.xml",
   201  		}
   202  		updateCmdFlag(&config, customFlags, newCodeqlExecuteScanTestsUtils())
   203  		assert.Equal(t, "mvn clean install --settings=test1.xml --global-settings=global1.xml", customFlags["--command"])
   204  		assert.Equal(t, "", customFlags["-c"])
   205  	})
   206  }
   207  
   208  func TestAddDataToInfluxDB(t *testing.T) {
   209  	repoUrl := "https://github.htllo.test/Testing/codeql"
   210  	repoRef := "https://github.htllo.test/Testing/codeql/tree/branch"
   211  	repoScanUrl := "https://github.htllo.test/Testing/codeql/security/code-scanning"
   212  	querySuite := "security.ql"
   213  
   214  	repoInfo := &codeql.RepoInfo{
   215  		FullUrl: repoUrl,
   216  		FullRef: repoRef,
   217  		ScanUrl: repoScanUrl,
   218  	}
   219  
   220  	t.Run("No findings", func(t *testing.T) {
   221  		scanResults := []codeql.CodeqlFindings{}
   222  		influx := &codeqlExecuteScanInflux{}
   223  		addDataToInfluxDB(repoInfo, querySuite, scanResults, influx)
   224  		assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL)
   225  		assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL)
   226  		assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink)
   227  		assert.Equal(t, querySuite, influx.codeql_data.fields.querySuite)
   228  		assert.Equal(t, 0, influx.codeql_data.fields.auditAllTotal)
   229  		assert.Equal(t, 0, influx.codeql_data.fields.auditAllAudited)
   230  		assert.Equal(t, 0, influx.codeql_data.fields.optionalTotal)
   231  		assert.Equal(t, 0, influx.codeql_data.fields.optionalAudited)
   232  	})
   233  
   234  	t.Run("Audit All findings category only", func(t *testing.T) {
   235  		scanResults := []codeql.CodeqlFindings{
   236  			{
   237  				ClassificationName: codeql.AuditAll,
   238  				Total:              100,
   239  				Audited:            50,
   240  			},
   241  		}
   242  		influx := &codeqlExecuteScanInflux{}
   243  		addDataToInfluxDB(repoInfo, querySuite, scanResults, influx)
   244  		assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL)
   245  		assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL)
   246  		assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink)
   247  		assert.Equal(t, querySuite, influx.codeql_data.fields.querySuite)
   248  		assert.Equal(t, scanResults[0].Total, influx.codeql_data.fields.auditAllTotal)
   249  		assert.Equal(t, scanResults[0].Audited, influx.codeql_data.fields.auditAllAudited)
   250  		assert.Equal(t, 0, influx.codeql_data.fields.optionalTotal)
   251  		assert.Equal(t, 0, influx.codeql_data.fields.optionalAudited)
   252  	})
   253  
   254  	t.Run("Optional findings category only", func(t *testing.T) {
   255  		scanResults := []codeql.CodeqlFindings{
   256  			{
   257  				ClassificationName: codeql.Optional,
   258  				Total:              100,
   259  				Audited:            50,
   260  			},
   261  		}
   262  		influx := &codeqlExecuteScanInflux{}
   263  		addDataToInfluxDB(repoInfo, querySuite, scanResults, influx)
   264  		assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL)
   265  		assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL)
   266  		assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink)
   267  		assert.Equal(t, querySuite, influx.codeql_data.fields.querySuite)
   268  		assert.Equal(t, 0, influx.codeql_data.fields.auditAllTotal)
   269  		assert.Equal(t, 0, influx.codeql_data.fields.auditAllAudited)
   270  		assert.Equal(t, scanResults[0].Total, influx.codeql_data.fields.optionalTotal)
   271  		assert.Equal(t, scanResults[0].Audited, influx.codeql_data.fields.optionalAudited)
   272  	})
   273  
   274  	t.Run("Both findings category", func(t *testing.T) {
   275  		scanResults := []codeql.CodeqlFindings{
   276  			{
   277  				ClassificationName: codeql.AuditAll,
   278  				Total:              100,
   279  				Audited:            50,
   280  			},
   281  			{
   282  				ClassificationName: codeql.Optional,
   283  				Total:              100,
   284  				Audited:            50,
   285  			},
   286  		}
   287  		influx := &codeqlExecuteScanInflux{}
   288  		addDataToInfluxDB(repoInfo, querySuite, scanResults, influx)
   289  		assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL)
   290  		assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL)
   291  		assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink)
   292  		assert.Equal(t, querySuite, influx.codeql_data.fields.querySuite)
   293  		assert.Equal(t, scanResults[0].Total, influx.codeql_data.fields.auditAllTotal)
   294  		assert.Equal(t, scanResults[0].Audited, influx.codeql_data.fields.auditAllAudited)
   295  		assert.Equal(t, scanResults[1].Total, influx.codeql_data.fields.optionalTotal)
   296  		assert.Equal(t, scanResults[1].Audited, influx.codeql_data.fields.optionalAudited)
   297  	})
   298  }
   299  
   300  func TestPrepareCmdForDatabaseCreate(t *testing.T) {
   301  	t.Parallel()
   302  
   303  	t.Run("No custom flags", func(t *testing.T) {
   304  		config := &codeqlExecuteScanOptions{
   305  			Database:     "codeqlDB",
   306  			ModulePath:   "./",
   307  			BuildTool:    "maven",
   308  			BuildCommand: "mvn clean install",
   309  		}
   310  		cmd, err := prepareCmdForDatabaseCreate(map[string]string{}, config, newCodeqlExecuteScanTestsUtils())
   311  		assert.NoError(t, err)
   312  		assert.NotEmpty(t, cmd)
   313  		assert.Equal(t, 10, len(cmd))
   314  		assert.Equal(t, "database create codeqlDB --overwrite --source-root . --working-dir ./ --language=java --command=mvn clean install",
   315  			strings.Join(cmd, " "))
   316  	})
   317  
   318  	t.Run("No custom flags, custom build tool", func(t *testing.T) {
   319  		config := &codeqlExecuteScanOptions{
   320  			Database:   "codeqlDB",
   321  			ModulePath: "./",
   322  			BuildTool:  "custom",
   323  			Language:   "javascript",
   324  		}
   325  		cmd, err := prepareCmdForDatabaseCreate(map[string]string{}, config, newCodeqlExecuteScanTestsUtils())
   326  		assert.NoError(t, err)
   327  		assert.NotEmpty(t, cmd)
   328  		assert.Equal(t, 9, len(cmd))
   329  		assert.Equal(t, "database create codeqlDB --overwrite --source-root . --working-dir ./ --language=javascript",
   330  			strings.Join(cmd, " "))
   331  	})
   332  
   333  	t.Run("No custom flags, custom build tool, no language specified", func(t *testing.T) {
   334  		config := &codeqlExecuteScanOptions{
   335  			Database:   "codeqlDB",
   336  			ModulePath: "./",
   337  			BuildTool:  "custom",
   338  		}
   339  		_, err := prepareCmdForDatabaseCreate(map[string]string{}, config, newCodeqlExecuteScanTestsUtils())
   340  		assert.Error(t, err)
   341  	})
   342  
   343  	t.Run("No custom flags, invalid build tool, no language specified", func(t *testing.T) {
   344  		config := &codeqlExecuteScanOptions{
   345  			Database:   "codeqlDB",
   346  			ModulePath: "./",
   347  			BuildTool:  "test",
   348  		}
   349  		_, err := prepareCmdForDatabaseCreate(map[string]string{}, config, newCodeqlExecuteScanTestsUtils())
   350  		assert.Error(t, err)
   351  	})
   352  
   353  	t.Run("No custom flags, invalid build tool, language specified", func(t *testing.T) {
   354  		config := &codeqlExecuteScanOptions{
   355  			Database:   "codeqlDB",
   356  			ModulePath: "./",
   357  			BuildTool:  "test",
   358  			Language:   "javascript",
   359  		}
   360  		cmd, err := prepareCmdForDatabaseCreate(map[string]string{}, config, newCodeqlExecuteScanTestsUtils())
   361  		assert.NoError(t, err)
   362  		assert.NotEmpty(t, cmd)
   363  		assert.Equal(t, 9, len(cmd))
   364  		assert.Equal(t, "database create codeqlDB --overwrite --source-root . --working-dir ./ --language=javascript",
   365  			strings.Join(cmd, " "))
   366  	})
   367  
   368  	t.Run("Custom flags, overwriting source-root", func(t *testing.T) {
   369  		config := &codeqlExecuteScanOptions{
   370  			Database:   "codeqlDB",
   371  			ModulePath: "./",
   372  			Language:   "javascript",
   373  		}
   374  		customFlags := map[string]string{
   375  			"--source-root": "--source-root=customSrcRoot/",
   376  		}
   377  		cmd, err := prepareCmdForDatabaseCreate(customFlags, config, newCodeqlExecuteScanTestsUtils())
   378  		assert.NoError(t, err)
   379  		assert.NotEmpty(t, cmd)
   380  		assert.Equal(t, 8, len(cmd))
   381  		assert.Equal(t, "database create codeqlDB --overwrite --working-dir ./ --language=javascript --source-root=customSrcRoot/",
   382  			strings.Join(cmd, " "))
   383  	})
   384  
   385  	t.Run("Custom flags, overwriting threads from config", func(t *testing.T) {
   386  		config := &codeqlExecuteScanOptions{
   387  			Database:   "codeqlDB",
   388  			ModulePath: "./",
   389  			Language:   "javascript",
   390  			Threads:    "0",
   391  			Ram:        "2000",
   392  		}
   393  		customFlags := map[string]string{
   394  			"--source-root": "--source-root=customSrcRoot/",
   395  			"-j":            "-j=1",
   396  		}
   397  		cmd, err := prepareCmdForDatabaseCreate(customFlags, config, newCodeqlExecuteScanTestsUtils())
   398  		assert.NoError(t, err)
   399  		assert.NotEmpty(t, cmd)
   400  		assert.Equal(t, 10, len(cmd))
   401  		assert.True(t, "database create codeqlDB --overwrite --working-dir ./ --language=javascript --ram=2000 -j=1 --source-root=customSrcRoot/" == strings.Join(cmd, " ") ||
   402  			"database create codeqlDB --overwrite --working-dir ./ --language=javascript --ram=2000 --source-root=customSrcRoot/ -j=1" == strings.Join(cmd, " "))
   403  	})
   404  
   405  }
   406  
   407  func TestPrepareCmdForDatabaseAnalyze(t *testing.T) {
   408  	t.Parallel()
   409  
   410  	t.Run("No additional flags, no querySuite, sarif format", func(t *testing.T) {
   411  		config := &codeqlExecuteScanOptions{
   412  			Database: "codeqlDB",
   413  		}
   414  		cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "target/codeqlReport.sarif")
   415  		assert.NoError(t, err)
   416  		assert.NotEmpty(t, cmd)
   417  		assert.Equal(t, 5, len(cmd))
   418  		assert.Equal(t, "database analyze --format=sarif-latest --output=target/codeqlReport.sarif codeqlDB", strings.Join(cmd, " "))
   419  	})
   420  
   421  	t.Run("No additional flags, no querySuite, csv format", func(t *testing.T) {
   422  		config := &codeqlExecuteScanOptions{
   423  			Database: "codeqlDB",
   424  		}
   425  		cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "csv", "target/codeqlReport.csv")
   426  		assert.NoError(t, err)
   427  		assert.NotEmpty(t, cmd)
   428  		assert.Equal(t, 5, len(cmd))
   429  		assert.Equal(t, "database analyze --format=csv --output=target/codeqlReport.csv codeqlDB", strings.Join(cmd, " "))
   430  	})
   431  
   432  	t.Run("No additional flags, set querySuite", func(t *testing.T) {
   433  		config := &codeqlExecuteScanOptions{
   434  			Database:   "codeqlDB",
   435  			QuerySuite: "security.ql",
   436  		}
   437  		cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "target/codeqlReport.sarif")
   438  		assert.NoError(t, err)
   439  		assert.NotEmpty(t, cmd)
   440  		assert.Equal(t, 6, len(cmd))
   441  		assert.Equal(t, "database analyze --format=sarif-latest --output=target/codeqlReport.sarif codeqlDB security.ql", strings.Join(cmd, " "))
   442  	})
   443  
   444  	t.Run("No custom flags, flags from config", func(t *testing.T) {
   445  		config := &codeqlExecuteScanOptions{
   446  			Database:   "codeqlDB",
   447  			QuerySuite: "security.ql",
   448  			Threads:    "1",
   449  			Ram:        "2000",
   450  		}
   451  		cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "target/codeqlReport.sarif")
   452  		assert.NoError(t, err)
   453  		assert.NotEmpty(t, cmd)
   454  		assert.Equal(t, 8, len(cmd))
   455  		assert.Equal(t, "database analyze --format=sarif-latest --output=target/codeqlReport.sarif codeqlDB --threads=1 --ram=2000 security.ql", strings.Join(cmd, " "))
   456  	})
   457  
   458  	t.Run("Custom flags, overwriting threads", func(t *testing.T) {
   459  		config := &codeqlExecuteScanOptions{
   460  			Database:   "codeqlDB",
   461  			QuerySuite: "security.ql",
   462  			Threads:    "1",
   463  			Ram:        "2000",
   464  		}
   465  		customFlags := map[string]string{
   466  			"--threads": "--threads=2",
   467  		}
   468  		cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "target/codeqlReport.sarif")
   469  		assert.NoError(t, err)
   470  		assert.NotEmpty(t, cmd)
   471  		assert.Equal(t, 8, len(cmd))
   472  		assert.Equal(t, "database analyze --format=sarif-latest --output=target/codeqlReport.sarif codeqlDB --ram=2000 --threads=2 security.ql", strings.Join(cmd, " "))
   473  	})
   474  
   475  	t.Run("Custom flags, overwriting threads (-j)", func(t *testing.T) {
   476  		config := &codeqlExecuteScanOptions{
   477  			Database:   "codeqlDB",
   478  			QuerySuite: "security.ql",
   479  			Threads:    "1",
   480  			Ram:        "2000",
   481  		}
   482  		customFlags := map[string]string{
   483  			"-j": "-j=2",
   484  		}
   485  		cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "target/codeqlReport.sarif")
   486  		assert.NoError(t, err)
   487  		assert.NotEmpty(t, cmd)
   488  		assert.Equal(t, 8, len(cmd))
   489  		assert.Equal(t, "database analyze --format=sarif-latest --output=target/codeqlReport.sarif codeqlDB --ram=2000 -j=2 security.ql", strings.Join(cmd, " "))
   490  	})
   491  
   492  	t.Run("Custom flags, no overwriting", func(t *testing.T) {
   493  		config := &codeqlExecuteScanOptions{
   494  			Database:   "codeqlDB",
   495  			QuerySuite: "security.ql",
   496  			Threads:    "1",
   497  			Ram:        "2000",
   498  		}
   499  		customFlags := map[string]string{
   500  			"--no-download": "--no-download",
   501  		}
   502  		cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "target/codeqlReport.sarif")
   503  		assert.NoError(t, err)
   504  		assert.NotEmpty(t, cmd)
   505  		assert.Equal(t, 9, len(cmd))
   506  		assert.Equal(t, "database analyze --format=sarif-latest --output=target/codeqlReport.sarif codeqlDB --threads=1 --ram=2000 --no-download security.ql", strings.Join(cmd, " "))
   507  	})
   508  }
   509  
   510  func TestPrepareCmdForUploadResults(t *testing.T) {
   511  	t.Parallel()
   512  
   513  	config := &codeqlExecuteScanOptions{
   514  		ModulePath: "./",
   515  	}
   516  
   517  	t.Run("All configs are set", func(t *testing.T) {
   518  		repoInfo := &codeql.RepoInfo{
   519  			CommitId:    "commitId",
   520  			ServerUrl:   "http://github.com",
   521  			Repo:        "repo",
   522  			Owner:       "owner",
   523  			AnalyzedRef: "refs/heads/branch",
   524  		}
   525  		cmd := prepareCmdForUploadResults(config, repoInfo, "token")
   526  		assert.NotEmpty(t, cmd)
   527  		assert.Equal(t, 8, len(cmd))
   528  	})
   529  
   530  	t.Run("Configs are set partially", func(t *testing.T) {
   531  		repoInfo := &codeql.RepoInfo{
   532  			CommitId:  "commitId",
   533  			ServerUrl: "http://github.com",
   534  			Repo:      "repo",
   535  		}
   536  		cmd := prepareCmdForUploadResults(config, repoInfo, "token")
   537  		assert.NotEmpty(t, cmd)
   538  		assert.Equal(t, 6, len(cmd))
   539  	})
   540  
   541  	t.Run("Empty token", func(t *testing.T) {
   542  		repoInfo := &codeql.RepoInfo{
   543  			CommitId:    "commitId",
   544  			ServerUrl:   "http://github.com",
   545  			Repo:        "repo",
   546  			Owner:       "owner",
   547  			AnalyzedRef: "refs/heads/branch",
   548  		}
   549  		cmd := prepareCmdForUploadResults(config, repoInfo, "")
   550  		assert.NotEmpty(t, cmd)
   551  		assert.Equal(t, 7, len(cmd))
   552  	})
   553  
   554  	t.Run("Empty configs and token", func(t *testing.T) {
   555  		repoInfo := &codeql.RepoInfo{}
   556  		cmd := prepareCmdForUploadResults(config, repoInfo, "")
   557  		assert.NotEmpty(t, cmd)
   558  		assert.Equal(t, 3, len(cmd))
   559  	})
   560  }
   561  
   562  func TestAppendCodeqlQuery(t *testing.T) {
   563  	t.Parallel()
   564  
   565  	t.Run("Empty query", func(t *testing.T) {
   566  		cmd := []string{"database", "analyze"}
   567  		query := ""
   568  		cmd = appendCodeqlQuery(cmd, query)
   569  		assert.Equal(t, 2, len(cmd))
   570  	})
   571  
   572  	t.Run("Not empty query", func(t *testing.T) {
   573  		cmd := []string{"database", "analyze"}
   574  		query := "java-extended.ql"
   575  		cmd = appendCodeqlQuery(cmd, query)
   576  		assert.Equal(t, 3, len(cmd))
   577  	})
   578  }
   579  
   580  func TestGetLangFromBuildTool(t *testing.T) {
   581  	t.Parallel()
   582  
   583  	t.Run("Build tool Maven", func(t *testing.T) {
   584  		assert.Equal(t, "java", getLangFromBuildTool("maven"))
   585  	})
   586  	t.Run("Build tool Pip", func(t *testing.T) {
   587  		assert.Equal(t, "python", getLangFromBuildTool("pip"))
   588  	})
   589  	t.Run("Build tool Npm", func(t *testing.T) {
   590  		assert.Equal(t, "javascript", getLangFromBuildTool("npm"))
   591  	})
   592  	t.Run("Build tool Yarn", func(t *testing.T) {
   593  		assert.Equal(t, "javascript", getLangFromBuildTool("yarn"))
   594  	})
   595  	t.Run("Build tool Golang", func(t *testing.T) {
   596  		assert.Equal(t, "go", getLangFromBuildTool("golang"))
   597  	})
   598  	t.Run("Build tool Unknown", func(t *testing.T) {
   599  		assert.Equal(t, "", getLangFromBuildTool("unknown"))
   600  	})
   601  }
   602  
   603  func TestGetToken(t *testing.T) {
   604  	t.Run("Token is set in config", func(t *testing.T) {
   605  		config := &codeqlExecuteScanOptions{GithubToken: "token"}
   606  		os.Setenv("GITHUB_TOKEN", "token_from_env")
   607  		hasToken, token := getToken(config)
   608  		os.Clearenv()
   609  		assert.True(t, hasToken)
   610  		assert.NotEmpty(t, token)
   611  		assert.Equal(t, "token", token)
   612  	})
   613  
   614  	t.Run("Token is set in env", func(t *testing.T) {
   615  		config := &codeqlExecuteScanOptions{}
   616  		os.Setenv("GITHUB_TOKEN", "token_from_env")
   617  		hasToken, token := getToken(config)
   618  		os.Clearenv()
   619  		assert.True(t, hasToken)
   620  		assert.NotEmpty(t, token)
   621  		assert.Equal(t, "token_from_env", token)
   622  	})
   623  
   624  	t.Run("Token is not set", func(t *testing.T) {
   625  		config := &codeqlExecuteScanOptions{}
   626  		hasToken, token := getToken(config)
   627  		assert.False(t, hasToken)
   628  		assert.Empty(t, token)
   629  	})
   630  }
   631  
   632  func TestCheckForCompliance(t *testing.T) {
   633  	t.Parallel()
   634  
   635  	config := &codeqlExecuteScanOptions{VulnerabilityThresholdTotal: 0}
   636  	repoInfo := &codeql.RepoInfo{
   637  		FullUrl:     "http://github.com/Test/repo",
   638  		AnalyzedRef: "refs/heads/branch",
   639  	}
   640  
   641  	t.Run("Project is compliant", func(t *testing.T) {
   642  		scanResults := []codeql.CodeqlFindings{
   643  			{
   644  				ClassificationName: codeql.AuditAll,
   645  				Total:              10,
   646  				Audited:            10,
   647  			},
   648  		}
   649  		assert.NoError(t, checkForCompliance(scanResults, config, repoInfo))
   650  	})
   651  
   652  	t.Run("Project is not compliant", func(t *testing.T) {
   653  		scanResults := []codeql.CodeqlFindings{
   654  			{
   655  				ClassificationName: codeql.AuditAll,
   656  				Total:              20,
   657  				Audited:            10,
   658  			},
   659  		}
   660  		assert.Error(t, checkForCompliance(scanResults, config, repoInfo))
   661  	})
   662  
   663  	t.Run("Don't check Optional findings", func(t *testing.T) {
   664  		scanResults := []codeql.CodeqlFindings{
   665  			{
   666  				ClassificationName: codeql.Optional,
   667  				Total:              10,
   668  				Audited:            0,
   669  			},
   670  		}
   671  		assert.NoError(t, checkForCompliance(scanResults, config, repoInfo))
   672  	})
   673  }