From 1f617b77fd77d09f327b909d2302f2f4efc6e0a5 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 29 Sep 2015 17:14:32 -0700 Subject: [PATCH 1/3] choose port for LocalGcdHelper dynamically --- .../datastore/DatastoreOptionsTest.java | 5 +- .../gcloud/datastore/DatastoreTest.java | 7 +-- .../gcloud/datastore/LocalGcdHelper.java | 53 ++++++++++++------- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java index e7dc71c50ff6..8a0d52aec9c8 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java @@ -34,6 +34,7 @@ public class DatastoreOptionsTest { private static final String PROJECT_ID = "project_id"; + private static final int PORT = LocalGcdHelper.findOpenPort(); private DatastoreRpcFactory datastoreRpcFactory; private DatastoreRpc datastoreRpc; private DatastoreOptions.Builder options; @@ -46,7 +47,7 @@ public void setUp() throws IOException, InterruptedException { .normalizeDataset(false) .serviceRpcFactory(datastoreRpcFactory) .projectId(PROJECT_ID) - .host("http://localhost:" + LocalGcdHelper.PORT); + .host("http://localhost:" + PORT); EasyMock.expect(datastoreRpcFactory.create(EasyMock.anyObject(DatastoreOptions.class))) .andReturn(datastoreRpc) .anyTimes(); @@ -60,7 +61,7 @@ public void testProjectId() throws Exception { @Test public void testHost() throws Exception { - assertEquals("http://localhost:" + LocalGcdHelper.PORT, options.build().host()); + assertEquals("http://localhost:" + PORT, options.build().host()); } @Test diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java index 156f9684f8ba..2c7e8f987cb1 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java @@ -101,11 +101,12 @@ public class DatastoreTest { private Datastore datastore; private static LocalGcdHelper gcdHelper; + private static final int PORT = LocalGcdHelper.findOpenPort(); @BeforeClass public static void beforeClass() throws IOException, InterruptedException { - if (!LocalGcdHelper.isActive(PROJECT_ID)) { - gcdHelper = LocalGcdHelper.start(PROJECT_ID); + if (!LocalGcdHelper.isActive(PROJECT_ID, PORT)) { + gcdHelper = LocalGcdHelper.start(PROJECT_ID, PORT); } } @@ -113,7 +114,7 @@ public static void beforeClass() throws IOException, InterruptedException { public void setUp() throws IOException, InterruptedException { options = DatastoreOptions.builder() .projectId(PROJECT_ID) - .host("http://localhost:" + LocalGcdHelper.PORT) + .host("http://localhost:" + PORT) .build(); datastore = DatastoreFactory.instance().get(options); StructuredQuery query = Query.keyQueryBuilder().build(); diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java index 888fd2157d3a..a78797bb88e4 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java @@ -35,6 +35,7 @@ import java.math.BigInteger; import java.net.HttpURLConnection; import java.net.MalformedURLException; +import java.net.ServerSocket; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; @@ -68,9 +69,10 @@ public class LocalGcdHelper { private final String projectId; private Path gcdPath; private ProcessStreamReader processReader; + private final int port; public static final String DEFAULT_PROJECT_ID = "projectid1"; - public static final int PORT = 8080; + private static final int DEFAULT_PORT = 8080; private static final String GCD_VERSION = "v1beta2"; private static final String GCD_BUILD = "rev1-2.1.2b"; private static final String GCD_BASENAME = "gcd-" + GCD_VERSION + "-" + GCD_BUILD; @@ -94,6 +96,17 @@ public class LocalGcdHelper { } } + public static int findOpenPort() { + int port; + try (ServerSocket temp_socket = new ServerSocket(0)) { + port = temp_socket.getLocalPort(); + temp_socket.close(); + } catch (IOException e) { + port = DEFAULT_PORT; + } + return port; + } + private static Path installedGcdPath() { String gcloudExecutableName; if (isWindows()) { @@ -283,8 +296,9 @@ public static CommandWrapper create() { } } - public LocalGcdHelper(String projectId) { + public LocalGcdHelper(String projectId, int port) { this.projectId = projectId; + this.port = port; } /** @@ -297,7 +311,7 @@ public LocalGcdHelper(String projectId) { */ public void start() throws IOException, InterruptedException { // send a quick request in case we have a hanging process from a previous run - sendQuitRequest(); + sendQuitRequest(port); // Each run is associated with its own folder that is deleted once test completes. gcdPath = Files.createTempDirectory("gcd"); File gcdFolder = gcdPath.toFile(); @@ -379,13 +393,12 @@ private void startGcd(Path executablePath) throws IOException, InterruptedExcept if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "Starting datastore emulator for the project: {0}", projectId); } - Process startProcess = - CommandWrapper.create() - .command(gcdAbsolutePath.toString(), "start", "--testing", "--allow_remote_shutdown", - projectId) - .directory(gcdPath) - .redirectErrorStream() - .start(); + Process startProcess = CommandWrapper.create() + .command(gcdAbsolutePath.toString(), "start", "--testing", "--allow_remote_shutdown", + "--port=" + Integer.toString(port), projectId) + .directory(gcdPath) + .redirectErrorStream() + .start(); processReader = ProcessStreamReader.start(startProcess, "Dev App Server is now running"); } @@ -419,9 +432,9 @@ private static void extractFile(ZipInputStream zipIn, File filePath) throws IOEx } } - public static void sendQuitRequest() { + public static void sendQuitRequest(int port) { try { - URL url = new URL("http", "localhost", PORT, "/_ah/admin/quit"); + URL url = new URL("http", "localhost", port, "/_ah/admin/quit"); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setDoOutput(true); @@ -439,7 +452,7 @@ public static void sendQuitRequest() { } public void stop() throws IOException, InterruptedException { - sendQuitRequest(); + sendQuitRequest(port); if (processReader != null) { processReader.terminate(); } @@ -468,8 +481,8 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO }); } - public static LocalGcdHelper start(String projectId) throws IOException, InterruptedException { - LocalGcdHelper helper = new LocalGcdHelper(projectId); + public static LocalGcdHelper start(String projectId, int port) throws IOException, InterruptedException { + LocalGcdHelper helper = new LocalGcdHelper(projectId, port); helper.start(); return helper; } @@ -478,15 +491,15 @@ public static void main(String... args) throws IOException, InterruptedException if (args.length == 1) { switch (args[0]) { case "START": - if (!isActive(DEFAULT_PROJECT_ID)) { - LocalGcdHelper helper = start(DEFAULT_PROJECT_ID); + if (!isActive(DEFAULT_PROJECT_ID, DEFAULT_PORT)) { + LocalGcdHelper helper = start(DEFAULT_PROJECT_ID, DEFAULT_PORT); try (FileWriter writer = new FileWriter(".local_gcd_helper")) { writer.write(helper.gcdPath.toAbsolutePath().toString()); } } return; case "STOP": - sendQuitRequest(); + sendQuitRequest(DEFAULT_PORT); File file = new File(".local_gcd_helper"); if (file.exists()) { try (BufferedReader reader = new BufferedReader(new FileReader(file))) { @@ -503,9 +516,9 @@ public static void main(String... args) throws IOException, InterruptedException throw new RuntimeException("expecting only START | STOP"); } - public static boolean isActive(String projectId) { + public static boolean isActive(String projectId, int port) { try { - StringBuilder urlBuilder = new StringBuilder("http://localhost:").append(PORT); + StringBuilder urlBuilder = new StringBuilder("http://localhost:").append(port); urlBuilder.append("/datastore/v1beta2/datasets/").append(projectId).append("/lookup"); URL url = new URL(urlBuilder.toString()); try (BufferedReader reader = From 22a9e9915c1ba5fae4e1d194bf0b92686d4ba7d4 Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Tue, 29 Sep 2015 18:14:15 -0700 Subject: [PATCH 2/3] Allow a default port to be passed in as a parameter, and also fix names --- .../gcloud/datastore/DatastoreOptionsTest.java | 2 +- .../google/gcloud/datastore/DatastoreTest.java | 2 +- .../google/gcloud/datastore/LocalGcdHelper.java | 17 +++++++---------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java index 8a0d52aec9c8..b3365876773e 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreOptionsTest.java @@ -34,7 +34,7 @@ public class DatastoreOptionsTest { private static final String PROJECT_ID = "project_id"; - private static final int PORT = LocalGcdHelper.findOpenPort(); + private static final int PORT = LocalGcdHelper.findAvailablePort(LocalGcdHelper.DEFAULT_PORT); private DatastoreRpcFactory datastoreRpcFactory; private DatastoreRpc datastoreRpc; private DatastoreOptions.Builder options; diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java index 2c7e8f987cb1..b03472a9a6f8 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/DatastoreTest.java @@ -101,7 +101,7 @@ public class DatastoreTest { private Datastore datastore; private static LocalGcdHelper gcdHelper; - private static final int PORT = LocalGcdHelper.findOpenPort(); + private static final int PORT = LocalGcdHelper.findAvailablePort(LocalGcdHelper.DEFAULT_PORT); @BeforeClass public static void beforeClass() throws IOException, InterruptedException { diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java index a78797bb88e4..ce069bd9709d 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java @@ -72,7 +72,7 @@ public class LocalGcdHelper { private final int port; public static final String DEFAULT_PROJECT_ID = "projectid1"; - private static final int DEFAULT_PORT = 8080; + public static final int DEFAULT_PORT = 8080; private static final String GCD_VERSION = "v1beta2"; private static final String GCD_BUILD = "rev1-2.1.2b"; private static final String GCD_BASENAME = "gcd-" + GCD_VERSION + "-" + GCD_BUILD; @@ -96,15 +96,12 @@ public class LocalGcdHelper { } } - public static int findOpenPort() { - int port; - try (ServerSocket temp_socket = new ServerSocket(0)) { - port = temp_socket.getLocalPort(); - temp_socket.close(); + public static int findAvailablePort(int defaultPort) { + try (ServerSocket tempSocket = new ServerSocket(0)) { + return tempSocket.getLocalPort(); } catch (IOException e) { - port = DEFAULT_PORT; + return defaultPort; } - return port; } private static Path installedGcdPath() { @@ -491,8 +488,8 @@ public static void main(String... args) throws IOException, InterruptedException if (args.length == 1) { switch (args[0]) { case "START": - if (!isActive(DEFAULT_PROJECT_ID, DEFAULT_PORT)) { - LocalGcdHelper helper = start(DEFAULT_PROJECT_ID, DEFAULT_PORT); + if (!isActive(DEFAULT_PROJECT_ID, findAvailablePort(DEFAULT_PORT))) { + LocalGcdHelper helper = start(DEFAULT_PROJECT_ID, findAvailablePort(DEFAULT_PORT)); try (FileWriter writer = new FileWriter(".local_gcd_helper")) { writer.write(helper.gcdPath.toAbsolutePath().toString()); } From 00ec9564ba161ad92183bfcb980e3168e89ac24c Mon Sep 17 00:00:00 2001 From: Ajay Kannan Date: Wed, 30 Sep 2015 10:25:56 -0700 Subject: [PATCH 3/3] Allow option to specify port in LocalGcdHelper's main --- .../gcloud/datastore/LocalGcdHelper.java | 74 +++++++++++++------ 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java index ce069bd9709d..0e0e726a7fba 100644 --- a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java +++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/LocalGcdHelper.java @@ -50,8 +50,10 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.regex.Pattern; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -478,39 +480,65 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO }); } - public static LocalGcdHelper start(String projectId, int port) throws IOException, InterruptedException { + public static LocalGcdHelper start(String projectId, int port) + throws IOException, InterruptedException { LocalGcdHelper helper = new LocalGcdHelper(projectId, port); helper.start(); return helper; } public static void main(String... args) throws IOException, InterruptedException { - if (args.length == 1) { - switch (args[0]) { - case "START": - if (!isActive(DEFAULT_PROJECT_ID, findAvailablePort(DEFAULT_PORT))) { - LocalGcdHelper helper = start(DEFAULT_PROJECT_ID, findAvailablePort(DEFAULT_PORT)); - try (FileWriter writer = new FileWriter(".local_gcd_helper")) { - writer.write(helper.gcdPath.toAbsolutePath().toString()); - } + Map parsedArgs = parseArgs(args); + String action = parsedArgs.get("action"); + int port = (parsedArgs.get("port") == null) ? DEFAULT_PORT + : Integer.parseInt(parsedArgs.get("port")); + switch (action) { + case "START": + if (!isActive(DEFAULT_PROJECT_ID, port)) { + LocalGcdHelper helper = start(DEFAULT_PROJECT_ID, port); + try (FileWriter writer = new FileWriter(".local_gcd_helper")) { + writer.write( + helper.gcdPath.toAbsolutePath().toString() + System.lineSeparator()); + writer.write(Integer.toString(port)); } - return; - case "STOP": - sendQuitRequest(DEFAULT_PORT); - File file = new File(".local_gcd_helper"); - if (file.exists()) { - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String path = reader.readLine(); - deleteRecurse(Paths.get(path)); - } - file.delete(); + } + return; + case "STOP": + File file = new File(".local_gcd_helper"); + String path = null; + boolean fileExists = file.exists(); + if (fileExists) { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + path = reader.readLine(); + port = Integer.parseInt(reader.readLine()); } - return; - default: - break; + } + sendQuitRequest(port); + if (fileExists) { + deleteRecurse(Paths.get(path)); + file.delete(); + } + return; + default: + break; + } + } + + private static Map parseArgs(String[] args) { + Map parsedArgs = new HashMap(); + for (String arg : args) { + if (arg.startsWith("--port=")) { + parsedArgs.put("port", arg.substring("--port=".length())); + } else if (arg.equals("START") || arg.equals("STOP")) { + parsedArgs.put("action", arg); + } else { + throw new RuntimeException("Only accepts START, STOP, and --port= as arguments"); } } - throw new RuntimeException("expecting only START | STOP"); + if (parsedArgs.get("action") == null) { + throw new RuntimeException("EXPECTING START | STOP"); + } + return parsedArgs; } public static boolean isActive(String projectId, int port) {