kudu-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From granthe...@apache.org
Subject kudu git commit: [test] Adjust Kudu binary locator logic.
Date Fri, 21 Sep 2018 16:07:54 GMT
Repository: kudu
Updated Branches:
  refs/heads/master fd1ffd0fb -> 34e88d3da


[test] Adjust Kudu binary locator logic.

This patch adjusts the binary locating logic to be less
fragile and more externally useful. It also breaks the
logic out of the TestUtils class into it’s own class.
I broke out the remaining TestUtils methods as
well and remove any that were unused.

This patch also adjusts the Maven and Gradle build
to define the `kuduBinDir` system property. Doing
this means we don’t need to detect git repos and
search the repository for binaries.  This also fixes
the issue where Maven tests would fail to locate the
binary because they were using jars installed into
the local repository.

Change-Id: I365dfb9fdeeb4fd985f370a6b8305345e0a2ac7d
Reviewed-on: http://gerrit.cloudera.org:8080/11475
Tested-by: Kudu Jenkins
Reviewed-by: Adar Dembo <adar@cloudera.com>
Reviewed-by: Dan Burkert <danburkert@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/34e88d3d
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/34e88d3d
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/34e88d3d

Branch: refs/heads/master
Commit: 34e88d3dafc421ccaabae5767aad2fd9fa015d39
Parents: fd1ffd0
Author: Grant Henke <granthenke@apache.org>
Authored: Wed Sep 19 14:04:36 2018 -0500
Committer: Grant Henke <granthenke@apache.org>
Committed: Fri Sep 21 16:07:20 2018 +0000

----------------------------------------------------------------------
 java/README.adoc                                |   2 +-
 .../org/apache/kudu/gradle/DistTestTask.java    |   2 +-
 java/gradle/tests.gradle                        |   5 +-
 .../org/apache/kudu/backup/TestKuduBackup.scala |   4 +-
 .../org/apache/kudu/client/BaseKuduTest.java    |   3 +-
 .../org/apache/kudu/client/MiniKuduCluster.java |   3 +-
 .../apache/kudu/client/TestAsyncKuduClient.java |   7 +-
 .../apache/kudu/client/TestRemoteTablet.java    |   5 +-
 .../org/apache/kudu/client/TestTestUtils.java   | 115 ---------
 .../java/org/apache/kudu/client/TestUtils.java  | 238 -------------------
 .../org/apache/kudu/util/KuduBinaryLocator.java |  94 ++++++++
 .../org/apache/kudu/util/ProtobufUtils.java     |  64 +++++
 .../java/org/apache/kudu/util/RandomUtils.java  |  49 ++++
 java/pom.xml                                    |   6 +
 14 files changed, 232 insertions(+), 365 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/README.adoc
----------------------------------------------------------------------
diff --git a/java/README.adoc b/java/README.adoc
index 23052c6..42da7e7 100644
--- a/java/README.adoc
+++ b/java/README.adoc
@@ -55,7 +55,7 @@ for Kudu, those should be present already.
 
 If for some reason the binaries aren't in the expected location
 as shown above, you can pass
-`-DbinDir=/path/to/directory`.
+`-DkuduBinDir=/path/to/directory`.
 
 Once everything is setup correctly, run:
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java
----------------------------------------------------------------------
diff --git a/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java b/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java
index 3645017..32c5b24 100644
--- a/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java
+++ b/java/buildSrc/src/main/groovy/org/apache/kudu/gradle/DistTestTask.java
@@ -185,7 +185,7 @@ public class DistTestTask extends DefaultTask {
     for (Map.Entry<String, Object> e : test.getSystemProperties().entrySet()) {
       cmd.add("-D" + e.getKey() + "=" + e.getValue());
     }
-    cmd.add("-DbinDir=" + isolateFileDir.relativize(binDir),
+    cmd.add("-DkuduBinDir=" + isolateFileDir.relativize(binDir),
             "org.junit.runner.JUnitCore",
             testClass);
 

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/gradle/tests.gradle
----------------------------------------------------------------------
diff --git a/java/gradle/tests.gradle b/java/gradle/tests.gradle
index 19f85ee..d356ad0 100644
--- a/java/gradle/tests.gradle
+++ b/java/gradle/tests.gradle
@@ -57,9 +57,12 @@ tasks.withType(Test) {
   systemProperty "java.net.preferIPv4Stack", true
   systemProperty "java.security.egd", "file:/dev/urandom" // Improve RNG generation speed.
 
-  // Set rerunFailingTestsCount for use in BaseKuduTest.java to rerun failing tests
+  // Set rerunFailingTestsCount for use in BaseKuduTest.java to rerun failing tests.
   systemProperty "rerunFailingTestsCount", propertyWithDefault("rerunFailingTestsCount",
0)
 
+  // Set kuduBinDir to the binaries to use with the MiniKuduCluster.
+  systemProperty "kuduBinDir", "$project.rootDir/../build/latest/bin"
+
   // Don't fail the build if a --tests filter doesn't match any tests.
   // This is useful for filtering tests from the top of the project where some
   // subprojects won't match the filter. Without this, those subprojects would fail.

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala
----------------------------------------------------------------------
diff --git a/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala b/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala
index aa4d603..1dc7b96 100644
--- a/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala
+++ b/java/kudu-backup/src/test/scala/org/apache/kudu/backup/TestKuduBackup.scala
@@ -30,12 +30,12 @@ import org.apache.kudu.client.CreateTableOptions
 import org.apache.kudu.client.KuduTable
 import org.apache.kudu.client.PartialRow
 import org.apache.kudu.client.PartitionSchema
-import org.apache.kudu.client.TestUtils
 import org.apache.kudu.ColumnSchema
 import org.apache.kudu.Schema
 import org.apache.kudu.Type
 import org.apache.kudu.spark.kudu._
 import org.apache.kudu.util.DecimalUtil
+import org.apache.kudu.util.RandomUtils
 import org.junit.Assert._
 import org.junit.Test
 import org.slf4j.Logger
@@ -85,7 +85,7 @@ class TestKuduBackup extends KuduTestSuite {
 
   @Test
   def testRandomBackupAndRestore() {
-    Random.javaRandomToRandom(TestUtils.getRandom)
+    Random.javaRandomToRandom(RandomUtils.getRandom)
 
     val table = createRandomTable()
     val tableName = table.getName

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java b/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
index d66a65e..959b92c 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/BaseKuduTest.java
@@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
 import com.google.common.base.Stopwatch;
 import com.stumbleupon.async.Deferred;
 import org.apache.kudu.junit.RetryRule;
+import org.apache.kudu.util.RandomUtils;
 import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.yetus.audience.InterfaceStability;
 import org.junit.After;
@@ -51,7 +52,7 @@ public class BaseKuduTest {
   // to complete, etc.
   protected static final int DEFAULT_SLEEP = 50000;
 
-  private final Random randomForTSRestart = TestUtils.getRandom();
+  private final Random randomForTSRestart = RandomUtils.getRandom();
 
   private static final int NUM_MASTERS = 3;
   private static final int NUM_TABLET_SERVERS = 3;

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/client/MiniKuduCluster.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/MiniKuduCluster.java b/java/kudu-client/src/test/java/org/apache/kudu/client/MiniKuduCluster.java
index 5bc960a..a372dfc 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/MiniKuduCluster.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/MiniKuduCluster.java
@@ -52,6 +52,7 @@ import org.apache.kudu.tools.Tool.KinitRequestPB;
 import org.apache.kudu.tools.Tool.StartClusterRequestPB;
 import org.apache.kudu.tools.Tool.StartDaemonRequestPB;
 import org.apache.kudu.tools.Tool.StopDaemonRequestPB;
+import org.apache.kudu.util.KuduBinaryLocator;
 import org.apache.kudu.util.SecurityUtil;
 import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.yetus.audience.InterfaceStability;
@@ -187,7 +188,7 @@ public class MiniKuduCluster implements AutoCloseable {
 
     // Start the control shell and the communication channel to it.
     List<String> commandLine = Lists.newArrayList(
-        TestUtils.findBinary("kudu"),
+        KuduBinaryLocator.findBinary("kudu"),
         "test",
         "mini_cluster",
         "--serialization=pb");

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduClient.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduClient.java
b/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduClient.java
index 56d5d6e..6c793bf 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduClient.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestAsyncKuduClient.java
@@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
 import com.google.common.base.Stopwatch;
 import com.google.protobuf.ByteString;
 import com.stumbleupon.async.Deferred;
+import org.apache.kudu.util.ProtobufUtils;
 import org.junit.Test;
 
 import org.apache.kudu.ColumnSchema;
@@ -142,7 +143,7 @@ public class TestAsyncKuduClient extends BaseKuduTest {
       partition.setPartitionKeyEnd(ByteString.copyFrom("b" + i, UTF_8.name()));
       tabletPb.setPartition(partition);
       tabletPb.setTabletId(ByteString.copyFromUtf8("some id " + i));
-      tabletPb.addReplicas(TestUtils.getFakeTabletReplicaPB(
+      tabletPb.addReplicas(ProtobufUtils.getFakeTabletReplicaPB(
           "uuid", badHostname + i, i, Metadata.RaftPeerPB.Role.FOLLOWER));
       tabletLocations.add(tabletPb.build());
     }
@@ -177,9 +178,9 @@ public class TestAsyncKuduClient extends BaseKuduTest {
     // Fake a master lookup that only returns one follower for the tablet.
     List<Master.TabletLocationsPB> tabletLocations = new ArrayList<>();
     Master.TabletLocationsPB.Builder tabletPb = Master.TabletLocationsPB.newBuilder();
-    tabletPb.setPartition(TestUtils.getFakePartitionPB());
+    tabletPb.setPartition(ProtobufUtils.getFakePartitionPB());
     tabletPb.setTabletId(ByteString.copyFrom(tablet.getTabletId()));
-    tabletPb.addReplicas(TestUtils.getFakeTabletReplicaPB(
+    tabletPb.addReplicas(ProtobufUtils.getFakeTabletReplicaPB(
         "master", leader.getRpcHost(), leader.getRpcPort(), Metadata.RaftPeerPB.Role.FOLLOWER));
     tabletLocations.add(tabletPb.build());
     try {

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/client/TestRemoteTablet.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRemoteTablet.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRemoteTablet.java
index b9cbd46..c5cc27f 100644
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestRemoteTablet.java
+++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestRemoteTablet.java
@@ -28,6 +28,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import com.google.protobuf.ByteString;
+import org.apache.kudu.util.ProtobufUtils;
 import org.junit.Test;
 
 import org.apache.kudu.consensus.Metadata;
@@ -154,7 +155,7 @@ public class TestRemoteTablet {
   static RemoteTablet getTablet(int leaderIndex, int localReplicaIndex) {
     Master.TabletLocationsPB.Builder tabletPb = Master.TabletLocationsPB.newBuilder();
 
-    tabletPb.setPartition(TestUtils.getFakePartitionPB());
+    tabletPb.setPartition(ProtobufUtils.getFakePartitionPB());
     tabletPb.setTabletId(ByteString.copyFromUtf8("fake tablet"));
     List<ServerInfo> servers = new ArrayList<>();
     for (int i = 0; i < 3; i++) {
@@ -173,7 +174,7 @@ public class TestRemoteTablet {
       servers.add(new ServerInfo(uuid,
                                  new HostAndPort("host", 1000 + i),
                                  addr));
-      tabletPb.addReplicas(TestUtils.getFakeTabletReplicaPB(
+      tabletPb.addReplicas(ProtobufUtils.getFakeTabletReplicaPB(
           uuid, "host", i,
           leaderIndex == i ? Metadata.RaftPeerPB.Role.LEADER : Metadata.RaftPeerPB.Role.FOLLOWER));
     }

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/client/TestTestUtils.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestTestUtils.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestTestUtils.java
deleted file mode 100644
index ce55921..0000000
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestTestUtils.java
+++ /dev/null
@@ -1,115 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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 org.apache.kudu.client;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.junit.After;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Tests for non-trivial helper methods in TestUtils.
- */
-public class TestTestUtils {
-
-  public static final Logger LOG = LoggerFactory.getLogger(TestUtils.class);
-
-  private Process proc;
-
-  @After
-  public void tearDown() {
-    if (proc != null) {
-      proc.destroy();
-    }
-  }
-
-  /**
-   * Starts a process that executes the "yes" command (which prints 'y' in a loop),
-   * sends a SIGSTOP to the process, and ensures that SIGSTOP does indeed pause the process.
-   * Afterwards, sends a SIGCONT to the process and ensures that the process resumes.
-   */
-  @Test(timeout = 2000)
-  public void testPauseAndResume() throws Exception {
-    ProcessBuilder processBuilder = new ProcessBuilder("yes");
-    proc = processBuilder.start();
-    LineCounterRunnable lineCounter = new LineCounterRunnable(proc.getInputStream());
-    Thread thread = new Thread(lineCounter);
-    thread.setDaemon(true);
-    thread.start();
-    TestUtils.pauseProcess(proc);
-    long prevCount;
-    do {
-      prevCount = lineCounter.getCount();
-      Thread.sleep(10);
-    } while (prevCount != lineCounter.getCount());
-    assertEquals(prevCount, lineCounter.getCount());
-    TestUtils.resumeProcess(proc);
-    do {
-      prevCount = lineCounter.getCount();
-      Thread.sleep(10);
-    } while (prevCount == lineCounter.getCount());
-    assertTrue(lineCounter.getCount() > prevCount);
-  }
-
-  /**
-   * Counts the number of lines in a specified input stream.
-   */
-  static class LineCounterRunnable implements Runnable {
-    private final AtomicLong counter;
-    private final InputStream is;
-
-    public LineCounterRunnable(InputStream is) {
-      this.is = is;
-      counter = new AtomicLong(0);
-    }
-
-    @Override
-    public void run() {
-      BufferedReader in = null;
-      try {
-        in = new BufferedReader(new InputStreamReader(is, UTF_8));
-        while (in.readLine() != null) {
-          counter.incrementAndGet();
-        }
-      } catch (Exception e) {
-        LOG.error("Error while reading from the process", e);
-      } finally {
-        if (in != null) {
-          try {
-            in.close();
-          } catch (IOException e) {
-            LOG.error("Error closing the stream", e);
-          }
-        }
-      }
-    }
-
-    public long getCount() {
-      return counter.get();
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/client/TestUtils.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestUtils.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestUtils.java
deleted file mode 100644
index 03ac43d..0000000
--- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestUtils.java
+++ /dev/null
@@ -1,238 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you 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 org.apache.kudu.client;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Field;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.Random;
-import java.util.Set;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableSet;
-import com.google.protobuf.ByteString;
-import org.apache.yetus.audience.InterfaceAudience;
-import org.apache.yetus.audience.InterfaceStability;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.kudu.Common;
-import org.apache.kudu.consensus.Metadata;
-import org.apache.kudu.master.Master;
-
-/**
- * A grouping of methods that help unit testing.
- */
-@InterfaceAudience.Private
-@InterfaceStability.Unstable
-public class TestUtils {
-  private static final Logger LOG = LoggerFactory.getLogger(TestUtils.class);
-
-  private static Set<String> VALID_SIGNALS =  ImmutableSet.of("STOP", "CONT", "TERM",
"KILL");
-
-  private static final String BIN_DIR_PROP = "binDir";
-
-  private static final String TEST_RANDOM_SEED_PROP = "testRandomSeed";
-
-  /**
-   * Return the path portion of a file URL, after decoding the escaped
-   * components. This fixes issues when trying to build within a
-   * working directory with special characters.
-   */
-  private static String urlToPath(URL u) {
-    try {
-      return URLDecoder.decode(u.getPath(), "UTF-8");
-    } catch (UnsupportedEncodingException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Find the nearest directory up in the path hierarchy that is a git source directory.
-   */
-  private static File findParentGitDir(File dir) {
-    while (dir != null) {
-      if (new File(dir, ".git").exists()) {
-        return dir;
-      }
-      dir = dir.getParentFile();
-    }
-    return null;
-  }
-
-  /**
-   * Find the binary directory within the build tree.
-   */
-  private static String findBinDir() {
-    // First check the system property, which is our standard override.
-    String binDirProp = System.getProperty(BIN_DIR_PROP);
-    if (binDirProp != null) {
-      LOG.info("Using binary directory specified by property: {}", binDirProp);
-      return binDirProp;
-    }
-
-    // Next, attempt to traverse from the location of the class file.
-    URL codeSrcUrl = BaseKuduTest.class.getProtectionDomain().getCodeSource().getLocation();
-    File srcDir = findParentGitDir(new File(urlToPath(codeSrcUrl)));
-    if (srcDir != null) {
-      return new File(srcDir, "build/latest/bin").getAbsolutePath();
-    }
-
-    // Note: It has been discussed in the past whether to also search from the current working
-    // directory to find the source directory. At this time we have elected *not* to support
this,
-    // instead relying on setting -DbinDir for cases where the test libs may be in the Maven
repo.
-    // See the following code reviews for the discussion: https://gerrit.cloudera.org/5328
and
-    // https://gerrit.cloudera.org/4630
-    // Note: Builds using Gradle do not have this issue.
-
-    LOG.warn("Unable to find bin dir! codeSrcUrl={}", codeSrcUrl);
-    return null;
-  }
-
-  /**
-   * @param binName the binary to look for (eg 'kudu-tserver')
-   * @return the absolute path of that binary
-   * @throws FileNotFoundException if no such binary is found
-   */
-  public static String findBinary(String binName) throws FileNotFoundException {
-    String binDir = findBinDir();
-
-    File candidate = new File(binDir, binName);
-    if (candidate.canExecute()) {
-      return candidate.getAbsolutePath();
-    }
-    throw new FileNotFoundException("Cannot find binary " + binName +
-        " in binary directory " + binDir);
-  }
-
-  /**
-   * Gets the pid of a specified process. Relies on reflection and only works on
-   * UNIX process, not guaranteed to work on JDKs other than Oracle and OpenJDK.
-   * @param proc The specified process.
-   * @return The process UNIX pid.
-   * @throws IllegalArgumentException If the process is not a UNIXProcess.
-   * @throws Exception If there are other getting the pid via reflection.
-   */
-  static int pidOfProcess(Process proc) throws Exception {
-    Class<?> procCls = proc.getClass();
-    try {
-      // Note: In Java 9+ you can call proc.getPid(). We use reflection
-      // because we support earlier version of java.
-      Field pidField = procCls.getDeclaredField("pid");
-      pidField.setAccessible(true);
-      return (Integer) pidField.get(proc);
-    } catch (ReflectiveOperationException e) {
-      throw new IllegalArgumentException("pidOfProcess could not find or access the pid field"
+
-          "via reflection on the class " + procCls.getName(), e);
-    }
-  }
-
-  /**
-   * Send a code specified by its string representation to the specified process.
-   * TODO: Use a JNR/JNR-Posix instead of forking the JVM to exec "kill".
-   * @param proc The specified process.
-   * @param sig The string representation of the process (e.g., STOP for SIGSTOP).
-   * @throws IllegalArgumentException If the signal type is not supported.
-   * @throws IllegalStateException If we are unable to send the specified signal.
-   */
-  static void signalProcess(Process proc, String sig) throws Exception {
-    if (!VALID_SIGNALS.contains(sig)) {
-      throw new IllegalArgumentException(sig + " is not a supported signal, only " +
-              Joiner.on(",").join(VALID_SIGNALS) + " are supported");
-    }
-    int pid = pidOfProcess(proc);
-    int rv = Runtime.getRuntime()
-            .exec(String.format("kill -%s %d", sig, pid))
-            .waitFor();
-    if (rv != 0) {
-      throw new IllegalStateException(String.format("unable to send SIG%s to process %s(pid=%d):
" +
-              "expected return code from kill, but got %d instead", sig, proc, pid, rv));
-    }
-  }
-
-  /**
-   * Pause the specified process by sending a SIGSTOP using the kill command.
-   * @param proc The specified process.
-   * @throws Exception If error prevents us from pausing the process.
-   */
-  static void pauseProcess(Process proc) throws Exception {
-    signalProcess(proc, "STOP");
-  }
-
-  /**
-   * Resumes the specified process by sending a SIGCONT using the kill command.
-   * @param proc The specified process.
-   * @throws Exception If error prevents us from resuming the process.
-   */
-  static void resumeProcess(Process proc) throws Exception {
-    signalProcess(proc, "CONT");
-  }
-
-  /**
-   * Get a PartitionPB with empty start and end keys.
-   * @return a fake partition
-   */
-  static Common.PartitionPB.Builder getFakePartitionPB() {
-    Common.PartitionPB.Builder partition = Common.PartitionPB.newBuilder();
-    partition.setPartitionKeyStart(ByteString.EMPTY);
-    partition.setPartitionKeyEnd(ByteString.EMPTY);
-    return partition;
-  }
-
-  /**
-   * Create a ReplicaPB based on the passed information.
-   * @param uuid server's identifier
-   * @param host server's hostname
-   * @param port server's port
-   * @param role server's role in the configuration
-   * @return a fake ReplicaPB
-   */
-  static Master.TabletLocationsPB.ReplicaPB.Builder getFakeTabletReplicaPB(
-      String uuid, String host, int port, Metadata.RaftPeerPB.Role role) {
-    Master.TSInfoPB.Builder tsInfoBuilder = Master.TSInfoPB.newBuilder();
-    Common.HostPortPB.Builder hostBuilder = Common.HostPortPB.newBuilder();
-    hostBuilder.setHost(host);
-    hostBuilder.setPort(port);
-    tsInfoBuilder.addRpcAddresses(hostBuilder);
-    tsInfoBuilder.setPermanentUuid(ByteString.copyFromUtf8(uuid));
-    Master.TabletLocationsPB.ReplicaPB.Builder replicaBuilder =
-        Master.TabletLocationsPB.ReplicaPB.newBuilder();
-    replicaBuilder.setTsInfo(tsInfoBuilder);
-    replicaBuilder.setRole(role);
-    return replicaBuilder;
-  }
-
-  /**
-   * Get an instance of Random for use in tests and logs the seed used.
-   *
-   * Uses a default seed of System.currentTimeMillis() with the option to
-   * override via the testRandomSeed system property.
-   */
-  public static Random getRandom() {
-    // First check the system property.
-    long seed = System.currentTimeMillis();
-    if (System.getProperty(TEST_RANDOM_SEED_PROP) != null) {
-      seed = Long.parseLong(System.getProperty(TEST_RANDOM_SEED_PROP));
-      LOG.info("System property {} is defined. Overriding random seed.", TEST_RANDOM_SEED_PROP,
seed);
-    }
-    LOG.info("Using random seed: {}", seed);
-    return new Random(seed);
-  }
-}

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/util/KuduBinaryLocator.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/util/KuduBinaryLocator.java b/java/kudu-client/src/test/java/org/apache/kudu/util/KuduBinaryLocator.java
new file mode 100644
index 0000000..1b11d61
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/util/KuduBinaryLocator.java
@@ -0,0 +1,94 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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 org.apache.kudu.util;
+
+import com.google.common.io.CharStreams;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class KuduBinaryLocator {
+  private static final Logger LOG = LoggerFactory.getLogger(KuduBinaryLocator.class);
+
+  private static final String KUDU_BIN_DIR_PROP = "kuduBinDir";
+
+  /**
+   * Find the binary directory within the build tree.
+   *
+   * Uses the following priority:
+   *    - If kuduBinDir system property is set, use that.
+   *    - If the `kudu` binary is found on the PATH using `which kudu`,
+   *      use its parent directory.
+   */
+  private static String findBinaryDir() {
+    // If kuduBinDir system property is set, use that.
+    String kuduBinDirProp = System.getProperty(KUDU_BIN_DIR_PROP);
+    if (kuduBinDirProp != null) {
+      LOG.info("Using Kudu binary directory specified by system property '{}': {}",
+          KUDU_BIN_DIR_PROP, kuduBinDirProp);
+      return kuduBinDirProp;
+    }
+
+    // If the `kudu` binary is found on the PATH using `which kudu`, use its parent directory.
+    try {
+      Runtime runtime = Runtime.getRuntime();
+      Process process = runtime.exec("which kudu");
+      int errorCode = process.waitFor();
+      if (errorCode == 0) {
+        try(Reader reader = new InputStreamReader(process.getInputStream(), UTF_8)) {
+          String kuduBinary = CharStreams.toString(reader);
+          String kuduBinDir = new File(kuduBinary).getParent();
+          LOG.info("Using Kudu binary directory found on path with 'which kudu': {}", kuduBinDir);
+          return kuduBinDir;
+        }
+      }
+    } catch (IOException | InterruptedException ex) {
+      throw new RuntimeException("Error while locating kudu binary", ex);
+    }
+
+    throw new RuntimeException("Could not locate the kudu binary directory. " +
+        "Set the system variable " + KUDU_BIN_DIR_PROP +
+        " or ensure the `kudu` binary is on your path.");
+  }
+
+  /**
+   * @param binName the binary to look for (eg 'kudu-tserver')
+   * @return the absolute path of that binary
+   * @throws FileNotFoundException if no such binary is found
+   */
+  public static String findBinary(String binName) throws FileNotFoundException {
+    String binDir = findBinaryDir();
+
+    File candidate = new File(binDir, binName);
+    if (candidate.canExecute()) {
+      return candidate.getAbsolutePath();
+    }
+    throw new FileNotFoundException("Cannot find binary " + binName +
+        " in binary directory " + binDir);
+  }
+}

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/util/ProtobufUtils.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/util/ProtobufUtils.java b/java/kudu-client/src/test/java/org/apache/kudu/util/ProtobufUtils.java
new file mode 100644
index 0000000..70ae846
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/util/ProtobufUtils.java
@@ -0,0 +1,64 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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 org.apache.kudu.util;
+
+import com.google.protobuf.ByteString;
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+
+import org.apache.kudu.Common;
+import org.apache.kudu.consensus.Metadata;
+import org.apache.kudu.master.Master;
+
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class ProtobufUtils {
+
+  /**
+   * Get a PartitionPB with empty start and end keys.
+   * @return a fake partition
+   */
+  public static Common.PartitionPB.Builder getFakePartitionPB() {
+    Common.PartitionPB.Builder partition = Common.PartitionPB.newBuilder();
+    partition.setPartitionKeyStart(ByteString.EMPTY);
+    partition.setPartitionKeyEnd(ByteString.EMPTY);
+    return partition;
+  }
+
+  /**
+   * Create a ReplicaPB based on the passed information.
+   * @param uuid server's identifier
+   * @param host server's hostname
+   * @param port server's port
+   * @param role server's role in the configuration
+   * @return a fake ReplicaPB
+   */
+  public static Master.TabletLocationsPB.ReplicaPB.Builder getFakeTabletReplicaPB(
+      String uuid, String host, int port, Metadata.RaftPeerPB.Role role) {
+    Master.TSInfoPB.Builder tsInfoBuilder = Master.TSInfoPB.newBuilder();
+    Common.HostPortPB.Builder hostBuilder = Common.HostPortPB.newBuilder();
+    hostBuilder.setHost(host);
+    hostBuilder.setPort(port);
+    tsInfoBuilder.addRpcAddresses(hostBuilder);
+    tsInfoBuilder.setPermanentUuid(ByteString.copyFromUtf8(uuid));
+    Master.TabletLocationsPB.ReplicaPB.Builder replicaBuilder =
+        Master.TabletLocationsPB.ReplicaPB.newBuilder();
+    replicaBuilder.setTsInfo(tsInfoBuilder);
+    replicaBuilder.setRole(role);
+    return replicaBuilder;
+  }
+}

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/kudu-client/src/test/java/org/apache/kudu/util/RandomUtils.java
----------------------------------------------------------------------
diff --git a/java/kudu-client/src/test/java/org/apache/kudu/util/RandomUtils.java b/java/kudu-client/src/test/java/org/apache/kudu/util/RandomUtils.java
new file mode 100644
index 0000000..2b45464
--- /dev/null
+++ b/java/kudu-client/src/test/java/org/apache/kudu/util/RandomUtils.java
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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 org.apache.kudu.util;
+
+import org.apache.yetus.audience.InterfaceAudience;
+import org.apache.yetus.audience.InterfaceStability;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Random;
+
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+public class RandomUtils {
+  private static final Logger LOG = LoggerFactory.getLogger(RandomUtils.class);
+
+  private static final String TEST_RANDOM_SEED_PROP = "testRandomSeed";
+
+  /**
+   * Get an instance of Random for use in tests and logs the seed used.
+   *
+   * Uses a default seed of System.currentTimeMillis() with the option to
+   * override via the testRandomSeed system property.
+   */
+  public static Random getRandom() {
+    // First check the system property.
+    long seed = System.currentTimeMillis();
+    if (System.getProperty(TEST_RANDOM_SEED_PROP) != null) {
+      seed = Long.parseLong(System.getProperty(TEST_RANDOM_SEED_PROP));
+      LOG.info("System property {} is defined. Overriding random seed.", TEST_RANDOM_SEED_PROP,
seed);
+    }
+    LOG.info("Using random seed: {}", seed);
+    return new Random(seed);
+  }
+}

http://git-wip-us.apache.org/repos/asf/kudu/blob/34e88d3d/java/pom.xml
----------------------------------------------------------------------
diff --git a/java/pom.xml b/java/pom.xml
index a234e3c..cb3fdc9 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -151,6 +151,9 @@
                         <reuseForks>false</reuseForks>
                         <redirectTestOutputToFile>true</redirectTestOutputToFile>
                         <argLine>${testArgLine}</argLine>
+                        <systemPropertyVariables>
+                            <kuduBinDir>${project.basedir}/../../build/latest/bin</kuduBinDir>
+                        </systemPropertyVariables>
                     </configuration>
                 </plugin>
                 <plugin>
@@ -162,6 +165,9 @@
                         <reuseForks>false</reuseForks>
                         <redirectTestOutputToFile>true</redirectTestOutputToFile>
                         <argLine>${testArgLine}</argLine>
+                        <systemPropertyVariables>
+                            <kuduBinDir>${project.basedir}/../../build/latest/bin</kuduBinDir>
+                        </systemPropertyVariables>
                     </configuration>
                 </plugin>
                 <plugin>


Mime
View raw message