func/test/e2e/scenario_runtime-http_test.go

143 lines
3.9 KiB
Go

//go:build e2elc
package e2e
import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"gotest.tools/v3/assert"
"knative.dev/func/test/testhttp"
common "knative.dev/func/test/common"
)
var runtimeSupportMap = map[string][]string{
"node": {"pack", "s2i"},
"go": {"pack", "s2i"},
"rust": {"pack"},
"python": {"pack", "s2i"},
"quarkus": {"pack", "s2i"},
"springboot": {"pack"},
"typescript": {"pack", "s2i"},
}
type lifecycleTestCase struct {
Runtime string
Builder string
}
// prepareTestMatrix creates a list of runtime x builder that will be part of the lifecycle test.
func prepareTestMatrix() (testCase []lifecycleTestCase) {
targetBuilder, _ := os.LookupEnv("FUNC_BUILDER")
runtimes, present := os.LookupEnv("E2E_RUNTIMES")
var runtimeList = []string{}
if present {
if runtimes != "" {
runtimeList = strings.Split(runtimes, " ")
}
} else {
for k := range runtimeSupportMap {
runtimeList = append(runtimeList, k)
}
}
for _, r := range runtimeList {
for _, supportedBuilder := range runtimeSupportMap[r] {
if targetBuilder == "" || supportedBuilder == targetBuilder {
testCase = append(testCase, lifecycleTestCase{r, supportedBuilder})
}
}
}
return
}
// TestFunctionCloudEventsTemplate will invoke a language runtime test against (by default) all supported runtimes.
// The Environment Variable E2E_RUNTIMES can be used to select the languages/runtimes to be tested
// The Environment Variable FUNC_BUILDER can be used to select the builder (s2i or pack).
func TestFunctionHttpTemplate(t *testing.T) {
var testMatrix = prepareTestMatrix()
for _, tc := range testMatrix {
t.Run(fmt.Sprintf("%v_%v_test", tc.Runtime, tc.Builder), func(t *testing.T) {
lifecycleHttpTest(t, tc.Runtime, tc.Builder)
})
}
}
func lifecycleHttpTest(t *testing.T, language string, builder string) {
var funcName = "http-function-" + language + "-" + builder
var funcPath = filepath.Join(t.TempDir(), funcName)
knFunc := common.NewKnFuncShellCli(t)
knFunc.Exec("create", "--language", language, "--template", "http", funcPath)
knFunc.Exec("deploy", "--registry", common.GetRegistry(), "--builder", builder, "--path", funcPath)
defer knFunc.Exec("delete", "--path", funcPath)
_, functionUrl := common.WaitForFunctionReady(t, funcName)
validator, ok := httpFuncValidatorMap[language]
if ok {
validator.InvokeAndAssert(t, functionUrl)
}
}
// Basic function responsiveness Test Validator
type FuncResponsivenessValidator struct {
urlMask string
method string
contentType string
bodyData string
expects string
customValidator func(statusCode int, responseBody string) error
}
func (f *FuncResponsivenessValidator) InvokeAndAssert(t *testing.T, functionUrl string) {
targetUrl := fmt.Sprintf(f.urlMask, functionUrl)
headers := testhttp.HeaderBuilder().AddNonEmpty("Content-Type", f.contentType).Headers
statusCode, funcResponse := testhttp.TestUrl(t, f.method, f.bodyData, targetUrl, headers)
if f.customValidator != nil {
err := f.customValidator(statusCode, funcResponse)
assert.NilError(t, err)
} else {
assert.Assert(t, statusCode == 200)
assert.Assert(t, strings.Contains(funcResponse, f.expects), "Function response body does not contains %s", f.expects)
}
}
var httpFuncValidatorMap = map[string]FuncResponsivenessValidator{
"node": {
urlMask: "%s?message=hello",
expects: `{"message":"hello"}`,
},
"go": {
urlMask: "%s?message=hello",
expects: "message=hello",
},
"python": {
urlMask: "%s?message=hello",
expects: `{"message": "hello"}`,
},
"quarkus": {
urlMask: "%s?message=hello",
expects: `{"message":"hello"}`,
},
"springboot": {
urlMask: "%s?message=hello",
expects: "{message=hello}",
},
"typescript": {
urlMask: "%s",
method: "POST",
contentType: "application/json",
bodyData: `{"message":"hello"}`,
expects: `{"message":"hello"}`,
},
}