gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/benchmarks/base/base.go (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package base holds utility methods common to the base tests.
    16  package base
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  	"time"
    23  
    24  	"gvisor.dev/gvisor/pkg/test/dockerutil"
    25  	"gvisor.dev/gvisor/test/benchmarks/harness"
    26  )
    27  
    28  // ServerArgs wraps args for startServers and runServerWorkload.
    29  type ServerArgs struct {
    30  	Machine harness.Machine
    31  	Port    int
    32  	RunOpts dockerutil.RunOpts
    33  	Cmd     []string
    34  }
    35  
    36  // StartServers starts b.N containers defined by 'runOpts' and 'cmd' and uses
    37  // 'machine' to check that each is up.
    38  func StartServers(ctx context.Context, b *testing.B, args ServerArgs) []*dockerutil.Container {
    39  	b.Helper()
    40  	servers := make([]*dockerutil.Container, 0, b.N)
    41  
    42  	// Create N servers and wait until each of them is serving.
    43  	for i := 0; i < b.N; i++ {
    44  		server, err := StartServer(ctx, b, args)
    45  		if err != nil {
    46  			CleanUpContainers(ctx, servers)
    47  			b.Fatalf("failed to start server: %v", err)
    48  		}
    49  		servers = append(servers, server)
    50  	}
    51  	return servers
    52  }
    53  
    54  // StartServer starts a single server and cleans it up if it fails.
    55  func StartServer(ctx context.Context, b *testing.B, args ServerArgs) (*dockerutil.Container, error) {
    56  	server := args.Machine.GetContainer(ctx, b)
    57  	if err := server.Spawn(ctx, args.RunOpts, args.Cmd...); err != nil {
    58  		server.CleanUp(ctx)
    59  		return server, fmt.Errorf("failed to spawn server: %v", err)
    60  	}
    61  	// Wait until server is running.
    62  	if err := harness.WaitUntilContainerServing(ctx, args.Machine, server, args.Port); err != nil {
    63  		server.CleanUp(ctx)
    64  		return server, fmt.Errorf("failed to wait for serving server %q: %v", server.Name, err)
    65  	}
    66  	return server, nil
    67  }
    68  
    69  // CleanUpContainers cleans up a slice of containers.
    70  func CleanUpContainers(ctx context.Context, containers []*dockerutil.Container) {
    71  	for _, c := range containers {
    72  		if c != nil {
    73  			c.CleanUp(ctx)
    74  		}
    75  	}
    76  }
    77  
    78  // RedisInstance returns a Redis container and its reachable IP.
    79  func RedisInstance(ctx context.Context, b *testing.B, machine harness.Machine) *dockerutil.Container {
    80  	b.Helper()
    81  	// Spawn a redis instance for the app to use.
    82  	redis := machine.GetNativeContainer(ctx, b)
    83  	if err := redis.Spawn(ctx, dockerutil.RunOpts{
    84  		Image: "benchmarks/redis",
    85  	}); err != nil {
    86  		redis.CleanUp(ctx)
    87  		b.Fatalf("failed to spawn redis instance: %v", err)
    88  	}
    89  
    90  	if out, err := redis.WaitForOutput(ctx, "Ready to accept connections", 3*time.Second); err != nil {
    91  		redis.CleanUp(ctx)
    92  		b.Fatalf("failed to start redis server: %v %s", err, out)
    93  	}
    94  	return redis
    95  }