You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2018/09/06 16:03:41 UTC
[31/51] [abbrv] mina-sshd git commit: [SSHD-842] Split common
utilities code from sshd-core into sshd-common (new artifact)
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java b/sshd-common/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
new file mode 100644
index 0000000..0ea58f7
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/signature/BuiltinSignaturesTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.sshd.common.signature;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.sshd.common.NamedResource;
+import org.apache.sshd.common.signature.BuiltinSignatures.ParseResult;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+import org.mockito.Mockito;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class BuiltinSignaturesTest extends JUnitTestSupport {
+ public BuiltinSignaturesTest() {
+ super();
+ }
+
+ @Test
+ public void testFromName() {
+ for (BuiltinSignatures expected : BuiltinSignatures.VALUES) {
+ String name = expected.getName();
+ BuiltinSignatures actual = BuiltinSignatures.fromFactoryName(name);
+ assertSame(name, expected, actual);
+ }
+ }
+
+ @Test
+ public void testParseSignaturesList() {
+ List<String> builtin = NamedResource.getNameList(BuiltinSignatures.VALUES);
+ List<String> unknown = Arrays.asList(getClass().getPackage().getName(), getClass().getSimpleName(), getCurrentTestName());
+ Random rnd = new Random();
+ for (int index = 0; index < (builtin.size() + unknown.size()); index++) {
+ Collections.shuffle(builtin, rnd);
+ Collections.shuffle(unknown, rnd);
+
+ List<String> weavedList = new ArrayList<>(builtin.size() + unknown.size());
+ for (int bIndex = 0, uIndex = 0; (bIndex < builtin.size()) || (uIndex < unknown.size());) {
+ boolean useBuiltin = false;
+ if (bIndex < builtin.size()) {
+ useBuiltin = uIndex >= unknown.size() || rnd.nextBoolean();
+ }
+
+ if (useBuiltin) {
+ weavedList.add(builtin.get(bIndex));
+ bIndex++;
+ } else if (uIndex < unknown.size()) {
+ weavedList.add(unknown.get(uIndex));
+ uIndex++;
+ }
+ }
+
+ String fullList = GenericUtils.join(weavedList, ',');
+ ParseResult result = BuiltinSignatures.parseSignatureList(fullList);
+ List<String> parsed = NamedResource.getNameList(result.getParsedFactories());
+ List<String> missing = result.getUnsupportedFactories();
+
+ // makes sure not only that the contents are the same but also the order
+ assertListEquals(fullList + "[parsed]", builtin, parsed);
+ assertListEquals(fullList + "[unsupported]", unknown, missing);
+ }
+ }
+
+ @Test
+ public void testResolveFactoryOnBuiltinValues() {
+ for (SignatureFactory expected : BuiltinSignatures.VALUES) {
+ String name = expected.getName();
+ SignatureFactory actual = BuiltinSignatures.resolveFactory(name);
+ assertSame(name, expected, actual);
+ }
+ }
+
+ @Test
+ public void testNotAllowedToRegisterBuiltinFactories() {
+ for (SignatureFactory expected : BuiltinSignatures.VALUES) {
+ try {
+ BuiltinSignatures.registerExtension(expected);
+ fail("Unexpected success for " + expected.getName());
+ } catch (IllegalArgumentException e) {
+ // expected - ignored
+ }
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNotAllowedToOverrideRegisteredFactories() {
+ SignatureFactory expected = Mockito.mock(SignatureFactory.class);
+ Mockito.when(expected.getName()).thenReturn(getCurrentTestName());
+
+ String name = expected.getName();
+ try {
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ BuiltinSignatures.registerExtension(expected);
+ assertEquals("Unexpected success at attempt #" + index, 1, index);
+ }
+ } finally {
+ BuiltinSignatures.unregisterExtension(name);
+ }
+ }
+
+ @Test
+ public void testResolveFactoryOnRegisteredExtension() {
+ SignatureFactory expected = Mockito.mock(SignatureFactory.class);
+ Mockito.when(expected.getName()).thenReturn(getCurrentTestName());
+
+ String name = expected.getName();
+ try {
+ assertNull("Extension already registered", BuiltinSignatures.resolveFactory(name));
+ BuiltinSignatures.registerExtension(expected);
+
+ SignatureFactory actual = BuiltinSignatures.resolveFactory(name);
+ assertSame("Mismatched resolved instance", expected, actual);
+ } finally {
+ SignatureFactory actual = BuiltinSignatures.unregisterExtension(name);
+ assertSame("Mismatched unregistered instance", expected, actual);
+ assertNull("Extension not un-registered", BuiltinSignatures.resolveFactory(name));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureDSATest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureDSATest.java b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureDSATest.java
new file mode 100644
index 0000000..d9f507d
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureDSATest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.sshd.common.signature;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.spec.DSAPublicKeySpec;
+
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class SignatureDSATest extends JUnitTestSupport {
+ public SignatureDSATest() {
+ super();
+ }
+
+ @Test
+ public void testTooShortSignature() throws Exception {
+ KeyFactory kf = SecurityUtils.getKeyFactory(KeyUtils.DSS_ALGORITHM);
+ SignatureDSA signatureDSA = new SignatureDSA(KeyUtils.DSS_ALGORITHM) {
+ @Override
+ protected java.security.Signature doInitSignature(String algo, boolean forSigning) throws GeneralSecurityException {
+ return java.security.Signature.getInstance(algo);
+
+ }
+ };
+
+ byte[] y = new byte[] {
+ 0, -92, 59, 5, 72, 124, 101, 124, -18, 114, 7, 100, 98, -61, 73, -104,
+ 120, -98, 54, 118, 17, -62, 91, -110, 29, 98, 50, -101, -41, 99, -116,
+ 101, 107, -123, 124, -97, 62, 119, 88, -109, -110, -1, 109, 119, -51,
+ 69, -98, -105, 2, -69, -121, -82, -118, 23, -6, 96, -61, -65, 102, -58,
+ -74, 32, -104, 116, -6, -35, -83, -10, -88, -68, 106, -112, 72, -2, 35,
+ 38, 15, -11, -22, 30, -114, -46, -47, -18, -17, -71, 24, -25, 28, 13, 29,
+ -40, 101, 18, 81, 45, -120, -67, -53, -41, 11, 50, -89, -33, 50, 54, -14,
+ -91, -35, 12, -42, 13, -84, -19, 100, -3, -85, -18, 74, 99, -49, 64, -49,
+ 51, -83, -82, -127, 116, 64 };
+ byte[] p = new byte[] {
+ 0, -3, 127, 83, -127, 29, 117, 18, 41, 82, -33, 74, -100, 46, -20, -28,
+ -25, -10, 17, -73, 82, 60, -17, 68, 0, -61, 30, 63, -128, -74, 81, 38,
+ 105, 69, 93, 64, 34, 81, -5, 89, 61, -115, 88, -6, -65, -59, -11, -70,
+ 48, -10, -53, -101, 85, 108, -41, -127, 59, -128, 29, 52, 111, -14, 102,
+ 96, -73, 107, -103, 80, -91, -92, -97, -97, -24, 4, 123, 16, 34, -62, 79,
+ -69, -87, -41, -2, -73, -58, 27, -8, 59, 87, -25, -58, -88, -90, 21, 15, 4,
+ -5, -125, -10, -45, -59, 30, -61, 2, 53, 84, 19, 90, 22, -111, 50, -10, 117,
+ -13, -82, 43, 97, -41, 42, -17, -14, 34, 3, 25, -99, -47, 72, 1, -57 };
+ byte[] q = new byte[] {
+ 0, -105, 96, 80, -113, 21, 35, 11, -52, -78, -110, -71, -126, -94, -21,
+ -124, 11, -16, 88, 28, -11 };
+ byte[] g = new byte[] {
+ 0, -9, -31, -96, -123, -42, -101, 61, -34, -53, -68, -85, 92, 54, -72, 87,
+ -71, 121, -108, -81, -69, -6, 58, -22, -126, -7, 87, 76, 11, 61, 7, -126,
+ 103, 81, 89, 87, -114, -70, -44, 89, 79, -26, 113, 7, 16, -127, -128, -76,
+ 73, 22, 113, 35, -24, 76, 40, 22, 19, -73, -49, 9, 50, -116, -56, -90, -31,
+ 60, 22, 122, -117, 84, 124, -115, 40, -32, -93, -82, 30, 43, -77, -90, 117,
+ -111, 110, -93, 127, 11, -6, 33, 53, 98, -15, -5, 98, 122, 1, 36, 59, -52,
+ -92, -15, -66, -88, 81, -112, -119, -88, -125, -33, -31, 90, -27, -97, 6,
+ -110, -117, 102, 94, -128, 123, 85, 37, 100, 1, 76, 59, -2, -49, 73, 42 };
+
+ BigInteger bigY = new BigInteger(y);
+ BigInteger bigP = new BigInteger(p);
+ BigInteger bigQ = new BigInteger(q);
+ BigInteger bigG = new BigInteger(g);
+
+ DSAPublicKeySpec dsaPublicKey = new DSAPublicKeySpec(bigY, bigP, bigQ, bigG);
+ signatureDSA.initVerifier(kf.generatePublic(dsaPublicKey));
+ byte[] h = new byte[] {
+ -4, 111, -103, 111, 72, -106, 105, -19, 81, -123, 84, -13, -40, -53, -3,
+ -97, -8, 43, -22, -2, -23, -15, 28, 116, -63, 96, -79, -127, -84, 63, -6, -94 };
+ signatureDSA.update(h);
+
+ byte[] sig_of_h = new byte[] {
+ 0, 0, 0, 7, 115, 115, 104, 45, 100, 115, 115, 0, 0, 0, 40, 0, 79,
+ 84, 118, -50, 11, -117, -112, 52, -25, -78, -50, -20, 6, -69, -26,
+ 7, 90, -34, -124, 80, 76, -32, -23, -8, 43, 38, -48, -89, -17, -60,
+ -1, -78, 112, -88, 14, -39, -78, -98, -80 };
+ boolean verified = signatureDSA.verify(sig_of_h);
+
+ assertTrue(verified);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java
new file mode 100644
index 0000000..5671ac3
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignatureRSATest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.sshd.common.signature;
+
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.Base64;
+import java.util.Map;
+
+import org.apache.sshd.common.Factory;
+import org.apache.sshd.common.config.keys.KeyUtils;
+import org.apache.sshd.common.util.security.SecurityUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class SignatureRSATest extends JUnitTestSupport {
+ private static final Base64.Decoder B64_DECODER = Base64.getDecoder();
+ @SuppressWarnings("checkstyle:linelength")
+ private static final byte[] TEST_MSG =
+ B64_DECODER.decode("AAAAFPHgK1MeV9zNnok3pwNJhCd8SONqMgAAAAlidWlsZHVzZXIAAAAOc3NoLWNvbm5lY3Rpb24AAAAJcHVibGlja2V5AQAAAAdzc2gtcnNhAAABFQAAAAdzc2gtcnNhAAAAASMAAAEBAMs9HO/NH/Now+6fSnESebaG4wzaYQWA1b/q1TGV1wHNtCg9fGFGVSKs0VxKF4cfVyrSLtgLjnlXQTn+Lm7xiYKGbBbsTQWOqEDaBVBsRbAkxIkpuvr6/EBxwrtDbKmSQYTJZVJSD2bZRYjGsR9gpZXPorOOKFd5EPCMHXsqnhp2hidTGH7cK6RuLk7MNnPISsY0Nbx8/ZvikiPROGcoTZ8bzUv4IaLr3veW6epSeQem8tJqhnrpTHhbLU99zf045M0Gsnk/azjjlBM+qrHZ5FNdC1kowJnLtf2Oy/rUQNpkGJtcBPT8xvreV0wLsn9t3hSxzsc0+VkDNTQRlfU+o3M=");
+ @SuppressWarnings("checkstyle:linelength")
+ private static final byte[] TEST_SIGNATURE =
+ B64_DECODER.decode("AAAAB3NzaC1yc2EAAAD/+Ntnf4qfr2J1voDS6I+u3VRjtMn+LdWJsAZfkLDxRkK1rQxP7QAjLdNqpT4CkWHp8dtoTGFlBFt6NieNJCMTA2KSOxJMZKsX7e/lHkh7C+vhQvJ9eLTKWjCxSFUrcM0NvFhmwbRCffwXSHvAKak4wbmofxQMpd+G4jZkNMz5kGpmeICBcNjRLPb7oXzuGr/g4x/3ge5Qaawqrg/gcZr/sKN6SdE8SszgKYO0SB320N4gcUoShVdLYr9uwdJ+kJoobfkUK6Or171JCctP/cu2nM79lDqVnJw/2jOG8OnTc8zRDXAh0RKoR5rOU8cOHm0Ls2MATsFdnyRU5FGUxqZ+");
+ private static PublicKey testKey;
+
+ public SignatureRSATest() {
+ super();
+ }
+
+ @BeforeClass
+ public static void initializeTestKey() throws GeneralSecurityException {
+ byte[] exp = B64_DECODER.decode("Iw==");
+ @SuppressWarnings("checkstyle:linelength")
+ byte[] mod = B64_DECODER.decode("AMs9HO/NH/Now+6fSnESebaG4wzaYQWA1b/q1TGV1wHNtCg9fGFGVSKs0VxKF4cfVyrSLtgLjnlXQTn+Lm7xiYKGbBbsTQWOqEDaBVBsRbAkxIkpuvr6/EBxwrtDbKmSQYTJZVJSD2bZRYjGsR9gpZXPorOOKFd5EPCMHXsqnhp2hidTGH7cK6RuLk7MNnPISsY0Nbx8/ZvikiPROGcoTZ8bzUv4IaLr3veW6epSeQem8tJqhnrpTHhbLU99zf045M0Gsnk/azjjlBM+qrHZ5FNdC1kowJnLtf2Oy/rUQNpkGJtcBPT8xvreV0wLsn9t3hSxzsc0+VkDNTQRlfU+o3M=");
+ KeyFactory kf = SecurityUtils.getKeyFactory(KeyUtils.RSA_ALGORITHM);
+ testKey = kf.generatePublic(new RSAPublicKeySpec(new BigInteger(mod), new BigInteger(exp)));
+ }
+
+ @Test // see SSHD-642
+ public void testLeadingZeroesBC() throws Throwable {
+ testLeadingZeroes(new Factory<SignatureRSA>() {
+ @Override
+ public SignatureRSA create() {
+ return new SignatureRSA() {
+ @Override
+ protected java.security.Signature doInitSignature(String algo, boolean forSigning) throws GeneralSecurityException {
+ assertFalse("Signature not initialized for verification", forSigning);
+ java.security.Signature signature = super.doInitSignature(algo, forSigning);
+ if (SecurityUtils.isBouncyCastleRegistered()) {
+ Provider provider = signature.getProvider();
+ String name = provider.getName();
+ assertEquals("Mismatched BC provider name", SecurityUtils.BOUNCY_CASTLE, name);
+ }
+ return signature;
+ }
+ };
+ }
+ });
+ }
+
+ @Test // see SSHD-642
+ public void testLeadingZeroesJCE() throws Throwable {
+ testLeadingZeroes(() -> new SignatureRSA() {
+ @Override
+ protected java.security.Signature doInitSignature(String algo, boolean forSigning) throws GeneralSecurityException {
+ assertFalse("Signature not initialized for verification", forSigning);
+ java.security.Signature signature = java.security.Signature.getInstance(algo);
+ Provider provider = signature.getProvider();
+ String name = provider.getName();
+ assertNotEquals("BC provider used although not required", SecurityUtils.BOUNCY_CASTLE, name);
+ return signature;
+ }
+ });
+ }
+
+ private void testLeadingZeroes(Factory<? extends SignatureRSA> factory) throws Exception {
+ SignatureRSA rsa = factory.create();
+ rsa.initVerifier(testKey);
+
+ int vSize = rsa.getVerifierSignatureSize();
+ assertTrue("Verifier signature size not initialized", vSize > 0);
+
+ // make sure padding is required
+ Map.Entry<String, byte[]> encoding = rsa.extractEncodedSignature(TEST_SIGNATURE);
+ assertNotNull("Signature is not encoded", encoding);
+ byte[] data = encoding.getValue();
+ assertTrue("Signature data size (" + data.length + ") not below verifier size (" + vSize + ")", data.length < vSize);
+
+ rsa.update(TEST_MSG);
+ assertTrue("Failed to verify", rsa.verify(TEST_SIGNATURE));
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java
new file mode 100644
index 0000000..2e15341
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/signature/SignaturesDevelopment.java
@@ -0,0 +1,81 @@
+/*
+ * 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.sshd.common.signature;
+
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.buffer.BufferUtils;
+import org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.junit.Ignore;
+
+/**
+ * A "scratch-pad" class for testing signatures related code during development
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@Ignore("Used only for development")
+public class SignaturesDevelopment extends JUnitTestSupport {
+ public SignaturesDevelopment() {
+ super();
+ }
+
+ public static void testSignatureFactory(
+ SignatureFactory factory, KeyPair kp, byte[] data, boolean generateSignature, byte[] signature)
+ throws Exception {
+ Signature signer = factory.create();
+ if (generateSignature) {
+ signer.initSigner(kp.getPrivate());
+ signer.update(data);
+ signature = signer.sign();
+ System.out.append('\t').append("Signature: ").println(BufferUtils.toHex(':', signature));
+ } else {
+ signer.initVerifier(kp.getPublic());
+ signer.update(data);
+ if (signer.verify(signature)) {
+ System.out.append('\t').println("Valid signature");
+ } else {
+ System.err.append('\t').println("Invalid signature");
+ }
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+
+ // args[0]=signatureName, args[1]=publicKey, args[2]=privateKey, args[3]=sign/verify, args[4]=data, args[5]=signature(if verify required)
+ public static void main(String[] args) throws Exception {
+ SignatureFactory factory = BuiltinSignatures.resolveFactory(args[0]);
+ // TODO recover public/private keys according to factory name
+ byte[] publicKey = BufferUtils.decodeHex(':', args[1]);
+ PublicKey pubKey = EdDSASecurityProviderUtils.generateEDDSAPublicKey(publicKey);
+ byte[] privateKey = BufferUtils.decodeHex(':', args[2]);
+ PrivateKey prvKey = EdDSASecurityProviderUtils.generateEDDSAPrivateKey(privateKey);
+ String op = args[3];
+ byte[] data = BufferUtils.decodeHex(':', args[4]);
+ byte[] signature = GenericUtils.EMPTY_BYTE_ARRAY;
+ if ("verify".equalsIgnoreCase(op)) {
+ signature = BufferUtils.decodeHex(':', args[5]);
+ }
+
+ testSignatureFactory(factory, new KeyPair(pubKey, prvKey), data, "sign".equalsIgnoreCase(op), signature);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/EventListenerUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/EventListenerUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/EventListenerUtilsTest.java
new file mode 100644
index 0000000..1619cd3
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/EventListenerUtilsTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.sshd.common.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EventListener;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class EventListenerUtilsTest extends JUnitTestSupport {
+ public EventListenerUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testProxyWrapper() {
+ List<ProxyListenerImpl> impls = new ArrayList<>();
+ for (int index = 0; index < Byte.SIZE; index++) {
+ impls.add(new ProxyListenerImpl());
+ }
+
+ ProxyListener listener = EventListenerUtils.proxyWrapper(ProxyListener.class, impls);
+ String expStr = getCurrentTestName();
+ Number expNum = System.currentTimeMillis();
+ listener.callMeWithString(expStr);
+ listener.callMeWithNumber(expNum);
+
+ for (int index = 0; index < impls.size(); index++) {
+ ProxyListenerImpl l = impls.get(index);
+ assertSame("Mismatched string at listener #" + index, expStr, l.getStringValue());
+ assertSame("Mismatched number at listener #" + index, expNum, l.getNumberValue());
+ }
+ }
+
+ @Test
+ public void testListenerInstanceComparatorOnProxy() {
+ Comparator<? super EventListener> comparator = EventListenerUtils.LISTENER_INSTANCE_COMPARATOR;
+ ProxyListener p1 = EventListenerUtils.proxyWrapper(ProxyListener.class, Collections.singletonList(new ProxyListenerImpl()));
+ assertEquals("Mismatched self reference comparison", 0, comparator.compare(p1, p1));
+
+ EventListener l = new EventListener() { /* nothing extra */ };
+ assertEquals("Mismatched proxy vs. non-proxy result", 1, Integer.signum(comparator.compare(p1, l)));
+ assertEquals("Mismatched non-proxy vs. proxy result", -1, Integer.signum(comparator.compare(l, p1)));
+
+ ProxyListener p2 = EventListenerUtils.proxyWrapper(ProxyListener.class, Collections.singletonList(new ProxyListenerImpl()));
+ int p1vsp2 = Integer.signum(comparator.compare(p1, p2));
+ assertNotEquals("Mismatched p1 vs. p2 comparison", 0, p1vsp2);
+ assertEquals("Mismatched p2 vs. p1 comparison result", 0 - p1vsp2, Integer.signum(comparator.compare(p2, p1)));
+ }
+
+ @Test
+ public void testListenerInstanceComparatorOnNonProxy() {
+ Comparator<? super EventListener> comparator = EventListenerUtils.LISTENER_INSTANCE_COMPARATOR;
+ EventListener l1 = new EventListener() { /* nothing extra */ };
+ assertEquals("Mismatched self reference comparison", 0, comparator.compare(l1, l1));
+
+ EventListener l2 = new EventListener() { /* nothing extra */ };
+ int l1vsl2 = Integer.signum(comparator.compare(l1, l2));
+ assertNotEquals("Mismatched l1 vs. l2 comparison result", 0, l1vsl2);
+ assertEquals("Mismatched l2 vs. l1 comparison result", 0 - l1vsl2, Integer.signum(comparator.compare(l2, l1)));
+ }
+
+ @Test
+ public void testSynchronizedListenersSetOnProxies() {
+ ProxyListener p1 = EventListenerUtils.proxyWrapper(ProxyListener.class, Collections.singletonList(new ProxyListenerImpl()));
+ Set<ProxyListener> s = EventListenerUtils.synchronizedListenersSet();
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ boolean modified = s.add(p1);
+ assertEquals("Mismatched p1 modification indicator at attempt #" + index, index == 1, modified);
+ assertEquals("Mismatched p1 set size at attempt #" + index, 1, s.size());
+ }
+
+ ProxyListener p2 = EventListenerUtils.proxyWrapper(ProxyListener.class, Collections.singletonList(new ProxyListenerImpl()));
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ boolean modified = s.add(p2);
+ assertEquals("Mismatched p2 modification indicator at attempt #" + index, index == 1, modified);
+ assertEquals("Mismatched p2 set size at attempt #" + index, 2, s.size());
+ }
+
+ assertTrue("Failed to remove p1", s.remove(p1));
+ assertEquals("Mismatched post p1-remove size", 1, s.size());
+ assertTrue("Failed to remove p2", s.remove(p2));
+ assertEquals("Mismatched post p2-remove size", 0, s.size());
+ }
+
+ interface ProxyListener extends SshdEventListener {
+ void callMeWithString(String s);
+
+ void callMeWithNumber(Number n);
+ }
+
+ static class ProxyListenerImpl implements ProxyListener {
+ private String strValue;
+ private Number numValue;
+
+ ProxyListenerImpl() {
+ super();
+ }
+
+ public String getStringValue() {
+ return strValue;
+ }
+
+ @Override
+ public void callMeWithString(String s) {
+ strValue = s;
+ }
+
+ public Number getNumberValue() {
+ return numValue;
+ }
+
+ @Override
+ public void callMeWithNumber(Number n) {
+ numValue = n;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
new file mode 100644
index 0000000..5727e88
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/GenericUtilsTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.sshd.common.util;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category(NoIoTestCase.class)
+public class GenericUtilsTest extends JUnitTestSupport {
+ public GenericUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testSplitAndJoin() {
+ List<String> expected = Collections.unmodifiableList(
+ Arrays.asList(getClass().getPackage().getName().replace('.', '/'), getClass().getSimpleName(), getCurrentTestName()));
+
+ // NOTE: we also test characters that have meaning in String.split(...) as regex ones
+ for (char ch : new char[]{',', '.', '*', '?'}) {
+ String sep = String.valueOf(ch);
+ String s = GenericUtils.join(expected, sep);
+ String[] actual = GenericUtils.split(s, ch);
+ assertEquals("Mismatched split length for separator=" + sep, expected.size(), GenericUtils.length((Object[]) actual));
+
+ for (int index = 0; index < actual.length; index++) {
+ String e = expected.get(index);
+ String a = actual[index];
+ if (!e.endsWith(a)) {
+ fail("Mismatched value at index=" + index + " for separator=" + sep + ": expected=" + e + ", actual=" + a);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testStripQuotes() {
+ String expected = getCurrentTestName();
+ assertSame("Unexpected un-quoted stripping", expected, GenericUtils.stripQuotes(expected));
+
+ StringBuilder sb = new StringBuilder(2 + expected.length()).append('|').append(expected).append('|');
+ for (int index = 0; index < GenericUtils.QUOTES.length(); index++) {
+ char delim = GenericUtils.QUOTES.charAt(index);
+ sb.setCharAt(0, delim);
+ sb.setCharAt(sb.length() - 1, delim);
+
+ CharSequence actual = GenericUtils.stripQuotes(sb);
+ assertEquals("Mismatched result for delim (" + delim + ")", expected, actual.toString());
+ }
+ }
+
+ @Test
+ public void testStripOnlyFirstLayerQuotes() {
+ StringBuilder sb = new StringBuilder().append("||").append(getCurrentTestName()).append("||");
+ char[] delims = {'\'', '"', '"', '\''};
+ for (int index = 0; index < delims.length; index += 2) {
+ char topDelim = delims[index];
+ char innerDelim = delims[index + 1];
+ sb.setCharAt(0, topDelim);
+ sb.setCharAt(1, innerDelim);
+ sb.setCharAt(sb.length() - 2, innerDelim);
+ sb.setCharAt(sb.length() - 1, topDelim);
+
+ CharSequence expected = sb.subSequence(1, sb.length() - 1);
+ CharSequence actual = GenericUtils.stripQuotes(sb);
+ assertEquals("Mismatched result for delim (" + topDelim + "/" + innerDelim + ")", expected.toString(), actual.toString());
+ }
+ }
+
+ @Test
+ public void testStripDelimiters() {
+ String expected = getCurrentTestName();
+ final char delim = '|';
+ assertSame("Unexpected un-delimited stripping", expected, GenericUtils.stripDelimiters(expected, delim));
+
+ CharSequence actual = GenericUtils.stripDelimiters(
+ new StringBuilder(2 + expected.length()).append(delim).append(expected).append(delim), delim);
+ assertEquals("Mismatched stripped values", expected, actual.toString());
+ }
+
+ @Test
+ public void testStripDelimitersOnlyIfOnBothEnds() {
+ final char delim = '$';
+ StringBuilder expected = new StringBuilder().append(delim).append(getCurrentTestName()).append(delim);
+ for (int index : new int[]{0, expected.length() - 1}) {
+ // restore original delimiters
+ expected.setCharAt(0, delim);
+ expected.setCharAt(expected.length() - 1, delim);
+ // trash one end
+ expected.setCharAt(index, (char) (delim + 1));
+
+ assertSame("Mismatched result for delim at index=" + index, expected, GenericUtils.stripDelimiters(expected, delim));
+ }
+ }
+
+ @Test
+ public void testAccumulateExceptionOnNullValues() {
+ assertNull("Unexpected null/null result", GenericUtils.accumulateException(null, null));
+
+ Throwable expected = new NoSuchMethodException(getClass().getName() + "#" + getCurrentTestName());
+ assertSame("Mismatched null/extra result", expected, GenericUtils.accumulateException(null, expected));
+ assertSame("Mismatched current/null result", expected, GenericUtils.accumulateException(expected, null));
+ }
+
+ @Test
+ public void testAccumulateExceptionOnExistingCurrent() {
+ RuntimeException[] expected = new RuntimeException[]{
+ new IllegalArgumentException(getCurrentTestName()),
+ new ClassCastException(getClass().getName()),
+ new NoSuchElementException(getClass().getPackage().getName())
+ };
+ RuntimeException current = new UnsupportedOperationException("top");
+ for (RuntimeException extra : expected) {
+ RuntimeException actual = GenericUtils.accumulateException(current, extra);
+ assertSame("Mismatched returned actual exception", current, actual);
+ }
+
+ Throwable[] actual = current.getSuppressed();
+ assertArrayEquals("Suppressed", expected, actual);
+ }
+
+ @Test
+ public void testNullOrEmptyCharArrayComparison() {
+ char[][] values = new char[][]{null, GenericUtils.EMPTY_CHAR_ARRAY};
+ for (char[] c1 : values) {
+ for (char[] c2 : values) {
+ assertEquals(((c1 == null) ? "null" : "empty") + " vs. " + ((c2 == null) ? "null" : "empty"), 0, GenericUtils.compare(c1, c2));
+ }
+ }
+ }
+
+ @Test
+ public void testCharArrayComparison() {
+ String s1 = getClass().getSimpleName();
+ char[] c1 = s1.toCharArray();
+ assertEquals("Same value equality", 0, GenericUtils.compare(c1, s1.toCharArray()));
+
+ String s2 = getCurrentTestName();
+ char[] c2 = s2.toCharArray();
+ assertEquals("s1 vs. s2", Integer.signum(s1.compareTo(s2)), Integer.signum(GenericUtils.compare(c1, c2)));
+ assertEquals("s2 vs. s1", Integer.signum(s2.compareTo(s1)), Integer.signum(GenericUtils.compare(c2, c1)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java
new file mode 100644
index 0000000..b0c48ca
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/Int2IntFunctionTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.sshd.common.util;
+
+import java.util.Random;
+import java.util.function.IntUnaryOperator;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class Int2IntFunctionTest extends JUnitTestSupport {
+ public Int2IntFunctionTest() {
+ super();
+ }
+
+ @Test
+ public void testAdd() {
+ int factor = Byte.SIZE;
+ IntUnaryOperator func = Int2IntFunction.add(factor);
+ for (int index = 1, sum = 0; index <= Byte.SIZE; index++) {
+ sum = func.applyAsInt(sum);
+ assertEquals(factor * index, sum);
+ }
+ }
+
+ @Test
+ public void testAddIdentity() {
+ IntUnaryOperator func = Int2IntFunction.add(0);
+ Random rnd = new Random(System.nanoTime());
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ int expected = rnd.nextInt();
+ int actual = func.applyAsInt(expected);
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void testSub() {
+ int factor = Byte.SIZE;
+ IntUnaryOperator func = Int2IntFunction.sub(factor);
+ for (int index = 1, sum = 0; index <= Byte.SIZE; index++) {
+ sum = func.applyAsInt(sum);
+ assertEquals(factor * index * -1, sum);
+ }
+ }
+
+ @Test
+ public void testSubIdentity() {
+ IntUnaryOperator func = Int2IntFunction.sub(0);
+ Random rnd = new Random(System.nanoTime());
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ int expected = rnd.nextInt();
+ int actual = func.applyAsInt(expected);
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void testMul() {
+ int factor = 2;
+ IntUnaryOperator func = Int2IntFunction.mul(factor);
+ for (int index = 1, mul = 1, expected = factor; index <= Byte.SIZE; index++, expected *= factor) {
+ mul = func.applyAsInt(mul);
+ assertEquals(expected, mul);
+ }
+ }
+
+ @Test
+ public void testMulIdentity() {
+ IntUnaryOperator func = Int2IntFunction.mul(1);
+ Random rnd = new Random(System.nanoTime());
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ int expected = rnd.nextInt();
+ int actual = func.applyAsInt(expected);
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test
+ public void testMulZero() {
+ IntUnaryOperator func = Int2IntFunction.mul(0);
+ Random rnd = new Random(System.nanoTime());
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ int value = rnd.nextInt();
+ int actual = func.applyAsInt(value);
+ assertEquals(Integer.toString(value), 0, actual);
+ }
+ }
+
+ @Test
+ public void testConstant() {
+ int expected = 377347;
+ IntUnaryOperator func = Int2IntFunction.constant(expected);
+ Random rnd = new Random(System.nanoTime());
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ int value = rnd.nextInt();
+ int actual = func.applyAsInt(value);
+ assertEquals(Integer.toString(value), expected, actual);
+ }
+ }
+
+ @Test
+ public void testDiv() {
+ int factor = 2;
+ IntUnaryOperator func = Int2IntFunction.div(factor);
+ for (int index = 1, quot = 65536, expected = quot / factor; index <= Byte.SIZE; index++, expected /= factor) {
+ quot = func.applyAsInt(quot);
+ assertEquals(expected, quot);
+ }
+ }
+
+ @Test
+ public void testDivIdentity() {
+ IntUnaryOperator func = Int2IntFunction.div(1);
+ Random rnd = new Random(System.nanoTime());
+ for (int index = 1; index <= Byte.SIZE; index++) {
+ int expected = rnd.nextInt();
+ int actual = func.applyAsInt(expected);
+ assertEquals(expected, actual);
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testDivZeroFactor() {
+ IntUnaryOperator func = Int2IntFunction.div(0);
+ fail("Unexpected success: " + func);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/NumberUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/NumberUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/NumberUtilsTest.java
new file mode 100644
index 0000000..927cecb
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/NumberUtilsTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.sshd.common.util;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class NumberUtilsTest extends JUnitTestSupport {
+ public NumberUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testPowersOf2List() {
+ assertEquals("Mismatched values size for " + NumberUtils.POWERS_OF_TWO, Long.SIZE, GenericUtils.size(NumberUtils.POWERS_OF_TWO));
+ long expected = 1L;
+ for (int index = 0; index < Long.SIZE; index++, expected <<= 1) {
+ Long actual = NumberUtils.POWERS_OF_TWO.get(index);
+ assertEquals("Mismatched value at index=" + index, Long.toHexString(expected), Long.toHexString(actual));
+ }
+ }
+
+ @Test
+ public void testNextPowerOf2() {
+ for (Long v : NumberUtils.POWERS_OF_TWO) {
+ long expected = v;
+ if (expected > 2L) {
+ assertEquals("Mismatched lower bound value", expected, NumberUtils.getNextPowerOf2(expected - 1L));
+ }
+
+ if (expected > 0L) { // avoid the negative value
+ assertEquals("Mismatched exact value", expected, NumberUtils.getNextPowerOf2(expected));
+ }
+ }
+ }
+
+ @Test
+ public void testToInteger() {
+ assertNull("Unexpected null value", NumberUtils.toInteger(null));
+ for (Number n : new Number[]{
+ Byte.valueOf(Byte.MAX_VALUE), Short.valueOf(Short.MIN_VALUE),
+ Integer.valueOf(Short.MAX_VALUE), Long.valueOf(82007160L)}) {
+ Integer i = NumberUtils.toInteger(n);
+ if (n instanceof Integer) {
+ assertSame("Unexpected conversion", n, i);
+ } else {
+ assertEquals("Mismatched values", n.intValue(), i.intValue());
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/OsUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/OsUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/OsUtilsTest.java
new file mode 100644
index 0000000..af78a11
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/OsUtilsTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.sshd.common.util;
+
+import java.util.Objects;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class OsUtilsTest extends JUnitTestSupport {
+ public OsUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testSetOsTypeByProperty() {
+ try {
+ for (String osType : new String[]{"Some-Windows", "Some-Linux"}) {
+ OsUtils.setWin32(null); // force re-detection
+
+ try {
+ boolean expected = osType.contains("Windows");
+ System.setProperty(OsUtils.OS_TYPE_OVERRIDE_PROP, osType);
+ boolean actual = OsUtils.isWin32();
+ assertEquals(osType, expected, actual);
+ } finally {
+ System.clearProperty(OsUtils.OS_TYPE_OVERRIDE_PROP);
+ }
+ }
+ } finally {
+ OsUtils.setWin32(null); // force re-detection
+ }
+ }
+
+ @Test
+ public void testSetOsTypeProgrammatically() {
+ try {
+ for (boolean expected : new boolean[]{true, false}) {
+ OsUtils.setWin32(expected); // force value
+ assertEquals("Mismatched detection value", expected, OsUtils.isWin32());
+ }
+ } finally {
+ OsUtils.setWin32(null); // force re-detection
+ }
+ }
+
+ @Test
+ public void testSetCurrentUserByProperty() {
+ try {
+ for (String expected : new String[]{getClass().getSimpleName(), getCurrentTestName()}) {
+ OsUtils.setCurrentUser(null); // force re-detection
+
+ try {
+ System.setProperty(OsUtils.CURRENT_USER_OVERRIDE_PROP, expected);
+ String actual = OsUtils.getCurrentUser();
+ assertEquals("Mismatched reported current user", expected, actual);
+ } finally {
+ System.clearProperty(OsUtils.CURRENT_USER_OVERRIDE_PROP);
+ }
+ }
+ } finally {
+ OsUtils.setCurrentUser(null); // force re-detection
+ }
+ }
+
+ @Test
+ public void testSetCurrentUserProgrammatically() {
+ try {
+ for (String expected : new String[]{getClass().getSimpleName(), getCurrentTestName()}) {
+ OsUtils.setCurrentUser(expected); // force value
+ assertEquals("Mismatched detection value", expected, OsUtils.getCurrentUser());
+ }
+ } finally {
+ OsUtils.setCurrentUser(null); // force re-detection
+ }
+ }
+
+ @Test
+ public void testSetJavaVersionByProperty() {
+ try {
+ for (String value : new String[]{"7.3.6_5", "37.77.34_7-" + getCurrentTestName()}) {
+ OsUtils.setJavaVersion(null); // force re-detection
+
+ try {
+ System.setProperty(OsUtils.JAVA_VERSION_OVERRIDE_PROP, value);
+ String expected = value.replace('_', '.');
+ String actual = Objects.toString(OsUtils.getJavaVersion(), null);
+ assertTrue("Mismatched reported version value: " + actual, expected.startsWith(actual));
+ } finally {
+ System.clearProperty(OsUtils.JAVA_VERSION_OVERRIDE_PROP);
+ }
+ }
+ } finally {
+ OsUtils.setJavaVersion(null); // force re-detection
+ }
+ }
+
+ @Test
+ public void testSetJavaVersionProgrammatically() {
+ try {
+ for (VersionInfo expected : new VersionInfo[]{VersionInfo.parse("7.3.6.5"), VersionInfo.parse("37.77.34.7")}) {
+ OsUtils.setJavaVersion(expected); // force value
+ assertEquals("Mismatched detection value", expected, OsUtils.getJavaVersion());
+ }
+ } finally {
+ OsUtils.setJavaVersion(null); // force re-detection
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/SelectorUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/SelectorUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/SelectorUtilsTest.java
new file mode 100644
index 0000000..3044699
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/SelectorUtilsTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.sshd.common.util;
+
+import java.io.File;
+import java.util.Random;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.Assume;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class SelectorUtilsTest extends JUnitTestSupport {
+ public SelectorUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testApplyLinuxSeparatorSlashifyRules() {
+ testApplySlashifyRules('/');
+ }
+
+ @Test
+ public void testApplyWindowsSeparatorSlashifyRules() {
+ testApplySlashifyRules('\\');
+ }
+
+ private void testApplySlashifyRules(char slash) {
+ for (String expected : new String[]{
+ null, "", getCurrentTestName(),
+ getClass().getSimpleName() + Character.toString(slash) + getCurrentTestName(),
+ Character.toString(slash) + getClass().getSimpleName(),
+ Character.toString(slash) + getClass().getSimpleName() + Character.toString(slash) + getCurrentTestName()
+ }) {
+ String actual = SelectorUtils.applySlashifyRules(expected, slash);
+ assertSame("Mismatched results for '" + expected + "'", expected, actual);
+ }
+
+ String[] comps = {getClass().getSimpleName(), getCurrentTestName()};
+ Random rnd = new Random(System.nanoTime());
+ StringBuilder sb = new StringBuilder(Byte.MAX_VALUE);
+ for (int index = 0; index < Long.SIZE; index++) {
+ if (sb.length() > 0) {
+ sb.setLength(0); // start from scratch
+ }
+
+ boolean prepend = rnd.nextBoolean();
+ if (prepend) {
+ slashify(sb, rnd, slash);
+ }
+
+ sb.append(comps[0]);
+ for (int j = 1; j < comps.length; j++) {
+ slashify(sb, rnd, slash);
+ sb.append(comps[j]);
+ }
+
+ boolean append = rnd.nextBoolean();
+ if (append) {
+ slashify(sb, rnd, slash);
+ }
+
+ String path = sb.toString();
+ sb.setLength(0);
+ if (prepend) {
+ sb.append(slash);
+ }
+
+ sb.append(comps[0]);
+ for (int j = 1; j < comps.length; j++) {
+ sb.append(slash).append(comps[j]);
+ }
+
+ if (append) {
+ sb.append(slash).append('.');
+ }
+
+ String expected = sb.toString();
+ String actual = SelectorUtils.applySlashifyRules(path, slash);
+ assertEquals("Mismatched results for path=" + path, expected, actual);
+ }
+ }
+
+ private static int slashify(StringBuilder sb, Random rnd, char slash) {
+ int slashes = 1 /* at least one slash */ + rnd.nextInt(Byte.SIZE);
+ for (int k = 0; k < slashes; k++) {
+ sb.append(slash);
+ }
+
+ return slashes;
+ }
+
+ @Test
+ public void testTranslateToFileSystemPath() {
+ String path = getClass().getPackage().getName().replace('.', File.separatorChar)
+ + File.separator + getClass().getSimpleName()
+ + File.separator + getCurrentTestName();
+ for (String expected : new String[] {null, "", path}) {
+ String actual = SelectorUtils.translateToFileSystemPath(expected, File.separator, File.separator);
+ assertSame("Mismatched instance for translated result", expected, actual);
+ }
+
+ for (String fsSeparator : new String[] {String.valueOf('.'), "##"}) {
+ String expected = path.replace(File.separator, fsSeparator);
+ String actual = SelectorUtils.translateToFileSystemPath(path, File.separator, fsSeparator);
+ assertEquals("Mismatched translation result for separator='" + fsSeparator + "'", expected, actual);
+
+ actual = SelectorUtils.translateToFileSystemPath(actual, fsSeparator, File.separator);
+ assertEquals("Mismatched translation revert for separator='" + fsSeparator + "'", path, actual);
+ }
+ }
+
+ @Test
+ public void testAbsoluteWindowsPathTranslation() {
+ Assume.assumeTrue("Not tested on Windows", OsUtils.isWin32());
+ String expected = detectTargetFolder().toString();
+ for (String prefix : new String[]{"", "/"}) {
+ String actual = SelectorUtils.translateToLocalPath(prefix + expected.replace('/', File.separatorChar));
+ assertEquals("Mismatched result for prefix='" + prefix + "'", expected, actual);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java
new file mode 100644
index 0000000..10e6f5b
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/ThreadUtilsTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.sshd.common.util;
+
+import java.util.Collection;
+
+import org.apache.sshd.common.util.threads.CloseableExecutorService;
+import org.apache.sshd.common.util.threads.ThreadUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class ThreadUtilsTest extends JUnitTestSupport {
+ public ThreadUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testProtectExecutorServiceShutdown() {
+ for (boolean shutdownOnExit : new boolean[]{true, false}) {
+ assertNull("Unexpected instance for shutdown=" + shutdownOnExit, ThreadUtils.protectExecutorServiceShutdown(null, shutdownOnExit));
+ }
+
+ CloseableExecutorService service = ThreadUtils.newSingleThreadExecutor("pool");
+ try {
+ assertSame("Unexpected wrapped instance", service, ThreadUtils.protectExecutorServiceShutdown(service, true));
+
+ CloseableExecutorService wrapped = ThreadUtils.protectExecutorServiceShutdown(service, false);
+ try {
+ assertNotSame("No wrapping occurred", service, wrapped);
+
+ wrapped.shutdown();
+ assertTrue("Wrapped service not shutdown", wrapped.isShutdown());
+ assertFalse("Protected service is shutdown", service.isShutdown());
+
+ Collection<?> running = wrapped.shutdownNow();
+ assertTrue("Non-empty runners list", running.isEmpty());
+ assertTrue("Wrapped service not shutdownNow", wrapped.isShutdown());
+ assertFalse("Protected service is shutdownNow", service.isShutdown());
+ } finally {
+ wrapped.shutdownNow(); // just in case
+ }
+ } finally {
+ service.shutdownNow(); // just in case...
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/ValidateUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/ValidateUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/ValidateUtilsTest.java
new file mode 100644
index 0000000..9efd5f9
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/ValidateUtilsTest.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.sshd.common.util;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category(NoIoTestCase.class)
+public class ValidateUtilsTest extends JUnitTestSupport {
+ public ValidateUtilsTest() {
+ super();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void checkNotNull() {
+ ValidateUtils.checkNotNull(getClass(), getCurrentTestName());
+ ValidateUtils.checkNotNull(null, getCurrentTestName());
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/VersionInfoTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/VersionInfoTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/VersionInfoTest.java
new file mode 100644
index 0000000..834be24
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/VersionInfoTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.sshd.common.util;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class VersionInfoTest extends JUnitTestSupport {
+ public VersionInfoTest() {
+ super();
+ }
+
+ @Test
+ public void testLessThan4Components() {
+ VersionInfo expected = new VersionInfo(73, 65);
+ VersionInfo actual = VersionInfo.parse(NumberUtils.join('.', expected.getMajorVersion(), expected.getMinorVersion()));
+ assertEquals("Mismatched result", expected, actual);
+ }
+
+ @Test
+ public void testMoreThan4Components() {
+ VersionInfo expected = new VersionInfo(7, 3, 6, 5);
+ VersionInfo actual = VersionInfo.parse(expected.toString() + ".3.7.7.7.3.4.7");
+ assertEquals("Mismatched result", expected, actual);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferTest.java
new file mode 100644
index 0000000..6f41b76
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.sshd.common.util.buffer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class BufferTest extends JUnitTestSupport {
+ public BufferTest() {
+ super();
+ }
+
+ @Test
+ public void testGetLong() throws Exception {
+ long expected = 1234567890123456789L;
+
+ try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
+ try (DataOutputStream ds = new DataOutputStream(stream)) {
+ ds.writeLong(expected);
+ }
+
+ Buffer buffer = new ByteArrayBuffer(stream.toByteArray());
+ assertEquals("Mismatched recovered value", expected, buffer.getLong());
+ }
+ }
+
+ @Test
+ public void testPutCharsWithNullOrEmptyValue() {
+ Buffer buffer = new ByteArrayBuffer(Integer.SIZE);
+ for (char[] chars : new char[][]{null, GenericUtils.EMPTY_CHAR_ARRAY}) {
+ buffer.putChars(chars);
+
+ String value = buffer.getString();
+ assertEquals("Mismatched value for " + ((chars == null) ? "null" : "empty") + " characters", "", value);
+ }
+ }
+
+ @Test
+ public void testPutCharsOnNonEmptyValue() {
+ String expected = getCurrentTestName();
+ Buffer buffer = new ByteArrayBuffer(expected.length() + Byte.SIZE);
+ buffer.putChars(expected.toCharArray());
+
+ String actual = buffer.getString();
+ assertEquals("Mismatched recovered values", expected, actual);
+ }
+
+ @Test
+ public void testPutAndWipeChars() {
+ String expected = getCurrentTestName();
+ char[] chars = expected.toCharArray();
+ Buffer buffer = new ByteArrayBuffer(chars.length + Byte.SIZE);
+ buffer.putAndWipeChars(chars);
+
+ String actual = buffer.getString();
+ assertEquals("Mismatched recovered values", expected, actual);
+
+ for (int index = 0; index < chars.length; index++) {
+ assertEquals("Character not wiped at index=" + index, 0, chars[index]);
+ }
+ }
+
+ @Test
+ public void testPutAndWipeBytes() {
+ String expected = getCurrentTestName();
+ byte[] bytes = expected.getBytes(StandardCharsets.UTF_8);
+ Buffer buffer = new ByteArrayBuffer(bytes.length + Byte.SIZE);
+ buffer.putAndWipeBytes(bytes);
+ String actual = buffer.getString();
+ assertEquals("Mismatched recovered values", expected, actual);
+
+ for (int index = 0; index < bytes.length; index++) {
+ assertEquals("Value not wiped at index=" + index, 0, bytes[index]);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferUtilsTest.java
new file mode 100644
index 0000000..78122b7
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/buffer/BufferUtilsTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.sshd.common.util.buffer;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
+
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class BufferUtilsTest extends JUnitTestSupport {
+ public BufferUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testHexEncodeDecode() {
+ String expValue = getClass().getName() + "#" + getCurrentTestName();
+ byte[] expData = expValue.getBytes(StandardCharsets.UTF_8);
+ for (char sep : new char[]{BufferUtils.EMPTY_HEX_SEPARATOR, ':'}) {
+ String hexData = BufferUtils.toHex(sep, expData);
+ byte[] actData = BufferUtils.decodeHex(sep, hexData);
+ String actValue = new String(actData, StandardCharsets.UTF_8);
+ String sepName = (BufferUtils.EMPTY_HEX_SEPARATOR == sep) ? "EMPTY" : Character.toString(sep);
+ outputDebugMessage("Decode(sep=%s) expected=%s, actual=%s", sepName, expValue, actValue);
+ assertArrayEquals("Mismatched result for sep='" + sepName + "'", expData, actData);
+ }
+ }
+
+ @Test
+ public void testGetCompactClone() {
+ byte[] expected = getCurrentTestName().getBytes(StandardCharsets.UTF_8);
+ final int testOffset = Byte.SIZE / 2;
+ byte[] data = new byte[expected.length + 2 * testOffset];
+ Random rnd = new Random(System.nanoTime());
+ rnd.nextBytes(data);
+ System.arraycopy(expected, 0, data, testOffset, expected.length);
+
+ Buffer buf = ByteArrayBuffer.getCompactClone(data, testOffset, expected.length);
+ assertEquals("Mismatched cloned buffer read position", 0, buf.rpos());
+ assertEquals("Mismatched cloned buffer available size", expected.length, buf.available());
+
+ byte[] actual = buf.array();
+ assertNotSame("Original data not cloned", data, actual);
+ assertArrayEquals("Mismatched cloned contents", expected, actual);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/closeable/CloseableUtilsTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/closeable/CloseableUtilsTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/closeable/CloseableUtilsTest.java
new file mode 100644
index 0000000..6ed1187
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/closeable/CloseableUtilsTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.sshd.common.util.closeable;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.sshd.common.Closeable;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.util.threads.ThreadUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class CloseableUtilsTest extends JUnitTestSupport {
+ public CloseableUtilsTest() {
+ super();
+ }
+
+ @Test
+ public void testCloseImmediateNotCalledIfAlreadyClosed() throws IOException {
+ Closeable closeable = new IoBaseCloseable() {
+ @Override
+ public CloseFuture close(boolean immediately) {
+ fail("Unexpected call to close(" + immediately + ")");
+ return null;
+ }
+
+ @Override
+ public void addCloseFutureListener(SshFutureListener<CloseFuture> listener) {
+ fail("Unexpected call to addCloseFutureListener");
+ }
+
+ @Override
+ public void removeCloseFutureListener(SshFutureListener<CloseFuture> listener) {
+ fail("Unexpected call to removeCloseFutureListener");
+ }
+
+ @Override
+ public boolean isClosed() {
+ return true;
+ }
+
+ @Override
+ public boolean isClosing() {
+ return false;
+ }
+ };
+ closeable.close();
+ }
+
+ @Test
+ public void testCloseImmediateNotCalledIfIsClosing() throws IOException {
+ Closeable closeable = new IoBaseCloseable() {
+ @Override
+ public CloseFuture close(boolean immediately) {
+ fail("Unexpected call to close(" + immediately + ")");
+ return null;
+ }
+
+ @Override
+ public void addCloseFutureListener(SshFutureListener<CloseFuture> listener) {
+ fail("Unexpected call to addCloseFutureListener");
+ }
+
+ @Override
+ public void removeCloseFutureListener(SshFutureListener<CloseFuture> listener) {
+ fail("Unexpected call to removeCloseFutureListener");
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+
+ @Override
+ public boolean isClosing() {
+ return true;
+ }
+ };
+ closeable.close();
+ }
+
+ @Test
+ public void testCloseImmediateCalledAndWait() throws Exception {
+ DefaultCloseFuture future = new DefaultCloseFuture(this, this);
+ AtomicInteger callsCount = new AtomicInteger(0);
+ Closeable closeable = new IoBaseCloseable() {
+ @Override
+ public CloseFuture close(boolean immediately) {
+ assertTrue("Closure is not immediate", immediately);
+ assertEquals("Multiple close immediate calls", 1, callsCount.incrementAndGet());
+ return future;
+ }
+
+ @Override
+ public void addCloseFutureListener(SshFutureListener<CloseFuture> listener) {
+ fail("Unexpected call to addCloseFutureListener");
+ }
+
+ @Override
+ public void removeCloseFutureListener(SshFutureListener<CloseFuture> listener) {
+ fail("Unexpected call to removeCloseFutureListener");
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+
+ @Override
+ public boolean isClosing() {
+ return false;
+ }
+ };
+
+ ExecutorService service = ThreadUtils.newSingleThreadExecutor(getCurrentTestName());
+ try {
+ Future<?> task = service.submit((Runnable) () -> {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ future.setClosed(); // signal close complete
+ task.get(5L, TimeUnit.SECONDS); // make sure #await call terminated
+ assertEquals("Close immediate not called", 1, callsCount.get());
+ } finally {
+ service.shutdownNow();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-common/src/test/java/org/apache/sshd/common/util/io/EmptyInputStreamTest.java
----------------------------------------------------------------------
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/util/io/EmptyInputStreamTest.java b/sshd-common/src/test/java/org/apache/sshd/common/util/io/EmptyInputStreamTest.java
new file mode 100644
index 0000000..113758d
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/util/io/EmptyInputStreamTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.sshd.common.util.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.sshd.common.util.buffer.BufferUtils;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runners.MethodSorters;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@Category({ NoIoTestCase.class })
+public class EmptyInputStreamTest extends JUnitTestSupport {
+ public EmptyInputStreamTest() {
+ super();
+ }
+
+ @Test
+ public void testEmptyInputStream() throws IOException {
+ try (EmptyInputStream in = new EmptyInputStream()) {
+ testEmptyInputStream(in, false);
+ }
+ }
+
+ @Test
+ public void testCloseableEmptyInputStream() throws IOException {
+ try (EmptyInputStream in = new CloseableEmptyInputStream()) {
+ testEmptyInputStream(in, true);
+ }
+ }
+
+ private void testEmptyInputStream(InputStream in, boolean failAfterClose) throws IOException {
+ testEmptyInputStream("open", in, false);
+ in.close();
+ testEmptyInputStream("closed", in, failAfterClose);
+ }
+
+ private void testEmptyInputStream(String message, InputStream in, boolean errorExpected) {
+ assertFalse(message + ": unexpected markSupported()", in.markSupported());
+ try {
+ in.mark(Long.SIZE);
+ fail(message + ": unexpected mark success");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ int len = in.available();
+ assertFalse(message + ": Unexpected success in available(): " + len, errorExpected);
+ assertEquals(message + ": Mismatched available() result", 0, len);
+ } catch (IOException e) {
+ assertTrue(message + ": Unexpected error on available(): " + e.getMessage(), errorExpected);
+ }
+
+ try {
+ int data = in.read();
+ assertFalse(message + ": Unexpected success in read(): " + data, errorExpected);
+ assertEquals(message + ": Mismatched read() result", -1, data);
+ } catch (IOException e) {
+ assertTrue(message + ": Unexpected error on read(): " + e.getMessage(), errorExpected);
+ }
+
+ byte[] bytes = new byte[Byte.SIZE];
+ try {
+ int len = in.read(bytes);
+ assertFalse(message + ": Unexpected success in read([]): " + BufferUtils.toHex(':', bytes), errorExpected);
+ assertEquals(message + ": Mismatched read([]) result", -1, len);
+ } catch (IOException e) {
+ assertTrue(message + ": Unexpected error on read([]): " + e.getMessage(), errorExpected);
+ }
+
+ try {
+ int len = in.read(bytes, 0, bytes.length);
+ assertFalse(message + ": Unexpected success in read([],int,int): " + BufferUtils.toHex(':', bytes), errorExpected);
+ assertEquals(message + ": Mismatched read([],int,int) result", -1, len);
+ } catch (IOException e) {
+ assertTrue(message + ": Unexpected error on read([],int,int): " + e.getMessage(), errorExpected);
+ }
+
+ try {
+ long len = in.skip(Byte.MAX_VALUE);
+ assertFalse(message + ": Unexpected success in skip(): " + len, errorExpected);
+ assertEquals(message + ": Mismatched skip() result", 0L, len);
+ } catch (IOException e) {
+ assertTrue(message + ": Unexpected error on skip(): " + e.getMessage(), errorExpected);
+ }
+
+ try {
+ in.reset();
+ assertFalse(message + ": Unexpected success in reset()", errorExpected);
+ } catch (IOException e) {
+ assertTrue(message + ": Unexpected error on reset(): " + e.getMessage(), errorExpected);
+ }
+ }
+}