This is an automated email from the ASF dual-hosted git repository. lgoldstein pushed a commit to branch SSHD-897 in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit b47195e4f156e475639de2fe3ceae232376b0d1d Author: Lyor Goldstein <[email protected]> AuthorDate: Tue Feb 19 16:45:47 2019 +0200 [SSHD-897] Moved some shell stream related classes to sshd-common --- .../org/apache/sshd/common/channel/PtyMode.java | 108 ++++++++++++++++++++- .../sshd/server/shell/TtyFilterInputStream.java | 3 +- .../sshd/server/shell/TtyFilterOutputStream.java | 0 .../apache/sshd/common/channel/PtyModeTest.java | 8 +- .../sshd/common/channel/PtyModeValueTest.java | 97 ++++++++++++++++++ .../AuthorizedKeyEntryLoginOptionsParseTest.java | 6 +- .../server/shell/TtyFilterInputStreamTest.java | 4 +- .../server/shell/TtyFilterOutputStreamTest.java | 8 +- .../sshd/common/util/io/LineOutputStreamTest.java | 3 + 9 files changed, 222 insertions(+), 15 deletions(-) diff --git a/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java b/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java index 21af35e..a4745e5 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.NavigableMap; import java.util.Set; import java.util.function.Function; +import java.util.function.ToIntFunction; import org.apache.sshd.common.util.GenericUtils; @@ -295,10 +296,29 @@ public enum PtyMode { public static final Set<PtyMode> MODES = Collections.unmodifiableSet(EnumSet.allOf(PtyMode.class)); - private static final NavigableMap<Integer, PtyMode> COMMANDS = + public static final NavigableMap<Integer, PtyMode> COMMANDS = Collections.unmodifiableNavigableMap( GenericUtils.toSortedMap(MODES, PtyMode::toInt, Function.identity(), Comparator.naturalOrder())); + /** + * A {@code null}-safe {@link ToIntFunction} that returns the {@link PtyMode#toInt()} value and (-1) for {@code null} + */ + public static final ToIntFunction<PtyMode> OPCODE_EXTRACTOR = v -> (v == null) ? -1 : v.toInt(); + + /** + * A {@code null}-safe {@link Comparator} of {@link PtyMode} values + * according to their {@link PtyMode#toInt()} value + * @see #OPCODE_EXTRACTOR + */ + public static final Comparator<PtyMode> BY_OPCODE = new Comparator<PtyMode>() { + @Override + public int compare(PtyMode o1, PtyMode o2) { + int v1 = OPCODE_EXTRACTOR.applyAsInt(o1); + int v2 = OPCODE_EXTRACTOR.applyAsInt(o2); + return Integer.compare(v1, v2); + } + }; + private final int v; PtyMode(int v) { @@ -318,6 +338,20 @@ public enum PtyMode { return COMMANDS.get(0x00FF & b); } + public static PtyMode fromName(String name) { + if (GenericUtils.isEmpty(name)) { + return null; + } + + for (PtyMode m : MODES) { + if (name.equalsIgnoreCase(m.name())) { + return m; + } + } + + return null; + } + /** * @param options The options to enable - ignored if {@code null}/empty * @return A {@link Map} where all the specified {@link PtyMode}s have {@link #TRUE_SETTING} @@ -391,6 +425,63 @@ public enum PtyMode { } /** + * @param modes The {@link Map} of {@link PtyMode}s resolved by the "pty-req" message. + * @param enablers A {@link Collection} of enabler settings to be consulted + * @param defaultValue The default value to be used if no definite setting could be deduced + * @return {@code true} if the CR mode is enabled:</BR> + * <UL> + * <LI> + * If<tt>modes</tt> or <tt>enablers</tt> are {@code null}/empty + * then <tt>defaultValue</tt> is used + * </LI> + * + * <LI> + * If <U>any</U> of the <tt>enablers</tt> modes are enabled + * then the CR mode is enabled. + * </LI> + * + * <LI> + * If <U>none</U> of the <tt>enablers</tt> modes were specified + * then use <tt>defaultValue</tt> + * </LI> + * + * <LI> + * Otherwise (i.e., at least one or more of the <tt>enablers</tt> + * modes were specified, but <U>all</U> of them said {@code no}) + * then {@code false}. + * </LI> + * </UL> + */ + public static boolean getBooleanSettingValue( + Map<PtyMode, ?> modes, Collection<PtyMode> enablers, boolean defaultValue) { + if (GenericUtils.isEmpty(modes) || GenericUtils.isEmpty(enablers)) { + return defaultValue; + } + + int settingsCount = 0; + for (PtyMode m : enablers) { + Object v = modes.get(m); + if (v == null) { + continue; + } + + settingsCount++; + + // if any setting says yes then use it + if (getBooleanSettingValue(v)) { + return true; + } + } + + // ALL (!) settings have said NO + if (settingsCount > 0) { + return false; + } else { + return defaultValue; // none of the settings has been found - assume default + } + } + + /** * @param v The value to be tested * @return {@code true} if <U>all</U> of these conditions hold:</BR> * <UL> @@ -410,4 +501,19 @@ public enum PtyMode { public static boolean getBooleanSettingValue(int v) { return v != 0; } + + /** + * @param m The {@link PtyMode} + * @return {@code true} if not {@code null} and one of the settings that + * refers to a character value - name usually starts with {@code Vxxx} + */ + public static boolean isCharSetting(PtyMode m) { + if (m == null) { + return false; + } + + String name = m.name(); + char ch = name.charAt(0); + return (ch == 'v') || (ch == 'V'); + } } diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java b/sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java similarity index 98% rename from sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java rename to sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java index b894805..5760310 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java +++ b/sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java @@ -25,6 +25,7 @@ import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.Map; +import java.util.Objects; import java.util.Set; import org.apache.sshd.common.channel.PtyMode; @@ -51,7 +52,7 @@ public class TtyFilterInputStream extends FilterInputStream { } public TtyFilterInputStream(InputStream in, Collection<PtyMode> ttyOptions) { - super(in); + super(Objects.requireNonNull(in, "No input stream provided")); // we create a copy of the options so as to avoid concurrent modifications this.ttyOptions = GenericUtils.of(ttyOptions); // TODO validate non-conflicting options } diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java b/sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java similarity index 100% rename from sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java rename to sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java diff --git a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java index 3234948..69ae5e8 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java @@ -42,12 +42,8 @@ public class PtyModeTest extends JUnitTestSupport { } @Test - public void testFromInt() { - for (PtyMode expected : PtyMode.MODES) { - int num = expected.toInt(); - PtyMode actual = PtyMode.fromInt(num); - assertSame("Mismatched result for value=" + num, expected, actual); - } + public void testOpcodeExtractorOnNull() { + assertEquals(-1, PtyMode.OPCODE_EXTRACTOR.applyAsInt(null)); } @Test diff --git a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeValueTest.java b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeValueTest.java new file mode 100644 index 0000000..98ab7ce --- /dev/null +++ b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeValueTest.java @@ -0,0 +1,97 @@ +/* + * 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.channel; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory; +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.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.junit.runners.Parameterized.UseParametersRunnerFactory; + +/** + * TODO Add javadoc + * + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests +@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class) +@Category({ NoIoTestCase.class }) +public class PtyModeValueTest extends JUnitTestSupport { + private final PtyMode expected; + + public PtyModeValueTest(PtyMode expected) { + this.expected = expected; + } + + @Parameters(name = "{0}") + public static List<Object[]> parameters() { + return parameterize(PtyMode.MODES); + } + + @Test + public void testOpcodeExtractor() { + assertEquals(expected.toInt(), PtyMode.OPCODE_EXTRACTOR.applyAsInt(expected)); + } + + @Test + public void testByOpcodeComparator() { + int v1 = expected.toInt(); + for (PtyMode actual : PtyMode.MODES) { + int v2 = actual.toInt(); + int cmpExpected = Integer.signum(Integer.compare(v1, v2)); + int cmpActual = Integer.signum(PtyMode.BY_OPCODE.compare(expected, actual)); + assertEquals(expected + " vs. " + actual, cmpExpected, cmpActual); + } + } + + @Test + public void testFromName() { + String name = expected.name(); + for (int index = 0; index < Byte.SIZE; index++) { + PtyMode actual = PtyMode.fromName(name); + assertSame(name, expected, actual); + name = shuffleCase(name); + } + } + + @Test + public void testGetBooleanSettingValueOnNullOrEmptyValues() { + for (@SuppressWarnings("unchecked") Map<PtyMode, ?> modes : new Map[] {null, Collections.emptyMap()}) { + String s = (modes == null) ? "null" : "empty"; + assertFalse("Map is " + s, PtyMode.getBooleanSettingValue(modes, expected)); + } + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + expected + "]"; + } +} diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java index d912998..c37aa28 100644 --- a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java @@ -26,8 +26,10 @@ import java.util.Map; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory; 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.runner.RunWith; import org.junit.runners.MethodSorters; import org.junit.runners.Parameterized; @@ -40,13 +42,15 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class) +@Category({ NoIoTestCase.class }) public class AuthorizedKeyEntryLoginOptionsParseTest extends JUnitTestSupport { private final String value; private final String loginPart; private final String keyPart; private final Map<String, String> options; - public AuthorizedKeyEntryLoginOptionsParseTest(String value, String loginPart, String keyPart, Map<String, String> options) { + public AuthorizedKeyEntryLoginOptionsParseTest( + String value, String loginPart, String keyPart, Map<String, String> options) { this.value = value; this.loginPart = loginPart; this.keyPart = keyPart; diff --git a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java similarity index 98% rename from sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java rename to sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java index bd4913a..a17fa01 100644 --- a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java @@ -40,8 +40,8 @@ import org.apache.sshd.common.channel.PtyMode; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; import org.apache.sshd.common.util.io.IoUtils; -import org.apache.sshd.util.test.BaseTestSupport; import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory; +import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; import org.junit.FixMethodOrder; import org.junit.Test; @@ -59,7 +59,7 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory; @RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class) @Category({ NoIoTestCase.class }) -public class TtyFilterInputStreamTest extends BaseTestSupport { +public class TtyFilterInputStreamTest extends JUnitTestSupport { private static final List<PtyMode> MODES = Collections.unmodifiableList( Stream.concat(Stream.of(PtyMode.ECHO), TtyFilterInputStream.INPUT_OPTIONS.stream()) diff --git a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java similarity index 95% rename from sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java rename to sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java index 5844836..be72b32 100644 --- a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java +++ b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java @@ -34,8 +34,8 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import org.apache.sshd.common.channel.PtyMode; -import org.apache.sshd.util.test.BaseTestSupport; import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory; +import org.apache.sshd.util.test.JUnitTestSupport; import org.apache.sshd.util.test.NoIoTestCase; import org.junit.FixMethodOrder; import org.junit.Test; @@ -53,7 +53,7 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory; @RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class) @Category({ NoIoTestCase.class }) -public class TtyFilterOutputStreamTest extends BaseTestSupport { +public class TtyFilterOutputStreamTest extends JUnitTestSupport { private final PtyMode mode; public TtyFilterOutputStreamTest(PtyMode mode) { @@ -71,8 +71,8 @@ public class TtyFilterOutputStreamTest extends BaseTestSupport { getClass().getSimpleName(), getCurrentTestName(), "(" + mode + ")", new Date(System.currentTimeMillis()).toString()); - final AtomicInteger crCount = new AtomicInteger(0); - final AtomicInteger lfCount = new AtomicInteger(0); + AtomicInteger crCount = new AtomicInteger(0); + AtomicInteger lfCount = new AtomicInteger(0); try (OutputStream output = new OutputStream() { @Override public void write(int b) throws IOException { diff --git a/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java b/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java index c49f608..8a449ec 100644 --- a/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java +++ b/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java @@ -32,8 +32,10 @@ import java.util.List; import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory; 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.runner.RunWith; import org.junit.runners.MethodSorters; import org.junit.runners.Parameterized; @@ -46,6 +48,7 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @RunWith(Parameterized.class) // see https://github.com/junit-team/junit/wiki/Parameterized-tests @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class) +@Category({ NoIoTestCase.class }) public class LineOutputStreamTest extends JUnitTestSupport { private final boolean withCR;
