Bug: SecureTestCluster should allow its subclasses to pass their Class reference on HBaseKerberosUtils.setSSLConfiguration
Status: Resolved | Priority: Major | Resolution: Fixed
Created: 25/Feb/20 17:50
Affects Version/s: 2.2.3

Was working on a third party project that relies on hbase-server as a dependency and defines a UT class that extends *SecureTestCluster*. In this project, hbase-server jar is added on the test classpath, and it relies on *KeyStoreTestUtil* to decide where to place related ssl files. Current *KeyStoreTestUtil* code assumes related class files would be under an existing local FS path, but when those are loaded from a jar, related class URI path returns null and causes an NPE that errors out the test execution. 

 

The test code in this case extends *SecureTestCluster*, so when *SecureTestCluster.setup* runs, it calls *HBaseKerberosUtils.setSSLConfiguration* passing its own class reference [here|https://github.com/apache/hbase/blob/master/hbase-server/src/test/java/org/apache/hadoop/hbase/security/token/SecureTestCluster.java#L72].
**

*HBaseKerberosUtils.setSSLConfiguration*, in turn, calls *KeyStoreTestUtil.getClasspathDir* [here|https://github.com/apache/hbase/blob/master/hbase-server/src/test/java/org/apache/hadoop/hbase/security/HBaseKerberosUtils.java#L173]. *KeyStoreTestUtil.getClasspathDir* uses the passed class reference name to look for its related resource in the class loader. [This line|https://github.com/apache/hbase/blob/master/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java#L58] returns an URL value as follows, when the passed class reference resource resides on jar file in the class loader (instead of being in a valid local FS path):

{{jar:file:/Users/wellingtonchevreuil/.m2/repository/org/apache/hbase/hbase-server/2.2.3./hbase-server-2.2.3-tests.jar!/org/apache/hadoop/hbase/security/token/SecureTestCluster.class}}

This causes [subsequent line|https://github.com/apache/hbase/blob/master/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java#L59] calling {{url.toURI().getPath()}} to return null, then we get the NPE thrown in the following line, and the test errors out:

{{java.lang.NullPointerException at org.apache.hadoop.hbase.http.ssl.KeyStoreTestUtil.getClasspathDir(KeyStoreTestUtil.java:59) at org.apache.hadoop.hbase.security.HBaseKerberosUtils.setSSLConfiguration(HBaseKerberosUtils.java:173) at org.apache.hadoop.hbase.security.token.SecureTestCluster.setUp(SecureTestCluster.java:74) at com.cloudera.hbase.security.token.TestCldrManualDelegationToken.setUp(TestCldrManualDelegationToken.java:168) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:298) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:292) at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) at java.util.concurrent.FutureTask.run(FutureTask.java) at java.lang.Thread.run(Thread.java:748}}