Path: blob/main/test/tests/workspace/process_limit_test.go
2498 views
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package workspace56import (7"context"8"errors"9"strings"10"testing"11"time"1213agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api"14"github.com/gitpod-io/gitpod/test/pkg/integration"15wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api"16"sigs.k8s.io/e2e-framework/pkg/envconf"17"sigs.k8s.io/e2e-framework/pkg/features"18)1920func TestProcessLimit(t *testing.T) {21f := features.New("process limit").22WithLabel("component", "workspace").23WithLabel("type", "process limit").24Assess("it has a proc limit", func(testCtx context.Context, t *testing.T, cfg *envconf.Config) context.Context {25t.Parallel()2627ctx, cancel := context.WithTimeout(testCtx, time.Duration(5*time.Minute))28defer cancel()2930api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client())31t.Cleanup(func() {32api.Done(t)33})3435nfo, stopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api)36if err != nil {37t.Fatal(err)38}3940t.Cleanup(func() {41sctx, scancel := context.WithTimeout(context.Background(), 5*time.Minute)42defer scancel()4344sapi := integration.NewComponentAPI(sctx, cfg.Namespace(), kubeconfig, cfg.Client())45defer sapi.Done(t)4647if _, err = stopWs(true, sapi); err != nil {48t.Errorf("cannot stop workspace: %v", err)49}50})5152rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(), integration.WithInstanceID(nfo.Req.Id))53integration.DeferCloser(t, closer)54if err != nil {55t.Fatalf("unexpected error instrumenting workspace: %v", err)56}57defer rsa.Close()5859// Sometimes the workspace stops once we run out of processes (supervisor will exit with a failure),60// so also start watching for the workspace to stop and observe its exit status.61ready := make(chan struct{}, 1)62stopStatus := make(chan *wsmanapi.WorkspaceStatus, 1)63go func() {64status, err := integration.WaitForWorkspaceStop(t, ctx, ready, api, nfo.Req.Id, nfo.WorkspaceID, integration.WorkspaceCanFail)65if err != nil {66if !errors.Is(err, context.Canceled) {67// If context got canceled, we're just shutting down the test68// and the workspace didn't exit due to reaching the process limit.69t.Errorf("error waiting for workspace stop: %v", err)70}71stopStatus <- nil72return73}7475t.Logf("workspace stopped: %v", stopStatus)76stopStatus <- status77}()7879t.Logf("creating processes")80var res agent.ExecResponse81err = rsa.Call("WorkspaceAgent.Exec", &agent.ExecRequest{82Dir: "/workspace",83Command: "bash",84Args: []string{"-c", "timeout 20s bash -c 'while true; do sleep 20 && date & done'"},85}, &res)86if err != nil {87t.Logf("exec failed, most likely the workspace failed due to the process limit, so check for workspace failure status instead. Exec err: %v", err)88select {89case <-ctx.Done():90t.Fatalf("expected workspace to stop, but it didn't")91case s := <-stopStatus:92if s == nil {93t.Fatalf("there was an error getting the workspace stop status")94}9596if s.Conditions == nil || s.Conditions.Failed == "" {97t.Fatalf("expected workspace to fail, but it didn't: %v", s)98}99t.Logf("workspace stopped and failed (as expected): %v", s)100}101return testCtx102}103104t.Logf("checking output for fork errors due to process limiting")105if !strings.Contains(res.Stdout, "bash: fork: retry: Resource temporarily unavailable") {106t.Errorf("expected fork error (Resource temporarily unavailable), but got none (%d): %s", res.ExitCode, res.Stdout)107}108109return testCtx110}).111Feature()112113testEnv.Test(t, f)114}115116117