PageRenderTime 88ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientTest.java

https://github.com/alasdairhodge/jclouds
Java | 215 lines | 160 code | 31 blank | 24 comment | 0 complexity | 0482af3d633360d06b5b99d2daef3d98 MD5 | raw file
  1. /**
  2. * Licensed to jclouds, Inc. (jclouds) under one or more
  3. * contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. jclouds licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. package org.jclouds.sshj;
  20. import static com.google.inject.name.Names.bindProperties;
  21. import static org.easymock.EasyMock.expect;
  22. import static org.easymock.EasyMock.expectLastCall;
  23. import static org.easymock.classextension.EasyMock.createMock;
  24. import static org.easymock.classextension.EasyMock.replay;
  25. import static org.easymock.classextension.EasyMock.verify;
  26. import java.io.IOException;
  27. import java.net.ConnectException;
  28. import java.net.SocketTimeoutException;
  29. import java.util.Properties;
  30. import java.util.logging.Level;
  31. import net.schmizz.sshj.SSHClient;
  32. import net.schmizz.sshj.common.SSHException;
  33. import net.schmizz.sshj.connection.ConnectionException;
  34. import net.schmizz.sshj.transport.TransportException;
  35. import net.schmizz.sshj.userauth.UserAuthException;
  36. import org.jclouds.domain.Credentials;
  37. import org.jclouds.logging.BufferLogger;
  38. import org.jclouds.logging.BufferLogger.Record;
  39. import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
  40. import org.jclouds.net.IPSocket;
  41. import org.jclouds.rest.AuthorizationException;
  42. import org.jclouds.ssh.SshClient;
  43. import org.jclouds.sshj.config.SshjSshClientModule;
  44. import org.testng.Assert;
  45. import org.testng.annotations.BeforeTest;
  46. import org.testng.annotations.Test;
  47. import com.google.inject.AbstractModule;
  48. import com.google.inject.Guice;
  49. import com.google.inject.Injector;
  50. import com.google.inject.Module;
  51. /**
  52. *
  53. * @author Adrian Cole
  54. */
  55. @Test
  56. public class SshjSshClientTest {
  57. protected SshjSshClient ssh;
  58. @BeforeTest
  59. public void setupSsh() {
  60. ssh = createClient();
  61. }
  62. protected SshjSshClient createClient() {
  63. return createClient(new Properties());
  64. }
  65. protected SshjSshClient createClient(final Properties props) {
  66. Injector i = Guice.createInjector(module(), new AbstractModule() {
  67. @Override
  68. protected void configure() {
  69. bindProperties(binder(), props);
  70. }
  71. }, new SLF4JLoggingModule());
  72. SshClient.Factory factory = i.getInstance(SshClient.Factory.class);
  73. SshjSshClient ssh = SshjSshClient.class.cast(factory.create(new IPSocket("localhost", 22), new Credentials(
  74. "username", "password")));
  75. return ssh;
  76. }
  77. protected Module module() {
  78. return new SshjSshClientModule();
  79. }
  80. @Test(expectedExceptions = AuthorizationException.class)
  81. public void testPropateConvertsAuthException() {
  82. ssh.propagate(new UserAuthException(""), "");
  83. }
  84. public void testExceptionClassesRetry() {
  85. assert ssh.shouldRetry(new ConnectionException("Read timed out", new SSHException("Read timed out",
  86. new SocketTimeoutException("Read timed out"))));
  87. assert ssh.shouldRetry(new SocketTimeoutException("connect timed out"));
  88. assert ssh.shouldRetry(new TransportException("socket closed"));
  89. assert ssh.shouldRetry(new ConnectionException("problem"));
  90. assert ssh.shouldRetry(new ConnectException("Connection refused"));
  91. assert !ssh.shouldRetry(new IOException("channel %s is not open", new NullPointerException()));
  92. }
  93. public void testOnlyRetryAuthWhenSet() {
  94. SshjSshClient ssh1 = createClient();
  95. assert !ssh1.shouldRetry(new AuthorizationException("problem", null));
  96. assert !ssh1.shouldRetry(new UserAuthException("problem", null));
  97. ssh1.retryAuth = true;
  98. assert ssh1.shouldRetry(new AuthorizationException("problem", null));
  99. assert ssh1.shouldRetry(new UserAuthException("problem", null));
  100. }
  101. public void testOnlyRetryAuthWhenSetViaProperties() {
  102. Properties props = new Properties();
  103. props.setProperty("jclouds.ssh.retry-auth", "true");
  104. SshjSshClient ssh1 = createClient(props);
  105. assert ssh1.shouldRetry(new AuthorizationException("problem", null));
  106. assert ssh1.shouldRetry(new UserAuthException("problem", null));
  107. }
  108. public void testExceptionMessagesRetry() {
  109. assert !ssh.shouldRetry(new SSHException(""));
  110. assert !ssh.shouldRetry(new NullPointerException((String) null));
  111. }
  112. public void testCausalChainHasMessageContaining() {
  113. assert ssh.causalChainHasMessageContaining(
  114. new SSHException("Session.connect: java.io.IOException: End of IO Stream Read")).apply(
  115. " End of IO Stream Read");
  116. assert ssh.causalChainHasMessageContaining(
  117. new SSHException("Session.connect: java.net.SocketException: Connection reset")).apply("java.net.Socket");
  118. assert !ssh.causalChainHasMessageContaining(new NullPointerException()).apply(" End of IO Stream Read");
  119. }
  120. public void testRetryOnToStringNpe() {
  121. Exception nex = new NullPointerException();
  122. Properties props = new Properties();
  123. // ensure we test toString on the exception independently
  124. props.setProperty("jclouds.ssh.retryable-messages", nex.toString());
  125. SshjSshClient ssh1 = createClient(props);
  126. assert ssh1.shouldRetry(new RuntimeException(nex));
  127. }
  128. private static class ExceptionWithStrangeToString extends RuntimeException {
  129. private static final long serialVersionUID = 1L;
  130. private static final String MESSAGE = "foo-bar-exception-tostring";
  131. public String toString() {
  132. return MESSAGE;
  133. }
  134. }
  135. public void testRetryOnToStringCustom() {
  136. Exception nex = new ExceptionWithStrangeToString();
  137. Properties props = new Properties();
  138. props.setProperty("jclouds.ssh.retryable-messages", "foo-bar");
  139. SshjSshClient ssh1 = createClient(props);
  140. assert ssh1.shouldRetry(new RuntimeException(nex));
  141. }
  142. public void testDontThrowIOExceptionOnClear() throws Exception {
  143. SshjSshClient ssh1 = createClient();
  144. SSHClient ssh = createMock(SSHClient.class);
  145. expect(ssh.isConnected()).andReturn(true);
  146. ssh.disconnect();
  147. expectLastCall().andThrow(new ConnectionException("disconnected"));
  148. replay(ssh);
  149. ssh1.ssh = ssh;
  150. ssh1.sshConnection.clear();
  151. verify(ssh);
  152. }
  153. public void testRetryNotOnToStringCustomMismatch() {
  154. Exception nex = new ExceptionWithStrangeToString();
  155. Properties props = new Properties();
  156. props.setProperty("jclouds.ssh.retryable-messages", "foo-baR");
  157. SshjSshClient ssh1 = createClient(props);
  158. assert !ssh1.shouldRetry(new RuntimeException(nex));
  159. }
  160. public void testRetriesLoggedAtInfoWithCount() throws Exception {
  161. @SuppressWarnings("unchecked")
  162. SshjSshClient.Connection<net.schmizz.sshj.SSHClient> mockConnection = createMock(SshjSshClient.Connection.class);
  163. net.schmizz.sshj.SSHClient mockClient = createMock(net.schmizz.sshj.SSHClient.class);
  164. mockConnection.clear(); expectLastCall();
  165. mockConnection.create(); expectLastCall().andThrow(new ConnectionException("test1"));
  166. mockConnection.clear(); expectLastCall();
  167. //currently does two clears, one on failure (above) and one on next iteration (below)
  168. mockConnection.clear(); expectLastCall();
  169. mockConnection.create(); expectLastCall().andReturn(mockClient);
  170. replay(mockConnection);
  171. replay(mockClient);
  172. ssh.sshConnection = mockConnection;
  173. BufferLogger logcheck = new BufferLogger(ssh.getClass().getCanonicalName());
  174. ssh.logger = logcheck;
  175. logcheck.setLevel(Level.INFO);
  176. ssh.connect();
  177. Assert.assertEquals(ssh.ssh, mockClient);
  178. verify(mockConnection);
  179. verify(mockClient);
  180. Record r = logcheck.assertLogContains("attempt 1 of 5");
  181. logcheck.assertLogDoesntContain("attempt 2 of 5");
  182. Assert.assertEquals(Level.INFO, r.getLevel());
  183. }
  184. }