Reduce run time for //test/syscalls:socket_inet_loopback_test_runsc_ptrace.

* Tests are picked for a shard differently. It now picks one test from each
  block, instead of picking the whole block. This makes the same kind of tests
  spreads across different shards.

* Reduce the number of connect() calls in TCPListenClose.

PiperOrigin-RevId: 293019281
This commit is contained in:
Ting-Yu Wang
2020-02-03 15:42:21 -08:00
committed by gVisor bot
parent 80ce7f2537
commit e7846e50f2
4 changed files with 43 additions and 47 deletions
+29 -32
View File
@@ -434,43 +434,40 @@ func IsStatic(filename string) (bool, error) {
return true, nil
}
// TestBoundsForShard calculates the beginning and end indices for the test
// based on the TEST_SHARD_INDEX and TEST_TOTAL_SHARDS environment vars. The
// returned ints are the beginning (inclusive) and end (exclusive) of the
// subslice corresponding to the shard. If either of the env vars are not
// present, then the function will return bounds that include all tests. If
// there are more shards than there are tests, then the returned list may be
// empty.
func TestBoundsForShard(numTests int) (int, int, error) {
// TestIndicesForShard returns indices for this test shard based on the
// TEST_SHARD_INDEX and TEST_TOTAL_SHARDS environment vars.
//
// If either of the env vars are not present, then the function will return all
// tests. If there are more shards than there are tests, then the returned list
// may be empty.
func TestIndicesForShard(numTests int) ([]int, error) {
var (
begin = 0
end = numTests
shardIndex = 0
shardTotal = 1
)
indexStr, totalStr := os.Getenv("TEST_SHARD_INDEX"), os.Getenv("TEST_TOTAL_SHARDS")
if indexStr == "" || totalStr == "" {
return begin, end, nil
}
// Parse index and total to ints.
shardIndex, err := strconv.Atoi(indexStr)
if err != nil {
return 0, 0, fmt.Errorf("invalid TEST_SHARD_INDEX %q: %v", indexStr, err)
}
shardTotal, err := strconv.Atoi(totalStr)
if err != nil {
return 0, 0, fmt.Errorf("invalid TEST_TOTAL_SHARDS %q: %v", totalStr, err)
indexStr, totalStr := os.Getenv("TEST_SHARD_INDEX"), os.Getenv("TEST_TOTAL_SHARDS")
if indexStr != "" && totalStr != "" {
// Parse index and total to ints.
var err error
shardIndex, err = strconv.Atoi(indexStr)
if err != nil {
return nil, fmt.Errorf("invalid TEST_SHARD_INDEX %q: %v", indexStr, err)
}
shardTotal, err = strconv.Atoi(totalStr)
if err != nil {
return nil, fmt.Errorf("invalid TEST_TOTAL_SHARDS %q: %v", totalStr, err)
}
}
// Calculate!
shardSize := int(math.Ceil(float64(numTests) / float64(shardTotal)))
begin = shardIndex * shardSize
end = ((shardIndex + 1) * shardSize)
if begin > numTests {
// Nothing to run.
return 0, 0, nil
var indices []int
numBlocks := int(math.Ceil(float64(numTests) / float64(shardTotal)))
for i := 0; i < numBlocks; i++ {
pick := i*shardTotal + shardIndex
if pick < numTests {
indices = append(indices, pick)
}
}
if end > numTests {
end = numTests
}
return begin, end, nil
return indices, nil
}
+3 -6
View File
@@ -20,7 +20,6 @@ import (
"flag"
"fmt"
"io"
"log"
"os"
"sort"
"strings"
@@ -101,17 +100,15 @@ func getTests(d dockerutil.Docker, blacklist map[string]struct{}) ([]testing.Int
// shard.
tests := strings.Fields(list)
sort.Strings(tests)
begin, end, err := testutil.TestBoundsForShard(len(tests))
indices, err := testutil.TestIndicesForShard(len(tests))
if err != nil {
return nil, fmt.Errorf("TestsForShard() failed: %v", err)
}
log.Printf("Got bounds [%d:%d) for shard out of %d total tests", begin, end, len(tests))
tests = tests[begin:end]
var itests []testing.InternalTest
for _, tc := range tests {
for _, tci := range indices {
// Capture tc in this scope.
tc := tc
tc := tests[tci]
itests = append(itests, testing.InternalTest{
Name: tc,
F: func(t *testing.T) {
+8 -5
View File
@@ -325,6 +325,12 @@ TEST_P(SocketInetLoopbackTest, TCPListenClose) {
TestAddress const& listener = param.listener;
TestAddress const& connector = param.connector;
constexpr int kAcceptCount = 32;
constexpr int kBacklog = kAcceptCount * 2;
constexpr int kFDs = 128;
constexpr int kThreadCount = 4;
constexpr int kFDsPerThread = kFDs / kThreadCount;
// Create the listening socket.
FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE(
Socket(listener.family(), SOCK_STREAM, IPPROTO_TCP));
@@ -332,7 +338,7 @@ TEST_P(SocketInetLoopbackTest, TCPListenClose) {
ASSERT_THAT(bind(listen_fd.get(), reinterpret_cast<sockaddr*>(&listen_addr),
listener.addr_len),
SyscallSucceeds());
ASSERT_THAT(listen(listen_fd.get(), 1001), SyscallSucceeds());
ASSERT_THAT(listen(listen_fd.get(), kBacklog), SyscallSucceeds());
// Get the port bound by the listening socket.
socklen_t addrlen = listener.addr_len;
@@ -345,9 +351,6 @@ TEST_P(SocketInetLoopbackTest, TCPListenClose) {
DisableSave ds; // Too many system calls.
sockaddr_storage conn_addr = connector.addr;
ASSERT_NO_ERRNO(SetAddrPort(connector.family(), &conn_addr, port));
constexpr int kFDs = 2048;
constexpr int kThreadCount = 4;
constexpr int kFDsPerThread = kFDs / kThreadCount;
FileDescriptor clients[kFDs];
std::unique_ptr<ScopedThread> threads[kThreadCount];
for (int i = 0; i < kFDs; i++) {
@@ -371,7 +374,7 @@ TEST_P(SocketInetLoopbackTest, TCPListenClose) {
for (int i = 0; i < kThreadCount; i++) {
threads[i]->Join();
}
for (int i = 0; i < 32; i++) {
for (int i = 0; i < kAcceptCount; i++) {
auto accepted =
ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr));
}
+3 -4
View File
@@ -450,17 +450,16 @@ func main() {
}
// Get subset of tests corresponding to shard.
begin, end, err := testutil.TestBoundsForShard(len(testCases))
indices, err := testutil.TestIndicesForShard(len(testCases))
if err != nil {
fatalf("TestsForShard() failed: %v", err)
}
testCases = testCases[begin:end]
// Run the tests.
var tests []testing.InternalTest
for _, tc := range testCases {
for _, tci := range indices {
// Capture tc.
tc := tc
tc := testCases[tci]
testName := fmt.Sprintf("%s_%s", tc.Suite, tc.Name)
tests = append(tests, testing.InternalTest{
Name: testName,