summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/runtimes/README.md2
-rw-r--r--test/runtimes/go/Dockerfile5
-rw-r--r--test/runtimes/java/Dockerfile43
-rw-r--r--test/runtimes/java/proctor-java.go5
-rw-r--r--test/runtimes/nodejs/Dockerfile3
-rw-r--r--test/runtimes/php/Dockerfile3
-rw-r--r--test/runtimes/python/Dockerfile3
-rw-r--r--test/runtimes/runtimes_test.go34
-rw-r--r--test/syscalls/BUILD4
-rw-r--r--test/syscalls/linux/socket_inet_loopback.cc61
-rw-r--r--test/syscalls/linux/splice.cc75
11 files changed, 197 insertions, 41 deletions
diff --git a/test/runtimes/README.md b/test/runtimes/README.md
index 4e5a950bc..34d3507be 100644
--- a/test/runtimes/README.md
+++ b/test/runtimes/README.md
@@ -16,7 +16,7 @@ The following runtimes are currently supported:
1) [Install and configure Docker](https://docs.docker.com/install/)
-2) Build each Docker container:
+2) Build each Docker container from the runtimes directory:
```bash
$ docker build -f $LANG/Dockerfile [-t $NAME] .
diff --git a/test/runtimes/go/Dockerfile b/test/runtimes/go/Dockerfile
index cd55608cd..1d5202b70 100644
--- a/test/runtimes/go/Dockerfile
+++ b/test/runtimes/go/Dockerfile
@@ -23,9 +23,12 @@ ENV LANG_DIR=${GOROOT}
WORKDIR ${LANG_DIR}/src
RUN ./make.bash
+# Pre-compile the tests for faster execution
+RUN ["/root/go/bin/go", "tool", "dist", "test", "-compile-only"]
WORKDIR ${LANG_DIR}
-COPY proctor-go.go ${LANG_DIR}
+COPY common /root/go/src/gvisor.dev/gvisor/test/runtimes/common/common
+COPY go/proctor-go.go ${LANG_DIR}
ENTRYPOINT ["/root/go/bin/go", "run", "proctor-go.go"]
diff --git a/test/runtimes/java/Dockerfile b/test/runtimes/java/Dockerfile
index e162d7218..b9132b575 100644
--- a/test/runtimes/java/Dockerfile
+++ b/test/runtimes/java/Dockerfile
@@ -1,25 +1,16 @@
FROM ubuntu:bionic
# This hash is associated with a specific JDK release and needed for ensuring
# the same version is downloaded every time.
-ENV LANG_HASH=af47e0398606
-ENV LANG_VER=11u-dev
+ENV LANG_HASH=76072a077ee1
+ENV LANG_VER=11
ENV LANG_NAME=Java
RUN apt-get update && apt-get install -y \
autoconf \
build-essential \
- curl\
- file \
- libasound2-dev \
- libcups2-dev \
- libfontconfig1-dev \
- libx11-dev \
- libxext-dev \
- libxrandr-dev \
- libxrender-dev \
- libxt-dev \
- libxtst-dev \
+ curl \
make \
+ openjdk-${LANG_VER}-jdk \
unzip \
zip
@@ -27,26 +18,18 @@ WORKDIR /root
RUN curl -o go.tar.gz https://dl.google.com/go/go1.12.6.linux-amd64.tar.gz
RUN tar -zxf go.tar.gz
-# Use curl instead of ADD to prevent redownload every time.
-RUN curl -o jdk.tar.gz http://hg.openjdk.java.net/jdk-updates/jdk${LANG_VER}/archive/${LANG_HASH}.tar.gz
-# Download Java version N-1 to be used as the Boot JDK to build Java version N.
-RUN curl -o bootjdk.tar.gz https://download.java.net/openjdk/jdk10/ri/openjdk-10+44_linux-x64_bin_ri.tar.gz
-
-RUN tar -zxf jdk.tar.gz
-RUN tar -zxf bootjdk.tar.gz
-
-# Specify the JDK to be used by jtreg.
-ENV JT_JAVA=/root/jdk${LANG_VER}-${LANG_HASH}/build/linux-x86_64-normal-server-release/jdk
-ENV LANG_DIR=/root/jdk${LANG_VER}-${LANG_HASH}
-
-WORKDIR ${LANG_DIR}
+# Download the JDK test library.
+RUN set -ex \
+ && curl -fsSL --retry 10 -o /tmp/jdktests.tar.gz http://hg.openjdk.java.net/jdk/jdk${LANG_VER}/archive/${LANG_HASH}.tar.gz/test \
+ && tar -xzf /tmp/jdktests.tar.gz -C /root \
+ && rm -f /tmp/jdktests.tar.gz
RUN curl -o jtreg.tar.gz https://ci.adoptopenjdk.net/view/Dependencies/job/jtreg/lastSuccessfulBuild/artifact/jtreg-4.2.0-tip.tar.gz
RUN tar -xzf jtreg.tar.gz
-RUN bash configure --with-boot-jdk=/root/jdk-10 --with-jtreg=${LANG_DIR}/jtreg
-RUN make clean
-RUN make images
-COPY proctor-java.go ${LANG_DIR}
+ENV LANG_DIR=/root
+
+COPY common /root/go/src/gvisor.dev/gvisor/test/runtimes/common/common
+COPY java/proctor-java.go ${LANG_DIR}
ENTRYPOINT ["/root/go/bin/go", "run", "proctor-java.go"]
diff --git a/test/runtimes/java/proctor-java.go b/test/runtimes/java/proctor-java.go
index c1e611b4b..7f6a66f4f 100644
--- a/test/runtimes/java/proctor-java.go
+++ b/test/runtimes/java/proctor-java.go
@@ -29,6 +29,7 @@ import (
var (
dir = os.Getenv("LANG_DIR")
+ hash = os.Getenv("LANG_HASH")
jtreg = filepath.Join(dir, "jtreg/bin/jtreg")
exclDirs = regexp.MustCompile(`(^(sun\/security)|(java\/util\/stream)|(java\/time)| )`)
)
@@ -44,7 +45,7 @@ func main() {
func (j javaRunner) ListTests() ([]string, error) {
args := []string{
- "-dir:test/jdk",
+ "-dir:/root/jdk11-" + hash + "/test/jdk",
"-ignore:quiet",
"-a",
"-listtests",
@@ -69,7 +70,7 @@ func (j javaRunner) ListTests() ([]string, error) {
}
func (j javaRunner) RunTest(test string) error {
- args := []string{"-dir:test/jdk/", test}
+ args := []string{"-noreport", "-dir:/root/jdk11-" + hash + "/test/jdk", test}
cmd := exec.Command(jtreg, args...)
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
diff --git a/test/runtimes/nodejs/Dockerfile b/test/runtimes/nodejs/Dockerfile
index b2416cce8..aba30d2ee 100644
--- a/test/runtimes/nodejs/Dockerfile
+++ b/test/runtimes/nodejs/Dockerfile
@@ -22,7 +22,8 @@ RUN ./configure
RUN make
RUN make test-build
-COPY proctor-nodejs.go ${LANG_DIR}
+COPY common /root/go/src/gvisor.dev/gvisor/test/runtimes/common/common
+COPY nodejs/proctor-nodejs.go ${LANG_DIR}
# Including dumb-init emulates the Linux "init" process, preventing the failure
# of tests involving worker processes.
diff --git a/test/runtimes/php/Dockerfile b/test/runtimes/php/Dockerfile
index 1f8959b50..491ab902d 100644
--- a/test/runtimes/php/Dockerfile
+++ b/test/runtimes/php/Dockerfile
@@ -24,6 +24,7 @@ WORKDIR ${LANG_DIR}
RUN ./configure
RUN make
-COPY proctor-php.go ${LANG_DIR}
+COPY common /root/go/src/gvisor.dev/gvisor/test/runtimes/common/common
+COPY php/proctor-php.go ${LANG_DIR}
ENTRYPOINT ["/root/go/bin/go", "run", "proctor-php.go"]
diff --git a/test/runtimes/python/Dockerfile b/test/runtimes/python/Dockerfile
index 811f48f8a..710daee43 100644
--- a/test/runtimes/python/Dockerfile
+++ b/test/runtimes/python/Dockerfile
@@ -26,6 +26,7 @@ WORKDIR ${LANG_DIR}
RUN ./configure --with-pydebug
RUN make -s -j2
-COPY proctor-python.go ${LANG_DIR}
+COPY common /root/go/src/gvisor.dev/gvisor/test/runtimes/common/common
+COPY python/proctor-python.go ${LANG_DIR}
ENTRYPOINT ["/root/go/bin/go", "run", "proctor-python.go"]
diff --git a/test/runtimes/runtimes_test.go b/test/runtimes/runtimes_test.go
index 6bf954e78..43dd6f5b7 100644
--- a/test/runtimes/runtimes_test.go
+++ b/test/runtimes/runtimes_test.go
@@ -22,8 +22,16 @@ import (
"gvisor.dev/gvisor/runsc/test/testutil"
)
-func TestNodeJS(t *testing.T) {
- const img = "gcr.io/gvisor-proctor/nodejs"
+// Wait time for each test to run.
+const timeout = 180 * time.Second
+
+// Helper function to execute the docker container associated with the
+// language passed. Captures the output of the list function and executes
+// each test individually, supplying any errors recieved.
+func testLang(t *testing.T, lang string) {
+ t.Helper()
+
+ img := "gcr.io/gvisor-presubmit/" + lang
if err := testutil.Pull(img); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
@@ -49,7 +57,7 @@ func TestNodeJS(t *testing.T) {
}
defer d.CleanUp()
- status, err := d.Wait(60 * time.Second)
+ status, err := d.Wait(timeout)
if err != nil {
t.Fatalf("docker test %q failed to wait: %v", tc, err)
}
@@ -65,3 +73,23 @@ func TestNodeJS(t *testing.T) {
})
}
}
+
+func TestGo(t *testing.T) {
+ testLang(t, "go")
+}
+
+func TestJava(t *testing.T) {
+ testLang(t, "java")
+}
+
+func TestNodejs(t *testing.T) {
+ testLang(t, "nodejs")
+}
+
+func TestPhp(t *testing.T) {
+ testLang(t, "php")
+}
+
+func TestPython(t *testing.T) {
+ testLang(t, "python")
+}
diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD
index a3e43cad2..aa1e33fb4 100644
--- a/test/syscalls/BUILD
+++ b/test/syscalls/BUILD
@@ -440,7 +440,9 @@ syscall_test(
)
syscall_test(
- size = "medium",
+ size = "large",
+ parallel = False,
+ shard_count = 10,
test = "//test/syscalls/linux:socket_inet_loopback_test",
)
diff --git a/test/syscalls/linux/socket_inet_loopback.cc b/test/syscalls/linux/socket_inet_loopback.cc
index df31d25b5..322ee07ad 100644
--- a/test/syscalls/linux/socket_inet_loopback.cc
+++ b/test/syscalls/linux/socket_inet_loopback.cc
@@ -145,6 +145,67 @@ TEST_P(SocketInetLoopbackTest, TCP) {
ASSERT_THAT(shutdown(conn_fd.get(), SHUT_RDWR), SyscallSucceeds());
}
+TEST_P(SocketInetLoopbackTest, TCPListenClose) {
+ auto const& param = GetParam();
+
+ TestAddress const& listener = param.listener;
+ TestAddress const& connector = param.connector;
+
+ // Create the listening socket.
+ FileDescriptor listen_fd = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(listener.family(), SOCK_STREAM, IPPROTO_TCP));
+ sockaddr_storage listen_addr = listener.addr;
+ ASSERT_THAT(bind(listen_fd.get(), reinterpret_cast<sockaddr*>(&listen_addr),
+ listener.addr_len),
+ SyscallSucceeds());
+ ASSERT_THAT(listen(listen_fd.get(), 1001), SyscallSucceeds());
+
+ // Get the port bound by the listening socket.
+ socklen_t addrlen = listener.addr_len;
+ ASSERT_THAT(getsockname(listen_fd.get(),
+ reinterpret_cast<sockaddr*>(&listen_addr), &addrlen),
+ SyscallSucceeds());
+ uint16_t const port =
+ ASSERT_NO_ERRNO_AND_VALUE(AddrPort(listener.family(), listen_addr));
+
+ 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++) {
+ clients[i] = ASSERT_NO_ERRNO_AND_VALUE(
+ Socket(connector.family(), SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP));
+ }
+ for (int i = 0; i < kThreadCount; i++) {
+ threads[i] = absl::make_unique<ScopedThread>([&connector, &conn_addr,
+ &clients, i]() {
+ for (int j = 0; j < kFDsPerThread; j++) {
+ int k = i * kFDsPerThread + j;
+ int ret =
+ connect(clients[k].get(), reinterpret_cast<sockaddr*>(&conn_addr),
+ connector.addr_len);
+ if (ret != 0) {
+ EXPECT_THAT(ret, SyscallFailsWithErrno(EINPROGRESS));
+ }
+ }
+ });
+ }
+ for (int i = 0; i < kThreadCount; i++) {
+ threads[i]->Join();
+ }
+ for (int i = 0; i < 32; i++) {
+ auto accepted =
+ ASSERT_NO_ERRNO_AND_VALUE(Accept(listen_fd.get(), nullptr, nullptr));
+ }
+ // TODO(b/138400178): Fix cooperative S/R failure when ds.reset() is invoked
+ // before function end.
+ // ds.reset()
+}
+
TEST_P(SocketInetLoopbackTest, TCPbacklog) {
auto const& param = GetParam();
diff --git a/test/syscalls/linux/splice.cc b/test/syscalls/linux/splice.cc
index 1875f4533..e25f264f6 100644
--- a/test/syscalls/linux/splice.cc
+++ b/test/syscalls/linux/splice.cc
@@ -13,6 +13,7 @@
// limitations under the License.
#include <fcntl.h>
+#include <sys/eventfd.h>
#include <sys/sendfile.h>
#include <unistd.h>
@@ -135,6 +136,80 @@ TEST(SpliceTest, PipeOffsets) {
SyscallFailsWithErrno(ESPIPE));
}
+// Event FDs may be used with splice without an offset.
+TEST(SpliceTest, FromEventFD) {
+ // Open the input eventfd with an initial value so that it is readable.
+ constexpr uint64_t kEventFDValue = 1;
+ int efd;
+ ASSERT_THAT(efd = eventfd(kEventFDValue, 0), SyscallSucceeds());
+ const FileDescriptor inf(efd);
+
+ // Create a new pipe.
+ int fds[2];
+ ASSERT_THAT(pipe(fds), SyscallSucceeds());
+ const FileDescriptor rfd(fds[0]);
+ const FileDescriptor wfd(fds[1]);
+
+ // Splice 8-byte eventfd value to pipe.
+ constexpr int kEventFDSize = 8;
+ EXPECT_THAT(splice(inf.get(), nullptr, wfd.get(), nullptr, kEventFDSize, 0),
+ SyscallSucceedsWithValue(kEventFDSize));
+
+ // Contents should be equal.
+ std::vector<char> rbuf(kEventFDSize);
+ ASSERT_THAT(read(rfd.get(), rbuf.data(), rbuf.size()),
+ SyscallSucceedsWithValue(kEventFDSize));
+ EXPECT_EQ(memcmp(rbuf.data(), &kEventFDValue, rbuf.size()), 0);
+}
+
+// Event FDs may not be used with splice with an offset.
+TEST(SpliceTest, FromEventFDOffset) {
+ int efd;
+ ASSERT_THAT(efd = eventfd(0, 0), SyscallSucceeds());
+ const FileDescriptor inf(efd);
+
+ // Create a new pipe.
+ int fds[2];
+ ASSERT_THAT(pipe(fds), SyscallSucceeds());
+ const FileDescriptor rfd(fds[0]);
+ const FileDescriptor wfd(fds[1]);
+
+ // Attempt to splice 8-byte eventfd value to pipe with offset.
+ //
+ // This is not allowed because eventfd doesn't support pread.
+ constexpr int kEventFDSize = 8;
+ loff_t in_off = 0;
+ EXPECT_THAT(splice(inf.get(), &in_off, wfd.get(), nullptr, kEventFDSize, 0),
+ SyscallFailsWithErrno(EINVAL));
+}
+
+// Event FDs may not be used with splice with an offset.
+TEST(SpliceTest, ToEventFDOffset) {
+ // Create a new pipe.
+ int fds[2];
+ ASSERT_THAT(pipe(fds), SyscallSucceeds());
+ const FileDescriptor rfd(fds[0]);
+ const FileDescriptor wfd(fds[1]);
+
+ // Fill with a value.
+ constexpr int kEventFDSize = 8;
+ std::vector<char> buf(kEventFDSize);
+ buf[0] = 1;
+ ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()),
+ SyscallSucceedsWithValue(kEventFDSize));
+
+ int efd;
+ ASSERT_THAT(efd = eventfd(0, 0), SyscallSucceeds());
+ const FileDescriptor outf(efd);
+
+ // Attempt to splice 8-byte eventfd value to pipe with offset.
+ //
+ // This is not allowed because eventfd doesn't support pwrite.
+ loff_t out_off = 0;
+ EXPECT_THAT(splice(rfd.get(), nullptr, outf.get(), &out_off, kEventFDSize, 0),
+ SyscallFailsWithErrno(EINVAL));
+}
+
TEST(SpliceTest, ToPipe) {
// Open the input file.
const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());