github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/runtimes/proctor/main.go (about)

     1  // Copyright 2019 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  // Binary proctor runs the test for a particular runtime. It is meant to be
    16  // included in Docker images for all runtime tests.
    17  package main
    18  
    19  import (
    20  	"flag"
    21  	"fmt"
    22  	"log"
    23  	"os"
    24  	"strings"
    25  
    26  	"golang.org/x/sys/unix"
    27  	"github.com/SagerNet/gvisor/test/runtimes/proctor/lib"
    28  )
    29  
    30  var (
    31  	runtime   = flag.String("runtime", "", "name of runtime")
    32  	list      = flag.Bool("list", false, "list all available tests")
    33  	testNames = flag.String("tests", "", "run a subset of the available tests")
    34  	pause     = flag.Bool("pause", false, "cause container to pause indefinitely, reaping any zombie children")
    35  )
    36  
    37  // setNumFilesLimit changes the NOFILE soft rlimit if it is too high.
    38  func setNumFilesLimit() error {
    39  	// In docker containers, the default value of the NOFILE limit is
    40  	// 1048576. A few runtime tests (e.g. python:test_subprocess)
    41  	// enumerates all possible file descriptors and these tests can fail by
    42  	// timeout if the NOFILE limit is too high. On gVisor, syscalls are
    43  	// slower so these tests will need even more time to pass.
    44  	const nofile = 32768
    45  	rLimit := unix.Rlimit{}
    46  	err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rLimit)
    47  	if err != nil {
    48  		return fmt.Errorf("failed to get RLIMIT_NOFILE: %v", err)
    49  	}
    50  	if rLimit.Cur > nofile {
    51  		rLimit.Cur = nofile
    52  		err := unix.Setrlimit(unix.RLIMIT_NOFILE, &rLimit)
    53  		if err != nil {
    54  			return fmt.Errorf("failed to set RLIMIT_NOFILE: %v", err)
    55  		}
    56  	}
    57  	return nil
    58  }
    59  
    60  func main() {
    61  	flag.Parse()
    62  
    63  	if *pause {
    64  		lib.PauseAndReap()
    65  		panic("pauseAndReap should never return")
    66  	}
    67  
    68  	if *runtime == "" {
    69  		log.Fatalf("runtime flag must be provided")
    70  	}
    71  
    72  	tr, err := lib.TestRunnerForRuntime(*runtime)
    73  	if err != nil {
    74  		log.Fatalf("%v", err)
    75  	}
    76  
    77  	// List tests.
    78  	if *list {
    79  		tests, err := tr.ListTests()
    80  		if err != nil {
    81  			log.Fatalf("failed to list tests: %v", err)
    82  		}
    83  		for _, test := range tests {
    84  			fmt.Println(test)
    85  		}
    86  		return
    87  	}
    88  
    89  	var tests []string
    90  	if *testNames == "" {
    91  		// Run every test.
    92  		tests, err = tr.ListTests()
    93  		if err != nil {
    94  			log.Fatalf("failed to get all tests: %v", err)
    95  		}
    96  	} else {
    97  		// Run subset of test.
    98  		tests = strings.Split(*testNames, ",")
    99  	}
   100  
   101  	if err := setNumFilesLimit(); err != nil {
   102  		log.Fatalf("%v", err)
   103  	}
   104  
   105  	// Run tests.
   106  	cmds := tr.TestCmds(tests)
   107  	for _, cmd := range cmds {
   108  		cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
   109  		if err := cmd.Run(); err != nil {
   110  			log.Fatalf("FAIL: %v", err)
   111  		}
   112  	}
   113  }