github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/fortify/fortify_test.go (about) 1 //go:build unit 2 // +build unit 3 4 package fortify 5 6 import ( 7 "fmt" 8 "io" 9 "net/http" 10 "net/http/httptest" 11 "os" 12 "strings" 13 "testing" 14 "time" 15 16 "github.com/go-openapi/strfmt" 17 ff "github.com/piper-validation/fortify-client-go/fortify" 18 "github.com/piper-validation/fortify-client-go/models" 19 "github.com/sirupsen/logrus" 20 "github.com/stretchr/testify/assert" 21 22 piperHttp "github.com/SAP/jenkins-library/pkg/http" 23 ) 24 25 func spinUpServer(f func(http.ResponseWriter, *http.Request)) (*SystemInstance, *httptest.Server) { 26 server := httptest.NewServer(http.HandlerFunc(f)) 27 28 parts := strings.Split(server.URL, "://") 29 client := ff.NewHTTPClientWithConfig(strfmt.Default, &ff.TransportConfig{ 30 Host: parts[1], 31 Schemes: []string{parts[0]}, 32 BasePath: ""}, 33 ) 34 35 httpClient := &piperHttp.Client{} 36 httpClientOptions := piperHttp.ClientOptions{Token: "test2456", TransportTimeout: 60 * time.Second} 37 httpClient.SetOptions(httpClientOptions) 38 39 sys := NewSystemInstanceForClient(client, httpClient, server.URL, "test2456", 60*time.Second) 40 return sys, server 41 } 42 43 func TestCreateTransportConfig(t *testing.T) { 44 t.Run("Valid URL", func(t *testing.T) { 45 config := createTransportConfig("http://some.fortify.host.com/ssc", "/api/v2") 46 assert.Equal(t, []string{"http"}, config.Schemes) 47 assert.Equal(t, "some.fortify.host.com", config.Host) 48 assert.Equal(t, "ssc/api/v2", config.BasePath) 49 }) 50 t.Run("Slashes are trimmed", func(t *testing.T) { 51 config := createTransportConfig("http://some.fortify.host.com/ssc//", "//api/v2/") 52 assert.Equal(t, []string{"http"}, config.Schemes) 53 assert.Equal(t, "some.fortify.host.com", config.Host) 54 assert.Equal(t, "ssc/api/v2", config.BasePath) 55 }) 56 t.Run("URL missing scheme results in no error", func(t *testing.T) { 57 config := createTransportConfig("some.fortify.host.com/ssc", "api/v1") 58 assert.Equal(t, []string{"https"}, config.Schemes) 59 assert.Equal(t, "some.fortify.host.com", config.Host) 60 assert.Equal(t, "ssc/api/v1", config.BasePath) 61 }) 62 t.Run("URL with more than one slash is accepted", func(t *testing.T) { 63 config := createTransportConfig("https://some.fortify.host.com/some/path/ssc", "api/v1") 64 assert.Equal(t, []string{"https"}, config.Schemes) 65 assert.Equal(t, "some.fortify.host.com", config.Host) 66 assert.Equal(t, "some/path/ssc/api/v1", config.BasePath) 67 }) 68 } 69 70 func TestNewSystemInstance(t *testing.T) { 71 t.Run("fields are initialized", func(t *testing.T) { 72 sys := NewSystemInstance("https://some.fortify.host.com/ssc", "api/v1", "akjhskjhks", "", 10*time.Second) 73 assert.IsType(t, ff.Fortify{}, *sys.client, "Expected to get a Fortify client instance") 74 assert.IsType(t, piperHttp.Client{}, *sys.httpClient, "Expected to get a HTTP client instance") 75 assert.IsType(t, logrus.Entry{}, *sys.logger, "Expected to get a logrus entry instance") 76 assert.Equal(t, 10*time.Second, sys.timeout, "Expected different timeout value") 77 assert.Equal(t, "akjhskjhks", sys.token, "Expected different token value") 78 assert.Equal(t, "https://some.fortify.host.com/ssc", sys.serverURL) 79 }) 80 t.Run("SSC URL is trimmed", func(t *testing.T) { 81 sys := NewSystemInstance("https://some.fortify.host.com/ssc/", "api/v1", "akjhskjhks", "", 10*time.Second) 82 assert.Equal(t, "https://some.fortify.host.com/ssc", sys.serverURL) 83 }) 84 } 85 86 func TestGetProjectByName(t *testing.T) { 87 // Start a local HTTP server 88 autocreateCalled := false 89 commitCalled := false 90 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 91 if req.URL.Path == "/projects" && req.URL.RawQuery == "q=name%3A%22python-test%22" { 92 header := rw.Header() 93 header.Add("Content-type", "application/json") 94 rw.Write([]byte( 95 `{"data": [{"_href": "https://fortify/ssc/api/v1/projects/4711","createdBy": "someUser","name": "python-test", 96 "description": "","id": 4711,"creationDate": "2018-12-03T06:29:38.197+0000","issueTemplateId": "dasdasdasdsadasdasdasdasdas"}], 97 "count": 1,"responseCode": 200,"links": {"last": {"href": "https://fortify/ssc/api/v1/projects?q=name%A3python-test&start=0"}, 98 "first": {"href": "https://fortify/ssc/api/v1/projects?q=name%3Apython-test&start=0"}}}`)) 99 return 100 } 101 if req.URL.Path == "/projects" && req.URL.RawQuery == "q=name%3A%22python+with+space+test%22" { 102 header := rw.Header() 103 header.Add("Content-type", "application/json") 104 rw.Write([]byte( 105 `{"data": [{"_href": "https://fortify/ssc/api/v1/projects/4711","createdBy": "someUser","name": "python with space test", 106 "description": "","id": 4711,"creationDate": "2018-12-03T06:29:38.197+0000","issueTemplateId": "dasdasdasdsadasdasdasdasdas"}], 107 "count": 1,"responseCode": 200,"links": {"last": {"href": "https://fortify/ssc/api/v1/projects?q=name%3A%22python+with+space+test%22&start=0"}, 108 "first": {"href": "https://fortify/ssc/api/v1/projects?q=name%3A%22python+with+space+test%22&start=0"}}}`)) 109 return 110 } 111 if req.URL.Path == "/projects" && req.URL.RawQuery == "q=name%3A%22python-empty%22" { 112 header := rw.Header() 113 header.Add("Content-type", "application/json") 114 rw.Write([]byte( 115 `{"data": [],"count": 0,"responseCode": 404,"links": {}}`)) 116 return 117 } 118 if req.URL.Path == "/projects" && req.URL.RawQuery == "q=name%3A%22python-error%22" { 119 rw.WriteHeader(400) 120 return 121 } 122 if req.URL.Path == "/projectVersions" && req.Method == "POST" { 123 autocreateCalled = true 124 header := rw.Header() 125 header.Add("Content-type", "application/json") 126 rw.WriteHeader(201) 127 rw.Write([]byte( 128 `{"data":{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 129 "project":{"id":815,"name":"autocreate","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 130 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 131 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 132 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 133 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 134 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 135 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 136 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 137 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 138 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 139 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}, 140 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/815/versions?start=0"}, 141 "first":{"href":"https://fortify/ssc/api/v1/projects/815/versions?start=0"}}}`)) 142 return 143 } 144 if req.URL.Path == "/projectVersions/10172" { 145 commitCalled = true 146 header := rw.Header() 147 header.Add("Content-type", "application/json") 148 rw.Write([]byte( 149 `{"data": {"_href": "https://fortify/ssc/api/v1/projects/815", "committed": true,"createdBy": "someUser","name": "autocreate", 150 "description": "","id": 815,"creationDate": "2018-12-03T06:29:38.197+0000","issueTemplateId": "dasdasdasdsadasdasdasdasdas"}, 151 "count": 1,"responseCode": 200,"links": {"last": {"href": "https://fortify/ssc/api/v1/projects?q=name%3Apython-test&start=0"}, 152 "first": {"href": ""}}}`)) 153 return 154 } 155 }) 156 // Close the server when test finishes 157 defer server.Close() 158 159 t.Run("test success", func(t *testing.T) { 160 result, err := sys.GetProjectByName("python-test", false, "") 161 assert.NoError(t, err, "GetProjectByName call not successful") 162 assert.Equal(t, "python-test", strings.ToLower(*result.Name), "Expected to get python-test") 163 }) 164 165 t.Run("test space", func(t *testing.T) { 166 result, err := sys.GetProjectByName("python with space test", false, "") 167 assert.NoError(t, err, "GetProjectByName call not successful") 168 assert.Equal(t, "python with space test", strings.ToLower(*result.Name), "Expected to get python with space test") 169 }) 170 171 t.Run("test empty", func(t *testing.T) { 172 _, err := sys.GetProjectByName("python-empty", false, "") 173 assert.Error(t, err, "Expected error but got success") 174 }) 175 176 t.Run("test error", func(t *testing.T) { 177 _, err := sys.GetProjectByName("python-error", false, "") 178 assert.Error(t, err, "Expected error but got success") 179 }) 180 181 t.Run("test auto create success", func(t *testing.T) { 182 result, err := sys.GetProjectByName("autocreate", true, "123456") 183 assert.NoError(t, err, "GetProjectByName call not successful") 184 assert.Equal(t, true, autocreateCalled, "Expected autocreation function to be called but wasn't") 185 assert.Equal(t, true, commitCalled, "Expected commit function to be called but wasn't") 186 assert.Equal(t, "autocreate", strings.ToLower(*result.Name), "Expected to get autocreate project") 187 }) 188 } 189 190 func TestGetProjectVersionDetailsByProjectIDAndVersionName(t *testing.T) { 191 // Start a local HTTP server 192 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 193 if req.URL.Path == "/projects/4711/versions" { 194 header := rw.Header() 195 header.Add("Content-type", "application/json") 196 rw.Write([]byte( 197 `{"data":[{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 198 "project":{"id":4711,"name":"python-test","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 199 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 200 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 201 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 202 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 203 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 204 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 205 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 206 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 207 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 208 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}], 209 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}, 210 "first":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}}}`)) 211 return 212 } 213 if req.URL.Path == "/projects/777/versions" { 214 header := rw.Header() 215 header.Add("Content-type", "application/json") 216 rw.Write([]byte( 217 `{"data": [],"count": 0,"responseCode": 404,"links": {}}`)) 218 return 219 } 220 if req.URL.Path == "/projects/999/versions" { 221 rw.WriteHeader(500) 222 return 223 } 224 if req.URL.Path == "/projectVersions" { 225 header := rw.Header() 226 header.Add("Content-type", "application/json") 227 rw.WriteHeader(201) 228 rw.Write([]byte( 229 `{"data":{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 230 "project":{"id":815,"name":"autocreate","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 231 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 232 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 233 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 234 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 235 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 236 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 237 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 238 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 239 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 240 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}, 241 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/815/versions?start=0"}, 242 "first":{"href":"https://fortify/ssc/api/v1/projects/815/versions?start=0"}}}`)) 243 return 244 } 245 if req.URL.Path == "/projectVersions/0" { 246 header := rw.Header() 247 header.Add("Content-type", "application/json") 248 rw.Write([]byte( 249 `{"data":{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 250 "project":{"id":815,"name":"autocreate","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 251 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 252 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 253 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 254 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 255 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 256 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 257 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 258 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 259 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 260 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}, 261 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/815/versions?start=0"}, 262 "first":{"href":"https://fortify/ssc/api/v1/projects/815/versions?start=0"}}}`)) 263 return 264 } 265 if req.URL.Path == "/projects/8888/versions" && req.URL.RawQuery == "q=name%3A%221%22" { 266 header := rw.Header() 267 header.Add("Content-type", "application/json") 268 rw.Write([]byte(`{"data":[{"id":9910,"project":{"id":8888,"name":"test","description":"Created by Go script","creationDate":"2022-06-24T04:44:12.344+0000", 269 "createdBy":"jajajajja","issueTemplateId":"asxasca-asff-b57aedaf41"},"name":"1","description":"","createdBy":"afsafa","creationDate":"2021-07-17T04:09:17.909+0000", 270 "sourceBasePath":null,"committed":true,"issueTemplateId":"asdawffbcad88eb041","issueTemplateName":"aiudfnwofn","loadProperties":null,"staleIssueTemplate":false, 271 "snapshotOutOfDate":false,"refreshRequired":false,"attachmentsOutOfDate":false,"migrationVersion":null,"masterAttrGuid":"akjnfkjsnfkj686b","tracesOutOfDate":false, 272 "issueTemplateModifiedTime":1556502937909,"active":true,"obfuscatedId":null,"owner":"","serverVersion":21.2,"siteId":null,"latestScanId":null,"mode":"BASIC", 273 "currentState":{"id":9910,"committed":true,"attentionRequired":false,"analysisResultsExist":false,"auditEnabled":false,"lastFprUploadDate":null,"extraMessage":null, 274 "analysisUploadEnabled":true,"batchBugSubmissionExists":false,"hasCustomIssues":false,"metricEvaluationDate":null,"deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0, 275 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0},"bugTrackerPluginId":null,"bugTrackerEnabled":false,"securityGroup":null,"status":null, 276 "assignedIssuesCount":0,"customTagValuesAutoApply":null,"autoPredict":null,"predictionPolicy":null,"_href":"https://fortify/ssc/api/v1/projectVersions/8888"}],"count":1, 277 "responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/8888/versions?q=name%3A1&start=0"},"first":{"href":"https://fortify/ssc/api/v1/projects/8888/versions?q=name%3A1&start=0"}}}`)) 278 return 279 } 280 }) 281 282 // Close the server when test finishes 283 defer server.Close() 284 285 t.Run("test success", func(t *testing.T) { 286 result, err := sys.GetProjectVersionDetailsByProjectIDAndVersionName(4711, "0", false, "") 287 assert.NoError(t, err, "GetProjectVersionDetailsByNameAndProjectID call not successful") 288 assert.Equal(t, "0", *result.Name, "Expected to get project version with different name") 289 }) 290 291 t.Run("test empty", func(t *testing.T) { 292 _, err := sys.GetProjectVersionDetailsByProjectIDAndVersionName(777, "python-empty", false, "") 293 assert.Error(t, err, "Expected error but got success") 294 }) 295 296 t.Run("test HTTP error", func(t *testing.T) { 297 _, err := sys.GetProjectVersionDetailsByProjectIDAndVersionName(999, "python-http-error", false, "") 298 assert.Error(t, err, "Expected error but got success") 299 }) 300 301 t.Run("test auto create success", func(t *testing.T) { 302 result, err := sys.GetProjectVersionDetailsByProjectIDAndVersionName(815, "0", true, "autocreate") 303 assert.NoError(t, err, "GetProjectVersionDetailsByNameAndProjectID call not successful") 304 assert.Equal(t, "0", *result.Name, "Expected to get project version with different name") 305 assert.Equal(t, "autocreate", *result.Project.Name, "Expected to get project with different name") 306 }) 307 t.Run("test filter projectVersion", func(t *testing.T) { 308 result, err := sys.GetProjectVersionDetailsByProjectIDAndVersionName(8888, "1", true, "autocreate") 309 assert.NoError(t, err, "GetProjectVersionDetailsByNameAndProjectID call not successful") 310 assert.Equal(t, "1", *result.Name, "Expected to get exact project version") 311 }) 312 } 313 314 func TestGetProjectVersionAttributesByProjectVersionID(t *testing.T) { 315 // Start a local HTTP server 316 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 317 if req.URL.Path == "/projectVersions/4711/attributes" { 318 header := rw.Header() 319 header.Add("Content-type", "application/json") 320 rw.Write([]byte( 321 `{"data": [{"_href": "https://fortify/ssc/api/v1/projectVersions/4711/attributes/4712","attributeDefinitionId": 31, 322 "values": null,"guid": "gdgfdgfdgfdgfd","id": 4712,"value": "abcd"}],"count": 8,"responseCode": 200}`)) 323 return 324 } 325 if req.URL.Path == "/projectVersions/777/attributes" { 326 header := rw.Header() 327 header.Add("Content-type", "application/json") 328 rw.Write([]byte( 329 `{"data": [],"count": 0,"responseCode": 404,"links": {}}`)) 330 return 331 } 332 if req.URL.Path == "/projectVersions/999/attributes" { 333 rw.WriteHeader(500) 334 return 335 } 336 }) 337 338 // Close the server when test finishes 339 defer server.Close() 340 341 t.Run("test success", func(t *testing.T) { 342 result, err := sys.GetProjectVersionAttributesByProjectVersionID(4711) 343 assert.NoError(t, err, "GetProjectVersionAttributesByProjectVersionID call not successful") 344 assert.Equal(t, "abcd", *result[0].Value, "Expected to get attribute with different value") 345 assert.Equal(t, int64(4712), result[0].ID, "Expected to get attribute with different id") 346 }) 347 348 t.Run("test empty", func(t *testing.T) { 349 result, err := sys.GetProjectVersionAttributesByProjectVersionID(777) 350 assert.NoError(t, err, "GetProjectVersionAttributesByID call not successful") 351 assert.Equal(t, 0, len(result), "Expected to not get any attributes") 352 }) 353 354 t.Run("test HTTP error", func(t *testing.T) { 355 _, err := sys.GetProjectVersionAttributesByProjectVersionID(999) 356 assert.Error(t, err, "Expected error but got success") 357 }) 358 } 359 360 func TestSetProjectVersionAttributesByProjectVersionID(t *testing.T) { 361 // Start a local HTTP server 362 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 363 if req.URL.Path == "/projectVersions/4711/attributes" { 364 header := rw.Header() 365 header.Add("Content-type", "application/json") 366 bodyBytes, _ := io.ReadAll(req.Body) 367 bodyString := string(bodyBytes) 368 response := `{"data": ` 369 response += bodyString 370 response += `,"count": 1,"responseCode": 200}` 371 rw.WriteHeader(200) 372 rw.Write([]byte(response)) 373 return 374 } 375 }) 376 377 // Close the server when test finishes 378 defer server.Close() 379 380 t.Run("test success", func(t *testing.T) { 381 value := "abcd" 382 defID := int64(18) 383 attributes := []*models.Attribute{{ID: 4712, Value: &value, AttributeDefinitionID: &defID}} 384 result, err := sys.SetProjectVersionAttributesByProjectVersionID(4711, attributes) 385 assert.NoError(t, err, "SetProjectVersionAttributesByProjectVersionID call not successful") 386 assert.Equal(t, 1, len(result), "Expected to get slice with different amount of values") 387 assert.Equal(t, "abcd", *result[0].Value, "Expected to get attribute with different value") 388 assert.Equal(t, int64(4712), result[0].ID, "Expected to get attribute with different id") 389 }) 390 } 391 392 func TestCreateProjectVersion(t *testing.T) { 393 // Start a local HTTP server 394 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 395 if req.URL.Path == "/projectVersions" { 396 header := rw.Header() 397 header.Add("Content-type", "application/json") 398 bodyBytes, _ := io.ReadAll(req.Body) 399 bodyContent := string(bodyBytes) 400 responseContent := `{"data": ` 401 responseContent += bodyContent 402 responseContent += `,"count": 1,"responseCode": 201,"links": {}}` 403 fmt.Println(responseContent) 404 rw.WriteHeader(201) 405 rw.Write([]byte(responseContent)) 406 return 407 } 408 }) 409 410 // Close the server when test finishes 411 defer server.Close() 412 413 t.Run("test success", func(t *testing.T) { 414 int64Value := int64(65) 415 int32Value := int32(876) 416 float32Value := float32(19.12) 417 now := models.NewIso8601MilliDateTime() 418 enabled := true 419 disabled := false 420 name := "Test new PV" 421 owner := "someUser" 422 masterGUID := "dsadaoudoiud" 423 project := models.Project{CreatedBy: &owner, CreationDate: now, Description: name, ID: int64Value, IssueTemplateID: &name, Name: &name} 424 projectVersionState := models.ProjectVersionState{AnalysisResultsExist: &disabled, AnalysisUploadEnabled: &disabled, 425 AttentionRequired: &disabled, AuditEnabled: &enabled, BatchBugSubmissionExists: &disabled, Committed: &enabled, 426 CriticalPriorityIssueCountDelta: &int32Value, DeltaPeriod: &int32Value, ExtraMessage: &name, HasCustomIssues: &disabled, 427 ID: &int64Value, IssueCountDelta: &int32Value, LastFprUploadDate: &now, MetricEvaluationDate: &now, PercentAuditedDelta: &float32Value, 428 PercentCriticalPriorityIssuesAuditedDelta: &float32Value} 429 version := models.ProjectVersion{AssignedIssuesCount: int64Value, Project: &project, Name: &name, Active: &enabled, 430 Committed: &enabled, AttachmentsOutOfDate: disabled, AutoPredict: disabled, BugTrackerEnabled: &disabled, 431 CustomTagValuesAutoApply: disabled, RefreshRequired: disabled, Owner: &owner, ServerVersion: &float32Value, 432 SnapshotOutOfDate: &disabled, StaleIssueTemplate: &disabled, MasterAttrGUID: &masterGUID, 433 LatestScanID: &int64Value, IssueTemplateName: &name, IssueTemplateModifiedTime: &int64Value, 434 IssueTemplateID: &name, Description: &name, CreatedBy: &owner, BugTrackerPluginID: &name, Mode: "NONE", 435 CurrentState: &projectVersionState, ID: int64Value, LoadProperties: "", CreationDate: &now, 436 MigrationVersion: float32Value, ObfuscatedID: "", PredictionPolicy: "", SecurityGroup: "", 437 SiteID: "", SourceBasePath: "", Status: "", TracesOutOfDate: false} 438 result, err := sys.CreateProjectVersion(&version) 439 assert.NoError(t, err, "CreateProjectVersion call not successful") 440 assert.Equal(t, name, *result.Name, "Expected to get PV with different value") 441 assert.Equal(t, int64(65), result.ID, "Expected to get PV with different id") 442 }) 443 } 444 445 func TestProjectVersionCopyFromPartial(t *testing.T) { 446 // Start a local HTTP server 447 bodyContent := "" 448 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 449 if req.URL.Path == "/projectVersions/action/copyFromPartial" { 450 header := rw.Header() 451 header.Add("Content-type", "application/json") 452 bodyBytes, _ := io.ReadAll(req.Body) 453 bodyContent = string(bodyBytes) 454 rw.Write([]byte( 455 `{"data":[{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 456 "project":{"id":4711,"name":"python-test","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 457 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 458 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 459 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 460 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 461 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 462 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 463 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 464 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 465 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 466 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}], 467 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}, 468 "first":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}}}`)) 469 return 470 } 471 }) 472 // Close the server when test finishes 473 defer server.Close() 474 475 t.Run("test success", func(t *testing.T) { 476 expected := `{"copyAnalysisProcessingRules":true,"copyBugTrackerConfiguration":true,"copyCustomTags":true,"previousProjectVersionId":10172,"projectVersionId":10173} 477 ` 478 err := sys.ProjectVersionCopyFromPartial(10172, 10173) 479 assert.NoError(t, err, "ProjectVersionCopyFromPartial call not successful") 480 assert.Equal(t, expected, bodyContent, "Different request content expected") 481 }) 482 } 483 484 func TestProjectVersionCopyCurrentState(t *testing.T) { 485 // Start a local HTTP server 486 bodyContent := "" 487 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 488 if req.URL.Path == "/projectVersions/action/copyCurrentState" { 489 header := rw.Header() 490 header.Add("Content-type", "application/json") 491 bodyBytes, _ := io.ReadAll(req.Body) 492 bodyContent = string(bodyBytes) 493 rw.Write([]byte( 494 `{"data":[{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 495 "project":{"id":4711,"name":"python-test","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 496 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 497 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 498 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 499 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 500 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 501 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 502 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 503 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 504 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 505 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}], 506 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}, 507 "first":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}}}`)) 508 return 509 } 510 }) 511 // Close the server when test finishes 512 defer server.Close() 513 514 t.Run("test success", func(t *testing.T) { 515 expected := `{"previousProjectVersionId":10172,"projectVersionId":10173} 516 ` 517 err := sys.ProjectVersionCopyCurrentState(10172, 10173) 518 assert.NoError(t, err, "ProjectVersionCopyCurrentState call not successful") 519 assert.Equal(t, expected, bodyContent, "Different request content expected") 520 }) 521 } 522 523 func TestProjectVersionCopyPermissions(t *testing.T) { 524 // Start a local HTTP server 525 bodyContent := "" 526 referenceContent := `[{"displayName":"some user","email":"some.one@test.com","entityName":"some_user","firstName":"some","id":589,"lastName":"user","type":"User"}] 527 ` 528 response := `{"data": ` 529 response += referenceContent 530 response += `,"count": 1,"responseCode": 200}` 531 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 532 if req.URL.Path == "/projectVersions/10172/authEntities" { 533 header := rw.Header() 534 header.Add("Content-type", "application/json") 535 rw.Write([]byte(response)) 536 return 537 } 538 if req.URL.Path == "/projectVersions/10173/authEntities" { 539 header := rw.Header() 540 header.Add("Content-type", "application/json") 541 bodyBytes, _ := io.ReadAll(req.Body) 542 bodyContent = string(bodyBytes) 543 rw.Write([]byte(response)) 544 return 545 } 546 }) 547 // Close the server when test finishes 548 defer server.Close() 549 550 t.Run("test success", func(t *testing.T) { 551 err := sys.ProjectVersionCopyPermissions(10172, 10173) 552 assert.NoError(t, err, "ProjectVersionCopyPermissions call not successful") 553 assert.Equal(t, referenceContent, bodyContent, "Different request content expected") 554 }) 555 } 556 557 func TestCommitProjectVersion(t *testing.T) { 558 // Start a local HTTP server 559 bodyContent := "" 560 referenceContent := `{"active":null,"bugTrackerEnabled":null,"bugTrackerPluginId":null,"committed":true,"createdBy":null,"creationDate":null,"description":null,"issueTemplateId":null,"issueTemplateModifiedTime":null,"issueTemplateName":null,"latestScanId":null,"masterAttrGuid":null,"name":null,"owner":null,"serverVersion":null,"snapshotOutOfDate":null,"staleIssueTemplate":null} 561 ` 562 response := `{"data": ` 563 response += referenceContent 564 response += `,"count": 1,"responseCode": 200}` 565 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 566 if req.URL.Path == "/projectVersions/10172" { 567 header := rw.Header() 568 header.Add("Content-type", "application/json") 569 bodyBytes, _ := io.ReadAll(req.Body) 570 bodyContent = string(bodyBytes) 571 rw.Write([]byte(response)) 572 return 573 } 574 }) 575 // Close the server when test finishes 576 defer server.Close() 577 578 t.Run("test success", func(t *testing.T) { 579 result, err := sys.CommitProjectVersion(10172) 580 assert.NoError(t, err, "CommitProjectVersion call not successful") 581 assert.Equal(t, true, *result.Committed, "Different result content expected") 582 assert.Equal(t, referenceContent, bodyContent, "Different request content expected") 583 }) 584 } 585 586 func TestInactivateProjectVersion(t *testing.T) { 587 // Start a local HTTP server 588 bodyContent := "" 589 referenceContent := `{"active":false,"bugTrackerEnabled":null,"bugTrackerPluginId":null,"committed":true,"createdBy":null,"creationDate":null,"description":null,"issueTemplateId":null,"issueTemplateModifiedTime":null,"issueTemplateName":null,"latestScanId":null,"masterAttrGuid":null,"name":null,"owner":null,"serverVersion":null,"snapshotOutOfDate":null,"staleIssueTemplate":null} 590 ` 591 response := `{"data": ` 592 response += referenceContent 593 response += `,"count": 1,"responseCode": 200}` 594 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 595 if req.URL.Path == "/projectVersions/10172" { 596 header := rw.Header() 597 header.Add("Content-type", "application/json") 598 bodyBytes, _ := io.ReadAll(req.Body) 599 bodyContent = string(bodyBytes) 600 rw.Write([]byte(response)) 601 return 602 } 603 }) 604 // Close the server when test finishes 605 defer server.Close() 606 607 t.Run("test success", func(t *testing.T) { 608 result, err := sys.inactivateProjectVersion(10172) 609 assert.NoError(t, err, "InactivateProjectVersion call not successful") 610 assert.Equal(t, true, *result.Committed, "Different result content expected") 611 assert.Equal(t, false, *result.Active, "Different result content expected") 612 assert.Equal(t, referenceContent, bodyContent, "Different request content expected") 613 }) 614 } 615 616 func TestGetArtifactsOfProjectVersion(t *testing.T) { 617 // Start a local HTTP server 618 response := `{"data": [{"artifactType": "FPR","fileName": "df54e2ade34c4f6aaddf35679dd87a21.tmp","approvalDate": null,"messageCount": 0, 619 "scanErrorsCount": 0,"uploadIP": "10.238.8.48","allowApprove": false,"allowPurge": false,"lastScanDate": "2019-11-26T22:37:52.000+0000", 620 "fileURL": null,"id": 56,"purged": false,"webInspectStatus": "NONE","inModifyingStatus": false,"originalFileName": "result.fpr", 621 "allowDelete": true,"scaStatus": "PROCESSED","indexed": true,"runtimeStatus": "NONE","userName": "some_user","versionNumber": null, 622 "otherStatus": "NOT_EXIST","uploadDate": "2019-11-26T22:38:11.813+0000","approvalComment": null,"approvalUsername": null,"fileSize": 984703, 623 "messages": "","auditUpdated": false,"status": "PROCESS_COMPLETE"}],"count": 1,"responseCode": 200}` 624 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 625 if req.URL.Path == "/projectVersions/10172/artifacts" { 626 header := rw.Header() 627 header.Add("Content-type", "application/json") 628 rw.Write([]byte(response)) 629 return 630 } 631 }) 632 // Close the server when test finishes 633 defer server.Close() 634 635 t.Run("test success", func(t *testing.T) { 636 result, err := sys.GetArtifactsOfProjectVersion(10172) 637 assert.NoError(t, err, "GetArtifactsOfProjectVersion call not successful") 638 assert.Equal(t, 1, len(result), "Different result content expected") 639 assert.Equal(t, int64(56), result[0].ID, "Different result content expected") 640 }) 641 } 642 643 func TestGetFilterSetOfProjectVersionByTitle(t *testing.T) { 644 // Start a local HTTP server 645 response := `{"data":[{"defaultFilterSet":true,"folders":[ 646 {"id":1,"guid":"4711","name":"Corporate Security Requirements","color":"000000"}, 647 {"id":2,"guid":"4712","name":"Audit All","color":"ff0000"}, 648 {"id":3,"guid":"4713","name":"Spot Checks of Each Category","color":"ff8000"}, 649 {"id":4,"guid":"4714","name":"Optional","color":"808080"}],"description":"", 650 "guid":"666","title":"Special"}],"count":1,"responseCode":200}}` 651 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 652 if req.URL.Path == "/projectVersions/10172/filterSets" { 653 header := rw.Header() 654 header.Add("Content-type", "application/json") 655 rw.Write([]byte(response)) 656 return 657 } 658 }) 659 // Close the server when test finishes 660 defer server.Close() 661 662 t.Run("test success", func(t *testing.T) { 663 result, err := sys.GetFilterSetOfProjectVersionByTitle(10172, "Special") 664 assert.NoError(t, err, "GetFilterSetOfProjectVersionByTitle call not successful") 665 assert.Equal(t, "Special", result.Title, "Different result content expected") 666 }) 667 668 t.Run("test default", func(t *testing.T) { 669 result, err := sys.GetFilterSetOfProjectVersionByTitle(10172, "") 670 assert.NoError(t, err, "GetFilterSetOfProjectVersionByTitle call not successful") 671 assert.Equal(t, "Special", result.Title, "Different result content expected") 672 }) 673 } 674 675 func TestGetIssueFilterSelectorOfProjectVersionByName(t *testing.T) { 676 // Start a local HTTP server 677 response := `{"data":{"groupBySet": [{"entityType": "CUSTOMTAG","guid": "adsffghjkl","displayName": "Analysis", 678 "value": "87f2364f-dcd4-49e6-861d-f8d3f351686b","description": ""},{"entityType": "ISSUE","guid": "lkjhgfd", 679 "displayName": "Category","value": "11111111-1111-1111-1111-111111111165","description": ""}],"filterBySet":[{ 680 "entityType": "CUSTOMTAG","filterSelectorType": "LIST","guid": "87f2364f-dcd4-49e6-861d-f8d3f351686b","displayName": "Analysis", 681 "value": "87f2364f-dcd4-49e6-861d-f8d3f351686b","description": "The analysis tag must be set.", 682 "selectorOptions": []},{"entityType": "FOLDER","filterSelectorType": "LIST","guid": "userAssignment","displayName": "Folder", 683 "value": "FOLDER","description": "","selectorOptions": []}]},"responseCode":200}}` 684 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 685 if req.URL.Path == "/projectVersions/10172/issueSelectorSet" { 686 header := rw.Header() 687 header.Add("Content-type", "application/json") 688 rw.Write([]byte(response)) 689 return 690 } 691 }) 692 // Close the server when test finishes 693 defer server.Close() 694 695 t.Run("test success one", func(t *testing.T) { 696 result, err := sys.GetIssueFilterSelectorOfProjectVersionByName(10172, []string{"Analysis"}, nil) 697 assert.NoError(t, err, "GetIssueFilterSelectorOfProjectVersionByName call not successful") 698 assert.NotNil(t, result, "Expected non nil value") 699 assert.Equal(t, 1, len(result.FilterBySet), "Different result expected") 700 assert.Equal(t, 1, len(result.GroupBySet), "Different result expected") 701 }) 702 703 t.Run("test success several", func(t *testing.T) { 704 result, err := sys.GetIssueFilterSelectorOfProjectVersionByName(10172, []string{"Analysis", "Folder"}, nil) 705 assert.NoError(t, err, "GetIssueFilterSelectorOfProjectVersionByName call not successful") 706 assert.NotNil(t, result, "Expected non nil value") 707 assert.Equal(t, 2, len(result.FilterBySet), "Different result expected") 708 assert.Equal(t, 1, len(result.GroupBySet), "Different result expected") 709 }) 710 711 t.Run("test empty", func(t *testing.T) { 712 result, err := sys.GetIssueFilterSelectorOfProjectVersionByName(10172, []string{"Some", "Other"}, nil) 713 assert.NoError(t, err, "GetIssueFilterSelectorOfProjectVersionByName call not successful") 714 assert.NotNil(t, result, "Expected non nil value") 715 assert.Equal(t, 0, len(result.FilterBySet), "Different result expected") 716 assert.Equal(t, 0, len(result.GroupBySet), "Different result expected") 717 }) 718 } 719 720 func TestReduceIssueFilterSelectorSet(t *testing.T) { 721 sys, _ := spinUpServer(func(rw http.ResponseWriter, req *http.Request) {}) 722 name1 := "Special" 723 name2 := "Other" 724 guid := "FOLDER" 725 options := []*models.SelectorOption{{GUID: "1234567", DisplayName: "Test"}, {GUID: "1234568", DisplayName: "Test2"}} 726 filterSet := models.IssueFilterSelectorSet{FilterBySet: []*models.IssueFilterSelector{}, GroupBySet: []*models.IssueSelector{}} 727 filterSet.FilterBySet = append(filterSet.FilterBySet, &models.IssueFilterSelector{DisplayName: name1, SelectorOptions: options}) 728 filterSet.FilterBySet = append(filterSet.FilterBySet, &models.IssueFilterSelector{DisplayName: name2}) 729 filterSet.GroupBySet = append(filterSet.GroupBySet, &models.IssueSelector{DisplayName: &name2, GUID: &guid}) 730 reducedFilterSet := sys.ReduceIssueFilterSelectorSet(&filterSet, []string{"Special"}, []string{"Test"}) 731 assert.Equal(t, 1, len(reducedFilterSet.FilterBySet), "Different result expected") 732 assert.Equal(t, 1, len(reducedFilterSet.FilterBySet[0].SelectorOptions), "Different result expected") 733 assert.Equal(t, "Test", reducedFilterSet.FilterBySet[0].SelectorOptions[0].DisplayName, "Different result expected") 734 assert.Equal(t, 0, len(reducedFilterSet.GroupBySet), "Different result expected") 735 } 736 737 func TestGetProjectIssuesByIDAndFilterSetGroupedBySelector(t *testing.T) { 738 // Start a local HTTP server 739 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 740 if req.URL.Path == "/projectVersions/10172/filterSets" { 741 header := rw.Header() 742 header.Add("Content-type", "application/json") 743 rw.Write([]byte(`{"data":[{"defaultFilterSet":true,"folders":[ 744 {"id":1,"guid":"4711","name":"Corporate Security Requirements","color":"000000"}, 745 {"id":2,"guid":"4712","name":"Audit All","color":"ff0000"}, 746 {"id":3,"guid":"4713","name":"Spot Checks of Each Category","color":"ff8000"}, 747 {"id":4,"guid":"4714","name":"Optional","color":"808080"}],"description":"", 748 "guid":"666","title":"Special"}],"count":1,"responseCode":200}}`)) 749 return 750 } 751 if req.URL.Path == "/projectVersions/10172/issueGroups" { 752 assert.Equal(t, "filterset=666&groupingtype=FOLDER&showsuppressed=true", req.URL.RawQuery) 753 return 754 } 755 rw.WriteHeader(400) 756 }) 757 // Close the server when test finishes 758 defer server.Close() 759 760 t.Run("test success", func(t *testing.T) { 761 name := "Special" 762 guid := "FOLDER" 763 filterSet := models.IssueFilterSelectorSet{FilterBySet: []*models.IssueFilterSelector{}, GroupBySet: []*models.IssueSelector{}} 764 filterSet.FilterBySet = append(filterSet.FilterBySet, &models.IssueFilterSelector{DisplayName: name}) 765 filterSet.GroupBySet = append(filterSet.GroupBySet, &models.IssueSelector{DisplayName: &name, GUID: &guid}) 766 _, err := sys.GetProjectIssuesByIDAndFilterSetGroupedBySelector(10172, "", "666", &filterSet) 767 assert.NoError(t, err, "GetProjectIssuesByIDAndFilterSetGroupedByFolder call not successful") 768 }) 769 } 770 771 func TestGetProjectIssuesByIDAndFilterSetGroupedByCategory(t *testing.T) { 772 // Start a local HTTP server 773 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 774 if req.URL.Path == "/projectVersions/10172/filterSets" { 775 header := rw.Header() 776 header.Add("Content-type", "application/json") 777 rw.Write([]byte(`{"data":[{"defaultFilterSet":true,"folders":[ 778 {"id":1,"guid":"4711","name":"Corporate Security Requirements","color":"000000"}, 779 {"id":2,"guid":"4712","name":"Audit All","color":"ff0000"}, 780 {"id":3,"guid":"4713","name":"Spot Checks of Each Category","color":"ff8000"}, 781 {"id":4,"guid":"4714","name":"Optional","color":"808080"}],"description":"", 782 "guid":"666","title":"Special"}],"count":1,"responseCode":200}}`)) 783 return 784 } 785 if req.URL.Path == "/projectVersions/10172/issueGroups" { 786 assert.Equal(t, "filter=4713&filterset=666&groupingtype=11111111-1111-1111-1111-111111111165&showsuppressed=true", req.URL.RawQuery) 787 return 788 } 789 rw.WriteHeader(400) 790 }) 791 // Close the server when test finishes 792 defer server.Close() 793 794 t.Run("test success", func(t *testing.T) { 795 name := "Special" 796 guid := "11111111-1111-1111-1111-111111111165" 797 filterSet := models.IssueFilterSelectorSet{FilterBySet: []*models.IssueFilterSelector{}, GroupBySet: []*models.IssueSelector{}} 798 filterSet.FilterBySet = append(filterSet.FilterBySet, &models.IssueFilterSelector{DisplayName: name}) 799 filterSet.GroupBySet = append(filterSet.GroupBySet, &models.IssueSelector{DisplayName: &name, GUID: &guid}) 800 _, err := sys.GetProjectIssuesByIDAndFilterSetGroupedBySelector(10172, "4713", "666", &filterSet) 801 assert.NoError(t, err, "GetProjectIssuesByIDAndFilterSetGroupedByCategory call not successful") 802 }) 803 } 804 805 func TestGetProjectIssuesByIDAndFilterSetGroupedByAnalysis(t *testing.T) { 806 // Start a local HTTP server 807 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 808 if req.URL.Path == "/projectVersions/10172/filterSets" { 809 header := rw.Header() 810 header.Add("Content-type", "application/json") 811 rw.Write([]byte(`{"data":[{"defaultFilterSet":true,"folders":[ 812 {"id":1,"guid":"4711","name":"Corporate Security Requirements","color":"000000"}, 813 {"id":2,"guid":"4712","name":"Audit All","color":"ff0000"}, 814 {"id":3,"guid":"4713","name":"Spot Checks of Each Category","color":"ff8000"}, 815 {"id":4,"guid":"4714","name":"Optional","color":"808080"}],"description":"", 816 "guid":"666","title":"Special"}],"count":1,"responseCode":200}}`)) 817 return 818 } 819 if req.URL.Path == "/projectVersions/10172/issueGroups" { 820 assert.Equal(t, "filterset=666&groupingtype=87f2364f-dcd4-49e6-861d-f8d3f351686b&showsuppressed=true", req.URL.RawQuery) 821 return 822 } 823 rw.WriteHeader(400) 824 }) 825 // Close the server when test finishes 826 defer server.Close() 827 828 t.Run("test success", func(t *testing.T) { 829 name := "Special" 830 guid := "87f2364f-dcd4-49e6-861d-f8d3f351686b" 831 filterSet := models.IssueFilterSelectorSet{FilterBySet: []*models.IssueFilterSelector{}, GroupBySet: []*models.IssueSelector{}} 832 filterSet.FilterBySet = append(filterSet.FilterBySet, &models.IssueFilterSelector{DisplayName: name}) 833 filterSet.GroupBySet = append(filterSet.GroupBySet, &models.IssueSelector{DisplayName: &name, GUID: &guid}) 834 _, err := sys.GetProjectIssuesByIDAndFilterSetGroupedBySelector(10172, "", "666", &filterSet) 835 assert.NoError(t, err, "GetProjectIssuesByIDAndFilterSetGroupedByAnalysis call not successful") 836 }) 837 } 838 839 func TestGetIssueStatisticsOfProjectVersion(t *testing.T) { 840 // Start a local HTTP server 841 response := `{"data": [{"filterSetId": 3887,"hiddenCount": 0,"suppressedDisplayableCount": 0,"suppressedCount": 11,"hiddenDisplayableCount": 0,"projectVersionId": 10172, 842 "removedDisplayableCount": 0,"removedCount": 747}],"count": 1,"responseCode": 200}` 843 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 844 if req.URL.Path == "/projectVersions/10172/issueStatistics" { 845 header := rw.Header() 846 header.Add("Content-type", "application/json") 847 rw.Write([]byte(response)) 848 return 849 } 850 }) 851 // Close the server when test finishes 852 defer server.Close() 853 854 t.Run("test success", func(t *testing.T) { 855 result, err := sys.GetIssueStatisticsOfProjectVersion(10172) 856 assert.NoError(t, err, "GetArtifactsOfProjectVersion call not successful") 857 assert.Equal(t, 1, len(result), "Different result content expected") 858 assert.Equal(t, int64(10172), *result[0].ProjectVersionID, "Different result content expected") 859 assert.Equal(t, int32(11), *result[0].SuppressedCount, "Different result content expected") 860 }) 861 } 862 863 func TestGenerateQGateReport(t *testing.T) { 864 // Start a local HTTP server 865 data := "" 866 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 867 if req.URL.Path == "/reports" { 868 header := rw.Header() 869 header.Add("Content-type", "application/json") 870 bodyBytes, _ := io.ReadAll(req.Body) 871 data = string(bodyBytes) 872 response := `{"data": ` 873 response += data 874 response += `,"responseCode": 201}` 875 rw.WriteHeader(201) 876 rw.Write([]byte(response)) 877 return 878 } 879 }) 880 // Close the server when test finishes 881 defer server.Close() 882 883 t.Run("test success", func(t *testing.T) { 884 result, err := sys.GenerateQGateReport(2837, 17540, 18, "Fortify", "develop", "PDF") 885 assert.NoError(t, err, "GetArtifactsOfProjectVersion call not successful") 886 assert.Equal(t, int64(2837), result.Projects[0].ID, "Different result content expected") 887 assert.Equal(t, int64(17540), result.Projects[0].Versions[0].ID, "Different result content expected") 888 assert.Equal(t, int64(18), *result.ReportDefinitionID, "Different result content expected") 889 }) 890 } 891 892 func TestGetReportDetails(t *testing.T) { 893 // Start a local HTTP server 894 response := `{"data": {"id":999,"name":"FortifyReport","note":"","type":"PORTFOLIO","reportDefinitionId":18,"format":"PDF", 895 "projects":[{"id":2837,"name":"Fortify","versions":[{"id":17540,"name":"develop"}]}],"projectVersionDisplayName":"develop", 896 "inputReportParameters":[{"name":"Q-gate-report","identifier":"projectVersionId","paramValue":17540,"type":"SINGLE_PROJECT"}]},"count": 1,"responseCode": 200}` 897 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 898 if req.URL.Path == "/reports/999" { 899 header := rw.Header() 900 header.Add("Content-type", "application/json") 901 rw.Write([]byte(response)) 902 return 903 } 904 }) 905 // Close the server when test finishes 906 defer server.Close() 907 908 t.Run("test success", func(t *testing.T) { 909 result, err := sys.GetReportDetails(999) 910 assert.NoError(t, err, "GetReportDetails call not successful") 911 assert.Equal(t, int64(999), result.ID, "Different result content expected") 912 }) 913 } 914 915 func TestGetFileToken(t *testing.T) { 916 // Start a local HTTP server 917 bodyContent := "" 918 reference := `{"fileTokenType":"TOKEN_TYPE"} 919 ` 920 response := `{"data": {"fileTokenType": "TOKEN_TYPE","token": "ZjE1OTdjZjEtMjAzNS00NTFmLThiOWItNzBkYzI0MWEzZGNj"},"responseCode": 201}` 921 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 922 if req.URL.Path == "/fileTokens" { 923 header := rw.Header() 924 header.Add("Content-type", "application/json") 925 bodyBytes, _ := io.ReadAll(req.Body) 926 bodyContent = string(bodyBytes) 927 rw.WriteHeader(201) 928 rw.Write([]byte(response)) 929 return 930 } 931 }) 932 // Close the server when test finishes 933 defer server.Close() 934 935 t.Run("test success", func(t *testing.T) { 936 result, err := sys.getFileToken("TOKEN_TYPE") 937 assert.NoError(t, err) 938 assert.Equal(t, "ZjE1OTdjZjEtMjAzNS00NTFmLThiOWItNzBkYzI0MWEzZGNj", result.Token) 939 assert.Equal(t, reference, bodyContent) 940 }) 941 } 942 943 func TestInvalidateFileToken(t *testing.T) { 944 // Start a local HTTP server 945 response := `{"responseCode": 200}` 946 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 947 if req.URL.Path == "/fileTokens" && req.Method == "DELETE" { 948 header := rw.Header() 949 header.Add("Content-type", "application/json") 950 rw.WriteHeader(200) 951 rw.Write([]byte(response)) 952 return 953 } 954 }) 955 // Close the server when test finishes 956 defer server.Close() 957 958 t.Run("test success", func(t *testing.T) { 959 err := sys.invalidateFileTokens() 960 assert.NoError(t, err, "invalidateFileTokens call not successful") 961 }) 962 } 963 964 func TestUploadResultFile(t *testing.T) { 965 // Start a local HTTP server 966 bodyContent := "" 967 getTokenCalled := false 968 invalidateTokenCalled := false 969 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 970 if req.URL.Path == "/fileTokens" && req.Method == "DELETE" { 971 header := rw.Header() 972 header.Add("Content-type", "application/json") 973 rw.WriteHeader(200) 974 rw.Write([]byte(`{"responseCode": 200}`)) 975 invalidateTokenCalled = true 976 return 977 } 978 if req.URL.Path == "/fileTokens" && req.Method == "POST" { 979 header := rw.Header() 980 header.Add("Content-type", "application/json") 981 rw.WriteHeader(201) 982 rw.Write([]byte(`{"data": {"token": "89ee873"}, "responseCode": 201}`)) 983 getTokenCalled = true 984 return 985 } 986 if req.URL.Path == "/upload/resultFileUpload.html" && req.URL.RawQuery == "mat=89ee873" { 987 header := rw.Header() 988 header.Add("Content-type", "application/json") 989 bodyBytes, _ := io.ReadAll(req.Body) 990 bodyContent = string(bodyBytes) 991 rw.WriteHeader(200) 992 rw.Write([]byte("OK")) 993 return 994 } 995 }) 996 // Close the server when test finishes 997 defer server.Close() 998 999 testFile, err := os.CreateTemp("", "result.fpr") 1000 if err != nil { 1001 t.FailNow() 1002 } 1003 defer os.RemoveAll(testFile.Name()) // clean up 1004 1005 t.Run("test success", func(t *testing.T) { 1006 err := sys.UploadResultFile("/upload/resultFileUpload.html", testFile.Name(), 10770) 1007 assert.NoError(t, err, "UploadFile call not successful") 1008 assert.Contains(t, bodyContent, `Content-Disposition: form-data; name="file"; filename=`, "Expected different content in request body") 1009 assert.Contains(t, bodyContent, `Content-Disposition: form-data; name="entityId"`, "Expected different content in request body") 1010 assert.Contains(t, bodyContent, `10770`, "Expected different content in request body") 1011 assert.Equal(t, true, getTokenCalled, "Expected GetUploadToken to be called") 1012 assert.Equal(t, true, invalidateTokenCalled, "Expected InvalidateFileTokens to be called") 1013 }) 1014 } 1015 1016 func TestDownloadResultFile(t *testing.T) { 1017 // Start a local HTTP server 1018 bodyContent := "" 1019 getTokenCalled := false 1020 invalidateTokenCalled := false 1021 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 1022 if req.URL.Path == "/fileTokens" && req.Method == "DELETE" { 1023 header := rw.Header() 1024 header.Add("Content-type", "application/json") 1025 rw.WriteHeader(200) 1026 rw.Write([]byte(`{"responseCode": 200}`)) 1027 invalidateTokenCalled = true 1028 return 1029 } 1030 if req.URL.Path == "/fileTokens" && req.Method == "POST" { 1031 header := rw.Header() 1032 header.Add("Content-type", "application/json") 1033 rw.WriteHeader(201) 1034 rw.Write([]byte(`{"data": {"token": "89ee873"}, "responseCode": 201}`)) 1035 getTokenCalled = true 1036 return 1037 } 1038 if req.URL.Path == "/download/currentStateFprDownload.html" { 1039 header := rw.Header() 1040 header.Add("Content-type", "application/json") 1041 bodyContent = req.URL.RawQuery 1042 rw.WriteHeader(200) 1043 rw.Write([]byte("OK")) 1044 return 1045 } 1046 }) 1047 // Close the server when test finishes 1048 defer server.Close() 1049 1050 t.Run("test success", func(t *testing.T) { 1051 data, err := sys.DownloadResultFile("/download/currentStateFprDownload.html", 10775) 1052 assert.NoError(t, err, "DownloadResultFile call not successful") 1053 assert.Equal(t, "id=10775&mat=89ee873", bodyContent, "Expected different request body") 1054 assert.Equal(t, []byte("OK"), data, "Expected different result") 1055 assert.Equal(t, true, getTokenCalled, "Expected GetUploadToken to be called") 1056 assert.Equal(t, true, invalidateTokenCalled, "Expected InvalidateFileTokens to be called") 1057 }) 1058 } 1059 1060 func TestDownloadReportFile(t *testing.T) { 1061 // Start a local HTTP server 1062 getTokenCalled := false 1063 invalidateTokenCalled := false 1064 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 1065 if req.URL.Path == "/fileTokens" && req.Method == "DELETE" { 1066 header := rw.Header() 1067 header.Add("Content-type", "application/json") 1068 rw.WriteHeader(200) 1069 rw.Write([]byte(`{"responseCode": 200}`)) 1070 invalidateTokenCalled = true 1071 return 1072 } 1073 if req.URL.Path == "/fileTokens" && req.Method == "POST" { 1074 header := rw.Header() 1075 header.Add("Content-type", "application/json") 1076 rw.WriteHeader(201) 1077 rw.Write([]byte(`{"data": {"token": "89ee873"}, "responseCode": 201}`)) 1078 getTokenCalled = true 1079 return 1080 } 1081 if req.URL.Path == "/transfer/reportDownload.html" && req.URL.RawQuery == "id=10775&mat=89ee873" { 1082 header := rw.Header() 1083 header.Add("Content-type", "application/json") 1084 rw.WriteHeader(200) 1085 rw.Write([]byte("OK")) 1086 return 1087 } 1088 }) 1089 // Close the server when test finishes 1090 defer server.Close() 1091 1092 t.Run("test success", func(t *testing.T) { 1093 data, err := sys.DownloadReportFile("/transfer/reportDownload.html", 10775) 1094 assert.NoError(t, err, "DownloadReportFile call not successful") 1095 assert.Equal(t, []byte("OK"), data, "Expected different result") 1096 assert.Equal(t, true, getTokenCalled, "Expected GetUploadToken to be called") 1097 assert.Equal(t, true, invalidateTokenCalled, "Expected InvalidateFileTokens to be called") 1098 }) 1099 } 1100 1101 func TestLookupOrCreateProjectVersionDetailsForPullRequest(t *testing.T) { 1102 // Start a local HTTP server 1103 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 1104 if req.URL.Path == "/projects/4711/versions" { 1105 header := rw.Header() 1106 header.Add("Content-type", "application/json") 1107 rw.WriteHeader(200) 1108 rw.Write([]byte(`{"data": [], "count": 0, "responseCode": 200}`)) 1109 return 1110 } 1111 if req.URL.Path == "/projectVersions" && req.Method == "POST" { 1112 header := rw.Header() 1113 header.Add("Content-type", "application/json") 1114 bodyBytes, _ := io.ReadAll(req.Body) 1115 bodyContent := string(bodyBytes) 1116 responseContent := `{"data": ` 1117 responseContent += bodyContent 1118 responseContent += `,"count": 1,"responseCode": 201,"links": {}}` 1119 fmt.Println(responseContent) 1120 rw.WriteHeader(201) 1121 rw.Write([]byte(responseContent)) 1122 return 1123 } 1124 if req.URL.Path == "/projectVersions/4711/attributes" { 1125 header := rw.Header() 1126 header.Add("Content-type", "application/json") 1127 rw.Write([]byte( 1128 `{"data": [{"_href": "https://fortify/ssc/api/v1/projectVersions/4711/attributes/4712","attributeDefinitionId": 31, 1129 "values": null,"guid": "gdgfdgfdgfdgfd","id": 4712,"value": "abcd"}],"count": 8,"responseCode": 200}`)) 1130 return 1131 } 1132 if req.URL.Path == "/projectVersions/4712/attributes" { 1133 header := rw.Header() 1134 header.Add("Content-type", "application/json") 1135 bodyBytes, _ := io.ReadAll(req.Body) 1136 bodyString := string(bodyBytes) 1137 response := `{"data": ` 1138 response += bodyString 1139 response += `,"count": 1,"responseCode": 200}` 1140 rw.WriteHeader(200) 1141 rw.Write([]byte(response)) 1142 return 1143 } 1144 if req.URL.Path == "/projectVersions/action/copyFromPartial" { 1145 header := rw.Header() 1146 header.Add("Content-type", "application/json") 1147 rw.Write([]byte( 1148 `{"data":[{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 1149 "project":{"id":4711,"name":"python-test","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 1150 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 1151 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 1152 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 1153 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 1154 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 1155 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 1156 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 1157 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 1158 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 1159 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}], 1160 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}, 1161 "first":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}}}`)) 1162 return 1163 } 1164 if req.URL.Path == "/projectVersions/10172" { 1165 header := rw.Header() 1166 header.Add("Content-type", "application/json") 1167 rw.Write([]byte(`{"data": {"active":null,"bugTrackerEnabled":null,"bugTrackerPluginId":null,"committed":true,"createdBy":null,"creationDate":null,"description":null,"issueTemplateId":null,"issueTemplateModifiedTime":null,"issueTemplateName":null,"latestScanId":null,"masterAttrGuid":null,"name":null,"owner":null,"serverVersion":null,"snapshotOutOfDate":null,"staleIssueTemplate":null}, "responseCode": 200}`)) 1168 return 1169 } 1170 if req.URL.Path == "/projectVersions/action/copyCurrentState" { 1171 header := rw.Header() 1172 header.Add("Content-type", "application/json") 1173 rw.Write([]byte( 1174 `{"data":[{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 1175 "project":{"id":4711,"name":"python-test","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 1176 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 1177 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 1178 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 1179 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 1180 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 1181 "migrationVersion":null,"createdBy":"admin","name":"0","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 1182 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 1183 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 1184 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 1185 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}], 1186 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}, 1187 "first":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}}}`)) 1188 return 1189 } 1190 if req.URL.Path == "/projectVersions/10172/authEntities" { 1191 header := rw.Header() 1192 header.Add("Content-type", "application/json") 1193 rw.Write([]byte(`{"data": [{"displayName":"some user","email":"some.one@test.com","entityName":"some_user","firstName":"some","id":589,"lastName":"user","type":"User"}],"count": 1,"responseCode": 200}`)) 1194 return 1195 } 1196 if req.URL.Path == "/projectVersions/10173/authEntities" { 1197 header := rw.Header() 1198 header.Add("Content-type", "application/json") 1199 rw.Write([]byte(`{"data": [{"displayName":"some user","email":"some.one@test.com","entityName":"some_user","firstName":"some","id":589,"lastName":"user","type":"User"}],"count": 1,"responseCode": 200}`)) 1200 return 1201 } 1202 }) 1203 // Close the server when test finishes 1204 defer server.Close() 1205 1206 t.Run("test success", func(t *testing.T) { 1207 int64Value := int64(65) 1208 int32Value := int32(876) 1209 float32Value := float32(19.12) 1210 now := models.NewIso8601MilliDateTime() 1211 enabled := true 1212 disabled := false 1213 name := "Test new PV" 1214 owner := "someUser" 1215 masterGUID := "dsadaoudoiud" 1216 project := models.Project{CreatedBy: &owner, CreationDate: now, Description: name, ID: int64Value, IssueTemplateID: &name, Name: &name} 1217 projectVersionState := models.ProjectVersionState{AnalysisResultsExist: &disabled, AnalysisUploadEnabled: &disabled, 1218 AttentionRequired: &disabled, AuditEnabled: &enabled, BatchBugSubmissionExists: &disabled, Committed: &enabled, 1219 CriticalPriorityIssueCountDelta: &int32Value, DeltaPeriod: &int32Value, ExtraMessage: &name, HasCustomIssues: &disabled, 1220 ID: &int64Value, IssueCountDelta: &int32Value, LastFprUploadDate: &now, MetricEvaluationDate: &now, PercentAuditedDelta: &float32Value, 1221 PercentCriticalPriorityIssuesAuditedDelta: &float32Value} 1222 masterProjectVersion := models.ProjectVersion{AssignedIssuesCount: int64Value, Project: &project, Name: &name, Active: &enabled, 1223 Committed: &enabled, AttachmentsOutOfDate: disabled, AutoPredict: disabled, BugTrackerEnabled: &disabled, 1224 CustomTagValuesAutoApply: disabled, RefreshRequired: disabled, Owner: &owner, ServerVersion: &float32Value, 1225 SnapshotOutOfDate: &disabled, StaleIssueTemplate: &disabled, MasterAttrGUID: &masterGUID, 1226 LatestScanID: &int64Value, IssueTemplateName: &name, IssueTemplateModifiedTime: &int64Value, 1227 IssueTemplateID: &name, Description: &name, CreatedBy: &owner, BugTrackerPluginID: &name, Mode: "NONE", 1228 CurrentState: &projectVersionState, ID: int64Value, LoadProperties: "", CreationDate: &now, 1229 MigrationVersion: float32Value, ObfuscatedID: "", PredictionPolicy: "", SecurityGroup: "", 1230 SiteID: "", SourceBasePath: "", Status: "", TracesOutOfDate: false} 1231 prProjectVersion, err := sys.LookupOrCreateProjectVersionDetailsForPullRequest(4711, &masterProjectVersion, "PR-815") 1232 assert.NoError(t, err, "LookupOrCreateProjectVersionDetailsForPullRequest call not successful") 1233 assert.Equal(t, "PR-815", *prProjectVersion.Name, "Expected different result") 1234 assert.Equal(t, masterProjectVersion.Description, prProjectVersion.Description, "Expected different result") 1235 assert.Equal(t, masterProjectVersion.Active, prProjectVersion.Active, "Expected different result") 1236 assert.Equal(t, masterProjectVersion.Committed, prProjectVersion.Committed, "Expected different result") 1237 assert.Equal(t, masterProjectVersion.Project.Name, prProjectVersion.Project.Name, "Expected different result") 1238 assert.Equal(t, masterProjectVersion.Project.Description, prProjectVersion.Project.Description, "Expected different result") 1239 assert.Equal(t, masterProjectVersion.Project.ID, prProjectVersion.Project.ID, "Expected different result") 1240 assert.Equal(t, masterProjectVersion.IssueTemplateID, prProjectVersion.IssueTemplateID, "Expected different result") 1241 }) 1242 } 1243 1244 func TestMergeProjectVersionStateOfPRIntoMaster(t *testing.T) { 1245 // Start a local HTTP server 1246 getPRProjectVersionCalled := false 1247 invalidateTokenCalled := false 1248 getTokenCalled := false 1249 downloadCalled := false 1250 uploadCalled := false 1251 inactivateCalled := false 1252 sys, server := spinUpServer(func(rw http.ResponseWriter, req *http.Request) { 1253 if req.URL.Path == "/projects/4711/versions" { 1254 header := rw.Header() 1255 header.Add("Content-type", "application/json") 1256 rw.Write([]byte(`{"data":[{"latestScanId":null,"serverVersion":17.2,"tracesOutOfDate":false,"attachmentsOutOfDate":false,"description":"", 1257 "project":{"id":4711,"name":"product.some.com","description":"","creationDate":"2018-12-03T06:29:38.197+0000","createdBy":"someUser", 1258 "issueTemplateId":"dasdasdasdsadasdasdasdasdas"},"sourceBasePath":null,"mode":"BASIC","masterAttrGuid":"sddasdasda","obfuscatedId":null, 1259 "id":10172,"customTagValuesAutoApply":null,"issueTemplateId":"dasdasdasdsadasdasdasdasdas","loadProperties":null,"predictionPolicy":null, 1260 "bugTrackerPluginId":null,"owner":"admin","_href":"https://fortify/ssc/api/v1/projectVersions/10172", 1261 "committed":true,"bugTrackerEnabled":false,"active":true,"snapshotOutOfDate":false,"issueTemplateModifiedTime":1578411924701, 1262 "securityGroup":null,"creationDate":"2018-02-09T16:59:41.297+0000","refreshRequired":false,"issueTemplateName":"someTemplate", 1263 "migrationVersion":null,"createdBy":"admin","name":"PR-815","siteId":null,"staleIssueTemplate":false,"autoPredict":null, 1264 "currentState":{"id":10172,"committed":true,"attentionRequired":false,"analysisResultsExist":true,"auditEnabled":true, 1265 "lastFprUploadDate":"2018-02-09T16:59:53.497+0000","extraMessage":null,"analysisUploadEnabled":true,"batchBugSubmissionExists":false, 1266 "hasCustomIssues":false,"metricEvaluationDate":"2018-03-10T00:02:45.553+0000","deltaPeriod":7,"issueCountDelta":0,"percentAuditedDelta":0.0, 1267 "criticalPriorityIssueCountDelta":0,"percentCriticalPriorityIssuesAuditedDelta":0.0},"assignedIssuesCount":0,"status":null}], 1268 "count":1,"responseCode":200,"links":{"last":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}, 1269 "first":{"href":"https://fortify/ssc/api/v1/projects/4711/versions?start=0"}}}`)) 1270 getPRProjectVersionCalled = true 1271 return 1272 } 1273 if req.URL.Path == "/fileTokens" && req.Method == "DELETE" { 1274 header := rw.Header() 1275 header.Add("Content-type", "application/json") 1276 rw.WriteHeader(200) 1277 rw.Write([]byte(`{"responseCode": 200}`)) 1278 invalidateTokenCalled = true 1279 return 1280 } 1281 if req.URL.Path == "/fileTokens" && req.Method == "POST" { 1282 header := rw.Header() 1283 header.Add("Content-type", "application/json") 1284 rw.WriteHeader(201) 1285 rw.Write([]byte(`{"data": {"token": "89ee873"}, "responseCode": 201}`)) 1286 getTokenCalled = true 1287 return 1288 } 1289 if req.URL.Path == "/download/currentStateFprDownload.html" { 1290 header := rw.Header() 1291 header.Add("Content-type", "application/json") 1292 rw.WriteHeader(200) 1293 rw.Write([]byte("OK")) 1294 downloadCalled = true 1295 return 1296 } 1297 if req.URL.Path == "/upload/resultFileUpload.html" { 1298 header := rw.Header() 1299 header.Add("Content-type", "application/json") 1300 rw.WriteHeader(200) 1301 rw.Write([]byte("OK")) 1302 uploadCalled = true 1303 return 1304 } 1305 if req.URL.Path == "/projectVersions/10172" { 1306 header := rw.Header() 1307 header.Add("Content-type", "application/json") 1308 rw.Write([]byte(`{"data": {"active":false,"bugTrackerEnabled":null,"bugTrackerPluginId":null,"committed":true,"createdBy":null,"creationDate":null,"description":null,"issueTemplateId":null,"issueTemplateModifiedTime":null,"issueTemplateName":null,"latestScanId":null,"masterAttrGuid":null,"name":null,"owner":null,"serverVersion":null,"snapshotOutOfDate":null,"staleIssueTemplate":null}, "responseCode": 200}`)) 1309 inactivateCalled = true 1310 return 1311 } 1312 }) 1313 // Close the server when test finishes 1314 defer server.Close() 1315 1316 t.Run("test success", func(t *testing.T) { 1317 err := sys.MergeProjectVersionStateOfPRIntoMaster("/download/currentStateFprDownload.html", "/upload/resultFileUpload.html", 4711, 10171, "PR-815") 1318 assert.NoError(t, err, "MergeProjectVersionStateOfPRIntoMaster call not successful") 1319 assert.Equal(t, true, getPRProjectVersionCalled, "Expected different value") 1320 assert.Equal(t, true, invalidateTokenCalled, "Expected different value") 1321 assert.Equal(t, true, getTokenCalled, "Expected different value") 1322 assert.Equal(t, true, downloadCalled, "Expected different value") 1323 assert.Equal(t, true, uploadCalled, "Expected different value") 1324 assert.Equal(t, true, inactivateCalled, "Expected different value") 1325 }) 1326 } 1327 1328 func TestBase64EndodePlainToken(t *testing.T) { 1329 t.Run("Encoded token untouched", func(t *testing.T) { 1330 token := "OTUzODcwNDYtNWFjOC00NTcwLTg3NWQtYTVlYzhiZDhkM2Qy" 1331 encodedToken := base64EndodePlainToken(token) 1332 assert.Equal(t, token, encodedToken) 1333 }) 1334 t.Run("Unencoded token gets encoded", func(t *testing.T) { 1335 token := "95387046-5ac8-4570-875d-a5ec8bd8d3d2" 1336 encodedToken := base64EndodePlainToken(token) 1337 assert.Equal(t, "OTUzODcwNDYtNWFjOC00NTcwLTg3NWQtYTVlYzhiZDhkM2Qy", encodedToken) 1338 }) 1339 } 1340 1341 func TestCreateJSONReport(t *testing.T) { 1342 t.Run("test success", func(t *testing.T) { 1343 spotChecksCountByCategory := []SpotChecksAuditCount{} 1344 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 3, Total: 3, Type: "J2EE Misconfiguration: Missing Error Handling"}) 1345 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 1, Total: 3, Type: "J2EE Bad Practices: Leftover Debug Code"}) 1346 fortifyReportData := FortifyReportData{CorporateAudited: 30, CorporateTotal: 30, AuditAllTotal: 1, AuditAllAudited: 1, ProjectVersionID: 4999} 1347 jsonReport := CreateJSONReport(fortifyReportData, spotChecksCountByCategory, "https://fortify-test.com/ssc") 1348 assert.Equal(t, true, jsonReport.AtleastOneSpotChecksCategoryAudited) 1349 assert.Equal(t, true, jsonReport.IsSpotChecksPerCategoryAudited) 1350 assert.Equal(t, 1, jsonReport.AuditAllAudited) 1351 assert.Equal(t, 1, jsonReport.AuditAllTotal) 1352 assert.Equal(t, 30, jsonReport.CorporateAudited) 1353 assert.Equal(t, 30, jsonReport.CorporateTotal) 1354 assert.Equal(t, "https://fortify-test.com/ssc/html/ssc/version/4999", jsonReport.URL) 1355 assert.Equal(t, "https://fortify-test.com/ssc", jsonReport.ToolInstance) 1356 }) 1357 1358 t.Run("atleast one category spotchecks failed", func(t *testing.T) { 1359 spotChecksCountByCategory := []SpotChecksAuditCount{} 1360 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 3, Total: 3, Type: "J2EE Misconfiguration: Missing Error Handling"}) 1361 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 0, Total: 1, Type: "J2EE Bad Practices: Leftover Debug Code"}) 1362 fortifyReportData := FortifyReportData{CorporateAudited: 0, CorporateTotal: 0, AuditAllTotal: 0, AuditAllAudited: 0} 1363 jsonReport := CreateJSONReport(fortifyReportData, spotChecksCountByCategory, "https://fortify-test.com/ssc") 1364 assert.Equal(t, false, jsonReport.AtleastOneSpotChecksCategoryAudited) 1365 assert.Equal(t, false, jsonReport.IsSpotChecksPerCategoryAudited) 1366 }) 1367 1368 t.Run("no spot checks audited", func(t *testing.T) { 1369 spotChecksCountByCategory := []SpotChecksAuditCount{} 1370 fortifyReportData := FortifyReportData{CorporateAudited: 0, CorporateTotal: 0, AuditAllTotal: 0, AuditAllAudited: 0} 1371 jsonReport := CreateJSONReport(fortifyReportData, spotChecksCountByCategory, "https://fortify-test.com/ssc") 1372 assert.Equal(t, true, jsonReport.AtleastOneSpotChecksCategoryAudited) 1373 assert.Equal(t, true, jsonReport.IsSpotChecksPerCategoryAudited) 1374 }) 1375 1376 t.Run("isSpotChecksPerCategoryAudited passed spotchecks test 1", func(t *testing.T) { 1377 spotChecksCountByCategory := []SpotChecksAuditCount{} 1378 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 10, Total: 100, Type: "J2EE Misconfiguration: Missing Error Handling"}) 1379 fortifyReportData := FortifyReportData{CorporateAudited: 0, CorporateTotal: 0, AuditAllTotal: 0, AuditAllAudited: 0} 1380 jsonReport := CreateJSONReport(fortifyReportData, spotChecksCountByCategory, "https://fortify-test.com/ssc") 1381 assert.Equal(t, true, jsonReport.AtleastOneSpotChecksCategoryAudited) 1382 assert.Equal(t, true, jsonReport.IsSpotChecksPerCategoryAudited) 1383 }) 1384 1385 t.Run("isSpotChecksPerCategoryAudited failed spotchecks test 2", func(t *testing.T) { 1386 spotChecksCountByCategory := []SpotChecksAuditCount{} 1387 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 3, Total: 100, Type: "J2EE Misconfiguration: Missing Error Handling"}) 1388 fortifyReportData := FortifyReportData{CorporateAudited: 0, CorporateTotal: 0, AuditAllTotal: 0, AuditAllAudited: 0} 1389 jsonReport := CreateJSONReport(fortifyReportData, spotChecksCountByCategory, "https://fortify-test.com/ssc") 1390 assert.Equal(t, true, jsonReport.AtleastOneSpotChecksCategoryAudited) 1391 assert.Equal(t, false, jsonReport.IsSpotChecksPerCategoryAudited) 1392 }) 1393 1394 t.Run("isSpotChecksPerCategoryAudited failed spotchecks test 3", func(t *testing.T) { 1395 spotChecksCountByCategory := []SpotChecksAuditCount{} 1396 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 9, Total: 200, Type: "J2EE Misconfiguration: Missing Error Handling"}) 1397 fortifyReportData := FortifyReportData{CorporateAudited: 0, CorporateTotal: 0, AuditAllTotal: 0, AuditAllAudited: 0} 1398 jsonReport := CreateJSONReport(fortifyReportData, spotChecksCountByCategory, "https://fortify-test.com/ssc") 1399 assert.Equal(t, true, jsonReport.AtleastOneSpotChecksCategoryAudited) 1400 assert.Equal(t, false, jsonReport.IsSpotChecksPerCategoryAudited) 1401 }) 1402 1403 t.Run("isSpotChecksPerCategoryAudited passed spotchecks test 4", func(t *testing.T) { 1404 spotChecksCountByCategory := []SpotChecksAuditCount{} 1405 spotChecksCountByCategory = append(spotChecksCountByCategory, SpotChecksAuditCount{Audited: 10, Total: 200, Type: "J2EE Misconfiguration: Missing Error Handling"}) 1406 fortifyReportData := FortifyReportData{CorporateAudited: 0, CorporateTotal: 0, AuditAllTotal: 0, AuditAllAudited: 0} 1407 jsonReport := CreateJSONReport(fortifyReportData, spotChecksCountByCategory, "https://fortify-test.com/ssc") 1408 assert.Equal(t, true, jsonReport.AtleastOneSpotChecksCategoryAudited) 1409 assert.Equal(t, true, jsonReport.IsSpotChecksPerCategoryAudited) 1410 }) 1411 }