From: Adrian Villin Date: Mon, 8 Sep 2025 14:29:39 +0000 (+0200) Subject: hs-test: move hs-test to vpp/test-c X-Git-Tag: v26.02-rc0~21 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=9749352163d8fa2d05c97506a36e34335771d359;p=vpp.git hs-test: move hs-test to vpp/test-c - separated cluster tests from hs-test and moved them into test-c/kube-test - cleaned up kube-test and hs-test - kube-test setup-cluster.sh improvements - Makefile in extras/hs-test is temporary - kube-test stability improvements Type: test Change-Id: Iee9fc732ccd303d4b4635d329f673c03f95a4dd4 Signed-off-by: Adrian Villin --- diff --git a/.gitignore b/.gitignore index 68d47ba13ce..963a9da9bf1 100644 --- a/.gitignore +++ b/.gitignore @@ -137,18 +137,25 @@ compile_commands.json **/test-run-*-*-* # host stack test framework -/extras/hs-test/vpp-data -/extras/hs-test/hs-test -/extras/hs-test/http_server -/extras/hs-test/.build.ok -/extras/hs-test/.build.cov.ok -/extras/hs-test/.last_hst_ppid -/extras/hs-test/summary/ -/extras/hs-test/.last_state_hash -/extras/hs-test/.kind_deps.ok -/extras/hs-test/.go_cache/ -/extras/hs-test/kubernetes/calico-config.yaml -/extras/hs-test/kubernetes/.vars +/test-c/hs-test/vpp-data +/test-c/hs-test/hs-test +/test-c/hs-test/http_server +/test-c/hs-test/.build.ok +/test-c/hs-test/.build.cov.ok +/test-c/hs-test/.last_hst_ppid +/test-c/hs-test/summary/ +/test-c/hs-test/.last_state_hash +/test-c/hs-test/.go_cache/ + +# kube-test +/test-c/kube-test/vpp-data +/test-c/kube-test/.build.ok +/test-c/kube-test/.last_ppid +/test-c/kube-test/summary/ +/test-c/kube-test/.last_state_hash +/test-c/kube-test/.kube_deps.ok +/test-c/kube-test/kubernetes/calico-config.yaml +/test-c/kube-test/kubernetes/.vars # ./configure /CMakeFiles diff --git a/MAINTAINERS b/MAINTAINERS index 01fc7b1bff5..b00762ba2b6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -890,7 +890,13 @@ I: hs-test M: Florin Coras M: Matus Fabian M: Adrian Villin -F: extras/hs-test +F: test-c/hs-test + +Kube test framework +I: kube-test +M: Florin Coras +M: Adrian Villin +F: test-c/kube-test THE REST I: misc diff --git a/Makefile b/Makefile index a7ce9986e58..593ea4e98b2 100644 --- a/Makefile +++ b/Makefile @@ -580,7 +580,7 @@ test-cov: .PHONY: test-cov-hs test-cov-hs: build-gcov - @$(MAKE) CC=$(CC) -C extras/hs-test test-cov \ + @$(MAKE) CC=$(CC) -C test-c/hs-test test-cov \ VPP_BUILD_DIR=$(BR)/build-vpp_gcov-native/vpp .PHONY: test-cov-post-standalone @@ -698,7 +698,7 @@ test-wipe-all: .PHONY: test-checkstyle test-checkstyle: @$(MAKE) -C test checkstyle-python-all - @$(MAKE) -C extras/hs-test checkstyle-go + @$(MAKE) -C test-c/hs-test checkstyle-go # Note: All python venv consolidated in test/Makefile, test/requirements*.txt .PHONY: test-checkstyle-diff @@ -839,7 +839,11 @@ go-api-files: json-api-files .PHONY: cleanup-hst cleanup-hst: - $(MAKE) -C extras/hs-test cleanup-hst + $(MAKE) -C test-c/hs-test cleanup-hst + +.PHONY: cleanup-perf +cleanup-perf: + $(MAKE) -C test-c/kube-test cleanup-perf .PHONY: ctags ctags: ctags.files @@ -885,11 +889,13 @@ checkstyle-python: .PHONY: checkstyle-go checkstyle-go: - @$(MAKE) -C extras/hs-test checkstyle-go + @$(MAKE) -C test-c/hs-test checkstyle-go + @$(MAKE) -C test-c/kube-test checkstyle-go .PHONY: fixstyle-go fixstyle-go: - @$(MAKE) -C extras/hs-test fixstyle-go + @$(MAKE) -C test-c/hs-test fixstyle-go + @$(MAKE) -C test-c/kube-test fixstyle-go .PHONY: checkstyle-all checkstyle-all: checkstyle-commit checkstyle checkstyle-python docs-spell checkstyle-go diff --git a/docs/developer/extras/hs_test.rst b/docs/developer/extras/hs_test.rst index b7ace7940a9..0bbda04e4ff 120000 --- a/docs/developer/extras/hs_test.rst +++ b/docs/developer/extras/hs_test.rst @@ -1 +1 @@ -../../../extras/hs-test/README.rst \ No newline at end of file +../../../test-c/hs-test/README.rst \ No newline at end of file diff --git a/extras/hs-test/Makefile b/extras/hs-test/Makefile index 8788d823830..99a8f883d49 100644 --- a/extras/hs-test/Makefile +++ b/extras/hs-test/Makefile @@ -1,385 +1,3 @@ -export HS_ROOT=$(CURDIR) - -# sets WS_ROOT if called from extras/hs-test -ifeq ($(WS_ROOT),) -export WS_ROOT=$(HS_ROOT)/../.. -endif - -ifeq ($(VERBOSE),) -VERBOSE=false -endif - -ifeq ($(PERSIST),) -PERSIST=false -endif - -ifeq ($(UNCONFIGURE),) -UNCONFIGURE=false -endif - -ifeq ($(TEST),) -TEST=all -endif - -ifeq ($(TEST-HS),) -TEST-HS=all -endif - -ifeq ($(DEBUG),) -DEBUG=false -endif - -ifeq ($(CPUS),) -CPUS=1 -endif - -ifeq ($(VPP_CPUS),) -VPP_CPUS=1 -endif - -ifeq ($(PARALLEL),) -PARALLEL=1 -endif - -ifeq ($(REPEAT),) -REPEAT=0 -endif - -ifeq ($(CPU0),) -CPU0=false -endif - -ifeq ($(VPPSRC),) -VPPSRC=$(shell pwd)/../.. -endif - -ifeq ($(UBUNTU_CODENAME),) -UBUNTU_CODENAME=$(shell grep '^UBUNTU_CODENAME=' /etc/os-release | cut -f2- -d=) -endif - -ifeq ($(ARCH),) -ARCH=$(shell dpkg --print-architecture) -endif - -ifeq ($(NO_COLOR),) -VERBOSE=false -endif - -ifeq ($(TIMEOUT),) -TIMEOUT=5 -endif - -ifeq ($(GINKGO_TIMEOUT),) -GINKGO_TIMEOUT=3h -endif - -CORE_PATTERN := $(shell cat /proc/sys/kernel/core_pattern) -CORE_VOLUME:= -DOCKER_TTY:= - -ifeq ($(shell expr "$(CORE_PATTERN)" : '^/'), 1) -CORE_VOLUME := -v $(CORE_PATTERN):$(CORE_PATTERN) -endif - -ifeq ($(shell tty -s && echo $$?), 0) -DOCKER_TTY := -it -endif - -FORCE_BUILD?=true - -# privileged is needed for "ip netns" otherwise we are not able to create namespace -DOCKER_CAPABILITIES:=--privileged -DOCKER_DEVICES:=--device /dev/vhost-net:/dev/vhost-net --device /dev/net/tun:/dev/net/tun -DOCKER_VOLUMES:=-v $(WS_ROOT):$(WS_ROOT) -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/hs-test:/tmp/hs-test \ - -v /etc/localtime:/etc/localtime:ro $(CORE_VOLUME) -v $(HS_ROOT)/.go_cache/mod:/root/go/pkg/mod \ - -v $(HS_ROOT)/.go_cache/build:/root/.cache/go-build -DOCKER_PROXY:=-e HTTP_PROXY=$(HTTP_PROXY) -e HTTPS_PROXY=$(HTTPS_PROXY) -e NO_PROXY=$(NO_PROXY) - -.PHONY: help -help: - @echo "Make targets:" - @echo " test - run tests" - @echo " test-debug - run tests (vpp debug image)" - @echo " test-leak - run memory leak tests (vpp debug image)" - @echo " test-perf - run performance tests (requires a running cluster)" - @echo " build - build test infra" - @echo " build-cov - coverage build of VPP and Docker images" - @echo " build-debug - build test infra (vpp debug image)" - @echo " build-go - just build golang files" - @echo " cluster-help - print info about KinD cluster setup (perf testing)" - @echo " master-cluster - setup KinD cluster for performance testing (master CalicoVPP + VPP)" - @echo " rebuild-master-cluster - rebuild VPP and update related pods without shutting down the cluster" - @echo " release-cluster - setup KinD cluster for performance testing (latest CalicoVPP release)" - @echo " checkstyle-go - check style of .go source files" - @echo " fixstyle-go - format .go source files" - @echo " cleanup-hst - removes all docker containers and namespaces from last test run" - @echo " cleanup-perf - removes all kubernetes pods and namespaces from last test run" - @echo " list-tests - list all tests" - @echo " install-deps - install software dependencies" - @echo " install-kind-deps - install software dependencies for cluster" - @echo - @echo "'make build' and 'make test' arguments:" - @echo " UBUNTU_VERSION - ubuntu version for docker image" - @echo " FORCE_BUILD=[true|false] - force docker image building" - @echo - @echo "'make test' specific arguments:" - @echo " PERSIST=[true|false] - whether clean up topology and dockers after test" - @echo " VERBOSE=[true|false] - verbose output" - @echo " UNCONFIGURE=[true|false] - unconfigure selected test" - @echo " DEBUG=[true|false] - attach VPP to GDB" - @echo " TEST=[name1,name2...] - specific test(s) to run" - @echo " SKIP=[name1,name2...] - specific test(s) to skip" - @echo " CPUS=[n] - number of cpus to allocate to each non-VPP container (default = 1)" - @echo " VPP_CPUS=[n] - number of cpus to allocate to each VPP container (default = 1)" - @echo " VPPSRC=[path-to-vpp-src] - path to vpp source files (for gdb)" - @echo " PARALLEL=[n] - number of test processes to spawn to run in parallel" - @echo " REPEAT=[n] - repeat tests up to N times or until a failure occurs" - @echo " CPU0=[true|false] - use cpu0" - @echo " DRYRUN=[true|false] - set up containers but don't run tests" - @echo " NO_COLOR=[true|false] - disables colorful Docker and Ginkgo output" - @echo " TIMEOUT=[minutes] - test timeout override (5 minutes by default)" - @echo " GINKGO_TIMEOUT=[Ns/m/h] - Ginkgo timeout override (3h by default)" - @echo - @echo "'make setup-cluster' arguments:" - @echo " BASE=[master|latest] - build master CalicoVPP with master VPP or use latest release of CalicoVPP (default = latest)" - -.PHONY: list-tests -list-tests: - @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --seed=2 | head -n -1 | grep 'test.go' | \ - sed 's/^/* /; s/\(Suite\) /\1\//g' - -.PHONY: build-vpp-release -build-vpp-release: - @$(MAKE) -C ../.. build-release - -.PHONY: build-vpp-debug -build-vpp-debug: - @$(MAKE) -C ../.. build - -.PHONY: build-vpp-gcov -build-vpp-gcov: - @$(MAKE) -C ../.. build-gcov - -.build.ok: build - @touch .build.ok - -.build.cov.ok: build-cov - @touch .build.ok - -.build_debug.ok: build-debug - @touch .build.ok - -.PHONY: test -test: FORCE_BUILD=false -test: .deps.ok .build.ok - docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ - -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ - .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \ - --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \ - --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --cpu0=$(CPU0) \ - --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \ - --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \ - ./script/compress.sh $$? - -.PHONY: test-debug -test-debug: FORCE_BUILD=false -test-debug: .deps.ok .build_debug.ok - docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ - -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ - .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \ - --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \ - --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --debug_build=true \ - --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \ - --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \ - ./script/compress.sh $$? - -.PHONY: wipe-lcov -wipe-lcov: - @lcov --zerocounters --directory $(WS_ROOT)/build-root/build-vpp_gcov-native/vpp - -.PHONY: test-cov -test-cov: FORCE_BUILD=false -test-cov: .deps.ok .build.cov.ok wipe-lcov - -docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ - -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ - .$(HS_ROOT)/hs_test.sh --coverage=true --persist=$(PERSIST) --verbose=$(VERBOSE) \ - --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST-HS) --cpus=$(CPUS) \ - --vppsrc=$(VPPSRC) --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) \ - --timeout=$(TIMEOUT) --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \ - ./script/compress.sh $$? - $(MAKE) -C ../.. test-cov-post-standalone HS_TEST=1 - -.PHONY: test-leak -test-leak: FORCE_BUILD=false -test-leak: .deps.ok .build_debug.ok - docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ - -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ - .$(HS_ROOT)/hs_test.sh --test=$(TEST) --debug_build=true --leak_check=true --vppsrc=$(VPPSRC) --timeout=$(TIMEOUT) \ - --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); - -.PHONY: test-perf -test-perf: FORCE_BUILD=false -test-perf: .deps.ok .build.ok - @bash ./hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \ - --test=$(TEST) --vppsrc=$(VPPSRC) --repeat=$(REPEAT) \ - --skip=$(SKIP) --no_color=$(NO_COLOR) --perf=true --timeout=$(TIMEOUT) \ - --ginkgo_timeout=$(GINKGO_TIMEOUT); \ - ./script/compress.sh $$? - -.PHONY: cluster-help -cluster-help: - @bash ./kubernetes/setup-cluster.sh help - -.PHONY: release-cluster -release-cluster: .kind_deps.ok - @bash ./kubernetes/setup-cluster.sh release-cluster - -.PHONY: master-cluster -master-cluster: .kind_deps.ok - @bash ./kubernetes/setup-cluster.sh master-cluster - -.PHONY: rebuild-master-cluster -rebuild-master-cluster: .kind_deps.ok - @bash ./kubernetes/setup-cluster.sh rebuild-master-cluster - -# this is executed in a container by hs-test.sh -.PHONY: build-go -build-go: - go build --buildvcs=false ./tools/http_server - -.PHONY: build -build: .deps.ok build-vpp-release - @rm -f .build.ok - bash ./script/build_hst.sh release $(FORCE_BUILD) - @touch .build.ok - -.PHONY: build-cov -build-cov: .deps.ok build-vpp-gcov - @rm -f .build.cov.ok - bash ./script/build_hst.sh gcov $(FORCE_BUILD) - @touch .build.cov.ok - -.PHONY: build-debug -build-debug: .deps.ok build-vpp-debug - @rm -f .build.ok - bash ./script/build_hst.sh debug $(FORCE_BUILD) - @touch .build.ok - -.deps.ok: - @$(MAKE) install-deps - -.kind_deps.ok: - @$(MAKE) install-kind-deps - -.PHONY: install-kind-deps -install-kind-deps: .deps.ok - -@if ! command -v kind >/dev/null 2>&1; then \ - echo "Installing KinD"; \ - go install sigs.k8s.io/kind@v0.29.0; \ - echo "Creating symlink from '$(HOME)/go/bin/kind' to '/usr/bin/kind'"; \ - sudo ln -s $(HOME)/go/bin/kind /usr/bin/kind; \ - else \ - echo "KinD is already installed. Skipping."; \ - fi - @if ! command -v kubectl >/dev/null 2>&1; then \ - echo "kubectl not found. Installing kubectl..."; \ - sudo -E apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg; \ - curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \ - sudo -E chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \ - echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list; \ - sudo -E chmod 644 /etc/apt/sources.list.d/kubernetes.list; \ - sudo apt-get update && sudo apt-get install -y kubectl; \ - else \ - echo "kubectl is already installed. Skipping."; \ - fi - @touch .kind_deps.ok - -.PHONY: install-deps -install-deps: - @rm -f .deps.ok - @if [ -d "/usr/local/go" ]; then \ - echo "Go is already installed. You may have to update it manually if version < 1.23.10"; \ - go version; \ - else \ - echo "Installing Go 1.23"; \ - wget -t 2 https://go.dev/dl/go1.23.10.linux-$(ARCH).tar.gz -O /tmp/go1.23.10.linux-$(ARCH).tar.gz && sudo tar -C /usr/local -xzf /tmp/go1.23.10.linux-$(ARCH).tar.gz; \ - sudo ln -s /usr/local/go/bin/go /usr/bin/go ; \ - fi - @sudo -E apt-get update - @sudo -E apt-get install -y apt-transport-https ca-certificates curl software-properties-common \ - bridge-utils gpg - @if [ ! -f /usr/share/keyrings/docker-archive-keyring.gpg ] ; then \ - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg; \ - echo "deb [arch=$(ARCH) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(UBUNTU_CODENAME) stable" \ - | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ; \ - apt-get update; \ - fi - @sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - @touch .deps.ok - -.PHONY: checkstyle-go -checkstyle-go: - @output=$$(find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/goimports@v0.35.0 -d {} +); \ - status=$$?; \ - if [ $$status -ne 0 ]; then \ - exit $$status; \ - elif [ -z "$$output" ]; then \ - echo "******************************************************************************"; \ - echo "* HST Golang Checkstyle OK."; \ - echo "******************************************************************************"; \ - else \ - echo "$$output"; \ - echo "******************************************************************************"; \ - echo "* HST Golang Checkstyle FAILED. Use 'make fixstyle-go' or fix errors manually."; \ - echo "******************************************************************************"; \ - exit 1; \ - fi - -.PHONY: fixstyle-go -fixstyle-go: - @echo "Modified files:" - @find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/goimports@v0.35.0 -w -l {} + - @go mod tidy - @echo "*******************************************************************" - @echo "Fixstyle done." - @echo "*******************************************************************" - -.PHONY: cleanup-hst -cleanup-hst: - @if [ ! -f ".last_hst_ppid" ]; then \ - echo "'.last_hst_ppid' file does not exist."; \ - exit 1; \ - fi - @echo "****************************" - @echo "Removing docker containers:" - @# "-" ignores errors - @-sudo docker rm $$(sudo docker stop $$(sudo docker ps -a -q --filter "name=$$(cat .last_hst_ppid)") -t 0) - @echo "****************************" - @echo "Removing IP address files:" - @find . -type f -regextype egrep -regex '.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' -exec sudo rm -v {} \; - @find . -type f -name "fd00:0*" -exec sudo rm -v {} \; - @echo "****************************" - @echo "Removing network namespaces:" - @for ns in $$(ip netns list | grep $$(cat .last_hst_ppid) | awk '{print $$1}'); do \ - echo $$ns; \ - sudo ip netns delete $$ns; \ - done - @echo "****************************" - @echo "Done." - @echo "****************************" - -.PHONY: cleanup-perf -cleanup-perf: - @if [ ! -f ".last_hst_ppid" ]; then \ - echo "'.last_hst_ppid' file does not exist."; \ - exit 1; \ - fi - @echo "****************************" - @echo "Removing kubernetes pods:" - @kubectl delete pods --all --grace-period=0 -n hs-test$$(cat .last_hst_ppid) - @echo "****************************" - @echo "Removing kubernetes namespace:" - @kubectl delete namespace hs-test$$(cat .last_hst_ppid) - @echo "****************************" - @echo "Done." - @echo "****************************" +# Temp redirect +%: + $(MAKE) -C ../../test-c/hs-test/ -f Makefile $@ \ No newline at end of file diff --git a/extras/hs-test/infra/common/suite_common.go b/extras/hs-test/infra/common/suite_common.go deleted file mode 100644 index be9a0a6ee37..00000000000 --- a/extras/hs-test/infra/common/suite_common.go +++ /dev/null @@ -1,209 +0,0 @@ -package hst_common - -import ( - "flag" - "fmt" - "io" - "log" - "net/http" - "os" - "strconv" - "strings" - "time" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var IsCoverage = flag.Bool("coverage", false, "use coverage run config") -var IsPersistent = flag.Bool("persist", false, "persists topology config") -var IsVerbose = flag.Bool("verbose", false, "verbose test output") -var WhoAmI = flag.String("whoami", "root", "what user ran hs-test") -var ParallelTotal = flag.Lookup("ginkgo.parallel.total") -var IsVppDebug = flag.Bool("debug", false, "attach gdb to vpp") -var DryRun = flag.Bool("dryrun", false, "set up containers but don't run tests") -var Timeout = flag.Int("timeout", 5, "test timeout override (in minutes)") -var PerfTesting = flag.Bool("perf", false, "perf test flag") -var NumaAwareCpuAlloc bool -var TestTimeout time.Duration -var RunningInCi bool - -const ( - LogDir string = "/tmp/hs-test/" - VolumeDir string = "/vol" -) - -type HstCommon struct { - Ppid string - ProcessIndex string - Logger *log.Logger - LogFile *os.File -} - -func (s *HstCommon) Skip(args string) { - Skip(args) -} - -func (s *HstCommon) SetupTest() { - TestCounterFunc() - s.Log("[* TEST SETUP]") -} - -func (s *HstCommon) SetupSuite() { - s.CreateLogger() - s.Log("[* SUITE SETUP]") - s.Ppid = fmt.Sprint(os.Getppid()) - // remove last number so we have space to prepend a process index (interfaces have a char limit) - s.Ppid = s.Ppid[:len(s.Ppid)-1] - s.ProcessIndex = fmt.Sprint(GinkgoParallelProcess()) -} - -func (s *HstCommon) TeardownTest() { - if *IsPersistent || *DryRun { - s.Skip("Skipping test teardown") - } - s.Log("[* TEST TEARDOWN]") -} - -func (s *HstCommon) TeardownSuite() { - if *IsPersistent || *DryRun { - s.Skip("Skipping suite teardown") - } - s.Log("[* SUITE TEARDOWN]") -} - -func (s *HstCommon) GetCurrentSuiteName() string { - return CurrentSpecReport().ContainerHierarchyTexts[0] -} - -func (s *HstCommon) CreateLogger() { - suiteName := s.GetCurrentSuiteName() - var err error - s.LogFile, err = os.Create("summary/" + suiteName + ".log") - if err != nil { - Fail("Unable to create log file.") - } - s.Logger = log.New(io.Writer(s.LogFile), "", log.LstdFlags) -} - -// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter -// to keep console tidy -func (s *HstCommon) Log(log any, arg ...any) { - var logStr string - if len(arg) == 0 { - logStr = fmt.Sprint(log) - } else { - logStr = fmt.Sprintf(fmt.Sprint(log), arg...) - } - logs := strings.Split(logStr, "\n") - - for _, line := range logs { - s.Logger.Println(line) - } - if *IsVerbose { - GinkgoWriter.Println(logStr) - } -} - -func (s *HstCommon) AssertNil(object any, msgAndArgs ...any) { - ExpectWithOffset(2, object).To(BeNil(), msgAndArgs...) -} - -func (s *HstCommon) AssertNotNil(object any, msgAndArgs ...any) { - ExpectWithOffset(2, object).ToNot(BeNil(), msgAndArgs...) -} - -func (s *HstCommon) AssertEqual(expected, actual any, msgAndArgs ...any) { - ExpectWithOffset(2, actual).To(Equal(expected), msgAndArgs...) -} - -func (s *HstCommon) AssertNotEqual(expected, actual any, msgAndArgs ...any) { - ExpectWithOffset(2, actual).ToNot(Equal(expected), msgAndArgs...) -} - -func (s *HstCommon) AssertContains(testString, contains any, msgAndArgs ...any) { - ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).To(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...) -} - -func (s *HstCommon) AssertNotContains(testString, contains any, msgAndArgs ...any) { - ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).ToNot(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...) -} - -func (s *HstCommon) AssertEmpty(object any, msgAndArgs ...any) { - ExpectWithOffset(2, object).To(BeEmpty(), msgAndArgs...) -} - -func (s *HstCommon) AssertNotEmpty(object any, msgAndArgs ...any) { - ExpectWithOffset(2, object).ToNot(BeEmpty(), msgAndArgs...) -} - -func (s *HstCommon) AssertMatchError(actual, expected error, msgAndArgs ...any) { - ExpectWithOffset(2, actual).To(MatchError(expected), msgAndArgs...) -} - -func (s *HstCommon) AssertGreaterEqual(actual, expected any, msgAndArgs ...any) { - ExpectWithOffset(2, actual).Should(BeNumerically(">=", expected), msgAndArgs...) -} - -func (s *HstCommon) AssertGreaterThan(actual, expected any, msgAndArgs ...any) { - ExpectWithOffset(2, actual).Should(BeNumerically(">", expected), msgAndArgs...) -} - -func (s *HstCommon) AssertLessEqual(actual, expected any, msgAndArgs ...any) { - ExpectWithOffset(2, actual).Should(BeNumerically("<=", expected), msgAndArgs...) -} - -func (s *HstCommon) AssertLessThan(actual, expected any, msgAndArgs ...any) { - ExpectWithOffset(2, actual).Should(BeNumerically("<", expected), msgAndArgs...) -} - -func (s *HstCommon) AssertEqualWithinThreshold(actual, expected, threshold any, msgAndArgs ...any) { - ExpectWithOffset(2, actual).Should(BeNumerically("~", expected, threshold), msgAndArgs...) -} - -func (s *HstCommon) AssertTimeEqualWithinThreshold(actual, expected time.Time, threshold time.Duration, msgAndArgs ...any) { - ExpectWithOffset(2, actual).Should(BeTemporally("~", expected, threshold), msgAndArgs...) -} - -func (s *HstCommon) AssertHttpStatus(resp *http.Response, expectedStatus int, msgAndArgs ...any) { - ExpectWithOffset(2, resp).To(HaveHTTPStatus(expectedStatus), msgAndArgs...) -} - -func (s *HstCommon) AssertHttpHeaderWithValue(resp *http.Response, key string, value any, msgAndArgs ...any) { - ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue(key, value), msgAndArgs...) -} - -func (s *HstCommon) AssertHttpHeaderNotPresent(resp *http.Response, key string, msgAndArgs ...any) { - ExpectWithOffset(2, resp.Header.Get(key)).To(BeEmpty(), msgAndArgs...) -} - -func (s *HstCommon) AssertHttpContentLength(resp *http.Response, expectedContentLen int64, msgAndArgs ...any) { - ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue("Content-Length", strconv.FormatInt(expectedContentLen, 10)), msgAndArgs...) -} - -func (s *HstCommon) AssertHttpBody(resp *http.Response, expectedBody string, msgAndArgs ...any) { - ExpectWithOffset(2, resp).To(HaveHTTPBody(expectedBody), msgAndArgs...) -} - -// Coverage builds take longer to finish -> assert timeout is set to 'TestTimeout - 30 seconds' to let the test finish properly -func (s *HstCommon) AssertChannelClosed(timeout time.Duration, channel chan error) { - if *IsCoverage && timeout > time.Second*30 { - timeout = TestTimeout - time.Second*30 - s.Log("Coverage build, assert timeout is set to %s", timeout.String()) - } - EventuallyWithOffset(2, channel).WithTimeout(timeout).Should(BeClosed()) -} - -// Pass the parsed result struct and the minimum amount of data transferred in MB. -// Won't do anything when testing a coverage build. -func (s *HstCommon) AssertIperfMinTransfer(result IPerfResult, minTransferred int) { - if *IsCoverage { - s.Log("Coverage build; not asserting") - return - } - if result.Start.Details.Protocol == "TCP" { - s.AssertGreaterEqual(result.End.TcpReceived.MBytes, minTransferred) - } else { - s.AssertGreaterEqual(result.End.Udp.MBytes, minTransferred) - } -} diff --git a/extras/hs-test/infra/kind/utils.go b/extras/hs-test/infra/kind/utils.go deleted file mode 100644 index ea82085f324..00000000000 --- a/extras/hs-test/infra/kind/utils.go +++ /dev/null @@ -1,9 +0,0 @@ -package hst_kind - -func boolPtr(b bool) *bool { - return &b -} - -func int64Ptr(integer int64) *int64 { - return &integer -} diff --git a/extras/hs-test/vars b/extras/hs-test/vars deleted file mode 100644 index d1ca078fe21..00000000000 --- a/extras/hs-test/vars +++ /dev/null @@ -1,7 +0,0 @@ -export VPP_WS=../../ - -export HST_LDPRELOAD=${VPP_WS}/build-root/build-vpp-native/vpp/lib/x86_64-linux-gnu/libvcl_ldpreload.so -export PATH=${VPP_WS}/build-root/build-vpp-native/vpp/bin:$PATH - -export UBUNTU_VERSION=$(lsb_release -rs) -export HST_EXTENDED_TESTS=false diff --git a/test-c/hs-test/Makefile b/test-c/hs-test/Makefile new file mode 100644 index 00000000000..033d8ab1c63 --- /dev/null +++ b/test-c/hs-test/Makefile @@ -0,0 +1,308 @@ +export HS_ROOT=$(CURDIR) + +# sets WS_ROOT if called from test-c/hs-test +ifeq ($(WS_ROOT),) +export WS_ROOT=$(HS_ROOT)/../.. +endif + +ifeq ($(VERBOSE),) +VERBOSE=false +endif + +ifeq ($(PERSIST),) +PERSIST=false +endif + +ifeq ($(UNCONFIGURE),) +UNCONFIGURE=false +endif + +ifeq ($(TEST),) +TEST=all +endif + +ifeq ($(TEST-HS),) +TEST-HS=all +endif + +ifeq ($(DEBUG),) +DEBUG=false +endif + +ifeq ($(CPUS),) +CPUS=1 +endif + +ifeq ($(VPP_CPUS),) +VPP_CPUS=1 +endif + +ifeq ($(PARALLEL),) +PARALLEL=1 +endif + +ifeq ($(REPEAT),) +REPEAT=0 +endif + +ifeq ($(CPU0),) +CPU0=false +endif + +ifeq ($(VPPSRC),) +VPPSRC=$(shell pwd)/../.. +endif + +ifeq ($(UBUNTU_CODENAME),) +UBUNTU_CODENAME=$(shell grep '^UBUNTU_CODENAME=' /etc/os-release | cut -f2- -d=) +endif + +ifeq ($(ARCH),) +ARCH=$(shell dpkg --print-architecture) +endif + +ifeq ($(NO_COLOR),) +VERBOSE=false +endif + +ifeq ($(TIMEOUT),) +TIMEOUT=5 +endif + +ifeq ($(GINKGO_TIMEOUT),) +GINKGO_TIMEOUT=3h +endif + +CORE_PATTERN := $(shell cat /proc/sys/kernel/core_pattern) +CORE_VOLUME:= +DOCKER_TTY:= + +ifeq ($(shell expr "$(CORE_PATTERN)" : '^/'), 1) +CORE_VOLUME := -v $(CORE_PATTERN):$(CORE_PATTERN) +endif + +ifeq ($(shell tty -s && echo $$?), 0) +DOCKER_TTY := -it +endif + +FORCE_BUILD?=true + +# privileged is needed for "ip netns" otherwise we are not able to create namespace +DOCKER_CAPABILITIES:=--privileged +DOCKER_DEVICES:=--device /dev/vhost-net:/dev/vhost-net --device /dev/net/tun:/dev/net/tun +DOCKER_VOLUMES:=-v $(WS_ROOT):$(WS_ROOT) -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/hs-test:/tmp/hs-test \ + -v /etc/localtime:/etc/localtime:ro $(CORE_VOLUME) -v $(HS_ROOT)/.go_cache/mod:/root/go/pkg/mod \ + -v $(HS_ROOT)/.go_cache/build:/root/.cache/go-build +DOCKER_PROXY:=-e HTTP_PROXY=$(HTTP_PROXY) -e HTTPS_PROXY=$(HTTPS_PROXY) -e NO_PROXY=$(NO_PROXY) + +.PHONY: help +help: + @echo "Make targets:" + @echo " test - run tests" + @echo " test-debug - run tests (vpp debug image)" + @echo " test-leak - run memory leak tests (vpp debug image)" + @echo " build - build test infra" + @echo " build-cov - coverage build of VPP and Docker images" + @echo " build-debug - build test infra (vpp debug image)" + @echo " build-go - just build golang files" + @echo " checkstyle-go - check style of .go source files" + @echo " fixstyle-go - format .go source files" + @echo " cleanup-hst - removes all docker containers and namespaces from last test run" + @echo " list-tests - list all tests" + @echo " install-deps - install software dependencies" + @echo + @echo "'make build' and 'make test' arguments:" + @echo " UBUNTU_VERSION - ubuntu version for docker image" + @echo " FORCE_BUILD=[true|false] - force docker image building" + @echo + @echo "'make test' specific arguments:" + @echo " PERSIST=[true|false] - whether clean up topology and dockers after test" + @echo " VERBOSE=[true|false] - verbose output" + @echo " UNCONFIGURE=[true|false] - unconfigure selected test" + @echo " DEBUG=[true|false] - attach VPP to GDB" + @echo " TEST=[name1,name2...] - specific test(s) to run" + @echo " SKIP=[name1,name2...] - specific test(s) to skip" + @echo " CPUS=[n] - number of cpus to allocate to each non-VPP container (default = 1)" + @echo " VPP_CPUS=[n] - number of cpus to allocate to each VPP container (default = 1)" + @echo " VPPSRC=[path-to-vpp-src] - path to vpp source files (for gdb)" + @echo " PARALLEL=[n] - number of test processes to spawn to run in parallel" + @echo " REPEAT=[n] - repeat tests up to N times or until a failure occurs" + @echo " CPU0=[true|false] - use cpu0" + @echo " DRYRUN=[true|false] - set up containers but don't run tests" + @echo " NO_COLOR=[true|false] - disables colorful Docker and Ginkgo output" + @echo " TIMEOUT=[minutes] - test timeout override (5 minutes by default)" + @echo " GINKGO_TIMEOUT=[Ns/m/h] - Ginkgo timeout override (3h by default)" + +.PHONY: list-tests +list-tests: + @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --seed=2 | head -n -1 | grep 'test.go' | \ + sed 's/^/* /; s/\(Suite\) /\1\//g' + +.PHONY: build-vpp-release +build-vpp-release: + @$(MAKE) -C ../.. build-release + +.PHONY: build-vpp-debug +build-vpp-debug: + @$(MAKE) -C ../.. build + +.PHONY: build-vpp-gcov +build-vpp-gcov: + @$(MAKE) -C ../.. build-gcov + +.build.ok: build + @touch .build.ok + +.build.cov.ok: build-cov + @touch .build.ok + +.build_debug.ok: build-debug + @touch .build.ok + +.PHONY: test +test: FORCE_BUILD=false +test: .deps.ok .build.ok + docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ + -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ + .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \ + --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \ + --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --cpu0=$(CPU0) \ + --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \ + --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \ + ./script/compress.sh $$? + +.PHONY: test-debug +test-debug: FORCE_BUILD=false +test-debug: .deps.ok .build_debug.ok + docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ + -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ + .$(HS_ROOT)/hs_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \ + --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST) --cpus=$(CPUS) \ + --vppsrc=$(VPPSRC) --parallel=$(PARALLEL) --repeat=$(REPEAT) --debug_build=true \ + --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \ + --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \ + ./script/compress.sh $$? + +.PHONY: wipe-lcov +wipe-lcov: + @lcov --zerocounters --directory $(WS_ROOT)/build-root/build-vpp_gcov-native/vpp + +.PHONY: test-cov +test-cov: FORCE_BUILD=false +test-cov: .deps.ok .build.cov.ok wipe-lcov + -docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ + -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ + .$(HS_ROOT)/hs_test.sh --coverage=true --persist=$(PERSIST) --verbose=$(VERBOSE) \ + --unconfigure=$(UNCONFIGURE) --debug=$(DEBUG) --test=$(TEST-HS) --cpus=$(CPUS) \ + --vppsrc=$(VPPSRC) --cpu0=$(CPU0) --dryrun=$(DRYRUN) --skip=$(SKIP) --no_color=$(NO_COLOR) \ + --timeout=$(TIMEOUT) --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); \ + ./script/compress.sh $$? + $(MAKE) -C ../.. test-cov-post-standalone HS_TEST=1 + +.PHONY: test-leak +test-leak: FORCE_BUILD=false +test-leak: .deps.ok .build_debug.ok + docker run $(DOCKER_TTY) --rm $(DOCKER_CAPABILITIES) $(DOCKER_DEVICES) $(DOCKER_PROXY)\ + -e BUILD_NUMBER=$(BUILD_NUMBER) $(DOCKER_VOLUMES) --name ginkgo hs-test/ginkgo \ + .$(HS_ROOT)/hs_test.sh --test=$(TEST) --debug_build=true --leak_check=true --vppsrc=$(VPPSRC) --timeout=$(TIMEOUT) \ + --ginkgo_timeout=$(GINKGO_TIMEOUT) --vpp_cpus=$(VPP_CPUS) --hs_root=$(HS_ROOT); + +# this is executed in a container by hs-test.sh +.PHONY: build-go +build-go: + go build --buildvcs=false ./tools/http_server + +.PHONY: build +build: .deps.ok build-vpp-release + @rm -f .build.ok + bash ./script/build_hst.sh release $(FORCE_BUILD) + @touch .build.ok + +.PHONY: build-cov +build-cov: .deps.ok build-vpp-gcov + @rm -f .build.cov.ok + bash ./script/build_hst.sh gcov $(FORCE_BUILD) + @touch .build.cov.ok + +.PHONY: build-debug +build-debug: .deps.ok build-vpp-debug + @rm -f .build.ok + bash ./script/build_hst.sh debug $(FORCE_BUILD) + @touch .build.ok + +.deps.ok: + @$(MAKE) install-deps + +.PHONY: install-deps +install-deps: + @rm -f .deps.ok + @if [ -d "/usr/local/go" ]; then \ + echo "Go is already installed. You may have to update it manually if version < 1.23.10"; \ + go version; \ + else \ + echo "Installing Go 1.23"; \ + wget -t 2 https://go.dev/dl/go1.23.10.linux-$(ARCH).tar.gz -O /tmp/go1.23.10.linux-$(ARCH).tar.gz && sudo tar -C /usr/local -xzf /tmp/go1.23.10.linux-$(ARCH).tar.gz; \ + sudo ln -s /usr/local/go/bin/go /usr/bin/go ; \ + fi + @sudo -E apt-get update + @sudo -E apt-get install -y apt-transport-https ca-certificates curl software-properties-common \ + bridge-utils gpg + @if [ ! -f /usr/share/keyrings/docker-archive-keyring.gpg ] ; then \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg; \ + echo "deb [arch=$(ARCH) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(UBUNTU_CODENAME) stable" \ + | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ; \ + apt-get update; \ + fi + @sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + @touch .deps.ok + +.PHONY: checkstyle-go +checkstyle-go: + @output=$$(find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/goimports@v0.35.0 -d {} +); \ + status=$$?; \ + if [ $$status -ne 0 ]; then \ + exit $$status; \ + elif [ -z "$$output" ]; then \ + echo "******************************************************************************"; \ + echo "* HST Golang Checkstyle OK."; \ + echo "******************************************************************************"; \ + else \ + echo "$$output"; \ + echo "******************************************************************************"; \ + echo "* HST Golang Checkstyle FAILED. Use 'make fixstyle-go' or fix errors manually."; \ + echo "******************************************************************************"; \ + exit 1; \ + fi + +.PHONY: fixstyle-go +fixstyle-go: + @echo "Modified files:" + @find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/goimports@v0.35.0 -w -l {} + + @go mod tidy + @echo "*******************************************************************" + @echo "Fixstyle done." + @echo "*******************************************************************" + +.PHONY: cleanup-hst +cleanup-hst: + @if [ ! -f ".last_hst_ppid" ]; then \ + echo "'.last_hst_ppid' file does not exist."; \ + exit 1; \ + fi + @echo "****************************" + @echo "Removing docker containers:" + @# "-" ignores errors + @-sudo docker rm $$(sudo docker stop $$(sudo docker ps -a -q --filter "name=$$(cat .last_hst_ppid)") -t 0) + @echo "****************************" + @echo "Removing IP address files:" + @find . -type f -regextype egrep -regex '.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' -exec sudo rm -v {} \; + @find . -type f -name "fd00:0*" -exec sudo rm -v {} \; + @echo "****************************" + @echo "Removing network namespaces:" + @for ns in $$(ip netns list | grep $$(cat .last_hst_ppid) | awk '{print $$1}'); do \ + echo $$ns; \ + sudo ip netns delete $$ns; \ + done + @echo "****************************" + @echo "Done." + @echo "****************************" diff --git a/extras/hs-test/README.rst b/test-c/hs-test/README.rst similarity index 100% rename from extras/hs-test/README.rst rename to test-c/hs-test/README.rst diff --git a/extras/hs-test/cpu_pinning_test.go b/test-c/hs-test/cpu_pinning_test.go similarity index 100% rename from extras/hs-test/cpu_pinning_test.go rename to test-c/hs-test/cpu_pinning_test.go diff --git a/extras/hs-test/docker/Dockerfile.ab b/test-c/hs-test/docker/Dockerfile.ab similarity index 100% rename from extras/hs-test/docker/Dockerfile.ab rename to test-c/hs-test/docker/Dockerfile.ab diff --git a/extras/hs-test/docker/Dockerfile.base b/test-c/hs-test/docker/Dockerfile.base similarity index 100% rename from extras/hs-test/docker/Dockerfile.base rename to test-c/hs-test/docker/Dockerfile.base diff --git a/extras/hs-test/docker/Dockerfile.curl b/test-c/hs-test/docker/Dockerfile.curl similarity index 100% rename from extras/hs-test/docker/Dockerfile.curl rename to test-c/hs-test/docker/Dockerfile.curl diff --git a/extras/hs-test/docker/Dockerfile.envoy b/test-c/hs-test/docker/Dockerfile.envoy similarity index 100% rename from extras/hs-test/docker/Dockerfile.envoy rename to test-c/hs-test/docker/Dockerfile.envoy diff --git a/extras/hs-test/docker/Dockerfile.ginkgo b/test-c/hs-test/docker/Dockerfile.ginkgo similarity index 100% rename from extras/hs-test/docker/Dockerfile.ginkgo rename to test-c/hs-test/docker/Dockerfile.ginkgo diff --git a/extras/hs-test/docker/Dockerfile.h2load b/test-c/hs-test/docker/Dockerfile.h2load similarity index 100% rename from extras/hs-test/docker/Dockerfile.h2load rename to test-c/hs-test/docker/Dockerfile.h2load diff --git a/extras/hs-test/docker/Dockerfile.nginx b/test-c/hs-test/docker/Dockerfile.nginx similarity index 100% rename from extras/hs-test/docker/Dockerfile.nginx rename to test-c/hs-test/docker/Dockerfile.nginx diff --git a/extras/hs-test/docker/Dockerfile.nginx-http3 b/test-c/hs-test/docker/Dockerfile.nginx-http3 similarity index 100% rename from extras/hs-test/docker/Dockerfile.nginx-http3 rename to test-c/hs-test/docker/Dockerfile.nginx-http3 diff --git a/extras/hs-test/docker/Dockerfile.nginx-server b/test-c/hs-test/docker/Dockerfile.nginx-server similarity index 100% rename from extras/hs-test/docker/Dockerfile.nginx-server rename to test-c/hs-test/docker/Dockerfile.nginx-server diff --git a/extras/hs-test/docker/Dockerfile.vpp b/test-c/hs-test/docker/Dockerfile.vpp similarity index 100% rename from extras/hs-test/docker/Dockerfile.vpp rename to test-c/hs-test/docker/Dockerfile.vpp diff --git a/extras/hs-test/docker/Dockerfile.wrk b/test-c/hs-test/docker/Dockerfile.wrk similarity index 100% rename from extras/hs-test/docker/Dockerfile.wrk rename to test-c/hs-test/docker/Dockerfile.wrk diff --git a/extras/hs-test/docker/setup-local-registry.sh b/test-c/hs-test/docker/setup-local-registry.sh similarity index 100% rename from extras/hs-test/docker/setup-local-registry.sh rename to test-c/hs-test/docker/setup-local-registry.sh diff --git a/extras/hs-test/echo_test.go b/test-c/hs-test/echo_test.go similarity index 100% rename from extras/hs-test/echo_test.go rename to test-c/hs-test/echo_test.go diff --git a/extras/hs-test/framework_test.go b/test-c/hs-test/framework_test.go similarity index 91% rename from extras/hs-test/framework_test.go rename to test-c/hs-test/framework_test.go index 67aab3f403b..0117d4d735b 100644 --- a/extras/hs-test/framework_test.go +++ b/test-c/hs-test/framework_test.go @@ -7,11 +7,15 @@ import ( "testing" "time" - . "fd.io/hs-test/infra/common" + . "fd.io/hs-test/infra" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) +var _ = ReportBeforeSuite(func(report Report) { + TestsThatWillRun = report.PreRunStats.SpecsThatWillRun +}) + var _ = ReportAfterSuite("VPP version under test", func(report Report) { for i := range report.SpecReports { specReport := report.SpecReports[i] diff --git a/extras/hs-test/go.mod b/test-c/hs-test/go.mod similarity index 65% rename from extras/hs-test/go.mod rename to test-c/hs-test/go.mod index ec840a95367..9fc6e49a00b 100644 --- a/extras/hs-test/go.mod +++ b/test-c/hs-test/go.mod @@ -17,62 +17,38 @@ require ( go.fd.io/govpp v0.12.0 golang.org/x/net v0.37.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.30.2 - k8s.io/apimachinery v0.30.2 - k8s.io/client-go v0.30.2 ) require ( github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/a8m/envsubst v1.4.2 github.com/containerd/log v0.1.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.6.0 // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/emicklei/go-restful/v3 v3.11.2 // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/errors v0.22.0 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-openapi/validate v0.24.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect github.com/hashicorp/hcl v1.0.1-vault-5 // indirect - github.com/imdario/mergo v0.3.16 // indirect - github.com/joho/godotenv v1.5.1 - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/lunixbochs/struc v0.0.0-20200521075829-a4cb8d33dbbe // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/spdystream v0.2.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect - github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/viper v1.19.0 // indirect github.com/vishvananda/netns v0.0.4 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect @@ -85,22 +61,16 @@ require ( golang.org/x/crypto v0.36.0 // indirect golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/mod v0.23.0 // indirect - golang.org/x/oauth2 v0.18.0 // indirect golang.org/x/sync v0.13.0 // indirect golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.30.0 // indirect - google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.36.5 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gotest.tools/v3 v3.5.1 // indirect + k8s.io/apimachinery v0.30.2 // indirect + k8s.io/client-go v0.30.2 // indirect k8s.io/klog/v2 v2.120.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/extras/hs-test/go.sum b/test-c/hs-test/go.sum similarity index 78% rename from extras/hs-test/go.sum rename to test-c/hs-test/go.sum index 2dda539c6f9..302454c7b1c 100644 --- a/extras/hs-test/go.sum +++ b/test-c/hs-test/go.sum @@ -2,10 +2,6 @@ github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEK github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg= -github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -32,8 +28,6 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/edwarnicke/exechelper v1.0.3 h1:OY2ocGAITTqnEDvZk0dRQSeMIQvyH0SyL/4ncz+5GeQ= github.com/edwarnicke/exechelper v1.0.3/go.mod h1:R65OUPKns4bgeHkCmfSHbmqLBU8aHZxTgLmEyUBUk4U= -github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU= -github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -69,28 +63,14 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= @@ -98,20 +78,17 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= @@ -131,21 +108,10 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= @@ -196,7 +162,6 @@ github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -216,7 +181,6 @@ github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1Y github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.fd.io/govpp v0.12.0 h1:5HnMzsKHSFdxglsFyEhR0g+CzncWiLYXG2NDYgNUrnE= @@ -248,53 +212,36 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/W golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -303,15 +250,12 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= @@ -319,41 +263,24 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= -k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI= k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50= k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/extras/hs-test/h2spec_extras/h2spec_extras.go b/test-c/hs-test/h2spec_extras/h2spec_extras.go similarity index 100% rename from extras/hs-test/h2spec_extras/h2spec_extras.go rename to test-c/hs-test/h2spec_extras/h2spec_extras.go diff --git a/extras/hs-test/hs_test.sh b/test-c/hs-test/hs_test.sh similarity index 92% rename from extras/hs-test/hs_test.sh rename to test-c/hs-test/hs_test.sh index ac6b40760d3..68fb1fd7552 100755 --- a/extras/hs-test/hs_test.sh +++ b/test-c/hs-test/hs_test.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash -source vars - args= focused_test=0 persist_set=0 @@ -16,7 +14,6 @@ tc_names=() skip_names=() dryrun= no_color= -perf= hs_root= for i in "$@" @@ -119,10 +116,6 @@ case "${i}" in ginkgo_args="$ginkgo_args --no-color" fi ;; - --perf=*) - perf="${i#*=}" - args="$args -perf" - ;; --timeout=*) args="$args -timeout ${i#*=}" ;; @@ -132,12 +125,6 @@ case "${i}" in esac done -if [ "$perf" = "true" ]; then - ginkgo_args="$ginkgo_args --label-filter=Perf" -else - ginkgo_args="$ginkgo_args --label-filter=!Perf" -fi - if [ ${#tc_names[@]} -gt 1 ] then focused_test=0 @@ -193,16 +180,13 @@ mkdir -p .go_cache make build-go mkdir -p summary +rm -f summary/* # shellcheck disable=SC2086 -CMD="sudo -E go run github.com/onsi/ginkgo/v2/ginkgo --json-report=summary/report.json $ginkgo_args -- $args" +CMD="go run github.com/onsi/ginkgo/v2/ginkgo --json-report=summary/report.json $ginkgo_args -- $args" echo "$CMD" $CMD exit_status=$? -if [ -e "summary/failed-summary.log" ]; then - rm summary/failed-summary.log -fi - if [ $exit_status != 0 ]; then jq -r '.[0] | .SpecReports[] | select((.State == "failed") or (.State == "timedout") or (.State == "panicked")) | select(.Failure != null) | "TestName: diff --git a/extras/hs-test/hsi_test.go b/test-c/hs-test/hsi_test.go similarity index 100% rename from extras/hs-test/hsi_test.go rename to test-c/hs-test/hsi_test.go diff --git a/extras/hs-test/http1_test.go b/test-c/hs-test/http1_test.go similarity index 100% rename from extras/hs-test/http1_test.go rename to test-c/hs-test/http1_test.go diff --git a/extras/hs-test/http2_test.go b/test-c/hs-test/http2_test.go similarity index 100% rename from extras/hs-test/http2_test.go rename to test-c/hs-test/http2_test.go diff --git a/extras/hs-test/infra/address_allocator.go b/test-c/hs-test/infra/address_allocator.go similarity index 100% rename from extras/hs-test/infra/address_allocator.go rename to test-c/hs-test/infra/address_allocator.go diff --git a/test-c/hs-test/infra/asserts.go b/test-c/hs-test/infra/asserts.go new file mode 100644 index 00000000000..6ca444b2088 --- /dev/null +++ b/test-c/hs-test/infra/asserts.go @@ -0,0 +1,114 @@ +package hst + +import ( + "fmt" + "net/http" + "strconv" + "strings" + "time" + + . "github.com/onsi/gomega" +) + +func (s *HstSuite) AssertNil(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).To(BeNil(), msgAndArgs...) +} + +func (s *HstSuite) AssertNotNil(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).ToNot(BeNil(), msgAndArgs...) +} + +func (s *HstSuite) AssertEqual(expected, actual any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).To(Equal(expected), msgAndArgs...) +} + +func (s *HstSuite) AssertNotEqual(expected, actual any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).ToNot(Equal(expected), msgAndArgs...) +} + +func (s *HstSuite) AssertContains(testString, contains any, msgAndArgs ...any) { + ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).To(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...) +} + +func (s *HstSuite) AssertNotContains(testString, contains any, msgAndArgs ...any) { + ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).ToNot(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...) +} + +func (s *HstSuite) AssertEmpty(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).To(BeEmpty(), msgAndArgs...) +} + +func (s *HstSuite) AssertNotEmpty(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).ToNot(BeEmpty(), msgAndArgs...) +} + +func (s *HstSuite) AssertMatchError(actual, expected error, msgAndArgs ...any) { + ExpectWithOffset(2, actual).To(MatchError(expected), msgAndArgs...) +} + +func (s *HstSuite) AssertGreaterEqual(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically(">=", expected), msgAndArgs...) +} + +func (s *HstSuite) AssertGreaterThan(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically(">", expected), msgAndArgs...) +} + +func (s *HstSuite) AssertLessEqual(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically("<=", expected), msgAndArgs...) +} + +func (s *HstSuite) AssertLessThan(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically("<", expected), msgAndArgs...) +} + +func (s *HstSuite) AssertEqualWithinThreshold(actual, expected, threshold any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically("~", expected, threshold), msgAndArgs...) +} + +func (s *HstSuite) AssertTimeEqualWithinThreshold(actual, expected time.Time, threshold time.Duration, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeTemporally("~", expected, threshold), msgAndArgs...) +} + +func (s *HstSuite) AssertHttpStatus(resp *http.Response, expectedStatus int, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPStatus(expectedStatus), msgAndArgs...) +} + +func (s *HstSuite) AssertHttpHeaderWithValue(resp *http.Response, key string, value any, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue(key, value), msgAndArgs...) +} + +func (s *HstSuite) AssertHttpHeaderNotPresent(resp *http.Response, key string, msgAndArgs ...any) { + ExpectWithOffset(2, resp.Header.Get(key)).To(BeEmpty(), msgAndArgs...) +} + +func (s *HstSuite) AssertHttpContentLength(resp *http.Response, expectedContentLen int64, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue("Content-Length", strconv.FormatInt(expectedContentLen, 10)), msgAndArgs...) +} + +func (s *HstSuite) AssertHttpBody(resp *http.Response, expectedBody string, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPBody(expectedBody), msgAndArgs...) +} + +// Coverage builds take longer to finish -> assert timeout is set to 'TestTimeout - 30 seconds' to let the test finish properly +func (s *HstSuite) AssertChannelClosed(timeout time.Duration, channel chan error) { + if *IsCoverage && timeout > time.Second*30 { + timeout = TestTimeout - time.Second*30 + s.Log("Coverage build, assert timeout is set to %s", timeout.String()) + } + EventuallyWithOffset(2, channel).WithTimeout(timeout).Should(BeClosed()) +} + +// Pass the parsed result struct and the minimum amount of data transferred in MB. +// Won't do anything when testing a coverage build. +func (s *HstSuite) AssertIperfMinTransfer(result IPerfResult, minTransferred int) { + if *IsCoverage { + s.Log("Coverage build; not asserting") + return + } + if result.Start.Details.Protocol == "TCP" { + s.AssertGreaterEqual(result.End.TcpReceived.MBytes, minTransferred) + } else { + s.AssertGreaterEqual(result.End.Udp.MBytes, minTransferred) + } +} diff --git a/extras/hs-test/infra/connect_udp_client.go b/test-c/hs-test/infra/connect_udp_client.go similarity index 100% rename from extras/hs-test/infra/connect_udp_client.go rename to test-c/hs-test/infra/connect_udp_client.go diff --git a/extras/hs-test/infra/container.go b/test-c/hs-test/infra/container.go similarity index 99% rename from extras/hs-test/infra/container.go rename to test-c/hs-test/infra/container.go index 8ea694dace9..e5771924f58 100644 --- a/extras/hs-test/infra/container.go +++ b/test-c/hs-test/infra/container.go @@ -13,7 +13,6 @@ import ( "text/template" "time" - . "fd.io/hs-test/infra/common" "github.com/cilium/cilium/pkg/sysctl" containerTypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" diff --git a/extras/hs-test/infra/cpu.go b/test-c/hs-test/infra/cpu.go similarity index 99% rename from extras/hs-test/infra/cpu.go rename to test-c/hs-test/infra/cpu.go index 589c51d96c7..621011bb5d2 100644 --- a/extras/hs-test/infra/cpu.go +++ b/test-c/hs-test/infra/cpu.go @@ -7,8 +7,6 @@ import ( "os" "os/exec" "strings" - - . "fd.io/hs-test/infra/common" ) var CgroupPath = "/sys/fs/cgroup/" diff --git a/extras/hs-test/infra/netconfig.go b/test-c/hs-test/infra/netconfig.go similarity index 100% rename from extras/hs-test/infra/netconfig.go rename to test-c/hs-test/infra/netconfig.go diff --git a/extras/hs-test/infra/hst_suite.go b/test-c/hs-test/infra/suite_base.go similarity index 91% rename from extras/hs-test/infra/hst_suite.go rename to test-c/hs-test/infra/suite_base.go index d7d9eb89f71..e4bc86c8339 100644 --- a/extras/hs-test/infra/hst_suite.go +++ b/test-c/hs-test/infra/suite_base.go @@ -4,6 +4,8 @@ import ( "bufio" "flag" "fmt" + "io" + "log" "net/http" "net/http/httputil" "os" @@ -14,7 +16,6 @@ import ( "strings" "time" - . "fd.io/hs-test/infra/common" containerTypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" "github.com/edwarnicke/exechelper" @@ -35,9 +36,30 @@ var VppSourceFileDir = flag.String("vppsrc", "", "vpp source file directory") var IsDebugBuild = flag.Bool("debug_build", false, "some paths are different with debug build") var UseCpu0 = flag.Bool("cpu0", false, "use cpu0") var IsLeakCheck = flag.Bool("leak_check", false, "run leak-check tests") +var IsCoverage = flag.Bool("coverage", false, "use coverage run config") +var IsPersistent = flag.Bool("persist", false, "persists topology config") +var IsVerbose = flag.Bool("verbose", false, "verbose test output") +var WhoAmI = flag.String("whoami", "root", "what user ran hs-test") +var ParallelTotal = flag.Lookup("ginkgo.parallel.total") +var IsVppDebug = flag.Bool("debug", false, "attach gdb to vpp") +var DryRun = flag.Bool("dryrun", false, "set up containers but don't run tests") +var Timeout = flag.Int("timeout", 5, "test timeout override (in minutes)") +var PerfTesting = flag.Bool("perf", false, "perf test flag") +var NumaAwareCpuAlloc bool +var TestTimeout time.Duration +var RunningInCi bool +var TestsThatWillRun int + +const ( + LogDir string = "/tmp/hs-test/" + VolumeDir string = "/vol" +) type HstSuite struct { - HstCommon + Ppid string + ProcessIndex string + Logger *log.Logger + LogFile *os.File AllContainers map[string]*Container StartedContainers []*Container NetConfigs []NetConfig @@ -189,25 +211,6 @@ func (s *HstSuite) newDockerClient() { s.Log("docker client created") } -func (s *HstSuite) SetupSuite() { - RegisterFailHandler(func(message string, callerSkip ...int) { - s.HstFail() - Fail(message, callerSkip...) - }) - s.HstCommon.SetupSuite() - s.newDockerClient() - - var err error - s.CpuAllocator, err = CpuAllocator() - s.CpuAllocator.suite = s - if err != nil { - Fail("failed to init cpu allocator: " + fmt.Sprint(err)) - } - s.CpusPerContainer = *NConfiguredCpus - s.CpusPerVppContainer = *NConfiguredVppCpus - s.CoverageRun = *IsCoverage -} - func (s *HstSuite) AllocateCpus(containerName string) []int { var cpuCtx *CpuContext var err error @@ -233,8 +236,49 @@ func (s *HstSuite) AddCpuContext(cpuCtx *CpuContext) { s.CpuContexts = append(s.CpuContexts, cpuCtx) } +func (s *HstSuite) Skip(args string) { + Skip(args) +} + +func (s *HstSuite) CreateLogger() { + suiteName := s.GetCurrentSuiteName() + var err error + s.LogFile, err = os.Create("summary/" + suiteName + ".log") + if err != nil { + Fail("Unable to create log file.") + } + s.Logger = log.New(io.Writer(s.LogFile), "", log.LstdFlags) +} + +func (s *HstSuite) SetupSuite() { + RegisterFailHandler(func(message string, callerSkip ...int) { + s.HstFail() + Fail(message, callerSkip...) + }) + s.CreateLogger() + s.Log("[* SUITE SETUP]") + s.Ppid = fmt.Sprint(os.Getppid()) + // remove last number so we have space to prepend a process index (interfaces have a char limit) + s.Ppid = s.Ppid[:len(s.Ppid)-1] + s.ProcessIndex = fmt.Sprint(GinkgoParallelProcess()) + s.newDockerClient() + + var err error + s.CpuAllocator, err = CpuAllocator() + s.CpuAllocator.suite = s + if err != nil { + Fail("failed to init cpu allocator: " + fmt.Sprint(err)) + } + s.CpusPerContainer = *NConfiguredCpus + s.CpusPerVppContainer = *NConfiguredVppCpus + s.CoverageRun = *IsCoverage +} + func (s *HstSuite) TeardownSuite() { - s.HstCommon.TeardownSuite() + if *IsPersistent || *DryRun { + s.Skip("Skipping suite teardown") + } + s.Log("[* SUITE TEARDOWN]") // allow ports to be reused by removing them from reservedPorts slice reservedPorts = reservedPorts[:len(reservedPorts)-s.numOfNewPorts] if s.Ip4AddrAllocator != nil { @@ -249,8 +293,21 @@ func (s *HstSuite) TeardownSuite() { s.UnconfigureNetworkTopology() } +func (s *HstSuite) SetupTest() { + TestCounterFunc() + s.Log("[* TEST SETUP]") + // doesn't impact MW/solo tests + s.CpuAllocator.lastCpu = (GinkgoParallelProcess() - 1) * 4 + s.StartedContainers = s.StartedContainers[:0] + s.SkipIfUnconfiguring() + s.SetupContainers() +} + func (s *HstSuite) TeardownTest() { - s.HstCommon.TeardownTest() + if *IsPersistent || *DryRun { + s.Skip("Skipping test teardown") + } + s.Log("[* TEST TEARDOWN]") s.SkipIfNotEnoguhCpus = false // reset to defaults s.CpusPerContainer = *NConfiguredCpus @@ -275,15 +332,6 @@ func (s *HstSuite) SkipIfNotCoverage() { } } -func (s *HstSuite) SetupTest() { - s.HstCommon.SetupTest() - // doesn't impact MW/solo tests - s.CpuAllocator.lastCpu = (GinkgoParallelProcess() - 1) * 4 - s.StartedContainers = s.StartedContainers[:0] - s.SkipIfUnconfiguring() - s.SetupContainers() -} - func (s *HstSuite) SetupContainers() { for _, container := range s.AllContainers { if !container.IsOptional { diff --git a/extras/hs-test/infra/suite_cpu_pinning.go b/test-c/hs-test/infra/suite_cpu_pinning.go similarity index 98% rename from extras/hs-test/infra/suite_cpu_pinning.go rename to test-c/hs-test/infra/suite_cpu_pinning.go index a9f3d020838..bd7677d0bde 100644 --- a/extras/hs-test/infra/suite_cpu_pinning.go +++ b/test-c/hs-test/infra/suite_cpu_pinning.go @@ -6,7 +6,6 @@ import ( "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_envoy_proxy.go b/test-c/hs-test/infra/suite_envoy_proxy.go similarity index 99% rename from extras/hs-test/infra/suite_envoy_proxy.go rename to test-c/hs-test/infra/suite_envoy_proxy.go index 1932f18116f..9ad7b769077 100644 --- a/extras/hs-test/infra/suite_envoy_proxy.go +++ b/test-c/hs-test/infra/suite_envoy_proxy.go @@ -12,7 +12,6 @@ import ( "strings" "time" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_hsi.go b/test-c/hs-test/infra/suite_hsi.go similarity index 99% rename from extras/hs-test/infra/suite_hsi.go rename to test-c/hs-test/infra/suite_hsi.go index 05755770478..997cdc2ae73 100644 --- a/extras/hs-test/infra/suite_hsi.go +++ b/test-c/hs-test/infra/suite_hsi.go @@ -7,7 +7,6 @@ import ( "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_http1.go b/test-c/hs-test/infra/suite_http1.go similarity index 99% rename from extras/hs-test/infra/suite_http1.go rename to test-c/hs-test/infra/suite_http1.go index ead9c89b401..0190d9f36dd 100644 --- a/extras/hs-test/infra/suite_http1.go +++ b/test-c/hs-test/infra/suite_http1.go @@ -5,7 +5,6 @@ import ( "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_http2.go b/test-c/hs-test/infra/suite_http2.go similarity index 99% rename from extras/hs-test/infra/suite_http2.go rename to test-c/hs-test/infra/suite_http2.go index 770f6313d08..67410d64ad2 100644 --- a/extras/hs-test/infra/suite_http2.go +++ b/test-c/hs-test/infra/suite_http2.go @@ -13,7 +13,6 @@ import ( "time" "fd.io/hs-test/h2spec_extras" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" "github.com/summerwind/h2spec" "github.com/summerwind/h2spec/config" @@ -457,16 +456,12 @@ var _ = Describe("H2SpecSuite", Ordered, ContinueOnFailure, func() { switch sp.tg { case GenericTestGroup: tg = generic.Spec() - break case HpackTestGroup: tg = hpack.Spec() - break case Http2TestGroup: tg = http2.Spec() - break case ExtrasTestGroup: tg = h2spec_extras.Spec() - break } tg.Test(conf) @@ -498,11 +493,9 @@ func h2specdVerifyResult(s Http2Suite, nExecuted int) bool { defer resp.Body.Close() report, err := io.ReadAll(resp.Body) s.AssertContains(string(report), "0 failed") + s.AssertNil(err) expected := fmt.Sprintf("
%d tests, %d passed", nExecuted, nExecuted) - if !strings.Contains(string(report), expected) { - return false - } - return true + return strings.Contains(string(report), expected) } var _ = Describe("H2SpecClientSuite", Ordered, Serial, func() { diff --git a/extras/hs-test/infra/suite_iperf_linux.go b/test-c/hs-test/infra/suite_iperf_linux.go similarity index 98% rename from extras/hs-test/infra/suite_iperf_linux.go rename to test-c/hs-test/infra/suite_iperf_linux.go index 0e31c9c17af..e061eb28261 100644 --- a/extras/hs-test/infra/suite_iperf_linux.go +++ b/test-c/hs-test/infra/suite_iperf_linux.go @@ -5,7 +5,6 @@ import ( "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_ldp.go b/test-c/hs-test/infra/suite_ldp.go similarity index 99% rename from extras/hs-test/infra/suite_ldp.go rename to test-c/hs-test/infra/suite_ldp.go index 7009631beca..ea73efe1bd6 100644 --- a/extras/hs-test/infra/suite_ldp.go +++ b/test-c/hs-test/infra/suite_ldp.go @@ -7,7 +7,6 @@ import ( "strings" "time" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_nginx_proxy.go b/test-c/hs-test/infra/suite_nginx_proxy.go similarity index 99% rename from extras/hs-test/infra/suite_nginx_proxy.go rename to test-c/hs-test/infra/suite_nginx_proxy.go index 90306bdea36..2ef84e37153 100644 --- a/extras/hs-test/infra/suite_nginx_proxy.go +++ b/test-c/hs-test/infra/suite_nginx_proxy.go @@ -6,7 +6,6 @@ import ( "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_no_topo.go b/test-c/hs-test/infra/suite_no_topo.go similarity index 99% rename from extras/hs-test/infra/suite_no_topo.go rename to test-c/hs-test/infra/suite_no_topo.go index 5a411adc294..787c857cea6 100644 --- a/extras/hs-test/infra/suite_no_topo.go +++ b/test-c/hs-test/infra/suite_no_topo.go @@ -6,7 +6,6 @@ import ( "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_no_topo6.go b/test-c/hs-test/infra/suite_no_topo6.go similarity index 99% rename from extras/hs-test/infra/suite_no_topo6.go rename to test-c/hs-test/infra/suite_no_topo6.go index 0997e8a1720..499e970d04b 100644 --- a/extras/hs-test/infra/suite_no_topo6.go +++ b/test-c/hs-test/infra/suite_no_topo6.go @@ -6,7 +6,6 @@ import ( "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_veth.go b/test-c/hs-test/infra/suite_veth.go similarity index 99% rename from extras/hs-test/infra/suite_veth.go rename to test-c/hs-test/infra/suite_veth.go index 37907f1fcb2..a3db5cd073c 100644 --- a/extras/hs-test/infra/suite_veth.go +++ b/test-c/hs-test/infra/suite_veth.go @@ -7,7 +7,6 @@ import ( "strings" "time" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_veth6.go b/test-c/hs-test/infra/suite_veth6.go similarity index 99% rename from extras/hs-test/infra/suite_veth6.go rename to test-c/hs-test/infra/suite_veth6.go index a57a7526da8..f3e7fda4dac 100644 --- a/extras/hs-test/infra/suite_veth6.go +++ b/test-c/hs-test/infra/suite_veth6.go @@ -7,7 +7,6 @@ import ( "strings" "time" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/infra/suite_vpp_proxy.go b/test-c/hs-test/infra/suite_vpp_proxy.go similarity index 99% rename from extras/hs-test/infra/suite_vpp_proxy.go rename to test-c/hs-test/infra/suite_vpp_proxy.go index 7b108b966f3..0c7c15119ae 100644 --- a/extras/hs-test/infra/suite_vpp_proxy.go +++ b/test-c/hs-test/infra/suite_vpp_proxy.go @@ -17,7 +17,6 @@ import ( "time" "fd.io/hs-test/h2spec_extras" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" "github.com/summerwind/h2spec/config" ) diff --git a/extras/hs-test/infra/suite_vpp_udp_proxy.go b/test-c/hs-test/infra/suite_vpp_udp_proxy.go similarity index 99% rename from extras/hs-test/infra/suite_vpp_udp_proxy.go rename to test-c/hs-test/infra/suite_vpp_udp_proxy.go index 912ab64eaa3..43b89f134b1 100644 --- a/extras/hs-test/infra/suite_vpp_udp_proxy.go +++ b/test-c/hs-test/infra/suite_vpp_udp_proxy.go @@ -13,7 +13,6 @@ import ( "fd.io/hs-test/h2spec_extras" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" "github.com/summerwind/h2spec/config" ) diff --git a/extras/hs-test/infra/topo.go b/test-c/hs-test/infra/topo.go similarity index 100% rename from extras/hs-test/infra/topo.go rename to test-c/hs-test/infra/topo.go diff --git a/extras/hs-test/infra/utils.go b/test-c/hs-test/infra/utils.go similarity index 68% rename from extras/hs-test/infra/utils.go rename to test-c/hs-test/infra/utils.go index 6812ae7235c..3cf152ef572 100644 --- a/extras/hs-test/infra/utils.go +++ b/test-c/hs-test/infra/utils.go @@ -2,6 +2,7 @@ package hst import ( "crypto/tls" + "encoding/json" "errors" "fmt" "io" @@ -10,12 +11,15 @@ import ( "net/http/httputil" "os" "os/exec" + "path/filepath" "regexp" + "runtime" "strconv" "strings" "time" "github.com/edwarnicke/exechelper" + . "github.com/onsi/ginkgo/v2" ) const networkTopologyDir string = "topo-network/" @@ -382,3 +386,159 @@ func (s *HstSuite) ParseEchoClientTransfer(stats string) (uint64, error) { } return uVal, nil } + +// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter +// to keep console tidy +func (s *HstSuite) Log(log any, arg ...any) { + var logStr string + if len(arg) == 0 { + logStr = fmt.Sprint(log) + } else { + logStr = fmt.Sprintf(fmt.Sprint(log), arg...) + } + logs := strings.Split(logStr, "\n") + + for _, line := range logs { + s.Logger.Println(line) + } + if *IsVerbose { + GinkgoWriter.Println(logStr) + } +} + +func GetTestFilename() string { + _, filename, _, _ := runtime.Caller(2) + return filepath.Base(filename) +} + +var testCounter uint16 +var startTime time.Time = time.Now() + +func TestCounterFunc() { + if ParallelTotal.Value.String() != "1" { + return + } + testCounter++ + fmt.Printf("Test counter: %d/%d (%.2f%%)\n"+ + "Time elapsed: %.2fs\n", + testCounter, TestsThatWillRun, float64(testCounter)/float64(TestsThatWillRun)*100, time.Since(startTime).Seconds()) +} + +type IPerfResult struct { + Start struct { + Timestamp struct { + Time string `json:"time"` + } `json:"timestamp"` + Connected []struct { + Socket int `json:"socket"` + LocalHost string `json:"local_host"` + LocalPort int `json:"local_port"` + RemoteHost string `json:"remote_host"` + RemotePort int `json:"remote_port"` + } `json:"connected"` + Version string `json:"version"` + Details struct { + Protocol string `json:"protocol"` + } `json:"test_start"` + } `json:"start"` + End struct { + TcpSent *struct { + MbitsPerSecond float64 `json:"bits_per_second"` + MBytes float64 `json:"bytes"` + } `json:"sum_sent,omitempty"` + TcpReceived *struct { + MbitsPerSecond float64 `json:"bits_per_second"` + MBytes float64 `json:"bytes"` + } `json:"sum_received,omitempty"` + Udp *struct { + MbitsPerSecond float64 `json:"bits_per_second"` + JitterMs float64 `json:"jitter_ms,omitempty"` + LostPackets int `json:"lost_packets,omitempty"` + Packets int `json:"packets,omitempty"` + LostPercent float64 `json:"lost_percent,omitempty"` + MBytes float64 `json:"bytes"` + } `json:"sum,omitempty"` + } `json:"end"` +} + +func (s *HstSuite) ParseJsonIperfOutput(jsonResult []byte) IPerfResult { + var result IPerfResult + + // VCL/LDP debugging can pollute output so find the first occurrence of a curly brace to locate the start of JSON data + jsonStart := -1 + jsonEnd := len(jsonResult) + braceCount := 0 + for i := 0; i < len(jsonResult); i++ { + if jsonResult[i] == '{' { + if jsonStart == -1 { + jsonStart = i + } + braceCount++ + } else if jsonResult[i] == '}' { + braceCount-- + if braceCount == 0 { + jsonEnd = i + 1 + break + } + } + } + jsonResult = jsonResult[jsonStart:jsonEnd] + + // remove iperf warning line if present + if strings.Contains(string(jsonResult), "warning") { + index := strings.Index(string(jsonResult), "\n") + jsonResult = jsonResult[index+1:] + } + + err := json.Unmarshal(jsonResult, &result) + s.AssertNil(err) + + if result.Start.Details.Protocol == "TCP" { + result.End.TcpSent.MbitsPerSecond = result.End.TcpSent.MbitsPerSecond / 1000000 + result.End.TcpSent.MBytes = result.End.TcpSent.MBytes / 1000000 + result.End.TcpReceived.MbitsPerSecond = result.End.TcpReceived.MbitsPerSecond / 1000000 + result.End.TcpReceived.MBytes = result.End.TcpReceived.MBytes / 1000000 + } else { + result.End.Udp.MBytes = result.End.Udp.MBytes / 1000000 + result.End.Udp.MbitsPerSecond = result.End.Udp.MbitsPerSecond / 1000000 + } + + return result +} + +func (s *HstSuite) LogJsonIperfOutput(result IPerfResult) { + s.Log("\n*******************************************\n"+ + "%s\n"+ + "[%s] %s:%d connected to %s:%d\n"+ + "Started: %s\n", + result.Start.Version, + result.Start.Details.Protocol, + result.Start.Connected[0].LocalHost, result.Start.Connected[0].LocalPort, + result.Start.Connected[0].RemoteHost, result.Start.Connected[0].RemotePort, + result.Start.Timestamp.Time) + + if result.Start.Details.Protocol == "TCP" { + s.Log("Transfer (sent): %.2f MBytes\n"+ + "Bitrate (sent): %.2f Mbits/sec\n"+ + "Transfer (received): %.2f MBytes\n"+ + "Bitrate (received): %.2f Mbits/sec", + result.End.TcpSent.MBytes, + result.End.TcpSent.MbitsPerSecond, + result.End.TcpReceived.MBytes, + result.End.TcpReceived.MbitsPerSecond) + } else { + s.Log("Transfer: %.2f MBytes\n"+ + "Bitrate: %.2f Mbits/sec\n"+ + "Jitter: %.3f ms\n"+ + "Packets: %d\n"+ + "Packets lost: %d\n"+ + "Percent lost: %.2f%%", + result.End.Udp.MBytes, + result.End.Udp.MbitsPerSecond, + result.End.Udp.JitterMs, + result.End.Udp.Packets, + result.End.Udp.LostPackets, + result.End.Udp.LostPercent) + } + s.Log("*******************************************\n") +} diff --git a/extras/hs-test/infra/vppinstance.go b/test-c/hs-test/infra/vppinstance.go similarity index 99% rename from extras/hs-test/infra/vppinstance.go rename to test-c/hs-test/infra/vppinstance.go index cfb39592f9f..43eaaf3dc78 100644 --- a/extras/hs-test/infra/vppinstance.go +++ b/test-c/hs-test/infra/vppinstance.go @@ -16,7 +16,6 @@ import ( "syscall" "time" - . "fd.io/hs-test/infra/common" "go.fd.io/govpp/binapi/ethernet_types" "github.com/edwarnicke/exechelper" diff --git a/extras/hs-test/iperf_linux_test.go b/test-c/hs-test/iperf_linux_test.go similarity index 100% rename from extras/hs-test/iperf_linux_test.go rename to test-c/hs-test/iperf_linux_test.go diff --git a/extras/hs-test/ldp_test.go b/test-c/hs-test/ldp_test.go similarity index 99% rename from extras/hs-test/ldp_test.go rename to test-c/hs-test/ldp_test.go index b0c6276236f..94abafc9fb1 100644 --- a/extras/hs-test/ldp_test.go +++ b/test-c/hs-test/ldp_test.go @@ -6,7 +6,6 @@ import ( "time" . "fd.io/hs-test/infra" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) diff --git a/extras/hs-test/mem_leak_test.go b/test-c/hs-test/mem_leak_test.go similarity index 100% rename from extras/hs-test/mem_leak_test.go rename to test-c/hs-test/mem_leak_test.go diff --git a/extras/hs-test/nginx_test.go b/test-c/hs-test/nginx_test.go similarity index 100% rename from extras/hs-test/nginx_test.go rename to test-c/hs-test/nginx_test.go diff --git a/extras/hs-test/nsim_test.go b/test-c/hs-test/nsim_test.go similarity index 100% rename from extras/hs-test/nsim_test.go rename to test-c/hs-test/nsim_test.go diff --git a/extras/hs-test/proxy_test.go b/test-c/hs-test/proxy_test.go similarity index 100% rename from extras/hs-test/proxy_test.go rename to test-c/hs-test/proxy_test.go diff --git a/extras/hs-test/raw_session_test.go b/test-c/hs-test/raw_session_test.go similarity index 100% rename from extras/hs-test/raw_session_test.go rename to test-c/hs-test/raw_session_test.go diff --git a/extras/hs-test/resources/cert/localhost.crt b/test-c/hs-test/resources/cert/localhost.crt similarity index 100% rename from extras/hs-test/resources/cert/localhost.crt rename to test-c/hs-test/resources/cert/localhost.crt diff --git a/extras/hs-test/resources/cert/localhost.key b/test-c/hs-test/resources/cert/localhost.key similarity index 100% rename from extras/hs-test/resources/cert/localhost.key rename to test-c/hs-test/resources/cert/localhost.key diff --git a/extras/hs-test/resources/curl/write_out_download b/test-c/hs-test/resources/curl/write_out_download similarity index 100% rename from extras/hs-test/resources/curl/write_out_download rename to test-c/hs-test/resources/curl/write_out_download diff --git a/extras/hs-test/resources/curl/write_out_download_connect b/test-c/hs-test/resources/curl/write_out_download_connect similarity index 100% rename from extras/hs-test/resources/curl/write_out_download_connect rename to test-c/hs-test/resources/curl/write_out_download_connect diff --git a/extras/hs-test/resources/curl/write_out_upload b/test-c/hs-test/resources/curl/write_out_upload similarity index 100% rename from extras/hs-test/resources/curl/write_out_upload rename to test-c/hs-test/resources/curl/write_out_upload diff --git a/extras/hs-test/resources/curl/write_out_upload_connect b/test-c/hs-test/resources/curl/write_out_upload_connect similarity index 100% rename from extras/hs-test/resources/curl/write_out_upload_connect rename to test-c/hs-test/resources/curl/write_out_upload_connect diff --git a/extras/hs-test/resources/envoy/envoy.log b/test-c/hs-test/resources/envoy/envoy.log similarity index 100% rename from extras/hs-test/resources/envoy/envoy.log rename to test-c/hs-test/resources/envoy/envoy.log diff --git a/extras/hs-test/resources/envoy/proxy.yaml b/test-c/hs-test/resources/envoy/proxy.yaml similarity index 100% rename from extras/hs-test/resources/envoy/proxy.yaml rename to test-c/hs-test/resources/envoy/proxy.yaml diff --git a/extras/hs-test/resources/envoy/vcl.conf b/test-c/hs-test/resources/envoy/vcl.conf similarity index 100% rename from extras/hs-test/resources/envoy/vcl.conf rename to test-c/hs-test/resources/envoy/vcl.conf diff --git a/extras/hs-test/resources/nginx/html/index.html b/test-c/hs-test/resources/nginx/html/index.html similarity index 100% rename from extras/hs-test/resources/nginx/html/index.html rename to test-c/hs-test/resources/nginx/html/index.html diff --git a/extras/hs-test/resources/nginx/nginx.conf b/test-c/hs-test/resources/nginx/nginx.conf similarity index 100% rename from extras/hs-test/resources/nginx/nginx.conf rename to test-c/hs-test/resources/nginx/nginx.conf diff --git a/extras/hs-test/resources/nginx/nginx_http3.conf b/test-c/hs-test/resources/nginx/nginx_http3.conf similarity index 100% rename from extras/hs-test/resources/nginx/nginx_http3.conf rename to test-c/hs-test/resources/nginx/nginx_http3.conf diff --git a/extras/hs-test/resources/nginx/nginx_proxy_mirroring.conf b/test-c/hs-test/resources/nginx/nginx_proxy_mirroring.conf similarity index 100% rename from extras/hs-test/resources/nginx/nginx_proxy_mirroring.conf rename to test-c/hs-test/resources/nginx/nginx_proxy_mirroring.conf diff --git a/extras/hs-test/resources/nginx/nginx_server.conf b/test-c/hs-test/resources/nginx/nginx_server.conf similarity index 100% rename from extras/hs-test/resources/nginx/nginx_server.conf rename to test-c/hs-test/resources/nginx/nginx_server.conf diff --git a/extras/hs-test/resources/nginx/nginx_server_mirroring.conf b/test-c/hs-test/resources/nginx/nginx_server_mirroring.conf similarity index 100% rename from extras/hs-test/resources/nginx/nginx_server_mirroring.conf rename to test-c/hs-test/resources/nginx/nginx_server_mirroring.conf diff --git a/extras/hs-test/resources/nginx/vcl.conf b/test-c/hs-test/resources/nginx/vcl.conf similarity index 100% rename from extras/hs-test/resources/nginx/vcl.conf rename to test-c/hs-test/resources/nginx/vcl.conf diff --git a/extras/hs-test/script/build-images.sh b/test-c/hs-test/script/build-images.sh similarity index 100% rename from extras/hs-test/script/build-images.sh rename to test-c/hs-test/script/build-images.sh diff --git a/extras/hs-test/script/build_curl.sh b/test-c/hs-test/script/build_curl.sh similarity index 100% rename from extras/hs-test/script/build_curl.sh rename to test-c/hs-test/script/build_curl.sh diff --git a/extras/hs-test/script/build_hst.sh b/test-c/hs-test/script/build_hst.sh similarity index 100% rename from extras/hs-test/script/build_hst.sh rename to test-c/hs-test/script/build_hst.sh diff --git a/extras/hs-test/script/compress.sh b/test-c/hs-test/script/compress.sh similarity index 100% rename from extras/hs-test/script/compress.sh rename to test-c/hs-test/script/compress.sh diff --git a/extras/hs-test/script/nginx_ldp.sh b/test-c/hs-test/script/nginx_ldp.sh similarity index 100% rename from extras/hs-test/script/nginx_ldp.sh rename to test-c/hs-test/script/nginx_ldp.sh diff --git a/extras/hs-test/script/nginx_server_entrypoint.sh b/test-c/hs-test/script/nginx_server_entrypoint.sh similarity index 100% rename from extras/hs-test/script/nginx_server_entrypoint.sh rename to test-c/hs-test/script/nginx_server_entrypoint.sh diff --git a/extras/hs-test/tls_test.go b/test-c/hs-test/tls_test.go similarity index 100% rename from extras/hs-test/tls_test.go rename to test-c/hs-test/tls_test.go diff --git a/extras/hs-test/tools/http_server/http_server.go b/test-c/hs-test/tools/http_server/http_server.go similarity index 100% rename from extras/hs-test/tools/http_server/http_server.go rename to test-c/hs-test/tools/http_server/http_server.go diff --git a/extras/hs-test/topo-containers/2containers.yaml b/test-c/hs-test/topo-containers/2containers.yaml similarity index 100% rename from extras/hs-test/topo-containers/2containers.yaml rename to test-c/hs-test/topo-containers/2containers.yaml diff --git a/extras/hs-test/topo-containers/2peerVeth.yaml b/test-c/hs-test/topo-containers/2peerVeth.yaml similarity index 100% rename from extras/hs-test/topo-containers/2peerVeth.yaml rename to test-c/hs-test/topo-containers/2peerVeth.yaml diff --git a/extras/hs-test/topo-containers/envoyProxy.yaml b/test-c/hs-test/topo-containers/envoyProxy.yaml similarity index 100% rename from extras/hs-test/topo-containers/envoyProxy.yaml rename to test-c/hs-test/topo-containers/envoyProxy.yaml diff --git a/extras/hs-test/topo-containers/nginxProxy.yaml b/test-c/hs-test/topo-containers/nginxProxy.yaml similarity index 100% rename from extras/hs-test/topo-containers/nginxProxy.yaml rename to test-c/hs-test/topo-containers/nginxProxy.yaml diff --git a/extras/hs-test/topo-containers/single.yaml b/test-c/hs-test/topo-containers/single.yaml similarity index 100% rename from extras/hs-test/topo-containers/single.yaml rename to test-c/hs-test/topo-containers/single.yaml diff --git a/extras/hs-test/topo-containers/singleCpuPinning.yaml b/test-c/hs-test/topo-containers/singleCpuPinning.yaml similarity index 100% rename from extras/hs-test/topo-containers/singleCpuPinning.yaml rename to test-c/hs-test/topo-containers/singleCpuPinning.yaml diff --git a/extras/hs-test/topo-containers/vppProxy.yaml b/test-c/hs-test/topo-containers/vppProxy.yaml similarity index 100% rename from extras/hs-test/topo-containers/vppProxy.yaml rename to test-c/hs-test/topo-containers/vppProxy.yaml diff --git a/extras/hs-test/topo-network/2peerVeth.yaml b/test-c/hs-test/topo-network/2peerVeth.yaml similarity index 100% rename from extras/hs-test/topo-network/2peerVeth.yaml rename to test-c/hs-test/topo-network/2peerVeth.yaml diff --git a/extras/hs-test/topo-network/2peerVeth6.yaml b/test-c/hs-test/topo-network/2peerVeth6.yaml similarity index 100% rename from extras/hs-test/topo-network/2peerVeth6.yaml rename to test-c/hs-test/topo-network/2peerVeth6.yaml diff --git a/extras/hs-test/topo-network/2taps.yaml b/test-c/hs-test/topo-network/2taps.yaml similarity index 100% rename from extras/hs-test/topo-network/2taps.yaml rename to test-c/hs-test/topo-network/2taps.yaml diff --git a/extras/hs-test/topo-network/ns.yaml b/test-c/hs-test/topo-network/ns.yaml similarity index 100% rename from extras/hs-test/topo-network/ns.yaml rename to test-c/hs-test/topo-network/ns.yaml diff --git a/extras/hs-test/topo-network/tap.yaml b/test-c/hs-test/topo-network/tap.yaml similarity index 100% rename from extras/hs-test/topo-network/tap.yaml rename to test-c/hs-test/topo-network/tap.yaml diff --git a/extras/hs-test/topo-network/tap6.yaml b/test-c/hs-test/topo-network/tap6.yaml similarity index 100% rename from extras/hs-test/topo-network/tap6.yaml rename to test-c/hs-test/topo-network/tap6.yaml diff --git a/extras/hs-test/unittests_test.go b/test-c/hs-test/unittests_test.go similarity index 100% rename from extras/hs-test/unittests_test.go rename to test-c/hs-test/unittests_test.go diff --git a/extras/hs-test/vcl_test.go b/test-c/hs-test/vcl_test.go similarity index 100% rename from extras/hs-test/vcl_test.go rename to test-c/hs-test/vcl_test.go diff --git a/test-c/kube-test/Makefile b/test-c/kube-test/Makefile new file mode 100644 index 00000000000..4ab065e1144 --- /dev/null +++ b/test-c/kube-test/Makefile @@ -0,0 +1,220 @@ +ifeq ($(VERBOSE),) +VERBOSE=false +endif + +ifeq ($(PERSIST),) +PERSIST=false +endif + +ifeq ($(TEST),) +TEST=all +endif + +ifeq ($(REPEAT),) +REPEAT=0 +endif + +ifeq ($(UBUNTU_CODENAME),) +UBUNTU_CODENAME=$(shell grep '^UBUNTU_CODENAME=' /etc/os-release | cut -f2- -d=) +endif + +ifeq ($(ARCH),) +ARCH=$(shell dpkg --print-architecture) +endif + +ifeq ($(NO_COLOR),) +VERBOSE=false +endif + +ifeq ($(TIMEOUT),) +TIMEOUT=30 +endif + +ifeq ($(GINKGO_TIMEOUT),) +GINKGO_TIMEOUT=3h +endif + +FORCE_BUILD?=true + +.PHONY: help +help: + @echo "Make targets:" + @echo " test - run kube-test (requires a running cluster)" + @echo " build - build test infra" + @echo " build-debug - build test infra (vpp debug image)" + @echo " cluster-help - print info about KinD cluster setup (perf testing)" + @echo " master-cluster - setup KinD cluster for performance testing (master CalicoVPP + VPP)" + @echo " rebuild-master-cluster - rebuild VPP and update related pods without shutting down the cluster" + @echo " release-cluster - setup KinD cluster for performance testing (latest CalicoVPP release)" + @echo " checkstyle-go - check style of .go source files" + @echo " fixstyle-go - format .go source files" + @echo " cleanup-kube - removes all kubernetes pods and namespaces from last test run" + @echo " list-tests - list all tests" + @echo " install-deps - install software dependencies" + @echo " install-kube-deps - install software dependencies for kind cluster" + @echo + @echo "'make build' and 'make test' arguments:" + @echo " UBUNTU_VERSION - ubuntu version for docker image" + @echo " FORCE_BUILD=[true|false] - force docker image building" + @echo + @echo "'make test' specific arguments:" + @echo " PERSIST=[true|false] - whether clean up topology and dockers after test" + @echo " VERBOSE=[true|false] - verbose output" + @echo " TEST=[name1,name2...] - specific test(s) to run" + @echo " SKIP=[name1,name2...] - specific test(s) to skip" + @echo " REPEAT=[n] - repeat tests up to N times or until a failure occurs" + @echo " DRYRUN=[true|false] - set up containers but don't run tests" + @echo " NO_COLOR=[true|false] - disables colorful Docker and Ginkgo output" + @echo " TIMEOUT=[minutes] - test timeout override (30 minutes by default)" + @echo " GINKGO_TIMEOUT=[Ns/m/h] - Ginkgo timeout override (3h by default)" + +.PHONY: list-tests +list-tests: + @go run github.com/onsi/ginkgo/v2/ginkgo --dry-run -v --no-color --seed=2 | head -n -1 | grep 'test.go' | \ + sed 's/^/* /; s/\(Suite\) /\1\//g' + +.PHONY: build-vpp-release +build-vpp-release: + @$(MAKE) -C ../.. build-release + +.PHONY: build-vpp-debug +build-vpp-debug: + @$(MAKE) -C ../.. build + +.build.ok: build + @touch .build.ok + +.build_debug.ok: build-debug + @touch .build.ok + +.PHONY: test +test: FORCE_BUILD=false +test: .deps.ok .build.ok + @bash ./kube_test.sh --persist=$(PERSIST) --verbose=$(VERBOSE) \ + --test=$(TEST) --repeat=$(REPEAT) --skip=$(SKIP) \ + --no_color=$(NO_COLOR) --timeout=$(TIMEOUT) \ + --ginkgo_timeout=$(GINKGO_TIMEOUT); \ + ./script/compress.sh $$? + +.PHONY: cluster-help +cluster-help: + @bash ./script/setup-cluster.sh help + +.PHONY: release-cluster +release-cluster: .kube_deps.ok + @bash ./script/setup-cluster.sh release-cluster + +.PHONY: master-cluster +master-cluster: .kube_deps.ok + @bash ./script/setup-cluster.sh master-cluster + +.PHONY: rebuild-master-cluster +rebuild-master-cluster: .kube_deps.ok + @bash ./script/setup-cluster.sh rebuild-master-cluster + +.PHONY: build +build: .deps.ok build-vpp-release + @rm -f .build.ok + bash ./script/build_kube.sh release $(FORCE_BUILD) + @touch .build.ok + +.PHONY: build-debug +build-debug: .deps.ok build-vpp-debug + @rm -f .build.ok + bash ./script/build_kube.sh debug $(FORCE_BUILD) + @touch .build.ok + +.deps.ok: + @$(MAKE) install-deps + +.kube_deps.ok: + @$(MAKE) install-kube-deps + +.PHONY: install-kube-deps +install-kube-deps: .deps.ok + -@if ! command -v kube >/dev/null 2>&1; then \ + echo "Installing KinD"; \ + go install sigs.k8s.io/kind@v0.29.0; \ + echo "Creating symlink from '$(HOME)/go/bin/kind' to '/usr/bin/kind'"; \ + sudo ln -s $(HOME)/go/bin/kind /usr/bin/kind; \ + else \ + echo "KinD is already installed. Skipping."; \ + fi + @if ! command -v kubectl >/dev/null 2>&1; then \ + echo "kubectl not found. Installing kubectl..."; \ + sudo -E apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg; \ + curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \ + sudo -E chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg; \ + echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list; \ + sudo -E chmod 644 /etc/apt/sources.list.d/kubernetes.list; \ + sudo apt-get update && sudo apt-get install -y kubectl; \ + else \ + echo "kubectl is already installed. Skipping."; \ + fi + @touch .kube_deps.ok + +.PHONY: install-deps +install-deps: + @rm -f .deps.ok + @if [ -d "/usr/local/go" ]; then \ + echo "Go is already installed. You may have to update it manually if version < 1.23.10"; \ + go version; \ + else \ + echo "Installing Go 1.23"; \ + wget -t 2 https://go.dev/dl/go1.23.10.linux-$(ARCH).tar.gz -O /tmp/go1.23.10.linux-$(ARCH).tar.gz && sudo tar -C /usr/local -xzf /tmp/go1.23.10.linux-$(ARCH).tar.gz; \ + sudo ln -s /usr/local/go/bin/go /usr/bin/go ; \ + fi + @sudo -E apt-get update + @sudo -E apt-get install -y apt-transport-https ca-certificates curl software-properties-common \ + bridge-utils gpg + @if [ ! -f /usr/share/keyrings/docker-archive-keyring.gpg ] ; then \ + curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg; \ + echo "deb [arch=$(ARCH) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(UBUNTU_CODENAME) stable" \ + | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ; \ + apt-get update; \ + fi + @sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + @touch .deps.ok + +.PHONY: checkstyle-go +checkstyle-go: + @output=$$(find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/goimports@v0.35.0 -d {} +); \ + status=$$?; \ + if [ $$status -ne 0 ]; then \ + exit $$status; \ + elif [ -z "$$output" ]; then \ + echo "******************************************************************************"; \ + echo "* Kube-Test Golang Checkstyle OK."; \ + echo "******************************************************************************"; \ + else \ + echo "$$output"; \ + echo "******************************************************************************"; \ + echo "* Kube-Test Golang Checkstyle FAILED. Use 'make fixstyle-go' or fix errors manually."; \ + echo "******************************************************************************"; \ + exit 1; \ + fi + +.PHONY: fixstyle-go +fixstyle-go: + @echo "Modified files:" + @find . -type f -name '*.go' -not -path './.go_cache/*' -exec go run golang.org/x/tools/cmd/goimports@v0.35.0 -w -l {} + + @go mod tidy + @echo "*******************************************************************" + @echo "Fixstyle done." + @echo "*******************************************************************" + +.PHONY: cleanup-kube +cleanup-kube: + @if [ ! -f ".last_ppid" ]; then \ + echo "'.last_ppid' file does not exist."; \ + exit 1; \ + fi + @echo "****************************" + @echo "Removing kubernetes pods:" + @kubectl delete pods --all --grace-period=0 -n kube-test$$(cat .last_ppid) + @echo "****************************" + @echo "Removing kubernetes namespace:" + @kubectl delete namespace kube-test$$(cat .last_ppid) + @echo "****************************" + @echo "Done." + @echo "****************************" diff --git a/test-c/kube-test/docker/Dockerfile.ab b/test-c/kube-test/docker/Dockerfile.ab new file mode 100644 index 00000000000..d61e1255033 --- /dev/null +++ b/test-c/kube-test/docker/Dockerfile.ab @@ -0,0 +1,7 @@ +# Apache Bench container that uses the base image +ARG UBUNTU_VERSION=22.04 +FROM localhost:5001/vpp-test-base:latest + +# apache2-utils is now installed in the base image + +ENTRYPOINT ["ab"] diff --git a/test-c/kube-test/docker/Dockerfile.base b/test-c/kube-test/docker/Dockerfile.base new file mode 100644 index 00000000000..9130da0d907 --- /dev/null +++ b/test-c/kube-test/docker/Dockerfile.base @@ -0,0 +1,60 @@ +ARG UBUNTU_VERSION=22.04 +FROM ubuntu:${UBUNTU_VERSION} AS base + +# Set environment variables +ENV DEBIAN_FRONTEND=noninteractive + +# Install common dependencies needed across multiple containers +RUN apt-get update && apt-get install -y --no-install-recommends \ + # Basic utilities + ca-certificates \ + wget \ + curl \ + file \ + gnupg \ + gnupg2 \ + git \ + iproute2 \ + iputils-ping \ + less \ + lsb-release \ + ubuntu-keyring \ + vim \ + # Development & debugging + gdb \ + libunwind-dev \ + # Libraries frequently needed + libapr1 \ + libnl-3-dev \ + libnl-route-3-dev \ + libnuma1 \ + libsubunit0 \ + openssl \ + python3 \ + # Tools used in tests + iperf3 \ + xz-utils \ + # Tools moved from derived images + apache2-utils \ + nghttp2 \ + wrk + +# Because of http/3 support we can't use stock nginx in ubuntu 24.04 +RUN curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \ +| tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null +RUN echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ + http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \ + | tee /etc/apt/sources.list.d/nginx.list +RUN bash -c 'echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \ +| tee /etc/apt/preferences.d/99nginx' + +RUN apt update && apt install -y nginx=1.28.0* \ + # Clean up + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Add a non-root user (useful for containers that need it) +RUN groupadd -r vpp && useradd -r -g vpp -s /bin/bash vpp + +# Set default command +CMD ["/bin/bash"] diff --git a/test-c/kube-test/docker/Dockerfile.nginx b/test-c/kube-test/docker/Dockerfile.nginx new file mode 100644 index 00000000000..5a3e7e2a84d --- /dev/null +++ b/test-c/kube-test/docker/Dockerfile.nginx @@ -0,0 +1,19 @@ +# nginx container that uses the base image +ARG UBUNTU_VERSION=22.04 +FROM localhost:5001/vpp-test-base:latest + +# nginx is now installed in the base image + +COPY resources/nginx/nginx.conf /nginx.conf +COPY script/nginx_ldp.sh /usr/bin/nginx_ldp.sh + +ENV VCL_CONFIG=/tmp/nginx/vcl.conf +ENV LDP=/usr/lib/libvcl_ldpreload.so +ENV LDP_DEBUG=0 +ENV VCL_DEBUG=0 +ENV LDP_SID_BIT=8 + +# copy vpp-data last to take advantage of caching (do not change) +COPY vpp-data/lib/* /usr/lib/ + +ENTRYPOINT ["nginx_ldp.sh", "nginx", "-c", "/nginx.conf"] diff --git a/test-c/kube-test/docker/Dockerfile.vpp b/test-c/kube-test/docker/Dockerfile.vpp new file mode 100644 index 00000000000..20d2c65064a --- /dev/null +++ b/test-c/kube-test/docker/Dockerfile.vpp @@ -0,0 +1,38 @@ +# VPP container that uses the base image +ARG UBUNTU_VERSION=22.04 +FROM localhost:5001/vpp-test-base:latest + +# We don't need to install these packages as they're in the base image +# Just install anything specific to VPP that isn't in the base + +ARG OS_ARCH +RUN echo "I'm building for $OS_ARCH" + +ENV DIR=vpp-data/lib/vpp_plugins +COPY \ + $DIR/af_packet_plugin.so \ + $DIR/hs_apps_plugin.so \ + $DIR/http_plugin.so \ + $DIR/http_unittest_plugin.so \ + $DIR/unittest_plugin.so \ + $DIR/quic_plugin.so \ + $DIR/quic_quicly_plugin.so \ + $DIR/hsi_plugin.so \ + $DIR/http_static_plugin.so \ + $DIR/ping_plugin.so \ + $DIR/nsim_plugin.so \ + $DIR/prom_plugin.so \ + $DIR/tlsopenssl_plugin.so \ + $DIR/mactime_plugin.so \ + $DIR/arping_plugin.so \ + /usr/lib/$OS_ARCH-linux-gnu/vpp_plugins/ + +COPY vpp-data/bin/vpp /usr/bin/ +COPY vpp-data/bin/vppctl /usr/bin/ +COPY vpp-data/bin/vpp_echo /usr/bin/ +COPY vpp-data/bin/vcl_* /usr/bin/ +COPY vpp-data/lib/*.so /usr/lib/ + +# Group already created in base image + +ENTRYPOINT ["tail", "-f", "/dev/null"] diff --git a/test-c/kube-test/docker/Dockerfile.wrk b/test-c/kube-test/docker/Dockerfile.wrk new file mode 100644 index 00000000000..8517a058965 --- /dev/null +++ b/test-c/kube-test/docker/Dockerfile.wrk @@ -0,0 +1,7 @@ +# wrk HTTP benchmarking container that uses the base image +ARG UBUNTU_VERSION=22.04 +FROM localhost:5001/vpp-test-base:latest + +# wrk is installed in the base image + +ENTRYPOINT ["wrk"] diff --git a/test-c/kube-test/docker/setup-local-registry.sh b/test-c/kube-test/docker/setup-local-registry.sh new file mode 100755 index 00000000000..ea8cb1c24c1 --- /dev/null +++ b/test-c/kube-test/docker/setup-local-registry.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# Script to set up a local Docker registry + +set -e + +DOCKER_LOGIN_SCRIPT="/scratch/nomad/.docker-ro/dlogin.sh" +if [ -x "$DOCKER_LOGIN_SCRIPT" ] ; then + $DOCKER_LOGIN_SCRIPT +fi + +# Check if Docker is running +if ! docker info &>/dev/null; then + echo "Error: Docker is not running. Please start Docker and try again." + exit 1 +fi + +# Registry container name +REGISTRY_NAME="local-registry" +REGISTRY_PORT=${1:-5001} + +# Check if registry container is already running +if docker container inspect "$REGISTRY_NAME" &>/dev/null; then + echo "=== Local registry '$REGISTRY_NAME' is already running ===" + REGISTRY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$REGISTRY_NAME") + echo "Registry is available at: localhost:$REGISTRY_PORT or $REGISTRY_IP:$REGISTRY_PORT" +else + echo "=== Setting up local Docker registry ===" + + # Create a new registry container + docker run -d \ + --name "$REGISTRY_NAME" \ + --restart=always \ + -p "$REGISTRY_PORT:5000" \ + -v /var/lib/registry:/var/lib/registry \ + registry:2 + + REGISTRY_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$REGISTRY_NAME") + echo "Registry container created successfully!" + echo "Registry is available at: localhost:$REGISTRY_PORT or $REGISTRY_IP:$REGISTRY_PORT" + + # Configure Docker to trust this insecure registry + echo "=== Configuring Docker to trust insecure registry ===" + if [ -f /etc/docker/daemon.json ]; then + # Check if the file already has an insecure-registries entry + if grep -q "insecure-registries" /etc/docker/daemon.json; then + echo "Insecure registries already configured. Please make sure 'localhost:$REGISTRY_PORT' is included." + else + echo "Adding 'localhost:$REGISTRY_PORT' to insecure-registries in /etc/docker/daemon.json" + echo "You may need to restart Docker for changes to take effect" + echo "Please add the following to /etc/docker/daemon.json:" + echo "{ + \"insecure-registries\": [\"localhost:$REGISTRY_PORT\"] +}" + fi + else + echo "Creating /etc/docker/daemon.json with insecure-registries configuration" + echo "You may need to restart Docker for changes to take effect" + echo "Please create /etc/docker/daemon.json with the following content:" + echo "{ + \"insecure-registries\": [\"localhost:$REGISTRY_PORT\"] +}" + fi +fi + +echo "" +echo "=== Local Registry Setup Complete ===" +echo "To use the local registry, prefix your image tags with 'localhost:$REGISTRY_PORT/'" +echo "For example: localhost:$REGISTRY_PORT/hs-test/vpp:latest" diff --git a/test-c/kube-test/framework_test.go b/test-c/kube-test/framework_test.go new file mode 100644 index 00000000000..3aa121d7aab --- /dev/null +++ b/test-c/kube-test/framework_test.go @@ -0,0 +1,43 @@ +package main + +import ( + "fmt" + "os" + "testing" + "time" + + . "fd.io/kube-test/infra" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = ReportAfterSuite("VPP version under test", func(report Report) { + for i := range report.SpecReports { + specReport := report.SpecReports[i] + for j := range specReport.ReportEntries { + reportEntry := specReport.ReportEntries[j] + if reportEntry.Name == "VPP version" { + fmt.Println(reportEntry.Value) + return + } + } + } +}) + +func TestKube(t *testing.T) { + TestTimeout = time.Minute * time.Duration(*Timeout) + + // creates a file with PPID, used for 'make cleanup-kube' + ppid := fmt.Sprint(os.Getppid()) + ppid = ppid[:len(ppid)-1] + f, _ := os.Create(".last_ppid") + f.Write([]byte(ppid)) + f.Close() + + RegisterFailHandler(Fail) + RunSpecs(t, "Kube Test") + if *DryRun || *IsPersistent { + fmt.Println("\033[36m" + "Use 'make cleanup-kube' to remove pods " + + "and namespaces. \nPPID: " + ppid + "\033[0m") + } +} diff --git a/test-c/kube-test/go.mod b/test-c/kube-test/go.mod new file mode 100644 index 00000000000..ea98fbb731a --- /dev/null +++ b/test-c/kube-test/go.mod @@ -0,0 +1,65 @@ +module fd.io/kube-test + +go 1.23.8 + +toolchain go1.23.10 + +require ( + github.com/onsi/ginkgo/v2 v2.23.3 + github.com/onsi/gomega v1.37.0 + gopkg.in/yaml.v3 v3.0.1 + k8s.io/api v0.30.2 +) + +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.11.2 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/moby/spdystream v0.2.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/spf13/pflag v1.0.6 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/term v0.30.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect +) + +require ( + github.com/a8m/envsubst v1.4.2 + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect + github.com/imdario/mergo v0.3.16 // indirect + github.com/joho/godotenv v1.5.1 + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.24.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.30.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect + k8s.io/apimachinery v0.30.2 + k8s.io/client-go v0.30.2 + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect +) diff --git a/test-c/kube-test/go.sum b/test-c/kube-test/go.sum new file mode 100644 index 00000000000..c4ce2709792 --- /dev/null +++ b/test-c/kube-test/go.sum @@ -0,0 +1,174 @@ +github.com/a8m/envsubst v1.4.2 h1:4yWIHXOLEJHQEFd4UjrWDrYeYlV7ncFWJOCBRLOZHQg= +github.com/a8m/envsubst v1.4.2/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emicklei/go-restful/v3 v3.11.2 h1:1onLa9DcsMYO9P+CXaL0dStDqQ2EHHXLiz+BtnqkLAU= +github.com/emicklei/go-restful/v3 v3.11.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= +k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI= +k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= +k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50= +k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= +k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/test-c/kube-test/infra/asserts.go b/test-c/kube-test/infra/asserts.go new file mode 100644 index 00000000000..fcbd65a22f2 --- /dev/null +++ b/test-c/kube-test/infra/asserts.go @@ -0,0 +1,114 @@ +package kube_test + +import ( + "fmt" + "net/http" + "strconv" + "strings" + "time" + + . "github.com/onsi/gomega" +) + +func (s *BaseSuite) AssertNil(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).To(BeNil(), msgAndArgs...) +} + +func (s *BaseSuite) AssertNotNil(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).ToNot(BeNil(), msgAndArgs...) +} + +func (s *BaseSuite) AssertEqual(expected, actual any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).To(Equal(expected), msgAndArgs...) +} + +func (s *BaseSuite) AssertNotEqual(expected, actual any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).ToNot(Equal(expected), msgAndArgs...) +} + +func (s *BaseSuite) AssertContains(testString, contains any, msgAndArgs ...any) { + ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).To(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...) +} + +func (s *BaseSuite) AssertNotContains(testString, contains any, msgAndArgs ...any) { + ExpectWithOffset(2, strings.ToLower(fmt.Sprint(testString))).ToNot(ContainSubstring(strings.ToLower(fmt.Sprint(contains))), msgAndArgs...) +} + +func (s *BaseSuite) AssertEmpty(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).To(BeEmpty(), msgAndArgs...) +} + +func (s *BaseSuite) AssertNotEmpty(object any, msgAndArgs ...any) { + ExpectWithOffset(2, object).ToNot(BeEmpty(), msgAndArgs...) +} + +func (s *BaseSuite) AssertMatchError(actual, expected error, msgAndArgs ...any) { + ExpectWithOffset(2, actual).To(MatchError(expected), msgAndArgs...) +} + +func (s *BaseSuite) AssertGreaterEqual(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically(">=", expected), msgAndArgs...) +} + +func (s *BaseSuite) AssertGreaterThan(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically(">", expected), msgAndArgs...) +} + +func (s *BaseSuite) AssertLessEqual(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically("<=", expected), msgAndArgs...) +} + +func (s *BaseSuite) AssertLessThan(actual, expected any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically("<", expected), msgAndArgs...) +} + +func (s *BaseSuite) AssertEqualWithinThreshold(actual, expected, threshold any, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeNumerically("~", expected, threshold), msgAndArgs...) +} + +func (s *BaseSuite) AssertTimeEqualWithinThreshold(actual, expected time.Time, threshold time.Duration, msgAndArgs ...any) { + ExpectWithOffset(2, actual).Should(BeTemporally("~", expected, threshold), msgAndArgs...) +} + +func (s *BaseSuite) AssertHttpStatus(resp *http.Response, expectedStatus int, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPStatus(expectedStatus), msgAndArgs...) +} + +func (s *BaseSuite) AssertHttpHeaderWithValue(resp *http.Response, key string, value any, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue(key, value), msgAndArgs...) +} + +func (s *BaseSuite) AssertHttpHeaderNotPresent(resp *http.Response, key string, msgAndArgs ...any) { + ExpectWithOffset(2, resp.Header.Get(key)).To(BeEmpty(), msgAndArgs...) +} + +func (s *BaseSuite) AssertHttpContentLength(resp *http.Response, expectedContentLen int64, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPHeaderWithValue("Content-Length", strconv.FormatInt(expectedContentLen, 10)), msgAndArgs...) +} + +func (s *BaseSuite) AssertHttpBody(resp *http.Response, expectedBody string, msgAndArgs ...any) { + ExpectWithOffset(2, resp).To(HaveHTTPBody(expectedBody), msgAndArgs...) +} + +// Coverage builds take longer to finish -> assert timeout is set to 'TestTimeout - 30 seconds' to let the test finish properly +func (s *BaseSuite) AssertChannelClosed(timeout time.Duration, channel chan error) { + if *IsCoverage && timeout > time.Second*30 { + timeout = TestTimeout - time.Second*30 + s.Log("Coverage build, assert timeout is set to %s", timeout.String()) + } + EventuallyWithOffset(2, channel).WithTimeout(timeout).Should(BeClosed()) +} + +// Pass the parsed result struct and the minimum amount of data transferred in MB. +// Won't do anything when testing a coverage build. +func (s *BaseSuite) AssertIperfMinTransfer(result IPerfResult, minTransferred int) { + if *IsCoverage { + s.Log("Coverage build; not asserting") + return + } + if result.Start.Details.Protocol == "TCP" { + s.AssertGreaterEqual(result.End.TcpReceived.MBytes, minTransferred) + } else { + s.AssertGreaterEqual(result.End.Udp.MBytes, minTransferred) + } +} diff --git a/extras/hs-test/infra/kind/deployment.go b/test-c/kube-test/infra/deployment.go similarity index 89% rename from extras/hs-test/infra/kind/deployment.go rename to test-c/kube-test/infra/deployment.go index a215661d6fb..a57b11b1f76 100644 --- a/extras/hs-test/infra/kind/deployment.go +++ b/test-c/kube-test/infra/deployment.go @@ -1,4 +1,4 @@ -package hst_kind +package kube_test import ( "context" @@ -11,7 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (s *KindSuite) loadDockerImages() { +func (s *KubeSuite) loadDockerImages() { s.Log("This may take a while. If you encounter problems, " + "try loading docker images manually: 'kind load docker-image [image]'") @@ -27,7 +27,7 @@ func (s *KindSuite) loadDockerImages() { } } -func (s *KindSuite) createNamespace(name string) { +func (s *KubeSuite) createNamespace(name string) { namespace := &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -40,22 +40,22 @@ func (s *KindSuite) createNamespace(name string) { s.Log("Namespace '%s' created", name) } -func (s *KindSuite) deletePod(namespace string, podName string) error { +func (s *KubeSuite) deletePod(namespace string, podName string) error { delete(s.CurrentlyRunning, podName) return s.ClientSet.CoreV1().Pods(namespace).Delete(context.TODO(), podName, metav1.DeleteOptions{GracePeriodSeconds: int64Ptr(0)}) } -func (s *KindSuite) deleteNamespace(namespace string) error { +func (s *KubeSuite) deleteNamespace(namespace string) error { return s.ClientSet.CoreV1().Namespaces().Delete(context.TODO(), namespace, metav1.DeleteOptions{}) } -func (s *KindSuite) DeployPod(pod *Pod) { +func (s *KubeSuite) DeployPod(pod *Pod) { pod.CreatedPod = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Namespace: s.Namespace, Name: pod.Name, Labels: map[string]string{ - "app": "HST", + "app": "Kube-Test", }, Annotations: map[string]string{ "cni.projectcalico.org/vppVcl": "enable", diff --git a/extras/hs-test/infra/kind/pod.go b/test-c/kube-test/infra/pod.go similarity index 86% rename from extras/hs-test/infra/kind/pod.go rename to test-c/kube-test/infra/pod.go index 969882d0ab0..87bb5bcaf78 100644 --- a/extras/hs-test/infra/kind/pod.go +++ b/test-c/kube-test/infra/pod.go @@ -1,21 +1,22 @@ -package hst_kind +package kube_test import ( "bytes" "context" + "errors" + "fmt" "os" "os/exec" "slices" "text/template" - . "fd.io/hs-test/infra/common" "gopkg.in/yaml.v3" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/tools/remotecommand" ) type Pod struct { - suite *KindSuite + suite *KubeSuite Name string Image string ContainerName string @@ -48,7 +49,7 @@ type Config struct { Pods []PodYaml `yaml:"pods"` } -func (s *KindSuite) LoadPodConfigs() { +func (s *KubeSuite) LoadPodConfigs() { data, err := os.ReadFile("kubernetes/pod-definitions.yaml") s.AssertNil(err) @@ -61,7 +62,7 @@ func (s *KindSuite) LoadPodConfigs() { } } -func newPod(suite *KindSuite, input PodYaml) (*Pod, error) { +func newPod(suite *KubeSuite, input PodYaml) (*Pod, error) { var pod = new(Pod) pod.suite = suite pod.Name = input.Name + suite.Ppid @@ -83,7 +84,7 @@ func newPod(suite *KindSuite, input PodYaml) (*Pod, error) { return pod, nil } -func (s *KindSuite) initPods() { +func (s *KubeSuite) initPods() { s.Pods.Ab = s.getPodsByName("ab") s.Pods.ClientGeneric = s.getPodsByName("client-generic") s.Pods.ServerGeneric = s.getPodsByName("server-generic") @@ -91,7 +92,7 @@ func (s *KindSuite) initPods() { s.Pods.NginxProxy = s.getPodsByName("nginx-proxy") } -func (s *KindSuite) getPodsByName(podName string) *Pod { +func (s *KubeSuite) getPodsByName(podName string) *Pod { return s.AllPods[podName+s.Ppid] } @@ -122,7 +123,7 @@ func (pod *Pod) Exec(ctx context.Context, command []string) (string, error) { executor, err := remotecommand.NewSPDYExecutor(pod.suite.Config, "POST", req.URL()) if err != nil { - pod.suite.Log("Error creating executor: %s", err.Error()) + return "", err } err = executor.StreamWithContext(ctx, remotecommand.StreamOptions{ @@ -131,20 +132,19 @@ func (pod *Pod) Exec(ctx context.Context, command []string) (string, error) { Tty: true, }) - output := stdout.String() + stderr.String() - - if err != nil { - return output, err + output := stdout.String() + if stderr.String() != "" { + err = errors.New(stderr.String()) } - return output, nil + return output, err } func (pod *Pod) CreateConfigFromTemplate(targetConfigName string, templateName string, values any) { template := template.Must(template.ParseFiles(templateName)) - f, err := os.CreateTemp(LogDir, "hst-config") - pod.suite.AssertNil(err, err) + f, err := os.CreateTemp(LogDir, "kube-config") + pod.suite.AssertNil(err, fmt.Sprint(err)) defer os.Remove(f.Name()) err = template.Execute(f, values) diff --git a/test-c/kube-test/infra/suite_base.go b/test-c/kube-test/infra/suite_base.go new file mode 100644 index 00000000000..bdd1f9cf543 --- /dev/null +++ b/test-c/kube-test/infra/suite_base.go @@ -0,0 +1,142 @@ +package kube_test + +import ( + "flag" + "fmt" + "io" + "log" + "os" + "os/exec" + "strings" + "time" + + "github.com/joho/godotenv" + . "github.com/onsi/ginkgo/v2" +) + +var IsCoverage = flag.Bool("coverage", false, "use coverage run config") +var IsPersistent = flag.Bool("persist", false, "persists topology config") +var IsVerbose = flag.Bool("verbose", false, "verbose test output") +var WhoAmI = flag.String("whoami", "root", "what user ran kube-test") +var IsVppDebug = flag.Bool("debug", false, "attach gdb to vpp") +var DryRun = flag.Bool("dryrun", false, "set up containers but don't run tests") +var Timeout = flag.Int("timeout", 30, "test timeout override (in minutes)") +var TestTimeout time.Duration + +const ( + LogDir string = "/tmp/kube-test/" +) + +type BaseSuite struct { + Ppid string + Logger *log.Logger + LogFile *os.File +} + +func init() { + cmd := exec.Command("mkdir", "-p", LogDir) + if err := cmd.Run(); err != nil { + panic(err) + } +} + +func (s *BaseSuite) Skip(args string) { + Skip(args) +} + +func (s *BaseSuite) SetupTest() { + TestCounterFunc() + s.Log("[* TEST SETUP]") +} + +func (s *BaseSuite) SetupSuite() { + s.CreateLogger() + s.Log("[* SUITE SETUP]") + s.Ppid = fmt.Sprint(os.Getppid()) + // remove last number so we have space to prepend a process index (interfaces have a char limit) + s.Ppid = s.Ppid[:len(s.Ppid)-1] +} + +func (s *BaseSuite) TeardownTest() { + if *IsPersistent || *DryRun { + s.Skip("Skipping test teardown") + } + s.Log("[* TEST TEARDOWN]") +} + +func (s *BaseSuite) TeardownSuite() { + if *IsPersistent || *DryRun { + s.Skip("Skipping suite teardown") + } + s.Log("[* SUITE TEARDOWN]") +} + +func (s *BaseSuite) GetCurrentSuiteName() string { + return CurrentSpecReport().ContainerHierarchyTexts[0] +} + +func (s *BaseSuite) CreateLogger() { + suiteName := s.GetCurrentSuiteName() + var err error + s.LogFile, err = os.Create("summary/" + suiteName + ".log") + if err != nil { + Fail("Unable to create log file.") + } + s.Logger = log.New(io.Writer(s.LogFile), "", log.LstdFlags) +} + +// Logs to files by default, logs to stdout when VERBOSE=true with GinkgoWriter +// to keep console tidy +func (s *BaseSuite) Log(log any, arg ...any) { + var logStr string + if len(arg) == 0 { + logStr = fmt.Sprint(log) + } else { + logStr = fmt.Sprintf(fmt.Sprint(log), arg...) + } + logs := strings.Split(logStr, "\n") + + for _, line := range logs { + s.Logger.Println(line) + } + if *IsVerbose { + GinkgoWriter.Println(logStr) + } +} + +// sets CALICO_NETWORK_CONFIG, ADDITIONAL_VPP_CONFIG, env vars, applies configs and rollout restarts cluster +func (s *KubeSuite) SetMtuAndRestart(CALICO_NETWORK_CONFIG string, ADDITIONAL_VPP_CONFIG string) { + os.Setenv("CALICO_NETWORK_CONFIG", CALICO_NETWORK_CONFIG) + os.Setenv("ADDITIONAL_VPP_CONFIG", ADDITIONAL_VPP_CONFIG) + s.AssertNil(godotenv.Load("kubernetes/.vars")) + + s.Envsubst("kubernetes/calico-config-template.yaml", "kubernetes/calico-config.yaml") + + cmd := exec.Command("kubectl", "apply", "-f", "kubernetes/calico-config.yaml") + s.Log(cmd.String()) + o, err := cmd.CombinedOutput() + s.Log(string(o)) + s.AssertNil(err) + + cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "restart", "ds/calico-vpp-node") + s.Log(cmd.String()) + o, err = cmd.CombinedOutput() + s.Log(string(o)) + s.AssertNil(err) + + cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "status", "ds/calico-vpp-node") + s.Log(cmd.String()) + o, err = cmd.CombinedOutput() + s.Log(string(o)) + s.AssertNil(err) + + cmd = exec.Command("kubectl", "-n", "calico-system", "rollout", "status", "ds/calico-node") + s.Log(cmd.String()) + o, err = cmd.CombinedOutput() + s.Log(string(o)) + s.AssertNil(err) + + // let vpp-dataplane recover, should help with stability issues + s.Log("Waiting for 10 seconds") + time.Sleep(time.Second * 10) +} diff --git a/extras/hs-test/infra/kind/suite_kind.go b/test-c/kube-test/infra/suite_kube.go similarity index 66% rename from extras/hs-test/infra/kind/suite_kind.go rename to test-c/kube-test/infra/suite_kube.go index eb386f570f6..3fb4fd498ff 100644 --- a/extras/hs-test/infra/kind/suite_kind.go +++ b/test-c/kube-test/infra/suite_kube.go @@ -1,28 +1,24 @@ -package hst_kind +package kube_test import ( "context" "fmt" "os" - "os/exec" "reflect" "regexp" "runtime" "strings" - "time" - . "fd.io/hs-test/infra/common" "github.com/a8m/envsubst" . "github.com/onsi/ginkgo/v2" - "github.com/joho/godotenv" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" ) -type KindSuite struct { - HstCommon +type KubeSuite struct { + BaseSuite ClientSet *kubernetes.Clientset Config *rest.Config Namespace string @@ -41,7 +37,7 @@ type KindSuite struct { } var imagesLoaded bool -var kindTests = map[string][]func(s *KindSuite){} +var kubeTests = map[string][]func(s *KubeSuite){} const VclConfIperf = "echo \"vcl {\n" + "rx-fifo-size 4000000\n" + @@ -62,17 +58,17 @@ const VclConfNginx = "echo \"vcl {\n" + "app-socket-api abstract:vpp/session\n" + "}\" > /vcl.conf" -func RegisterKindTests(tests ...func(s *KindSuite)) { - kindTests[GetTestFilename()] = tests +func RegisterKubeTests(tests ...func(s *KubeSuite)) { + kubeTests[GetTestFilename()] = tests } -func (s *KindSuite) SetupTest() { +func (s *KubeSuite) SetupTest() { s.MainContext = context.Background() - s.HstCommon.SetupTest() + s.BaseSuite.SetupTest() } -func (s *KindSuite) SetupSuite() { - s.HstCommon.SetupSuite() +func (s *KubeSuite) SetupSuite() { + s.BaseSuite.SetupSuite() s.CurrentlyRunning = make(map[string]*Pod) s.LoadPodConfigs() @@ -102,45 +98,8 @@ func (s *KindSuite) SetupSuite() { } } -// sets CALICO_NETWORK_CONFIG, ADDITIONAL_VPP_CONFIG, env vars, applies configs and rollout restarts cluster -func (s *KindSuite) SetMtuAndRestart(CALICO_NETWORK_CONFIG string, ADDITIONAL_VPP_CONFIG string) { - os.Setenv("CALICO_NETWORK_CONFIG", CALICO_NETWORK_CONFIG) - os.Setenv("ADDITIONAL_VPP_CONFIG", ADDITIONAL_VPP_CONFIG) - s.AssertNil(godotenv.Load("kubernetes/.vars")) - - s.Envsubst("kubernetes/calico-config-template.yaml", "kubernetes/calico-config.yaml") - - cmd := exec.Command("kubectl", "apply", "-f", "kubernetes/calico-config.yaml") - s.Log(cmd.String()) - o, err := cmd.CombinedOutput() - s.Log(string(o)) - s.AssertNil(err) - - cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "restart", "ds/calico-vpp-node") - s.Log(cmd.String()) - o, err = cmd.CombinedOutput() - s.Log(string(o)) - s.AssertNil(err) - - cmd = exec.Command("kubectl", "-n", "calico-vpp-dataplane", "rollout", "status", "ds/calico-vpp-node") - s.Log(cmd.String()) - o, err = cmd.CombinedOutput() - s.Log(string(o)) - s.AssertNil(err) - - cmd = exec.Command("kubectl", "-n", "calico-system", "rollout", "status", "ds/calico-node") - s.Log(cmd.String()) - o, err = cmd.CombinedOutput() - s.Log(string(o)) - s.AssertNil(err) - - // let vpp-dataplane recover (tests might timeout otherwise) - s.Log("Waiting for 10 seconds") - time.Sleep(time.Second * 10) -} - -func (s *KindSuite) TeardownTest() { - s.HstCommon.TeardownTest() +func (s *KubeSuite) TeardownTest() { + s.BaseSuite.TeardownTest() if len(s.CurrentlyRunning) != 0 { s.Log("Removing:") for _, pod := range s.CurrentlyRunning { @@ -150,8 +109,8 @@ func (s *KindSuite) TeardownTest() { } } -func (s *KindSuite) TeardownSuite() { - s.HstCommon.TeardownSuite() +func (s *KubeSuite) TeardownSuite() { + s.BaseSuite.TeardownSuite() if len(s.CurrentlyRunning) == 0 { return } @@ -161,7 +120,7 @@ func (s *KindSuite) TeardownSuite() { // Quick and dirty fix for now. Runs 'ldd /usr/lib/libvcl_ldpreload.so' // and searches for the first version string, then creates symlinks. -func (s *KindSuite) FixVersionNumber(pods ...*Pod) { +func (s *KubeSuite) FixVersionNumber(pods ...*Pod) { regex := regexp.MustCompile(`lib.*\.so\.([0-9]+\.[0-9]+)`) var match []string for _, pod := range pods { @@ -192,7 +151,7 @@ func (s *KindSuite) FixVersionNumber(pods ...*Pod) { } } -func (s *KindSuite) CreateNginxConfig(pod *Pod) { +func (s *KubeSuite) CreateNginxConfig(pod *Pod) { values := struct { Workers uint8 Port uint16 @@ -207,13 +166,13 @@ func (s *KindSuite) CreateNginxConfig(pod *Pod) { ) } -func (s *KindSuite) Envsubst(inputPath string, outputPath string) { +func (s *KubeSuite) Envsubst(inputPath string, outputPath string) { o, err := envsubst.ReadFile(inputPath) s.AssertNil(err) os.WriteFile(outputPath, o, 0644) } -func (s *KindSuite) CreateNginxProxyConfig(pod *Pod) { +func (s *KubeSuite) CreateNginxProxyConfig(pod *Pod) { pod.Exec(context.TODO(), []string{"/bin/bash", "-c", "mkdir -p /tmp/nginx"}) values := struct { Workers uint8 @@ -241,8 +200,8 @@ func (s *KindSuite) CreateNginxProxyConfig(pod *Pod) { ) } -var _ = Describe("KindSuite", Ordered, ContinueOnFailure, Label("Perf"), func() { - var s KindSuite +var _ = Describe("KubeSuite", Ordered, ContinueOnFailure, Label("Perf"), func() { + var s KubeSuite BeforeAll(func() { s.SetupSuite() s.SetMtuAndRestart("", "") @@ -257,7 +216,7 @@ var _ = Describe("KindSuite", Ordered, ContinueOnFailure, Label("Perf"), func() s.TeardownSuite() }) - for filename, tests := range kindTests { + for filename, tests := range kubeTests { for _, test := range tests { test := test pc := reflect.ValueOf(test).Pointer() diff --git a/extras/hs-test/infra/kind/suite_large-mtu.go b/test-c/kube-test/infra/suite_large-mtu.go similarity index 92% rename from extras/hs-test/infra/kind/suite_large-mtu.go rename to test-c/kube-test/infra/suite_large-mtu.go index 0cf44c6b8ab..53484de3bc0 100644 --- a/extras/hs-test/infra/kind/suite_large-mtu.go +++ b/test-c/kube-test/infra/suite_large-mtu.go @@ -1,16 +1,15 @@ -package hst_kind +package kube_test import ( "reflect" "runtime" "strings" - . "fd.io/hs-test/infra/common" . "github.com/onsi/ginkgo/v2" ) type LargeMtuSuite struct { - KindSuite + KubeSuite } var largeMtuTests = map[string][]func(s *LargeMtuSuite){} @@ -20,7 +19,7 @@ func RegisterLargeMtuTests(tests ...func(s *LargeMtuSuite)) { } func (s *LargeMtuSuite) SetupSuite() { - s.KindSuite.SetupSuite() + s.KubeSuite.SetupSuite() s.SetMtuAndRestart("mtu: 9000", "tcp { mtu 8960 }") } diff --git a/extras/hs-test/infra/common/utils_common.go b/test-c/kube-test/infra/utils.go similarity index 94% rename from extras/hs-test/infra/common/utils_common.go rename to test-c/kube-test/infra/utils.go index 15db60b387e..87635945fee 100644 --- a/extras/hs-test/infra/common/utils_common.go +++ b/test-c/kube-test/infra/utils.go @@ -1,4 +1,4 @@ -package hst_common +package kube_test import ( "encoding/json" @@ -9,6 +9,14 @@ import ( "time" ) +func boolPtr(b bool) *bool { + return &b +} + +func int64Ptr(integer int64) *int64 { + return &integer +} + func GetTestFilename() string { _, filename, _, _ := runtime.Caller(2) return filepath.Base(filename) @@ -18,9 +26,6 @@ var testCounter uint16 var startTime time.Time = time.Now() func TestCounterFunc() { - if ParallelTotal.Value.String() != "1" { - return - } testCounter++ fmt.Printf("Test counter: %d\n"+ "Time elapsed: %.2fs\n", @@ -64,7 +69,7 @@ type IPerfResult struct { } `json:"end"` } -func (s *HstCommon) ParseJsonIperfOutput(jsonResult []byte) IPerfResult { +func (s *BaseSuite) ParseJsonIperfOutput(jsonResult []byte) IPerfResult { var result IPerfResult // VCL/LDP debugging can pollute output so find the first occurrence of a curly brace to locate the start of JSON data @@ -109,7 +114,7 @@ func (s *HstCommon) ParseJsonIperfOutput(jsonResult []byte) IPerfResult { return result } -func (s *HstCommon) LogJsonIperfOutput(result IPerfResult) { +func (s *BaseSuite) LogJsonIperfOutput(result IPerfResult) { s.Log("\n*******************************************\n"+ "%s\n"+ "[%s] %s:%d connected to %s:%d\n"+ diff --git a/extras/hs-test/kind_test.go b/test-c/kube-test/kube_test.go similarity index 67% rename from extras/hs-test/kind_test.go rename to test-c/kube-test/kube_test.go index 799df2aed64..1652dff5fce 100644 --- a/extras/hs-test/kind_test.go +++ b/test-c/kube-test/kube_test.go @@ -6,24 +6,28 @@ import ( "fmt" "time" - . "fd.io/hs-test/infra/common" - . "fd.io/hs-test/infra/kind" + . "fd.io/kube-test/infra" . "github.com/onsi/ginkgo/v2" ) func init() { - RegisterKindTests(KindTcpIperfVclTest, KindUdpIperfVclTest, NginxRpsTest, NginxProxyMirroringTest) - RegisterLargeMtuTests(KindTcpIperfVclLargeMTUTest) + RegisterKubeTests(KubeTcpIperfVclTest, KubeUdpIperfVclTest, NginxRpsTest, NginxProxyMirroringTest) + RegisterLargeMtuTests(KubeTcpIperfVclLargeMTUTest) } const vcl string = "VCL_CONFIG=/vcl.conf" const ldp string = "LD_PRELOAD=/usr/lib/libvcl_ldpreload.so" -func kindIperfVclTest(s *KindSuite, clientArgs string) IPerfResult { +func kubeIperfVclTest(s *KubeSuite, clientArgs string) IPerfResult { s.DeployPod(s.Pods.ClientGeneric) s.DeployPod(s.Pods.ServerGeneric) - ctx, cancel := context.WithTimeout(s.MainContext, time.Second*40) + ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*2) defer cancel() + defer func() { + o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c", "cat /iperf_server.log"}) + s.Log(o) + s.AssertNil(err) + }() _, err := s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", VclConfIperf}) s.AssertNil(err) @@ -32,14 +36,16 @@ func kindIperfVclTest(s *KindSuite, clientArgs string) IPerfResult { s.FixVersionNumber(s.Pods.ClientGeneric, s.Pods.ServerGeneric) - iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -b 40g -c %s", + iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -4 -b 40g -c %s", vcl, ldp, clientArgs, s.Pods.ServerGeneric.IpAddress) o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c", - vcl + " " + ldp + " iperf3 -s -D -4 -B " + s.Pods.ServerGeneric.IpAddress}) + vcl + " " + ldp + " iperf3 -s -D --logfile /iperf_server.log -B " + s.Pods.ServerGeneric.IpAddress}) + s.Log("Sleeping for 2s") + time.Sleep(time.Second * 2) s.AssertNil(err, o) - o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd}) + o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd}) s.AssertNil(err, o) result := s.ParseJsonIperfOutput([]byte(o)) s.LogJsonIperfOutput(result) @@ -47,11 +53,16 @@ func kindIperfVclTest(s *KindSuite, clientArgs string) IPerfResult { } // TODO: use interfaces to avoid duplicated code -func kindIperfVclMtuTest(s *LargeMtuSuite, clientArgs string) IPerfResult { +func kubeIperfVclMtuTest(s *LargeMtuSuite, clientArgs string) IPerfResult { s.DeployPod(s.Pods.ClientGeneric) s.DeployPod(s.Pods.ServerGeneric) - ctx, cancel := context.WithTimeout(s.MainContext, time.Second*40) + ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*2) defer cancel() + defer func() { + o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c", "cat /iperf_server.log"}) + s.Log(o) + s.AssertNil(err) + }() _, err := s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", VclConfIperf}) s.AssertNil(err) @@ -60,34 +71,36 @@ func kindIperfVclMtuTest(s *LargeMtuSuite, clientArgs string) IPerfResult { s.FixVersionNumber(s.Pods.ClientGeneric, s.Pods.ServerGeneric) - iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -b 40g -c %s", + iperfClientCmd := fmt.Sprintf("%s %s iperf3 %s -J -4 -b 40g -c %s", vcl, ldp, clientArgs, s.Pods.ServerGeneric.IpAddress) o, err := s.Pods.ServerGeneric.Exec(ctx, []string{"/bin/bash", "-c", - vcl + " " + ldp + " iperf3 -s -D -4 -B " + s.Pods.ServerGeneric.IpAddress}) + vcl + " " + ldp + " iperf3 -s -D --logfile /iperf_server.log -B " + s.Pods.ServerGeneric.IpAddress}) + s.Log("Sleeping for 2s") + time.Sleep(time.Second * 2) s.AssertNil(err, o) - o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd}) + o, err = s.Pods.ClientGeneric.Exec(ctx, []string{"/bin/bash", "-c", iperfClientCmd}) s.AssertNil(err, o) result := s.ParseJsonIperfOutput([]byte(o)) s.LogJsonIperfOutput(result) return result } -func KindTcpIperfVclTest(s *KindSuite) { - s.AssertIperfMinTransfer(kindIperfVclTest(s, "-M 1460"), 2000) +func KubeTcpIperfVclTest(s *KubeSuite) { + s.AssertIperfMinTransfer(kubeIperfVclTest(s, "-M 1460"), 2000) } -func KindTcpIperfVclLargeMTUTest(s *LargeMtuSuite) { - s.AssertIperfMinTransfer(kindIperfVclMtuTest(s, "-M 8960"), 2000) +func KubeTcpIperfVclLargeMTUTest(s *LargeMtuSuite) { + s.AssertIperfMinTransfer(kubeIperfVclMtuTest(s, "-M 8900"), 2000) } -func KindUdpIperfVclTest(s *KindSuite) { - s.AssertIperfMinTransfer(kindIperfVclTest(s, "-l 1460 -u"), 2000) +func KubeUdpIperfVclTest(s *KubeSuite) { + s.AssertIperfMinTransfer(kubeIperfVclTest(s, "-l 1460 -u"), 2000) } -func NginxRpsTest(s *KindSuite) { - ctx, cancel := context.WithCancel(s.MainContext) +func NginxRpsTest(s *KubeSuite) { + ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*3) defer cancel() s.DeployPod(s.Pods.Nginx) @@ -112,8 +125,8 @@ func NginxRpsTest(s *KindSuite) { s.AssertNil(err) } -func NginxProxyMirroringTest(s *KindSuite) { - ctx, cancel := context.WithCancel(s.MainContext) +func NginxProxyMirroringTest(s *KubeSuite) { + ctx, cancel := context.WithTimeout(s.MainContext, time.Minute*3) defer cancel() s.DeployPod(s.Pods.Nginx) diff --git a/test-c/kube-test/kube_test.sh b/test-c/kube-test/kube_test.sh new file mode 100755 index 00000000000..265b4934246 --- /dev/null +++ b/test-c/kube-test/kube_test.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash + +args= +focused_test=0 +persist_set=0 +dryrun_set=0 +debug_set=0 +debug_build= +ginkgo_args= +tc_names=() +skip_names=() +dryrun= +no_color= + +for i in "$@" +do +case "${i}" in + --persist=*) + persist="${i#*=}" + if [ "$persist" = "true" ]; then + args="$args -persist" + persist_set=1 + fi + ;; + --verbose=*) + verbose="${i#*=}" + if [ "$verbose" = "true" ]; then + args="$args -verbose" + fi + ;; + --test=*) + tc_list="${i#*=}" + ginkgo_args="$ginkgo_args -v" + if [ "$tc_list" != "all" ]; then + focused_test=1 + IFS=',' read -r -a tc_names <<< "$tc_list" + args="$args -verbose" + fi + ;; + --skip=*) + skip_list="${i#*=}" + IFS=',' read -r -a skip_names <<< "$skip_list" + ;; + --ginkgo_timeout=*) + ginkgo_args="$ginkgo_args --timeout=${i#*=}" + ;; + --repeat=*) + ginkgo_args="$ginkgo_args --repeat=${i#*=}" + ;; + --dryrun=*) + dryrun="${i#*=}" + if [ "$dryrun" = "true" ]; then + args="$args -dryrun" + dryrun_set=1 + fi + ;; + --no_color=*) + no_color="${i#*=}" + if [ "$no_color" = "true" ]; then + ginkgo_args="$ginkgo_args --no-color" + fi + ;; + --timeout=*) + args="$args -timeout ${i#*=}" + ;; +esac +done + +if [ ${#tc_names[@]} -gt 1 ] +then + focused_test=0 +fi + +for name in "${tc_names[@]}"; do + ginkgo_args="$ginkgo_args --focus $name" +done + +for skip in "${skip_names[@]}"; do + ginkgo_args="$ginkgo_args --skip $skip" +done + +if [ $focused_test -eq 0 ] && { [ $persist_set -eq 1 ] || [ $dryrun_set -eq 1 ]; }; then + echo -e "\e[1;31mpersist/dryrun flag is not supported while running all tests!\e[1;0m" + exit 2 +fi + +args="$args -whoami $(whoami)" + +if [ -n "${BUILD_NUMBER}" ]; then + ginkgo_args="$ginkgo_args --no-color" +fi + +mkdir -p summary +rm -f summary/* +# shellcheck disable=SC2086 +CMD="go run github.com/onsi/ginkgo/v2/ginkgo --json-report=summary/report.json $ginkgo_args -- $args" +echo "$CMD" +$CMD +exit_status=$? + +if [ $exit_status -ne 0 ]; then + jq -r '.[0] | .SpecReports[] | select((.State == "failed") or (.State == "timedout") or (.State == "panicked")) | select(.Failure != null) | +"TestName: + \(.LeafNodeText) +Suite: + \(.Failure.FailureNodeLocation.FileName) +Message:\n" ++ ( + if .ReportEntries? then + (.ReportEntries[] | select(.Name | contains("Backtrace")) | + "\tFull Back Trace: +\(.Value.Representation | ltrimstr("{{red}}") | rtrimstr("{{/}}"))" + ) // "\(.Failure.Message)" + else + "parse error" + end +) ++ ( + if .Failure.Message == "A spec timeout occurred" then + "\n" + else + "\nFull Stack Trace: +\(.Failure.Location.FullStackTrace)\n" + end +)' summary/report.json > summary/failed-summary.log \ +&& echo "Summary generated -> summary/failed-summary.log" + exit $exit_status +else + exit $exit_status +fi diff --git a/extras/hs-test/kubernetes/calico-config-template.yaml b/test-c/kube-test/kubernetes/calico-config-template.yaml similarity index 100% rename from extras/hs-test/kubernetes/calico-config-template.yaml rename to test-c/kube-test/kubernetes/calico-config-template.yaml diff --git a/extras/hs-test/kubernetes/kind-config.yaml b/test-c/kube-test/kubernetes/kind-config.yaml similarity index 100% rename from extras/hs-test/kubernetes/kind-config.yaml rename to test-c/kube-test/kubernetes/kind-config.yaml diff --git a/extras/hs-test/kubernetes/pod-definitions.yaml b/test-c/kube-test/kubernetes/pod-definitions.yaml similarity index 84% rename from extras/hs-test/kubernetes/pod-definitions.yaml rename to test-c/kube-test/kubernetes/pod-definitions.yaml index f15e552fbe3..d9104b67f70 100644 --- a/extras/hs-test/kubernetes/pod-definitions.yaml +++ b/test-c/kube-test/kubernetes/pod-definitions.yaml @@ -1,11 +1,11 @@ definitions: image-names: - - image: &hs-test - name: "hs-test/vpp:latest" + - image: &kube-test + name: "kube-test/vpp:latest" - image: &nginx-ldp - name: "hs-test/nginx-ldp:latest" + name: "kube-test/nginx-ldp:latest" - image: &ab - name: "hs-test/ab:latest" + name: "kube-test/ab:latest" container-names: - container: &client @@ -15,7 +15,7 @@ definitions: namespace-names: - namespace: &defaultNs - name: "hs-test" + name: "kube-test" worker-names: - worker: &worker1 @@ -26,7 +26,7 @@ definitions: pods: - name: "client-generic" image: - - <<: *hs-test + - <<: *kube-test container: - <<: *client worker: @@ -36,7 +36,7 @@ pods: - name: "server-generic" image: - - <<: *hs-test + - <<: *kube-test container: - <<: *server worker: diff --git a/extras/hs-test/kubernetes/registry.yaml b/test-c/kube-test/kubernetes/registry.yaml similarity index 100% rename from extras/hs-test/kubernetes/registry.yaml rename to test-c/kube-test/kubernetes/registry.yaml diff --git a/test-c/kube-test/resources/cert/localhost.crt b/test-c/kube-test/resources/cert/localhost.crt new file mode 100644 index 00000000000..b21fb48906e --- /dev/null +++ b/test-c/kube-test/resources/cert/localhost.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDZTCCAk2gAwIBAgIUF116CAipHqQBCyAEvNesV0u4u0swDQYJKoZIhvcNAQEL +BQAwQjELMAkGA1UEBhMCU0sxEDAOBgNVBAgMB1ZwcExhbmQxITAfBgNVBAoMGElu +dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA1MjkxMDI0MjhaFw0yNDA1Mjgx +MDI0MjhaMEIxCzAJBgNVBAYTAlNLMRAwDgYDVQQIDAdWcHBMYW5kMSEwHwYDVQQK +DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCy40rDzrrHPGIyhP24hOBQefEgKD5uUGgSUyJTCur4yB/r2PGt +LlfipKwDmNArmZuFOgKh8evipu2jYaxf4GHQmi7PGLddvPkqo5FWtVW8oAVJMcp+ +fwfs7OgkqtYD6Y7qjmjfXb9+rMpPN8WZ7cKbJwZpF3lf8GGaLqRmPiQg2j8qzcVy +nz8cIwBZP8BJVclA9GIagijY7Zcmz0HnTPrPoLMeyLJOTqPMfkUYA2H2eHeISkQP +BeoFoiwCI5eM35UiWiLyiv9Kojn4BHx6MLrfKBjV13WtcRMgYm5VftsWOZ92lmHm +bpj9mGgtd84JWtWxs33oG4mNRSAeujf9AE5VAgMBAAGjUzBRMB0GA1UdDgQWBBTj +s+A5M/Cao+0Phgg6xFBKIPxLqjAfBgNVHSMEGDAWgBTjs+A5M/Cao+0Phgg6xFBK +IPxLqjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQB3EcGDby5u +cEGjgAFR18kH4ztnYUdZUrPI72sOFfjRLtJpx00n759SBawqNW1Y2a1QRd+GgUBK +YpYd2gzWYFjf/4c5BN4SrjeZGnQ8N0YomqqGKvOQO0YdYK4i/lWJjLRaLiVBn9EX +Z+odYhGqQgoAJHnm5Mmqhx9ts8qxZLbdsh+T93mKvj+/yuai2Is+AJfLgZpdKPQN +bCoZemRm+nghRvEP8aX/469wiz7SOLqUzxrTOtXV48wTU5LWLDCs1lF9ZdGHR9/r +vj8unnEHIZiH3ZjN7OgaAoNHZE26Ywbmllc/a0vPw8iHdrLe7+Wtp4zXe2rcxhW7 +b+X1/yRCZ+Wg +-----END CERTIFICATE----- diff --git a/test-c/kube-test/resources/cert/localhost.key b/test-c/kube-test/resources/cert/localhost.key new file mode 100644 index 00000000000..2d65db50900 --- /dev/null +++ b/test-c/kube-test/resources/cert/localhost.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCy40rDzrrHPGIy +hP24hOBQefEgKD5uUGgSUyJTCur4yB/r2PGtLlfipKwDmNArmZuFOgKh8evipu2j +Yaxf4GHQmi7PGLddvPkqo5FWtVW8oAVJMcp+fwfs7OgkqtYD6Y7qjmjfXb9+rMpP +N8WZ7cKbJwZpF3lf8GGaLqRmPiQg2j8qzcVynz8cIwBZP8BJVclA9GIagijY7Zcm +z0HnTPrPoLMeyLJOTqPMfkUYA2H2eHeISkQPBeoFoiwCI5eM35UiWiLyiv9Kojn4 +BHx6MLrfKBjV13WtcRMgYm5VftsWOZ92lmHmbpj9mGgtd84JWtWxs33oG4mNRSAe +ujf9AE5VAgMBAAECggEANwiZ/bdh2t2G0Ef9zoCCif+Z4OzAmCuAePK+gpG/TB41 +Q9eQMlkpjH5gtRKUKHWvVMNOAAhvK2FzhmoMH8rmDMkCUZAnCV2TwjxkACr1X3xT +Y/s/cr8d7xPLL0ynXrjB0QNS3DT5Lr111/0ue3acAiN1Y2tnWc6YGFj1FsdTUg+O +zRysrpNUp3LAK+MXIhAXMCGKOOLxpjeyrcnUokH0I8e06of1AfAHX8jTn65MG5Ex +n9wBYPl+u2J3SjILHoqBKjcSoNILUfBN9mQGeXhoqCzwcnygDtOxIu9xgu2nCcJr +C1R/WXoQ8Jr6wa1n0aEVXDJeOEK9kKXLTt2/I4HB2QKBgQDemLy+o2/tbFwlU2Xy +8/tZa30kfLCAZ+kq+lE3Kkfqt3pPYzH+lfO7u/UWtavKRQRdsKsNKbpe/EdGq7c4 +YN3L1KG5JiIo3TxilUPilYacGHklfMMbEK7cs8Jebsl6rL7BgnKuqlXGY0HEEx8L +XqIKN1RdzL04WLOiA8qDGwYp7wKBgQDNu3DECCTkTa+mZdNDRntoffkgyd0AnwPA +PEf43BHORpKcfGwFIrf8QWRXcLdh72Yrc9o3D53GCq+NSYGPL2OiY+/3HoAy1mH1 +EBgS08qfkZBKr6+VGjWuVAlD2m2jW+AhGXMS+Lu4yzK3V+0EzlAu4WZVBUngg1// +6ZtyvXLf+wKBgQCozmO0nvUutFJc7BYQXP5sHZvVo8mmVyb4NMSKdUH8ug/DTJKJ +YuZnpG6FPlh9GEHrWyMc5Fw11FOpQGe+FZeeEC5k3ophOwWkLVZB6useTWDyEN9V +Ex3IuXnZa2LX6VDwJyEZXIuX24XwUB/m22k/Hh6Y079bj8kKQJ2/NytBeQKBgQCZ +RGMmJ8sUKqwJEyLoo8GcfvzyaHC03cI1nLMhuxGo0vq2ihsPWGYpD65pVhfIZkl/ +ZbfT/VZVC/DtGS3kNjHL8Rf8ykRHm18u6uaEYDQ73H3apjfwpK4JSaH9YuT7Jp87 +CXKpV5TCft8xp9d0FR+3TUSnYmE/WaBTTv335RuHsQKBgCFLyxzs0hM/MhCLHJ6b +AqyNPz36Xcwsgit1Svhwm1IC6FqkSJl3cRKhp1AP5w6ktUfUGNpF/TYI3x2jCg/m +c0nwmqi/3Cha64XKJcI4iT2+lyuE8jXovMdNiJEEKCDalpyYJbhzRaLsoSFSbiD1 +mFDl8/aNVaQKDDboSuj9AkKs +-----END PRIVATE KEY----- diff --git a/test-c/kube-test/resources/nginx/html/index.html b/test-c/kube-test/resources/nginx/html/index.html new file mode 100644 index 00000000000..6b7c97d7542 --- /dev/null +++ b/test-c/kube-test/resources/nginx/html/index.html @@ -0,0 +1,6 @@ + + nginx docker with quic + +

Greetings!

+ +
diff --git a/test-c/kube-test/resources/nginx/nginx.conf b/test-c/kube-test/resources/nginx/nginx.conf new file mode 100644 index 00000000000..7eac45c927f --- /dev/null +++ b/test-c/kube-test/resources/nginx/nginx.conf @@ -0,0 +1,31 @@ +master_process on; +worker_rlimit_nofile 10240; +worker_processes {{.Workers}}; +daemon off; + +events { + use epoll; + worker_connections 10240; + accept_mutex off; + multi_accept off; +} + +http { + keepalive_timeout 300s; + keepalive_requests 1000000; + sendfile on; + server { + listen {{.Port}}; + listen [::]:{{.Port}}; + root /usr/share/nginx; + index index.html index.htm; + location /return_ok + { + return 200 ''; + } + location /64B.json + { + return 200 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; + } + } +} diff --git a/test-c/kube-test/resources/nginx/nginx_http3.conf b/test-c/kube-test/resources/nginx/nginx_http3.conf new file mode 100644 index 00000000000..c09867576d6 --- /dev/null +++ b/test-c/kube-test/resources/nginx/nginx_http3.conf @@ -0,0 +1,27 @@ +master_process on; +worker_processes 2; +daemon off; + +error_log /tmp/nginx/{{.LogPrefix}}-error.log info; + +events { + use epoll; + accept_mutex off; + multi_accept off; +} + +http { + quic_gso on; + quic_retry off; + + access_log /tmp/nginx/{{.LogPrefix}}-access.log; + keepalive_timeout 300s; + sendfile on; + server { + listen {{.Address}}:{{.Port}} quic; + root /usr/share/nginx; + ssl_certificate /etc/nginx/ssl/localhost.crt; + ssl_certificate_key /etc/nginx/ssl/localhost.key; + index index.html index.htm; + } +} diff --git a/test-c/kube-test/resources/nginx/nginx_proxy_mirroring.conf b/test-c/kube-test/resources/nginx/nginx_proxy_mirroring.conf new file mode 100644 index 00000000000..9e0f276b02a --- /dev/null +++ b/test-c/kube-test/resources/nginx/nginx_proxy_mirroring.conf @@ -0,0 +1,85 @@ +master_process on; +worker_processes {{.Workers}}; +worker_rlimit_nofile 102400; +daemon off; + +error_log /tmp/nginx/{{.LogPrefix}}-error.log info; + +events { + use epoll; + worker_connections 102400; + accept_mutex off; +} + +http { + include mime.types; + default_type application/octet-stream; + + access_log off; + + keepalive_timeout 300; + keepalive_requests 1000000; + + proxy_connect_timeout 300; + large_client_header_buffers 4 512k; + client_max_body_size 3000m; + client_header_buffer_size 2048m; + client_body_buffer_size 1024m; + proxy_buffers 16 10240k; + proxy_buffer_size 10240k; + + gzip on; + + upstream bk { + server {{.Server}}:{{.Upstream1}}; + keepalive 30000; + } + upstream bk1 { + server {{.Server}}:{{.Upstream2}}; + keepalive 30000; + } + upstream bk2 { + server {{.Server}}:{{.Upstream3}}; + keepalive 30000; + } + + server { + access_log /tmp/nginx/{{.LogPrefix}}-access.log; + listen {{.Port}}; + server_name {{.Proxy}}; + + server_tokens off; + + proxy_redirect off; + + location / { + root html; + index index.html index.htm; + proxy_pass http://bk; + proxy_set_header Connection ""; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header Host $host:$server_port; + chunked_transfer_encoding on; + proxy_http_version 1.1; + mirror /mimic1; + mirror /mimic2; + mirror_request_body on; + } + location /mimic1 { + proxy_pass http://bk1$request_uri; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header Connection ""; + chunked_transfer_encoding on; + proxy_http_version 1.1; + proxy_set_header Host $host:$server_port; + } + location /mimic2 { + proxy_pass http://bk2$request_uri; + proxy_set_header X-Original-URI $request_uri; + proxy_set_header Host $host:$server_port; + proxy_set_header Connection ""; + proxy_http_version 1.1; + chunked_transfer_encoding on; + } + } +} diff --git a/test-c/kube-test/resources/nginx/nginx_server.conf b/test-c/kube-test/resources/nginx/nginx_server.conf new file mode 100644 index 00000000000..f5e4f9e4857 --- /dev/null +++ b/test-c/kube-test/resources/nginx/nginx_server.conf @@ -0,0 +1,61 @@ +master_process on; +worker_rlimit_nofile 10240; +worker_processes 2; +daemon off; + +error_log /tmp/nginx/{{.LogPrefix}}-error.log info; + +events { + use epoll; + worker_connections 10240; + accept_mutex off; + multi_accept off; +} + +http { + log_format access_log_fmt '$remote_addr - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent" ' + 'scheme=$scheme conn=$connection conn_reqs=$connection_requests'; + keepalive_timeout 300s; + keepalive_requests 1000000; + client_body_timeout {{.Timeout}}s; + client_header_timeout {{.Timeout}}s; + send_timeout {{.Timeout}}s; + sendfile on; + server { + access_log /tmp/nginx/{{.LogPrefix}}-access.log access_log_fmt; + listen {{.Port}}; + listen {{.PortSsl}} ssl; + server_name {{.Address}}; + root /usr/share/nginx; + ssl_certificate /etc/nginx/ssl/localhost.crt; + ssl_certificate_key /etc/nginx/ssl/localhost.key; + http2 {{.Http2}}; + index index.html index.htm; + # to allow POST on static pages + error_page 405 =200 $uri; + location ~ "/upload/([0-9a-zA-Z-.]*)$" { + alias /usr/share/nginx/upload/$1; + client_body_temp_path /tmp; + client_max_body_size 200M; + dav_methods PUT; + create_full_put_path off; + dav_access all:rw; + } + location /64B { + return 200 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; + } + location / { + sendfile on; + } + # HTTP2 will not wait for the post body and return 200 + location = /test_upload { + proxy_pass http://127.0.0.1:{{.Port}}/dev-null; + } + location = /dev-null { + return 200; + } + # HTTP2 upload fix end + } +} diff --git a/test-c/kube-test/resources/nginx/nginx_server_mirroring.conf b/test-c/kube-test/resources/nginx/nginx_server_mirroring.conf new file mode 100644 index 00000000000..3c28dbfeec8 --- /dev/null +++ b/test-c/kube-test/resources/nginx/nginx_server_mirroring.conf @@ -0,0 +1,33 @@ +master_process on; +worker_rlimit_nofile 10240; +worker_processes 2; +daemon off; + +error_log /tmp/nginx/{{.LogPrefix}}-error.log info; + +events { + use epoll; + worker_connections 10240; + accept_mutex off; + multi_accept off; +} + +http { + keepalive_timeout 300s; + keepalive_requests 1000000; + sendfile on; + server { + access_log /tmp/nginx/{{.LogPrefix}}-access.log; + listen {{.Address}}:{{.Upstream1}}; + listen {{.Address}}:{{.Upstream2}}; + listen {{.Address}}:{{.Upstream3}}; + root /usr/share/nginx; + index index.html index.htm; + location /64B { + return 200 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; + } + location / { + sendfile on; + } + } +} diff --git a/test-c/kube-test/resources/nginx/vcl.conf b/test-c/kube-test/resources/nginx/vcl.conf new file mode 100644 index 00000000000..27699248bcf --- /dev/null +++ b/test-c/kube-test/resources/nginx/vcl.conf @@ -0,0 +1,10 @@ +vcl { + heapsize 64M + segment-size 4000000000 + add-segment-size 4000000000 + rx-fifo-size 4000000 + tx-fifo-size 4000000 + event-queue-size 100000 + use-mq-eventfd + app-socket-api /tmp/nginx/var/run/app_ns_sockets/default +} diff --git a/test-c/kube-test/script/build-images.sh b/test-c/kube-test/script/build-images.sh new file mode 100755 index 00000000000..aa76304ac9a --- /dev/null +++ b/test-c/kube-test/script/build-images.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +# Build script for all Docker images based on the common base image + +set -e + +# Get default architecture for multi-arch builds +ARCH=${OS_ARCH:-$(dpkg --print-architecture)} +CODENAME=$(lsb_release -cs) + +# Set up buildx configuration +DOCKER_BUILD_DIR="/scratch/docker-build" +DOCKER_CACHE_DIR="${DOCKER_BUILD_DIR}/docker_cache" +DOCKER_HST_BUILDER="hst_builder" +DOCKER_LOGIN_SCRIPT="/scratch/nomad/.docker-ro/dlogin.sh" + +if [ -d "${DOCKER_BUILD_DIR}" ] ; then + mkdir -p "${DOCKER_CACHE_DIR}" + + if [ -x "$DOCKER_LOGIN_SCRIPT" ] ; then + $DOCKER_LOGIN_SCRIPT + fi + + # Create buildx builder if it doesn't exist + if ! docker buildx ls --format "{{.Name}}" | grep -q "${DOCKER_HST_BUILDER}"; then + docker buildx create --use \ + --driver-opt env.http_proxy="$HTTP_PROXY" \ + --driver-opt env.https_proxy="$HTTP_PROXY" \ + --driver-opt '"env.no_proxy='"$NO_PROXY"'"' \ + --name=${DOCKER_HST_BUILDER} \ + --driver=docker-container \ + --use --bootstrap || true + fi + + DOCKER_CACHE_ARGS="--builder=${DOCKER_HST_BUILDER} --load --cache-to type=local,dest=${DOCKER_CACHE_DIR},mode=max --cache-from type=local,src=${DOCKER_CACHE_DIR}" +fi + +# Set the tag for the base image +BASE_TAG=${BASE_TAG:-"localhost:5001/vpp-kube-test-base:latest"} + +echo "=== Building base image ===" +# shellcheck disable=2086 +docker buildx build ${DOCKER_CACHE_ARGS} \ + --build-arg UBUNTU_VERSION="${UBUNTU_VERSION:-22.04}" \ + --build-arg http_proxy="$HTTP_PROXY" \ + --build-arg https_proxy="$HTTP_PROXY" \ + --build-arg HTTP_PROXY="$HTTP_PROXY" \ + --build-arg HTTPS_PROXY="$HTTP_PROXY" \ + -t $BASE_TAG -f docker/Dockerfile.base . || { + echo "Error: Failed to build base image" + exit 1 +} + +# Push the base image to the local registry +docker push $BASE_TAG || { + echo "Error: Failed to push base image to local registry" + exit 1 +} + +# Function to build each image +build_image() { + local dockerfile="docker/$1" + local tag=$2 + local add_args="${3:-}" + + if [ ! -f "$dockerfile" ]; then + echo "Warning: Dockerfile $dockerfile doesn't exist, skipping" + return 0 + fi + + echo "=== Building $tag from $dockerfile ===" + echo "Building with architecture: $ARCH" + + # Check if the necessary files for VPP-based images are available + if [[ "$dockerfile" == *"vpp"* || "$dockerfile" == *"nginx"* || "$dockerfile" == *"vcl"* ]]; then + # Check for essential VPP files + for file in vpp-data/bin/vpp vpp-data/lib/*.so; do + if [ ! -e "$file" ]; then + echo "Warning: Required VPP file $file doesn't exist." + fi + done + fi + + # Build the image + # shellcheck disable=2086 + docker build \ + --build-arg UBUNTU_VERSION="${UBUNTU_VERSION:-22.04}" \ + --build-arg OS_ARCH="$ARCH" \ + --build-arg CODENAME="$CODENAME" \ + --build-arg http_proxy="$HTTP_PROXY" \ + --build-arg https_proxy="$HTTP_PROXY" \ + --build-arg HTTP_PROXY="$HTTP_PROXY" \ + --build-arg HTTPS_PROXY="$HTTP_PROXY" \ + $add_args \ + -t "$tag" \ + -f "$dockerfile" . || { + echo "Error: Failed to build $tag" + return 1 + } + + echo "=== Successfully built and pushed $tag ===" +} + +# Build all standard images +echo "=== Building standard images ===" +build_image "Dockerfile.vpp" "kube-test/vpp" +build_image "Dockerfile.nginx" "kube-test/nginx-ldp" +build_image "Dockerfile.ab" "kube-test/ab" +build_image "Dockerfile.wrk" "kube-test/wrk" + +# make cache directory multi-user friendly if it exists +if [ -d "${DOCKER_CACHE_DIR}" ] ; then + chgrp -R docker "${DOCKER_CACHE_DIR}" 2>/dev/null || true + chmod -R g+rwx "${DOCKER_CACHE_DIR}" 2>/dev/null || true +fi + +# cleanup detached images +images=$(docker images --filter "dangling=true" -q --no-trunc) +if [ -n "$images" ]; then + echo "=== Cleaning up dangling images ===" + # shellcheck disable=SC2086 + docker rmi $images || true +fi + +echo "=== All container images built successfully ===" diff --git a/test-c/kube-test/script/build_kube.sh b/test-c/kube-test/script/build_kube.sh new file mode 100755 index 00000000000..11c278d8233 --- /dev/null +++ b/test-c/kube-test/script/build_kube.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +if [ "$(lsb_release -is)" != Ubuntu ]; then + echo "Host stack test framework is supported only on Ubuntu" + exit 1 +fi + +export VPP_WS=../.. +export UBUNTU_VERSION=${UBUNTU_VERSION:-"$(lsb_release -rs)"} +echo "Ubuntu version is set to ${UBUNTU_VERSION}" + +if [ "$1" == "debug" ]; then + VPP_BUILD_ROOT=${VPP_WS}/build-root/build-vpp_debug-native/vpp +else + VPP_BUILD_ROOT=${VPP_WS}/build-root/build-vpp-native/vpp +fi + +LAST_STATE_FILE=".last_state_hash" + +# get current state hash and ubuntu version +ctime_hash1=$(stat -c %Z "$VPP_BUILD_ROOT"/.mu_build_install_timestamp | sha1sum | awk '{print $1}') +ctime_hash2=$(stat -c %Z docker/* | sha1sum | awk '{print $1}') +current_state_hash=$ctime_hash1-$ctime_hash2-$UBUNTU_VERSION$1 + +if [ -f "$LAST_STATE_FILE" ]; then + last_state_hash=$(cat "$LAST_STATE_FILE") +else + last_state_hash="" +fi + +# compare current state with last state and check FORCE_BUILD +if [ "$current_state_hash" = "$last_state_hash" ] && [ "$2" = "false" ]; then + echo "*** Skipping docker build - no new changes ***" + exit 0 +fi + +OS_ARCH="$(uname -m)" +DOCKER_BUILD_DIR="/scratch/docker-build" +DOCKER_CACHE_DIR="${DOCKER_BUILD_DIR}/docker_cache" +DOCKER_LOGIN_SCRIPT="/scratch/nomad/.docker-ro/dlogin.sh" +REGISTRY_PORT=5001 +if [ -x "$DOCKER_LOGIN_SCRIPT" ] ; then + $DOCKER_LOGIN_SCRIPT +fi + +# Set up the local registry before creating containers +echo "=== Setting up local registry ===" +if [ -x "$(dirname "$0")/../docker/setup-local-registry.sh" ]; then + "$(dirname "$0")/../docker/setup-local-registry.sh" "$REGISTRY_PORT" +else + echo "Warning: setup-local-registry.sh not found or not executable" + echo "Attempting to create and use local registry at localhost:5000" + if ! docker ps | grep -q "local-registry"; then + docker run -d --restart=always -p $REGISTRY_PORT:5000 --name local-registry registry:2 + fi +fi + +echo "Taking build objects from ${VPP_BUILD_ROOT}" + +export PATH=${VPP_BUILD_ROOT}/bin:$PATH + +bin=vpp-data/bin +lib=vpp-data/lib + +mkdir -p ${bin} ${lib} || true +rm -rf vpp-data/bin/* || true +rm -rf vpp-data/lib/* || true + +declare -i res=0 +cp ${VPP_BUILD_ROOT}/bin/* ${bin} +res+=$? +cp -r ${VPP_BUILD_ROOT}/lib/"${OS_ARCH}"-linux-gnu/* ${lib} +res+=$? +if [ "$res" -ne 0 ]; then + echo "Failed to copy VPP files. Is VPP built? Try running 'make build' in VPP directory." + exit 1 +fi + +# Use the build-images.sh script to build all containers +echo "=== Building all containers using build-images.sh ===" +( + # Export necessary environment variables for build-images.sh + export BASE_TAG="localhost:$REGISTRY_PORT/vpp-test-base:latest" + export OS_ARCH + export UBUNTU_VERSION + export HTTP_PROXY + export HTTPS_PROXY + export NO_PROXY + export DOCKER_CACHE_DIR="${DOCKER_CACHE_DIR}" + export DOCKER_HST_BUILDER="${DOCKER_HST_BUILDER}" + + # Run the build script + ./script/build-images.sh +) + +# Check if the build was successful +if [ $? -ne 0 ]; then + echo "Failed to build Docker images. Check the output above for errors." + exit 1 +fi + +echo "$current_state_hash" > "$LAST_STATE_FILE" diff --git a/test-c/kube-test/script/compress.sh b/test-c/kube-test/script/compress.sh new file mode 100755 index 00000000000..fed2164c6fe --- /dev/null +++ b/test-c/kube-test/script/compress.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +if [ $1 == 2 ] +then + exit 1 +fi + +# if failed-summary.log is not empty, exit status = 1 +if [ -s "${HS_ROOT}/summary/failed-summary.log" ] +then + if [ -n "${WORKSPACE}" ] + then + echo -n "Copying docker logs..." + dirs=$(jq -r '.[0] | .SpecReports[] | select((.State == "failed") or (.State == "timedout") or (.State == "panicked")) | .LeafNodeText | split("/")[1]' ${HS_ROOT}/summary/report.json) + for dirName in $dirs; do + logDir=/tmp/kube-test/$dirName + if [ -d "$logDir" ]; then + mkdir -p ${WORKSPACE}/archives/summary + rsync -a --exclude 'vol' $logDir ${WORKSPACE}/archives/summary/ + fi + done + echo "Done." + + echo -n "Copying failed test logs into build log archive directory (${WORKSPACE}/archives)... " + mkdir -p ${WORKSPACE}/archives/summary + cp -a ${HS_ROOT}/summary/* ${WORKSPACE}/archives/summary + echo "Done." + + echo -n "Compressing files in ${WORKSPACE}/archives from test runs... " + cd ${WORKSPACE}/archives + find . -type f \( -name "*.json" -o -name "*.log" \) -exec gzip {} \; + echo "Done." + + else + echo "Not compressing files in temporary directories from test runs." + fi + echo "*************************** SUMMARY ***************************" + cat "${HS_ROOT}/summary/failed-summary.log" + exit 1 +else + exit $1 +fi diff --git a/test-c/kube-test/script/nginx_ldp.sh b/test-c/kube-test/script/nginx_ldp.sh new file mode 100755 index 00000000000..416aa5499af --- /dev/null +++ b/test-c/kube-test/script/nginx_ldp.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC2068 +$1 -v && LD_PRELOAD=$LDP $@ > /proc/1/fd/1 2>&1 diff --git a/extras/hs-test/kubernetes/setup-cluster.sh b/test-c/kube-test/script/setup-cluster.sh similarity index 92% rename from extras/hs-test/kubernetes/setup-cluster.sh rename to test-c/kube-test/script/setup-cluster.sh index c7dbdff1f9e..296a7b42899 100755 --- a/extras/hs-test/kubernetes/setup-cluster.sh +++ b/test-c/kube-test/script/setup-cluster.sh @@ -4,10 +4,11 @@ set -e COMMAND=$1 CALICOVPP_DIR="$HOME/vpp-dataplane" VPP_DIR=$(pwd) -VPP_DIR=${VPP_DIR%extras*} +VPP_DIR=${VPP_DIR%test-c*} COMMIT_HASH=$(git rev-parse HEAD) reg_name='kind-registry' reg_port='5000' +BASE=${BASE:-"$COMMIT_HASH"} export CALICO_NETWORK_CONFIG=${CALICO_NETWORK_CONFIG:-"mtu: 9000"} export CALICOVPP_VERSION="${CALICOVPP_VERSION:-latest}" @@ -58,7 +59,8 @@ help() { echo "Usage:" echo -e " make master-cluster | rebuild-master-cluster | release-cluster\n" - echo "'master-cluster' pulls CalicoVPP and builds VPP from this directory, then brings up a KinD cluster." + echo "'master-cluster' pulls CalicoVPP and builds VPP from this directory, then brings up a KinD cluster. You can + override the version with: BASE=[(remote or local branch) | (commit hash)], e.g. BASE=origin/master" echo "'rebuild-master-cluster' stops CalicoVPP pods, rebuilds VPP and restarts CalicoVPP pods. Cluster keeps running." echo "'release-cluster' starts up a KinD cluster and uses latest CalicoVPP release (e.g. v3.29), or you can override versions by using env variables 'CALICOVPP_VERSION' and 'TIGERA_VERSION': @@ -93,12 +95,12 @@ cherry_pick() { STASHED_CHANGES=0 echo "checkpoint: $COMMIT_HASH" # chery-vpp hard resets the repo to a commit - we want to keep our changes - if [[ -n $(git status --porcelain) ]]; then + if ! git diff --quiet; then echo "Saving stash" - git stash save "HST: temp stash" + git stash push -u STASHED_CHANGES=1 fi - make -C $CALICOVPP_DIR cherry-vpp FORCE=y BASE=origin/master VPP_DIR=$VPP_DIR + make -C $CALICOVPP_DIR cherry-vpp FORCE=y BASE=$BASE VPP_DIR=$VPP_DIR # pop the stash to build VPP with CalicoVPP's patches + our changes if [ $STASHED_CHANGES -eq 1 ]; then @@ -107,7 +109,7 @@ cherry_pick() { } build_load_start_cni() { - make -C $VPP_DIR/extras/hs-test build-vpp-release + make -C $VPP_DIR/test-c/kube-test build-vpp-release make -C $CALICOVPP_DIR dev-kind make -C $CALICOVPP_DIR load-kind kubectl create --save-config -f kubernetes/calico-config.yaml @@ -115,9 +117,9 @@ build_load_start_cni() { restore_repo() { # stash changes, reset local repo to the original state and unstash changes (removes CalicoVPP's patches) - if [[ -n $(git status --porcelain) ]]; then + if ! git diff --quiet; then echo "Saving stash" - git stash save "HST: temp stash" + git stash push -u git reset --hard $COMMIT_HASH git stash pop else @@ -131,7 +133,7 @@ setup_master() { else cd $CALICOVPP_DIR git pull - cd $VPP_DIR/extras/hs-test + cd $VPP_DIR/test-c/kube-test fi echo -e "$kind_config" | kind create cluster --config=-