Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pkg/launcher/jvmLauncher.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"strconv"
"strings"

"github.com/google/uuid"

"github.com/galasa-dev/cli/pkg/api"
"github.com/galasa-dev/cli/pkg/embedded"
galasaErrors "github.com/galasa-dev/cli/pkg/errors"
Expand Down Expand Up @@ -301,6 +303,7 @@ func (launcher *JvmLauncher) SubmitTestRun(
localTest.testRun.SetTrace(isTraceEnabled)
localTest.testRun.SetType(requestType)
localTest.testRun.SetName(localTest.runId)
localTest.testRun.SetSubmissionId(uuid.New().String())

// The test run we started can be returned to the submitter.
testRuns.Runs = append(testRuns.Runs, *localTest.testRun)
Expand Down Expand Up @@ -527,6 +530,15 @@ func (launcher *JvmLauncher) GetRunsById(runId string) (*galasaapi.Run, error) {
return run, err
}

// Gets a run based on the submission ID of that run.
// For local runs, the submission ID is the same as the test run id.
func (launcher *JvmLauncher) GetRunsBySubmissionId(submissionId string, groupId string) (*galasaapi.Run, error) {
log.Printf("JvmLauncher: GetRunsBySubmissionId entered. runId=%s", submissionId)

log.Printf("JvmLauncher: Local runs cannot find tests based on submission ID")
return nil, nil
}

func createRunFromLocalTest(localTest *LocalTest) (*galasaapi.Run, error) {

var run = galasaapi.NewRun()
Expand Down
3 changes: 3 additions & 0 deletions pkg/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ type Launcher interface {
// GetRunsById gets the Run information for the run with a specific run identifier
GetRunsById(runId string) (*galasaapi.Run, error)

// Gets a run based on the submission ID of that run.
GetRunsBySubmissionId(submissionId string, groupId string) (*galasaapi.Run, error)

// GetStreams gets a list of streams available on this launcher
GetStreams() ([]string, error)

Expand Down
17 changes: 13 additions & 4 deletions pkg/launcher/launcherMock.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package launcher

import (
"fmt"
"strconv"
"strings"

"github.com/galasa-dev/cli/pkg/galasaapi"
Expand All @@ -28,16 +29,18 @@ type LaunchParameters struct {
}

type MockLauncher struct {
allTestRuns *galasaapi.TestRuns
nextRunId int
launches []LaunchParameters
allTestRuns *galasaapi.TestRuns
nextRunId int
launches []LaunchParameters
submissionId int
}

func NewMockLauncher() *MockLauncher {
launcher := new(MockLauncher)
launcher.allTestRuns = newEmptyTestRun()
launcher.allTestRuns.Runs = make([]galasaapi.TestRun, 0)
launcher.nextRunId = 100
launcher.submissionId = 0
return launcher
}

Expand Down Expand Up @@ -71,7 +74,7 @@ func (launcher *MockLauncher) SubmitTestRun(
stream string,
obrFromPortfolio string,
isTraceEnabled bool,
GherkinURL string,
GherkinURL string,
GherkinFeature string,
overrides map[string]interface{},
) (*galasaapi.TestRuns, error) {
Expand All @@ -93,6 +96,7 @@ func (launcher *MockLauncher) SubmitTestRun(

newTestRun := galasaapi.NewTestRun()
newTestRun.SetGroup(groupName)
newTestRun.SetSubmissionId(strconv.Itoa(launcher.submissionId))

classNameParts := strings.Split(className, "/")
bundleName := classNameParts[0]
Expand Down Expand Up @@ -123,6 +127,11 @@ func (launcher *MockLauncher) GetRunsById(runId string) (*galasaapi.Run, error)
return &galasaapi.Run{}, nil
}

// Gets a run based on the submission ID of that run.
func (launcher *MockLauncher) GetRunsBySubmissionId(submissionId string, groupId string) (*galasaapi.Run, error) {
return &galasaapi.Run{}, nil
}

// GetStreams gets a list of streams available on this launcher
func (launcher *MockLauncher) GetStreams() ([]string, error) {
return make([]string, 0), nil
Expand Down
65 changes: 60 additions & 5 deletions pkg/launcher/remoteLauncher.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io"
"log"
"net/http"
"strconv"
"strings"

"github.com/galasa-dev/cli/pkg/api"
Expand All @@ -36,7 +37,7 @@ func NewRemoteLauncher(commsClient api.APICommsClient) *RemoteLauncher {

// A comms client that communicates with the API server in a Galasa service.
launcher.commsClient = commsClient

return launcher
}

Expand Down Expand Up @@ -125,6 +126,60 @@ func (launcher *RemoteLauncher) GetRunsById(runId string) (*galasaapi.Run, error
return rasRun, err
}

// Gets the latest run based on the submission ID of that run.
// For local runs, the submission ID is the same as the test run id.
func (launcher *RemoteLauncher) GetRunsBySubmissionId(submissionId string, groupId string) (*galasaapi.Run, error) {
log.Printf("RemoteLauncher: GetRunsBySubmissionId entered. runId=%v groupId=%v", submissionId, groupId)
var err error
var rasRun *galasaapi.Run
var restApiVersion string

restApiVersion, err = embedded.GetGalasactlRestApiVersion()

if err == nil {
var runData *galasaapi.RunResults

err = launcher.commsClient.RunAuthenticatedCommandWithRateLimitRetries(func(apiClient *galasaapi.APIClient) error {
var err error
var httpResponse *http.Response
var context context.Context = nil

apicall := apiClient.ResultArchiveStoreAPIApi.GetRasSearchRuns(context).ClientApiVersion(restApiVersion).
IncludeCursor("true").
SubmissionId(submissionId).Group(groupId).Sort("from:desc")

runData, httpResponse, err = apicall.Execute()

var statusCode int
if httpResponse != nil {
defer httpResponse.Body.Close()
statusCode = httpResponse.StatusCode
}

if err != nil {
err = galasaErrors.NewGalasaErrorWithHttpStatusCode(statusCode, galasaErrors.GALASA_ERROR_QUERY_RUNS_FAILED, err.Error())
} else {
if statusCode != http.StatusOK {
httpError := "\nhttp response status code: " + strconv.Itoa(statusCode)
errString := httpError
err = galasaErrors.NewGalasaErrorWithHttpStatusCode(statusCode, galasaErrors.GALASA_ERROR_QUERY_RUNS_FAILED, errString)
} else {

log.Printf("HTTP status was OK")

if runData.GetAmountOfRuns() > 0 {
runs := runData.GetRuns()
rasRun = &runs[0]
}

}
}
return err
})
}
return rasRun, err
}

func (launcher *RemoteLauncher) GetStreams() ([]string, error) {

var streams []string
Expand Down Expand Up @@ -179,14 +234,14 @@ func (launcher *RemoteLauncher) GetTestCatalog(stream string) (TestCatalog, erro
if err == nil {
var cpsResponse *http.Response
err = launcher.commsClient.RunAuthenticatedCommandWithRateLimitRetries(func(apiClient *galasaapi.APIClient) error {
cpsProperty, cpsResponse, err = apiClient.ConfigurationPropertyStoreAPIApi.QueryCpsNamespaceProperties(context.TODO(), "framework").Prefix("test.stream."+stream).Suffix("location").ClientApiVersion(restApiVersion).Execute()
cpsProperty, cpsResponse, err = apiClient.ConfigurationPropertyStoreAPIApi.QueryCpsNamespaceProperties(context.TODO(), "framework").Prefix("test.stream." + stream).Suffix("location").ClientApiVersion(restApiVersion).Execute()

var statusCode int
if cpsResponse != nil {
defer cpsResponse.Body.Close()
statusCode = cpsResponse.StatusCode
}

if err != nil {
err = galasaErrors.NewGalasaErrorWithHttpStatusCode(statusCode, galasaErrors.GALASA_ERROR_PROPERTY_GET_FAILED, stream, err)
} else if len(cpsProperty) < 1 {
Expand All @@ -196,7 +251,7 @@ func (launcher *RemoteLauncher) GetTestCatalog(stream string) (TestCatalog, erro
})

if err == nil {
streamLocation :=cpsProperty[0].Data.Value
streamLocation := cpsProperty[0].Data.Value
catalogString := new(strings.Builder)
var resp *http.Response
resp, err = http.Get(*streamLocation)
Expand Down
75 changes: 37 additions & 38 deletions pkg/launcher/remoteLauncher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ func TestGetTestCatalogHttpErrorGetsReported(t *testing.T) {
}))
defer server.Close()


mockFactory := utils.NewMockFactory()
apiServerUrl := server.URL
apiClient := api.InitialiseAPI(apiServerUrl)
Expand All @@ -134,11 +133,11 @@ func TestGetTestCatalogHttpErrorGetsReported(t *testing.T) {
mockFileSystem := mockFactory.GetFileSystem()
mockEnvironment := mockFactory.GetEnvironment()
mockGalasaHome, _ := utils.NewGalasaHome(mockFileSystem, mockEnvironment, "")
mockFileSystem.WriteTextFile(mockGalasaHome.GetUrlFolderPath() + "/bootstrap.properties", "")
mockFileSystem.WriteTextFile(mockGalasaHome.GetUrlFolderPath()+"/bootstrap.properties", "")

bootstrap := ""
maxAttempts := 3
retryBackoffSeconds := 1
maxAttempts := 3
retryBackoffSeconds := 1

commsClient, _ := api.NewAPICommsClient(bootstrap, maxAttempts, float64(retryBackoffSeconds), mockFactory, mockGalasaHome)

Expand All @@ -153,56 +152,56 @@ func TestGetTestCatalogHttpErrorGetsReported(t *testing.T) {
func TestGetRunsByGroupWithInvalidBearerTokenGetsNewTokenOk(t *testing.T) {
groupId := "group1"

initialLoginOperation := utils.NewHttpInteraction("/auth/tokens", http.MethodPost)
initialLoginOperation.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusCreated)
initialLoginOperation := utils.NewHttpInteraction("/auth/tokens", http.MethodPost)
initialLoginOperation.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusCreated)

mockResponse := fmt.Sprintf(`{"jwt": "%s", "refresh_token": "abc"}`, mockExpiredJwt)
writer.Write([]byte(mockResponse))
}
writer.Write([]byte(mockResponse))
}

unauthorizedGetRunsInteraction := utils.NewHttpInteraction("/runs/" + groupId, http.MethodGet)
unauthorizedGetRunsInteraction.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusUnauthorized)
writer.Write([]byte(`{ "error_message": "Invalid bearer token provided!" }`))
}
unauthorizedGetRunsInteraction := utils.NewHttpInteraction("/runs/"+groupId, http.MethodGet)
unauthorizedGetRunsInteraction.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusUnauthorized)
writer.Write([]byte(`{ "error_message": "Invalid bearer token provided!" }`))
}

newLoginInteraction := utils.NewHttpInteraction("/auth/tokens", http.MethodPost)
newLoginInteraction.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusCreated)
newLoginInteraction.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusCreated)

newJwt := createValidMockJwt()
fmt.Println(newJwt)
mockResponse := fmt.Sprintf(`{"jwt": "%s", "refresh_token": "abc"}`, newJwt)
writer.Write([]byte(mockResponse))
}
writer.Write([]byte(mockResponse))
}

getRunsInteraction := utils.NewHttpInteraction("/runs/" + groupId, http.MethodGet)
getRunsInteraction.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusOK)
getRunsInteraction := utils.NewHttpInteraction("/runs/"+groupId, http.MethodGet)
getRunsInteraction.WriteHttpResponseFunc = func(writer http.ResponseWriter, req *http.Request) {
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusOK)

mockRun := galasaapi.NewTestRun()

mockRuns := galasaapi.NewTestRuns()
mockRuns.Runs = []galasaapi.TestRun{ *mockRun }
mockRuns.Runs = []galasaapi.TestRun{*mockRun}
mockRunsBytes, _ := json.Marshal(mockRuns)

writer.Write(mockRunsBytes)
}
writer.Write(mockRunsBytes)
}

interactions := []utils.HttpInteraction{
interactions := []utils.HttpInteraction{
initialLoginOperation,
unauthorizedGetRunsInteraction,
unauthorizedGetRunsInteraction,
newLoginInteraction,
getRunsInteraction,
}
}

server := utils.NewMockHttpServer(t, interactions)
defer server.Server.Close()
server := utils.NewMockHttpServer(t, interactions)
defer server.Server.Close()

mockFactory := utils.NewMockFactory()

Expand All @@ -212,16 +211,16 @@ func TestGetRunsByGroupWithInvalidBearerTokenGetsNewTokenOk(t *testing.T) {
mockGalasaHome, _ := utils.NewGalasaHome(mockFileSystem, mockEnvironment, "")
mockTimeService := mockFactory.GetTimeService()
jwtCache := auth.NewJwtCache(mockFileSystem, mockGalasaHome, mockTimeService)
mockFileSystem.WriteTextFile(mockGalasaHome.GetUrlFolderPath() + "/galasactl.properties", "GALASA_TOKEN=my:token")
mockFileSystem.WriteTextFile(mockGalasaHome.GetUrlFolderPath() + "/bootstrap.properties", "")

mockFileSystem.WriteTextFile(mockGalasaHome.GetUrlFolderPath()+"/galasactl.properties", "GALASA_TOKEN=my:token")
mockFileSystem.WriteTextFile(mockGalasaHome.GetUrlFolderPath()+"/bootstrap.properties", "")

authenticator := auth.NewAuthenticator(apiServerUrl, mockFileSystem, mockGalasaHome, mockTimeService, mockEnvironment, jwtCache)
mockFactory.Authenticator = authenticator

bootstrap := ""
maxAttempts := 3
retryBackoffSeconds := 1
maxAttempts := 3
retryBackoffSeconds := 1

commsClient, _ := api.NewAPICommsClient(bootstrap, maxAttempts, float64(retryBackoffSeconds), mockFactory, mockGalasaHome)

Expand Down
4 changes: 3 additions & 1 deletion pkg/runs/jsonReporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func TestJsonReportWorks(t *testing.T) {
Tests: []TestMethod{{Method: "method1", Result: "passed"}, {Method: "method2", Result: "passed"}},
GherkinUrl: "file:///my.feature",
GherkinFeature: "my",
SubmissionId: "123",
}

finishedRunsMap := make(map[string]*TestRun, 1)
Expand Down Expand Up @@ -79,7 +80,8 @@ func TestJsonReportWorks(t *testing.T) {
],
"GherkinUrl":"file:///my.feature",
"GherkinFeature":"my",
"group":""
"group":"",
"submissionId":"123"
}
]
}`
Expand Down
1 change: 1 addition & 0 deletions pkg/runs/runTypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type TestRun struct {
GherkinUrl string `yaml:"gherkin"`
GherkinFeature string `yaml:"feature"`
Group string `yaml:"group" json:"group"`
SubmissionId string `yaml:"submissionId" json:"submissionId"`
RunId string `yaml:"runId,omitempty" json:"runId,omitempty"`
}

Expand Down
Loading