mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-14 11:03:09 +02:00
cb3fa7c293
* add sonarqube measurements * fetch measurements from API * add api for fetching issue counts * add debug outputs * add further severities * log number of issues * report failure * expose method to send request * Fixed what was broken. * add debug output * wip * correct opaque property * push client handling to apiClient.go * use correct API URL * correct log outputs * remove logging * remove option validation * extend search options * restructure * rename api client file * simplify client usage * simplify issue client * write sonar values to influx * extract issue service * reorder imports * add sonar integration test * allow unknown fields * add test case * add test case * remove * fix * Update http.go * Apply suggestions from code review * Update cmd/sonarExecuteScan.go * rework test cases * use explicit returns * add task service * add waitfortask * fix typo * remove fixme * expose poll interval * rename test cases * add test cases * use newAPIClient method * use waitForTask * rename services * finalize code * handle error * move defer * move types * add test case * use http.status... * add test case * expose api endpoint names * extract api client * adjust test cases * Update integration-tests-pr.yaml * Update integration-tests.yaml * improve require message * Update integration-tests-pr.yaml * Update integration-tests-pr.yaml
232 lines
8.4 KiB
Go
232 lines
8.4 KiB
Go
package sonar
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jarcoal/httpmock"
|
|
sonargo "github.com/magicsong/sonargo/sonar"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
|
|
piperhttp "github.com/SAP/jenkins-library/pkg/http"
|
|
)
|
|
|
|
func TestGetTask(t *testing.T) {
|
|
testURL := "https://example.org"
|
|
t.Run("success", func(t *testing.T) {
|
|
httpmock.Activate()
|
|
defer httpmock.DeactivateAndReset()
|
|
|
|
sender := &piperhttp.Client{}
|
|
sender.SetOptions(piperhttp.ClientOptions{UseDefaultTransport: true})
|
|
// add response handler
|
|
httpmock.RegisterResponder(http.MethodGet, testURL+"/api/"+EndpointCeTask+"", httpmock.NewStringResponder(http.StatusOK, responseCeTaskSuccess))
|
|
// create service instance
|
|
serviceUnderTest := NewTaskService(testURL, mock.Anything, mock.Anything, sender)
|
|
// test
|
|
result, response, err := serviceUnderTest.GetTask(&sonargo.CeTaskOption{Id: mock.Anything})
|
|
// assert
|
|
assert.NoError(t, err)
|
|
assert.NotEmpty(t, result)
|
|
assert.NotEmpty(t, response)
|
|
assert.Equal(t, 1, httpmock.GetTotalCallCount(), "unexpected number of requests")
|
|
})
|
|
t.Run("request error", func(t *testing.T) {
|
|
httpmock.Activate()
|
|
defer httpmock.DeactivateAndReset()
|
|
|
|
sender := &piperhttp.Client{}
|
|
sender.SetOptions(piperhttp.ClientOptions{UseDefaultTransport: true})
|
|
// add response handler
|
|
httpmock.RegisterResponder(http.MethodGet, testURL+"/api/"+EndpointCeTask+"", httpmock.NewErrorResponder(errors.New("internal server error")))
|
|
// create service instance
|
|
serviceUnderTest := NewTaskService(testURL, mock.Anything, mock.Anything, sender)
|
|
// test
|
|
result, response, err := serviceUnderTest.GetTask(&sonargo.CeTaskOption{Id: mock.Anything})
|
|
// assert
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "internal server error")
|
|
assert.Empty(t, result)
|
|
assert.Empty(t, response)
|
|
assert.Equal(t, 1, httpmock.GetTotalCallCount(), "unexpected number of requests")
|
|
})
|
|
t.Run("server error", func(t *testing.T) {
|
|
httpmock.Activate()
|
|
defer httpmock.DeactivateAndReset()
|
|
|
|
sender := &piperhttp.Client{}
|
|
sender.SetOptions(piperhttp.ClientOptions{UseDefaultTransport: true})
|
|
// add response handler
|
|
httpmock.RegisterResponder(http.MethodGet, testURL+"/api/"+EndpointCeTask+"", httpmock.NewStringResponder(http.StatusNotFound, responseCeTaskError))
|
|
// create service instance
|
|
serviceUnderTest := NewTaskService(testURL, mock.Anything, mock.Anything, sender)
|
|
// test
|
|
result, response, err := serviceUnderTest.GetTask(&sonargo.CeTaskOption{Id: mock.Anything})
|
|
// assert
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "No activity found for task ")
|
|
assert.Empty(t, result)
|
|
assert.NotEmpty(t, response)
|
|
assert.Equal(t, 1, httpmock.GetTotalCallCount(), "unexpected number of requests")
|
|
})
|
|
}
|
|
|
|
func TestWaitForTask(t *testing.T) {
|
|
testURL := "https://example.org"
|
|
t.Run("success", func(t *testing.T) {
|
|
httpmock.Activate()
|
|
defer httpmock.DeactivateAndReset()
|
|
|
|
sender := &piperhttp.Client{}
|
|
sender.SetOptions(piperhttp.ClientOptions{UseDefaultTransport: true})
|
|
// add response handler
|
|
|
|
httpmock.RegisterResponder(http.MethodGet, testURL+"/api/"+EndpointCeTask+"", httpmock.ResponderFromMultipleResponses(
|
|
[]*http.Response{
|
|
httpmock.NewStringResponse(http.StatusOK, responseCeTaskPending),
|
|
httpmock.NewStringResponse(http.StatusOK, responseCeTaskProcessing),
|
|
httpmock.NewStringResponse(http.StatusOK, responseCeTaskSuccess),
|
|
},
|
|
))
|
|
// create service instance
|
|
serviceUnderTest := NewTaskService(testURL, mock.Anything, mock.Anything, sender)
|
|
serviceUnderTest.PollInterval = time.Millisecond
|
|
// test
|
|
err := serviceUnderTest.WaitForTask()
|
|
// assert
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 3, httpmock.GetTotalCallCount(), "unexpected number of requests")
|
|
})
|
|
t.Run("failure", func(t *testing.T) {
|
|
httpmock.Activate()
|
|
defer httpmock.DeactivateAndReset()
|
|
|
|
sender := &piperhttp.Client{}
|
|
sender.SetOptions(piperhttp.ClientOptions{UseDefaultTransport: true})
|
|
// add response handler
|
|
|
|
httpmock.RegisterResponder(http.MethodGet, testURL+"/api/"+EndpointCeTask+"", httpmock.ResponderFromMultipleResponses(
|
|
[]*http.Response{
|
|
httpmock.NewStringResponse(http.StatusOK, responseCeTaskPending),
|
|
httpmock.NewStringResponse(http.StatusOK, responseCeTaskProcessing),
|
|
httpmock.NewStringResponse(http.StatusNotFound, responseCeTaskFailure),
|
|
},
|
|
))
|
|
// create service instance
|
|
serviceUnderTest := NewTaskService(testURL, mock.Anything, mock.Anything, sender)
|
|
serviceUnderTest.PollInterval = time.Millisecond
|
|
// test
|
|
err := serviceUnderTest.WaitForTask()
|
|
// assert
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "status: FAILED")
|
|
assert.Equal(t, 3, httpmock.GetTotalCallCount(), "unexpected number of requests")
|
|
})
|
|
}
|
|
|
|
const responseCeTaskError = `{
|
|
"errors": [
|
|
{
|
|
"msg": "No activity found for task 'AXDj5ZWQ_ZJrW2xGuBWl'"
|
|
}
|
|
]
|
|
}`
|
|
|
|
const responseCeTaskPending = `{
|
|
"task": {
|
|
"id": "AXe5y_ZMPMpzvP5DRxw_",
|
|
"type": "REPORT",
|
|
"componentId": "AW8jANn5v4pDRYwyZIiM",
|
|
"componentKey": "Piper-Validation/Golang",
|
|
"componentName": "Piper-Validation: Golang",
|
|
"componentQualifier": "TRK",
|
|
"analysisId": "AXe5y_mgcqEbAZBpFc0V",
|
|
"status": "PENDING",
|
|
"submittedAt": "2021-02-19T10:18:07+0000",
|
|
"submitterLogin": "CCFenner",
|
|
"startedAt": "2021-02-19T10:18:08+0000",
|
|
"executedAt": "2021-02-19T10:18:09+0000",
|
|
"executionTimeMs": 551,
|
|
"logs": false,
|
|
"hasScannerContext": true,
|
|
"organization": "default-organization",
|
|
"warningCount": 1,
|
|
"warnings": []
|
|
}
|
|
}`
|
|
|
|
const responseCeTaskProcessing = `{
|
|
"task": {
|
|
"id": "AXe5y_ZMPMpzvP5DRxw_",
|
|
"type": "REPORT",
|
|
"componentId": "AW8jANn5v4pDRYwyZIiM",
|
|
"componentKey": "Piper-Validation/Golang",
|
|
"componentName": "Piper-Validation: Golang",
|
|
"componentQualifier": "TRK",
|
|
"analysisId": "AXe5y_mgcqEbAZBpFc0V",
|
|
"status": "IN_PROGRESS",
|
|
"submittedAt": "2021-02-19T10:18:07+0000",
|
|
"submitterLogin": "CCFenner",
|
|
"startedAt": "2021-02-19T10:18:08+0000",
|
|
"executedAt": "2021-02-19T10:18:09+0000",
|
|
"executionTimeMs": 551,
|
|
"logs": false,
|
|
"hasScannerContext": true,
|
|
"organization": "default-organization",
|
|
"warningCount": 1,
|
|
"warnings": []
|
|
}
|
|
}`
|
|
|
|
const responseCeTaskSuccess = `{
|
|
"task": {
|
|
"id": "AXe5y_ZMPMpzvP5DRxw_",
|
|
"type": "REPORT",
|
|
"componentId": "AW8jANn5v4pDRYwyZIiM",
|
|
"componentKey": "Piper-Validation/Golang",
|
|
"componentName": "Piper-Validation: Golang",
|
|
"componentQualifier": "TRK",
|
|
"analysisId": "AXe5y_mgcqEbAZBpFc0V",
|
|
"status": "SUCCESS",
|
|
"submittedAt": "2021-02-19T10:18:07+0000",
|
|
"submitterLogin": "CCFenner",
|
|
"startedAt": "2021-02-19T10:18:08+0000",
|
|
"executedAt": "2021-02-19T10:18:09+0000",
|
|
"executionTimeMs": 551,
|
|
"logs": false,
|
|
"hasScannerContext": true,
|
|
"organization": "default-organization",
|
|
"warningCount": 1,
|
|
"warnings": [
|
|
"The project key ‘Piper-Validation/Golang’ contains invalid characters. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit. You should update the project key with the expected format."
|
|
]
|
|
}
|
|
}`
|
|
|
|
const responseCeTaskFailure = `{
|
|
"task": {
|
|
"organization": "my-org-1",
|
|
"id": "AVAn5RKqYwETbXvgas-I",
|
|
"type": "REPORT",
|
|
"componentId": "AVAn5RJmYwETbXvgas-H",
|
|
"componentKey": "project_1",
|
|
"componentName": "Project One",
|
|
"componentQualifier": "TRK",
|
|
"analysisId": "123456",
|
|
"status": "FAILED",
|
|
"submittedAt": "2015-10-02T11:32:15+0200",
|
|
"startedAt": "2015-10-02T11:32:16+0200",
|
|
"executedAt": "2015-10-02T11:32:22+0200",
|
|
"executionTimeMs": 5286,
|
|
"errorMessage": "Fail to extract report AVaXuGAi_te3Ldc_YItm from database",
|
|
"logs": false,
|
|
"hasErrorStacktrace": true,
|
|
"errorStacktrace": "java.lang.IllegalStateException: Fail to extract report AVaXuGAi_te3Ldc_YItm from database\n\tat org.sonar.server.computation.task.projectanalysis.step.ExtractReportStep.execute(ExtractReportStep.java:50)",
|
|
"scannerContext": "SonarQube plugins:\n\t- Git 1.0 (scmgit)\n\t- Java 3.13.1 (java)",
|
|
"hasScannerContext": true
|
|
}
|
|
}`
|