-
-
Notifications
You must be signed in to change notification settings - Fork 112
/
ulimit_linux_test.go
91 lines (82 loc) · 2.63 KB
/
ulimit_linux_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// Copyright (c) 2019, Daniel Martí <[email protected]>
// See LICENSE for licensing information
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"testing"
"github.com/go-quicktest/qt"
"golang.org/x/sys/unix"
)
func init() {
// Here rather than in TestMain, to reuse the unix build tag.
if limit := os.Getenv("TEST_WITH_FILE_LIMIT"); limit != "" {
n, err := strconv.ParseUint(limit, 10, 64)
if err != nil {
panic(err)
}
rlimit := unix.Rlimit{Cur: n, Max: n}
if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil {
panic(err)
}
os.Exit(main1())
}
}
func TestWithLowOpenFileLimit(t *testing.T) {
// Safe to run in parallel, as we only change the limit for child processes.
t.Parallel()
tempDir := t.TempDir()
testBinary, err := os.Executable()
qt.Assert(t, qt.IsNil(err))
const (
// Enough directories to run into the ulimit.
// Enough number of files in total to run into the ulimit.
numberDirs = 500
numberFilesPerDir = 20
numberFilesTotal = numberDirs * numberFilesPerDir
)
t.Logf("writing %d tiny Go files", numberFilesTotal)
var allGoFiles []string
for i := 0; i < numberDirs; i++ {
// Prefix "p", so the package name is a valid identifier.
// Add one go.mod file per directory as well,
// which will help catch data races when loading module info.
dirName := fmt.Sprintf("p%03d", i)
dirPath := filepath.Join(tempDir, dirName)
err := os.MkdirAll(dirPath, 0o777)
qt.Assert(t, qt.IsNil(err))
err = os.WriteFile(filepath.Join(dirPath, "go.mod"),
[]byte(fmt.Sprintf("module %s\n\ngo 1.16", dirName)), 0o666)
qt.Assert(t, qt.IsNil(err))
for j := 0; j < numberFilesPerDir; j++ {
filePath := filepath.Join(dirPath, fmt.Sprintf("%03d.go", j))
err := os.WriteFile(filePath,
// Extra newlines so that "-l" prints all paths.
[]byte(fmt.Sprintf("package %s\n\n\n", dirName)), 0o666)
qt.Assert(t, qt.IsNil(err))
allGoFiles = append(allGoFiles, filePath)
}
}
if len(allGoFiles) != numberFilesTotal {
panic("allGoFiles doesn't have the expected number of files?")
}
runGofmt := func(paths ...string) {
t.Logf("running with %d paths", len(paths))
cmd := exec.Command(testBinary, append([]string{"-l"}, paths...)...)
// 256 is a relatively common low limit, e.g. on Mac.
cmd.Env = append(os.Environ(), "TEST_WITH_FILE_LIMIT=256")
out, err := cmd.Output()
var stderr []byte
if err, _ := err.(*exec.ExitError); err != nil {
stderr = err.Stderr
}
qt.Assert(t, qt.IsNil(err), qt.Commentf("stderr:\n%s", stderr))
qt.Assert(t, qt.Equals(bytes.Count(out, []byte("\n")), len(allGoFiles)))
}
runGofmt(tempDir)
runGofmt(allGoFiles...)
}