diff --git a/flume-bom/pom.xml b/flume-bom/pom.xml
index 9477ac6d16..f65016bd83 100644
--- a/flume-bom/pom.xml
+++ b/flume-bom/pom.xml
@@ -103,6 +103,11 @@
flume-ng-sdk
${project.version}
+
+ org.apache.flume
+ flume-ng-sdk-test
+ ${project.version}
+
org.apache.flume
flume-ng-node
diff --git a/flume-ng-core/pom.xml b/flume-ng-core/pom.xml
index 2f8044fe37..42efd81a2c 100644
--- a/flume-ng-core/pom.xml
+++ b/flume-ng-core/pom.xml
@@ -46,8 +46,7 @@
org.apache.flume
- flume-ng-sdk
- tests
+ flume-ng-sdk-test
test
diff --git a/flume-ng-core/src/test/java/org/apache/flume/sink/TestRollingFileSink.java b/flume-ng-core/src/test/java/org/apache/flume/sink/TestRollingFileSink.java
index c419a37b18..2d948b53db 100644
--- a/flume-ng-core/src/test/java/org/apache/flume/sink/TestRollingFileSink.java
+++ b/flume-ng-core/src/test/java/org/apache/flume/sink/TestRollingFileSink.java
@@ -32,7 +32,7 @@
import org.apache.flume.event.SimpleEvent;
import org.apache.flume.exception.ChannelException;
import org.apache.flume.instrumentation.SinkCounter;
-import org.apache.flume.util.Whitebox;
+import org.apache.flume.sdk.test.Whitebox;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.After;
diff --git a/flume-ng-sdk-test/pom.xml b/flume-ng-sdk-test/pom.xml
new file mode 100644
index 0000000000..6e5083d1fd
--- /dev/null
+++ b/flume-ng-sdk-test/pom.xml
@@ -0,0 +1,66 @@
+
+
+
+ 4.0.0
+
+
+ org.apache.flume
+ flume-parent
+ ${revision}
+ ../flume-parent/pom.xml
+
+
+ flume-ng-sdk-test
+ Flume NG SDK Test
+ Test fixtures shared by the Flume modules.
+ The fixtures live in `main`, so that they are packaged in a regular JAR instead of a test JAR.
+
+
+
+ false
+
+ 1
+ org.apache.flume.sdk.test
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+
+
+
+ org.bouncycastle
+ bcpkix-jdk18on
+
+
+
+ org.bouncycastle
+ bcprov-jdk18on
+
+
+
+ junit
+ junit
+ test
+
+
+
+
diff --git a/flume-ng-sdk/src/test/java/org/apache/flume/util/TestKeyStores.java b/flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/TestKeyStores.java
similarity index 98%
rename from flume-ng-sdk/src/test/java/org/apache/flume/util/TestKeyStores.java
rename to flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/TestKeyStores.java
index 7be6500271..5b7415c1b1 100644
--- a/flume-ng-sdk/src/test/java/org/apache/flume/util/TestKeyStores.java
+++ b/flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/TestKeyStores.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.flume.util;
+package org.apache.flume.sdk.test;
import java.io.OutputStream;
import java.nio.file.Files;
diff --git a/flume-ng-sdk/src/test/java/org/apache/flume/util/Whitebox.java b/flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/Whitebox.java
similarity index 97%
rename from flume-ng-sdk/src/test/java/org/apache/flume/util/Whitebox.java
rename to flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/Whitebox.java
index 995e0ae3fb..881c0cc2f1 100644
--- a/flume-ng-sdk/src/test/java/org/apache/flume/util/Whitebox.java
+++ b/flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/Whitebox.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.flume.util;
+package org.apache.flume.sdk.test;
import org.apache.commons.lang3.reflect.FieldUtils;
diff --git a/flume-ng-sdk/src/test/java/org/apache/flume/util/X509Certificates.java b/flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/X509Certificates.java
similarity index 99%
rename from flume-ng-sdk/src/test/java/org/apache/flume/util/X509Certificates.java
rename to flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/X509Certificates.java
index ac38450025..b1ae2f44cd 100644
--- a/flume-ng-sdk/src/test/java/org/apache/flume/util/X509Certificates.java
+++ b/flume-ng-sdk-test/src/main/java/org/apache/flume/sdk/test/X509Certificates.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.flume.util;
+package org.apache.flume.sdk.test;
import java.math.BigInteger;
import java.security.KeyPair;
diff --git a/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestSelfSignedKeyStores.java b/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestSelfSignedKeyStores.java
new file mode 100644
index 0000000000..b76fc8a651
--- /dev/null
+++ b/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestSelfSignedKeyStores.java
@@ -0,0 +1,67 @@
+/*
+ * 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.flume.sdk.test;
+
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestSelfSignedKeyStores {
+
+ private static final String PASSWORD = "password";
+
+ @Test
+ public void testKeyStoreHoldsThePrivateKey() throws Exception {
+ TestKeyStores credentials = TestKeyStores.selfSigned("CN=localhost");
+ KeyStore keyStore = credentials.keyStore("JKS", PASSWORD);
+
+ Assert.assertTrue(keyStore.isKeyEntry("key"));
+ Assert.assertEquals(credentials.certificate(), keyStore.getCertificateChain("key")[0]);
+ Assert.assertNotNull(keyStore.getKey("key", PASSWORD.toCharArray()));
+ }
+
+ @Test
+ public void testTrustStoreHoldsOnlyTheCertificate() throws Exception {
+ TestKeyStores credentials = TestKeyStores.selfSigned("CN=localhost");
+ KeyStore trustStore = credentials.trustStore("JKS");
+
+ Assert.assertFalse(trustStore.isKeyEntry("cert"));
+ Assert.assertEquals(credentials.certificate(), trustStore.getCertificate("cert"));
+ }
+
+ @Test
+ public void testWrittenKeyStoreCanBeReloaded() throws Exception {
+ TestKeyStores credentials = TestKeyStores.selfSigned("CN=localhost");
+ Path file = Files.createTempFile("keystore", ".jks");
+ try {
+ credentials.writeKeyStore(file, "JKS", PASSWORD);
+
+ KeyStore reloaded = KeyStore.getInstance("JKS");
+ try (InputStream in = Files.newInputStream(file)) {
+ reloaded.load(in, PASSWORD.toCharArray());
+ }
+ X509Certificate certificate = (X509Certificate) reloaded.getCertificateChain("key")[0];
+ Assert.assertEquals(credentials.certificate(), certificate);
+ } finally {
+ Files.deleteIfExists(file);
+ }
+ }
+}
diff --git a/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestWhitebox.java b/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestWhitebox.java
new file mode 100644
index 0000000000..16e15d2082
--- /dev/null
+++ b/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestWhitebox.java
@@ -0,0 +1,44 @@
+/*
+ * 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.flume.sdk.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestWhitebox {
+
+ private static final class Target {
+ private String value = "initial";
+ }
+
+ @Test
+ public void testGetInternalState() {
+ Assert.assertEquals("initial", Whitebox.getInternalState(new Target(), "value"));
+ }
+
+ @Test
+ public void testSetInternalState() {
+ Target target = new Target();
+ Whitebox.setInternalState(target, "value", "replaced");
+ Assert.assertEquals("replaced", target.value);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testUnknownFieldFails() {
+ Whitebox.getInternalState(new Target(), "missing");
+ }
+}
diff --git a/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestX509Certificates.java b/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestX509Certificates.java
new file mode 100644
index 0000000000..ea31fabe3b
--- /dev/null
+++ b/flume-ng-sdk-test/src/test/java/org/apache/flume/sdk/test/TestX509Certificates.java
@@ -0,0 +1,57 @@
+/*
+ * 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.flume.sdk.test;
+
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Date;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestX509Certificates {
+
+ @Test
+ public void testSelfSignedCertificate() throws Exception {
+ KeyPair keyPair = X509Certificates.generateKeyPair();
+ X509Certificate certificate = X509Certificates.generateSelfSignedCertificate(keyPair, "CN=localhost");
+
+ Assert.assertEquals(
+ "CN=localhost", certificate.getSubjectX500Principal().getName());
+ Assert.assertEquals(certificate.getSubjectX500Principal(), certificate.getIssuerX500Principal());
+ // A self-signed certificate verifies against its own public key.
+ certificate.verify(keyPair.getPublic());
+ certificate.checkValidity(new Date());
+ }
+
+ @Test
+ public void testServerCertificateExtensions() throws Exception {
+ KeyPair keyPair = X509Certificates.generateKeyPair();
+ X509Certificate certificate = X509Certificates.generateSelfSignedCertificate(keyPair, "CN=localhost");
+
+ // A negative path length constraint marks a certificate that is not a CA.
+ Assert.assertEquals(-1, certificate.getBasicConstraints());
+ Assert.assertEquals(Collections.singletonList("1.3.6.1.5.5.7.3.1"), certificate.getExtendedKeyUsage());
+ }
+
+ @Test
+ public void testKeyPairsAreDistinct() {
+ Assert.assertNotEquals(
+ X509Certificates.generateKeyPair().getPrivate(),
+ X509Certificates.generateKeyPair().getPrivate());
+ }
+}
diff --git a/flume-ng-sdk/pom.xml b/flume-ng-sdk/pom.xml
index c5b1d20d69..afc5fc81b9 100644
--- a/flume-ng-sdk/pom.xml
+++ b/flume-ng-sdk/pom.xml
@@ -44,19 +44,6 @@
test
-
-
- org.bouncycastle
- bcpkix-jdk18on
- test
-
-
-
- org.bouncycastle
- bcprov-jdk18on
- test
-
-
org.apache.logging.log4j
log4j-api
@@ -82,32 +69,6 @@
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
-
- test-jar
-
-
-
-
-
- true
- true
-
-
- pkg:maven/${project.groupId}/${project.artifactId}@${project.version}?classifier=tests&type=test-jar
-
-
-
-
-
-
-
org.apache.maven.plugins
maven-surefire-plugin
diff --git a/flume-ng-sources/flume-http-source/pom.xml b/flume-ng-sources/flume-http-source/pom.xml
index d7f2b58500..d3def5ee43 100644
--- a/flume-ng-sources/flume-http-source/pom.xml
+++ b/flume-ng-sources/flume-http-source/pom.xml
@@ -45,8 +45,7 @@
org.apache.flume
- flume-ng-sdk
- tests
+ flume-ng-sdk-test
test
diff --git a/flume-ng-sources/flume-http-source/src/test/java/org/apache/flume/source/http/TestHTTPSource.java b/flume-ng-sources/flume-http-source/src/test/java/org/apache/flume/source/http/TestHTTPSource.java
index 8aa5ea2e8f..4b182805d8 100644
--- a/flume-ng-sources/flume-http-source/src/test/java/org/apache/flume/source/http/TestHTTPSource.java
+++ b/flume-ng-sources/flume-http-source/src/test/java/org/apache/flume/source/http/TestHTTPSource.java
@@ -63,8 +63,8 @@
import org.apache.flume.conf.Configurables;
import org.apache.flume.event.JSONEvent;
import org.apache.flume.instrumentation.SourceCounter;
-import org.apache.flume.util.TestKeyStores;
-import org.apache.flume.util.Whitebox;
+import org.apache.flume.sdk.test.TestKeyStores;
+import org.apache.flume.sdk.test.Whitebox;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpOptions;
diff --git a/flume-ng-sources/flume-syslog-source/pom.xml b/flume-ng-sources/flume-syslog-source/pom.xml
index 1f0beb2f9a..50ef7a2014 100644
--- a/flume-ng-sources/flume-syslog-source/pom.xml
+++ b/flume-ng-sources/flume-syslog-source/pom.xml
@@ -49,8 +49,7 @@
org.apache.flume
- flume-ng-sdk
- tests
+ flume-ng-sdk-test
test
diff --git a/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestMultiportSyslogTCPSource.java b/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestMultiportSyslogTCPSource.java
index 4976e135e6..af739b5836 100644
--- a/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestMultiportSyslogTCPSource.java
+++ b/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestMultiportSyslogTCPSource.java
@@ -62,12 +62,12 @@
import org.apache.flume.conf.Configurables;
import org.apache.flume.exception.ChannelException;
import org.apache.flume.instrumentation.SourceCounter;
+import org.apache.flume.sdk.test.TestKeyStores;
+import org.apache.flume.sdk.test.Whitebox;
import org.apache.flume.source.syslog.MultiportSyslogTCPSource.LineSplitter;
import org.apache.flume.source.syslog.MultiportSyslogTCPSource.MultiportSyslogHandler;
import org.apache.flume.source.syslog.MultiportSyslogTCPSource.ParsedBuffer;
import org.apache.flume.source.syslog.MultiportSyslogTCPSource.ThreadSafeDecoder;
-import org.apache.flume.util.TestKeyStores;
-import org.apache.flume.util.Whitebox;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
diff --git a/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestSyslogTcpSource.java b/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestSyslogTcpSource.java
index d6cf09a49f..a4eb816fdb 100644
--- a/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestSyslogTcpSource.java
+++ b/flume-ng-sources/flume-syslog-source/src/test/java/org/apache/flume/source/syslog/TestSyslogTcpSource.java
@@ -50,7 +50,7 @@
import org.apache.flume.channel.ReplicatingChannelSelector;
import org.apache.flume.conf.Configurables;
import org.apache.flume.exception.ChannelException;
-import org.apache.flume.util.TestKeyStores;
+import org.apache.flume.sdk.test.TestKeyStores;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Assert;
diff --git a/flume-ng-sources/flume-taildir-source/pom.xml b/flume-ng-sources/flume-taildir-source/pom.xml
index d371c0f3b4..2444b0f84a 100644
--- a/flume-ng-sources/flume-taildir-source/pom.xml
+++ b/flume-ng-sources/flume-taildir-source/pom.xml
@@ -43,8 +43,7 @@
org.apache.flume
- flume-ng-sdk
- tests
+ flume-ng-sdk-test
test
diff --git a/flume-ng-sources/flume-taildir-source/src/test/java/org/apache/flume/source/taildir/TestTaildirSource.java b/flume-ng-sources/flume-taildir-source/src/test/java/org/apache/flume/source/taildir/TestTaildirSource.java
index 4c8ec6a6b4..ff4bb18f44 100644
--- a/flume-ng-sources/flume-taildir-source/src/test/java/org/apache/flume/source/taildir/TestTaildirSource.java
+++ b/flume-ng-sources/flume-taildir-source/src/test/java/org/apache/flume/source/taildir/TestTaildirSource.java
@@ -57,7 +57,7 @@
import org.apache.flume.exception.ChannelException;
import org.apache.flume.lifecycle.LifecycleController;
import org.apache.flume.lifecycle.LifecycleState;
-import org.apache.flume.util.Whitebox;
+import org.apache.flume.sdk.test.Whitebox;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
diff --git a/flume-parent/pom.xml b/flume-parent/pom.xml
index 8036ba0ae2..03005e9cf3 100644
--- a/flume-parent/pom.xml
+++ b/flume-parent/pom.xml
@@ -213,9 +213,8 @@
org.apache.flume
- flume-ng-sdk
+ flume-ng-sdk-test
${flume-project.version}
- tests
test
diff --git a/pom.xml b/pom.xml
index 061bef4214..019f9ad801 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,7 @@
-->
flume-ng-channels
flume-ng-sdk
+ flume-ng-sdk-test