Files
poseidon/tests/e2e/e2e_helpers.go
2024-05-07 14:48:17 +02:00

106 lines
3.5 KiB
Go

package e2e
import (
"encoding/json"
"fmt"
"github.com/openHPI/poseidon/internal/api"
"github.com/openHPI/poseidon/pkg/dto"
"github.com/openHPI/poseidon/pkg/logging"
"github.com/openHPI/poseidon/tests"
"github.com/openHPI/poseidon/tests/helpers"
"net/http"
"time"
)
var log = logging.GetLogger("e2e-helpers")
func CreateDefaultEnvironment(prewarmingPoolSize uint, image string) dto.ExecutionEnvironmentRequest {
path := helpers.BuildURL(api.BasePath, api.EnvironmentsPath, tests.DefaultEnvironmentIDAsString)
const smallCPULimit uint = 20
const smallMemoryLimit uint = 100
defaultNomadEnvironment := dto.ExecutionEnvironmentRequest{
PrewarmingPoolSize: prewarmingPoolSize,
CPULimit: smallCPULimit,
MemoryLimit: smallMemoryLimit,
Image: image,
NetworkAccess: false,
ExposedPorts: nil,
}
resp, err := helpers.HTTPPutJSON(path, defaultNomadEnvironment)
if err != nil || resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusNoContent {
log.WithError(err).Fatal("Couldn't create default environment for e2e tests")
}
err = resp.Body.Close()
if err != nil {
log.Fatal("Failed closing body")
}
return defaultNomadEnvironment
}
func WaitForDefaultEnvironment() {
path := helpers.BuildURL(api.BasePath, api.RunnersPath)
body := &dto.RunnerRequest{
ExecutionEnvironmentID: tests.DefaultEnvironmentIDAsInteger,
InactivityTimeout: 1,
}
var code int
const maxRetries = 60
for count := 0; count < maxRetries && code != http.StatusOK; count++ {
<-time.After(time.Second)
resp, err := helpers.HTTPPostJSON(path, body)
if err == nil {
code = resp.StatusCode
log.WithField("count", count).WithField("statusCode", code).Info("Waiting for idle runners")
} else {
log.WithField("count", count).WithError(err).Warn("Waiting for idle runners")
}
_ = resp.Body.Close()
}
if code != http.StatusOK {
log.Fatal("Failed to provide a runner")
}
}
// ProvideRunner creates a runner with the given RunnerRequest via an external request.
// It needs a running Poseidon instance to work.
func ProvideRunner(request *dto.RunnerRequest) (string, error) {
runnerURL := helpers.BuildURL(api.BasePath, api.RunnersPath)
resp, err := helpers.HTTPPostJSON(runnerURL, request)
if err != nil {
return "", fmt.Errorf("cannot post provide runner: %w", err)
}
if resp.StatusCode != http.StatusOK {
//nolint:goerr113 // dynamic error is ok in here, as it is a test
return "", fmt.Errorf("expected response code 200 when getting runner, got %v", resp.StatusCode)
}
runnerResponse := new(dto.RunnerResponse)
err = json.NewDecoder(resp.Body).Decode(runnerResponse)
if err != nil {
return "", fmt.Errorf("cannot decode runner response: %w", err)
}
_ = resp.Body.Close()
return runnerResponse.ID, nil
}
// ProvideWebSocketURL creates a WebSocket endpoint from the ExecutionRequest via an external api request.
// It requires a running Poseidon instance.
func ProvideWebSocketURL(runnerID string, request *dto.ExecutionRequest) (string, error) {
url := helpers.BuildURL(api.BasePath, api.RunnersPath, runnerID, api.ExecutePath)
resp, err := helpers.HTTPPostJSON(url, request)
if err != nil {
return "", fmt.Errorf("cannot post provide websocket url: %w", err)
} else if resp.StatusCode != http.StatusOK {
return "", dto.ErrMissingData
}
executionResponse := new(dto.ExecutionResponse)
err = json.NewDecoder(resp.Body).Decode(executionResponse)
if err != nil {
return "", fmt.Errorf("cannot parse execution response: %w", err)
}
_ = resp.Body.Close()
return executionResponse.WebSocketURL, nil
}