mirror of
https://github.com/alibaba/higress.git
synced 2026-02-26 13:40:49 +08:00
265 lines
8.3 KiB
Go
265 lines
8.3 KiB
Go
/*
|
|
Copyright 2022 The Kubernetes Authors.
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package suite
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/alibaba/higress/test/e2e/conformance/utils/config"
|
|
"github.com/alibaba/higress/test/e2e/conformance/utils/kubernetes"
|
|
"github.com/alibaba/higress/test/e2e/conformance/utils/roundtripper"
|
|
"istio.io/istio/pkg/util/sets"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
)
|
|
|
|
const (
|
|
TestAreaAll = "all"
|
|
TestAreaSetup = "setup"
|
|
TestAreaRun = "run"
|
|
TessAreaClean = "clean"
|
|
)
|
|
|
|
// ConformanceTestSuite defines the test suite used to run Gateway API
|
|
// conformance tests.
|
|
type ConformanceTestSuite struct {
|
|
Client client.Client
|
|
RoundTripper roundtripper.RoundTripper
|
|
GatewayAddress string
|
|
IngressClassName string
|
|
Debug bool
|
|
Cleanup bool
|
|
BaseManifests []string
|
|
Applier kubernetes.Applier
|
|
SkipTests sets.Set[string]
|
|
ExecuteTests sets.Set[string]
|
|
TimeoutConfig config.TimeoutConfig
|
|
SupportedFeatures sets.Set[string]
|
|
}
|
|
|
|
// Options can be used to initialize a ConformanceTestSuite.
|
|
type Options struct {
|
|
SupportedFeatures sets.Set[string]
|
|
ExemptFeatures sets.Set[string]
|
|
ExecuteTests string
|
|
|
|
EnableAllSupportedFeatures bool
|
|
Client client.Client
|
|
GatewayAddress string
|
|
IngressClassName string
|
|
Debug bool
|
|
RoundTripper roundtripper.RoundTripper
|
|
BaseManifests []string
|
|
NamespaceLabels map[string]string
|
|
// Options for wasm extended features
|
|
WASMOptions
|
|
|
|
// CleanupBaseResources indicates whether or not the base test
|
|
// resources such as Gateways should be cleaned up after the run.
|
|
CleanupBaseResources bool
|
|
TimeoutConfig config.TimeoutConfig
|
|
|
|
// IsEnvoyConfigTest indicates whether or not the test is for envoy config
|
|
IsEnvoyConfigTest bool
|
|
}
|
|
|
|
type WASMOptions struct {
|
|
IsWasmPluginTest bool
|
|
WasmPluginType string
|
|
WasmPluginName string
|
|
}
|
|
|
|
// New returns a new ConformanceTestSuite.
|
|
func New(s Options) *ConformanceTestSuite {
|
|
config.SetupTimeoutConfig(&s.TimeoutConfig)
|
|
|
|
roundTripper := s.RoundTripper
|
|
if roundTripper == nil {
|
|
roundTripper = &roundtripper.DefaultRoundTripper{Debug: s.Debug, TimeoutConfig: s.TimeoutConfig}
|
|
}
|
|
|
|
if s.SupportedFeatures == nil {
|
|
s.SupportedFeatures = sets.Set[string]{}
|
|
}
|
|
|
|
if s.IsWasmPluginTest {
|
|
feature, ok := WasmPluginTypeMap[s.WasmPluginType]
|
|
if ok {
|
|
s.SupportedFeatures.Insert(string(feature))
|
|
} else {
|
|
panic("WasmPluginType [" + s.WasmPluginType + "] not support")
|
|
}
|
|
} else if s.IsEnvoyConfigTest {
|
|
s.SupportedFeatures.Insert(string(EnvoyConfigConformanceFeature))
|
|
} else if s.EnableAllSupportedFeatures {
|
|
s.SupportedFeatures = AllFeatures
|
|
}
|
|
|
|
for feature := range s.ExemptFeatures {
|
|
s.SupportedFeatures.Delete(feature)
|
|
}
|
|
|
|
suite := &ConformanceTestSuite{
|
|
Client: s.Client,
|
|
RoundTripper: roundTripper,
|
|
IngressClassName: s.IngressClassName,
|
|
Debug: s.Debug,
|
|
Cleanup: s.CleanupBaseResources,
|
|
BaseManifests: s.BaseManifests,
|
|
SupportedFeatures: s.SupportedFeatures,
|
|
GatewayAddress: s.GatewayAddress,
|
|
ExecuteTests: sets.New[string](),
|
|
Applier: kubernetes.Applier{
|
|
NamespaceLabels: s.NamespaceLabels,
|
|
},
|
|
TimeoutConfig: s.TimeoutConfig,
|
|
}
|
|
|
|
// apply defaults
|
|
if suite.BaseManifests == nil {
|
|
suite.BaseManifests = []string{
|
|
"base/manifests.yaml",
|
|
"base/consul.yaml",
|
|
"base/eureka.yaml",
|
|
"base/nacos.yaml",
|
|
"base/dubbo.yaml",
|
|
"base/opa.yaml",
|
|
}
|
|
}
|
|
|
|
testNames := strings.Split(s.ExecuteTests, ",")
|
|
for i := range testNames {
|
|
if testNames[i] != "" {
|
|
suite.ExecuteTests = suite.ExecuteTests.Insert(testNames[i])
|
|
}
|
|
}
|
|
|
|
return suite
|
|
}
|
|
|
|
// Setup ensures the base resources required for conformance tests are installed
|
|
// in the cluster. It also ensures that all relevant resources are ready.
|
|
func (suite *ConformanceTestSuite) Setup(t *testing.T) {
|
|
t.Logf("📦 Test Setup: Ensuring IngressClass has been accepted")
|
|
|
|
suite.Applier.IngressClass = suite.IngressClassName
|
|
|
|
t.Logf("📦 Test Setup: Applying base manifests")
|
|
|
|
for _, baseManifest := range suite.BaseManifests {
|
|
suite.Applier.MustApplyWithCleanup(t, suite.Client, suite.TimeoutConfig, baseManifest, suite.Cleanup)
|
|
}
|
|
|
|
t.Logf("📦 Test Setup: Applying programmatic resources")
|
|
secret := kubernetes.MustCreateSelfSignedCertSecret(t, "higress-conformance-web-backend", "certificate", []string{"*"})
|
|
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
|
|
secret = kubernetes.MustCreateSelfSignedCertSecret(t, "higress-conformance-infra", "tls-validity-checks-certificate", []string{"*"})
|
|
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
|
|
|
|
t.Logf("📦 Test Setup: Ensuring Pods from base manifests are ready")
|
|
namespaces := []string{
|
|
"higress-conformance-infra",
|
|
"higress-conformance-app-backend",
|
|
"higress-conformance-web-backend",
|
|
}
|
|
kubernetes.NamespacesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, namespaces)
|
|
|
|
t.Logf("🌱 Supported Features: %+v", suite.SupportedFeatures.UnsortedList())
|
|
}
|
|
|
|
// Run runs the provided set of conformance tests.
|
|
func (suite *ConformanceTestSuite) Run(t *testing.T, tests []ConformanceTest) {
|
|
t.Logf("🚀 Start Running %d Test Cases: \n\n%s", len(tests), globalConformanceTestsListInfo(tests))
|
|
for _, test := range tests {
|
|
t.Run(test.ShortName, func(t *testing.T) {
|
|
test.Run(t, suite)
|
|
})
|
|
}
|
|
}
|
|
|
|
// Clean cleans up the base resources installed by Setup.
|
|
func (suite *ConformanceTestSuite) Clean(t *testing.T) {
|
|
if suite.Cleanup {
|
|
t.Logf("🧹 Test Cleanup: Ensuring base resources have been cleaned up")
|
|
|
|
for _, baseManifest := range suite.BaseManifests {
|
|
suite.Applier.MustDelete(t, suite.Client, suite.TimeoutConfig, baseManifest)
|
|
}
|
|
}
|
|
}
|
|
|
|
func globalConformanceTestsListInfo(tests []ConformanceTest) string {
|
|
var cases string
|
|
for index, test := range tests {
|
|
cases += fmt.Sprintf("🎯 CaseNum: %d\nCaseName: %s\nScenario: %s\nFeatures: %+v\n\n", index+1, test.ShortName, test.Description, test.Features)
|
|
}
|
|
|
|
return cases
|
|
}
|
|
|
|
type ConformanceTests []ConformanceTest
|
|
|
|
// ConformanceTest is used to define each individual conformance test.
|
|
type ConformanceTest struct {
|
|
ShortName string
|
|
Description string
|
|
PreDeleteRs []string
|
|
Manifests []string
|
|
Features []SupportedFeature
|
|
Slow bool
|
|
Parallel bool
|
|
Test func(*testing.T, *ConformanceTestSuite)
|
|
NotCleanup bool
|
|
}
|
|
|
|
// Run runs an individual tests, applying and cleaning up the required manifests
|
|
// before calling the Test function.
|
|
func (test *ConformanceTest) Run(t *testing.T, suite *ConformanceTestSuite) {
|
|
if test.Parallel {
|
|
t.Parallel()
|
|
}
|
|
|
|
// Check that all features exercised by the test have been opted into by
|
|
// the suite.
|
|
for _, feature := range test.Features {
|
|
if !suite.SupportedFeatures.Contains(string(feature)) {
|
|
t.Skipf("🏊🏼 Skipping %s: suite does not support %s", test.ShortName, feature)
|
|
}
|
|
}
|
|
|
|
// check that the test should not be skipped
|
|
if suite.SkipTests.Contains(test.ShortName) {
|
|
t.Skipf("🏊🏼 Skipping %s: test explicitly skipped", test.ShortName)
|
|
}
|
|
|
|
if len(suite.ExecuteTests) > 0 && !suite.ExecuteTests.Contains(test.ShortName) {
|
|
t.Skipf("🏊🏼 Skipping %s: test explicitly skipped", test.ShortName)
|
|
}
|
|
|
|
t.Logf("🔥 Running Conformance Test: %s", test.ShortName)
|
|
|
|
for _, manifestLocation := range test.PreDeleteRs {
|
|
t.Logf("🧳 Applying PreDeleteRs Manifests: %s", manifestLocation)
|
|
suite.Applier.MustDelete(t, suite.Client, suite.TimeoutConfig, manifestLocation)
|
|
}
|
|
|
|
for _, manifestLocation := range test.Manifests {
|
|
t.Logf("🧳 Applying Manifests: %s", manifestLocation)
|
|
suite.Applier.MustApplyWithCleanup(t, suite.Client, suite.TimeoutConfig, manifestLocation, !test.NotCleanup)
|
|
}
|
|
|
|
test.Test(t, suite)
|
|
}
|