aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/lib/server
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2015-11-18 11:19:09 +0000
committerGravatar Lukacs Berki <lberki@google.com>2015-11-18 15:32:05 +0000
commit9e1a62ae87feafc9d623a1b036f6ec0348663b76 (patch)
treedb0efeb35a4756d845a20690379c6c71f2d83e8d /src/test/java/com/google/devtools/build/lib/server
parent9b1e3a2957981ab6900dbb7d29c8c68ef9ba2f76 (diff)
Open-source RPC tests.
-- MOS_MIGRATED_REVID=108127872
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/server')
-rw-r--r--src/test/java/com/google/devtools/build/lib/server/RPCServerTest.java126
-rw-r--r--src/test/java/com/google/devtools/build/lib/server/RPCServiceTest.java115
-rw-r--r--src/test/java/com/google/devtools/build/lib/server/RPCTestingClient.java78
3 files changed, 319 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/server/RPCServerTest.java b/src/test/java/com/google/devtools/build/lib/server/RPCServerTest.java
new file mode 100644
index 0000000000..9f6ce729d6
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/server/RPCServerTest.java
@@ -0,0 +1,126 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.server;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.testutil.Suite;
+import com.google.devtools.build.lib.testutil.TestSpec;
+import com.google.devtools.build.lib.util.JavaClock;
+import com.google.devtools.build.lib.util.io.OutErr;
+import com.google.devtools.build.lib.util.io.RecordingOutErr;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.util.FsApparatus;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Run a real RPC server on localhost, and talk to it using the testing
+ * client.
+ */
+@TestSpec(size = Suite.MEDIUM_TESTS)
+public class RPCServerTest extends TestCase {
+
+ private static final long MAX_IDLE_MILLIS = 10000;
+ private static final long HEALTH_CHECK_MILLIS = 1000 * 3;
+ private static final String COMMAND_STDOUT = "Heelllloo....";
+ private static final String COMMAND_STDERR = "...world!";
+
+ private RPCServer server;
+ private FsApparatus scratch = FsApparatus.newNative();
+ private RecordingOutErr outErr = new RecordingOutErr();
+ private Path serverDir;
+ private Path workspaceDir;
+ private RPCTestingClient client;
+ private Thread serverThread = new Thread(){
+ @Override
+ public void run() {
+ server.serve();
+ }
+ };
+
+ private static final ServerCommand helloWorldCommand = new ServerCommand() {
+ @Override
+ public int exec(List<String> args, OutErr outErr, long firstContactTime) throws Exception {
+ outErr.printOut(COMMAND_STDOUT);
+ outErr.printErr(COMMAND_STDERR);
+ return 42;
+ }
+ @Override
+ public boolean shutdown() {
+ return false;
+ }
+ };
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Do not use `createUnixTempDir()` here since the file name that results is longer
+ // than 108 characters, so cannot be used as local socket address.
+ File file = File.createTempFile("scratch", ".tmp", new File("/tmp"));
+ file.delete();
+ file.mkdir();
+ serverDir = this.scratch.dir(file.getAbsolutePath());
+
+ workspaceDir = this.scratch.createUnixTempDir();
+ workspaceDir.createDirectory();
+ client = new RPCTestingClient(
+ outErr, serverDir.getRelative("server.socket"));
+ RPCService service = new RPCService(helloWorldCommand);
+ server = new RPCServer(new JavaClock(), service, MAX_IDLE_MILLIS, HEALTH_CHECK_MILLIS,
+ serverDir, workspaceDir);
+ serverThread.start();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ serverThread.interrupt();
+ serverThread.join();
+
+ FileSystemUtils.deleteTree(serverDir);
+ super.tearDown();
+ }
+
+ protected void testRequest(String request, int ret, String out, String err,
+ String control) throws Exception {
+ assertEquals(new ServerResponse(control, ret), client.sendRequest(request));
+ assertEquals(out, outErr.outAsLatin1());
+ assertThat(outErr.errAsLatin1()).contains(err);
+ }
+
+ public void testUnknownCommand() throws Exception {
+ testRequest("unknown", 2, "", "SERVER ERROR: Unknown command: unknown\n", "");
+ }
+
+ public void testEmptyBlazeCommand() throws Exception {
+ testRequest("unknown", 2, "", "SERVER ERROR: Unknown command: unknown\n", "");
+ }
+
+ public void testWorkspaceDies() throws Exception {
+ assertTrue(serverThread.isAlive());
+ testRequest("blaze", 42, COMMAND_STDOUT, COMMAND_STDERR, "");
+ Thread.sleep(HEALTH_CHECK_MILLIS * 2);
+ assertTrue(serverThread.isAlive());
+
+ assertTrue(workspaceDir.delete());
+ Thread.sleep(HEALTH_CHECK_MILLIS * 2);
+ assertFalse(serverThread.isAlive());
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/server/RPCServiceTest.java b/src/test/java/com/google/devtools/build/lib/server/RPCServiceTest.java
new file mode 100644
index 0000000000..42e2683af0
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/server/RPCServiceTest.java
@@ -0,0 +1,115 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.server;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.server.RPCService.UnknownCommandException;
+import com.google.devtools.build.lib.util.io.OutErr;
+import com.google.devtools.build.lib.util.io.RecordingOutErr;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Just makes sure the RPC service understands commands.
+ */
+public class RPCServiceTest extends TestCase {
+
+ private ServerCommand helloWorldCommand = new ServerCommand() {
+ @Override
+ public int exec(List<String> args, OutErr outErr, long firstContactTime) throws Exception {
+ outErr.printOut("Heelllloo....");
+ outErr.printErr("...world!");
+ return 42;
+ }
+ @Override
+ public boolean shutdown() {
+ return false;
+ }
+ };
+
+ private RPCService service =
+ new RPCService(helloWorldCommand);
+
+ public void testUnknownCommandException() {
+ try {
+ service.executeRequest(Arrays.asList("unknown"), new RecordingOutErr(), 0);
+ fail();
+ } catch (UnknownCommandException e) {
+ // success
+ } catch (Exception e){
+ fail();
+ }
+ }
+
+ public void testCommandGetsExecuted() throws Exception {
+ RecordingOutErr outErr = new RecordingOutErr();
+ int exitStatus = service.executeRequest(Arrays.asList("blaze"), outErr, 0);
+
+ assertEquals(42, exitStatus);
+ assertEquals("Heelllloo....", outErr.outAsLatin1());
+ assertEquals("...world!", outErr.errAsLatin1());
+ }
+
+ public void testDelimitation() throws Exception {
+ final List<String> savedArgs = new ArrayList<>();
+
+ RPCService service =
+ new RPCService(new ServerCommand() {
+ @Override
+ public int exec(List<String> args, OutErr outErr, long firstContactTime)
+ throws Exception {
+ savedArgs.addAll(args);
+ return 0;
+ }
+ @Override
+ public boolean shutdown() {
+ return false;
+ }
+ });
+
+ List<String> args = Arrays.asList("blaze", "", " \n", "", "", "", "foo");
+ service.executeRequest(args, new RecordingOutErr(), 0);
+ assertEquals(args.subList(1, args.size()),
+ savedArgs);
+ }
+
+ public void testShutdownState() throws Exception {
+ assertFalse(service.isShutdown());
+ service.shutdown();
+ assertTrue(service.isShutdown());
+ service.shutdown();
+ assertTrue(service.isShutdown());
+ }
+
+ public void testCommandFailsAfterShutdown() throws Exception {
+ RecordingOutErr outErr = new RecordingOutErr();
+ service.shutdown();
+ try {
+ service.executeRequest(Arrays.asList("blaze"), outErr, 0);
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e).hasMessage("Received request after shutdown.");
+ /* Make sure it does not execute the command! */
+ assertThat(outErr.outAsLatin1()).isEmpty();
+ assertThat(outErr.errAsLatin1()).isEmpty();
+ }
+ }
+
+}
diff --git a/src/test/java/com/google/devtools/build/lib/server/RPCTestingClient.java b/src/test/java/com/google/devtools/build/lib/server/RPCTestingClient.java
new file mode 100644
index 0000000000..e24e0bb3ac
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/server/RPCTestingClient.java
@@ -0,0 +1,78 @@
+// Copyright 2015 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.server;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.lib.unix.LocalClientSocket;
+import com.google.devtools.build.lib.unix.LocalSocketAddress;
+import com.google.devtools.build.lib.util.io.RecordingOutErr;
+import com.google.devtools.build.lib.util.io.StreamDemultiplexer;
+import com.google.devtools.build.lib.vfs.Path;
+
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+
+/**
+ * A client to test RPCServer.
+ */
+public class RPCTestingClient {
+
+ private final RecordingOutErr outErr;
+ private final Path socketFile;
+
+ /**
+ * Create a client to RPCServer. {@code socketFile} must be a file
+ * on disk; this will not work with the in-memory file system.
+ */
+ public RPCTestingClient(RecordingOutErr outErr, Path socketFile) {
+ this.socketFile = socketFile;
+ this.outErr = outErr;
+ }
+
+ public ServerResponse sendRequest(String command, String... params)
+ throws Exception {
+ String request = command;
+ for (String param : params) {
+ request += "\0" + param;
+ }
+ return sendRequest(request);
+ }
+
+ public ServerResponse sendRequest(String request) throws Exception {
+ LocalClientSocket connection = new LocalClientSocket();
+ connection.connect(new LocalSocketAddress(socketFile.getPathFile()));
+ try {
+ OutputStream out = connection.getOutputStream();
+ out.write(request.getBytes(UTF_8));
+ out.flush();
+ connection.shutdownOutput();
+
+ OutputStream stdout = outErr.getOutputStream();
+ OutputStream stderr = outErr.getErrorStream();
+ ByteArrayOutputStream control = new ByteArrayOutputStream();
+ StreamDemultiplexer demux = new StreamDemultiplexer((byte) '1',
+ stdout, stderr, control);
+ ByteStreams.copy(connection.getInputStream(), demux);
+ demux.flush();
+
+ return ServerResponse.parseFrom(control);
+ } finally {
+ connection.close();
+ }
+ }
+
+}