PageRenderTime 41ms CodeModel.GetById 28ms app.highlight 10ms 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 */
 19package org.jclouds.sshj;
 20
 21import static com.google.inject.name.Names.bindProperties;
 22import static org.easymock.EasyMock.expect;
 23import static org.easymock.EasyMock.expectLastCall;
 24import static org.easymock.classextension.EasyMock.createMock;
 25import static org.easymock.classextension.EasyMock.replay;
 26import static org.easymock.classextension.EasyMock.verify;
 27
 28import java.io.IOException;
 29import java.net.ConnectException;
 30import java.net.SocketTimeoutException;
 31import java.util.Properties;
 32import java.util.logging.Level;
 33
 34import net.schmizz.sshj.SSHClient;
 35import net.schmizz.sshj.common.SSHException;
 36import net.schmizz.sshj.connection.ConnectionException;
 37import net.schmizz.sshj.transport.TransportException;
 38import net.schmizz.sshj.userauth.UserAuthException;
 39
 40import org.jclouds.domain.Credentials;
 41import org.jclouds.logging.BufferLogger;
 42import org.jclouds.logging.BufferLogger.Record;
 43import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
 44import org.jclouds.net.IPSocket;
 45import org.jclouds.rest.AuthorizationException;
 46import org.jclouds.ssh.SshClient;
 47import org.jclouds.sshj.config.SshjSshClientModule;
 48import org.testng.Assert;
 49import org.testng.annotations.BeforeTest;
 50import org.testng.annotations.Test;
 51
 52import com.google.inject.AbstractModule;
 53import com.google.inject.Guice;
 54import com.google.inject.Injector;
 55import com.google.inject.Module;
 56
 57/**
 58 * 
 59 * @author Adrian Cole
 60 */
 61@Test
 62public class SshjSshClientTest {
 63
 64   protected SshjSshClient ssh;
 65
 66   @BeforeTest
 67   public void setupSsh() {
 68      ssh = createClient();
 69   }
 70
 71   protected SshjSshClient createClient() {
 72      return createClient(new Properties());
 73   }
 74
 75   protected SshjSshClient createClient(final Properties props) {
 76      Injector i = Guice.createInjector(module(), new AbstractModule() {
 77
 78         @Override
 79         protected void configure() {
 80            bindProperties(binder(), props);
 81         }
 82
 83      }, new SLF4JLoggingModule());
 84      SshClient.Factory factory = i.getInstance(SshClient.Factory.class);
 85      SshjSshClient ssh = SshjSshClient.class.cast(factory.create(new IPSocket("localhost", 22), new Credentials(
 86            "username", "password")));
 87      return ssh;
 88   }
 89
 90   protected Module module() {
 91      return new SshjSshClientModule();
 92   }
 93
 94   @Test(expectedExceptions = AuthorizationException.class)
 95   public void testPropateConvertsAuthException() {
 96      ssh.propagate(new UserAuthException(""), "");
 97   }
 98
 99   public void testExceptionClassesRetry() {
100      assert ssh.shouldRetry(new ConnectionException("Read timed out", new SSHException("Read timed out",
101            new SocketTimeoutException("Read timed out"))));
102      assert ssh.shouldRetry(new SocketTimeoutException("connect timed out"));
103      assert ssh.shouldRetry(new TransportException("socket closed"));
104      assert ssh.shouldRetry(new ConnectionException("problem"));
105      assert ssh.shouldRetry(new ConnectException("Connection refused"));
106      assert !ssh.shouldRetry(new IOException("channel %s is not open", new NullPointerException()));
107   }
108
109   public void testOnlyRetryAuthWhenSet() {
110      SshjSshClient ssh1 = createClient();
111      assert !ssh1.shouldRetry(new AuthorizationException("problem", null));
112      assert !ssh1.shouldRetry(new UserAuthException("problem", null));
113      ssh1.retryAuth = true;
114      assert ssh1.shouldRetry(new AuthorizationException("problem", null));
115      assert ssh1.shouldRetry(new UserAuthException("problem", null));
116   }
117
118   public void testOnlyRetryAuthWhenSetViaProperties() {
119      Properties props = new Properties();
120      props.setProperty("jclouds.ssh.retry-auth", "true");
121      SshjSshClient ssh1 = createClient(props);
122      assert ssh1.shouldRetry(new AuthorizationException("problem", null));
123      assert ssh1.shouldRetry(new UserAuthException("problem", null));
124   }
125
126   public void testExceptionMessagesRetry() {
127      assert !ssh.shouldRetry(new SSHException(""));
128      assert !ssh.shouldRetry(new NullPointerException((String) null));
129   }
130
131   public void testCausalChainHasMessageContaining() {
132      assert ssh.causalChainHasMessageContaining(
133            new SSHException("Session.connect: java.io.IOException: End of IO Stream Read")).apply(
134            " End of IO Stream Read");
135      assert ssh.causalChainHasMessageContaining(
136            new SSHException("Session.connect: java.net.SocketException: Connection reset")).apply("java.net.Socket");
137      assert !ssh.causalChainHasMessageContaining(new NullPointerException()).apply(" End of IO Stream Read");
138   }
139
140   public void testRetryOnToStringNpe() {
141      Exception nex = new NullPointerException();
142      Properties props = new Properties();
143      // ensure we test toString on the exception independently
144      props.setProperty("jclouds.ssh.retryable-messages", nex.toString());
145      SshjSshClient ssh1 = createClient(props);
146      assert ssh1.shouldRetry(new RuntimeException(nex));
147   }
148
149   private static class ExceptionWithStrangeToString extends RuntimeException {
150      private static final long serialVersionUID = 1L;
151      private static final String MESSAGE = "foo-bar-exception-tostring";
152
153      public String toString() {
154         return MESSAGE;
155      }
156   }
157
158   public void testRetryOnToStringCustom() {
159      Exception nex = new ExceptionWithStrangeToString();
160      Properties props = new Properties();
161      props.setProperty("jclouds.ssh.retryable-messages", "foo-bar");
162      SshjSshClient ssh1 = createClient(props);
163      assert ssh1.shouldRetry(new RuntimeException(nex));
164   }
165
166   public void testDontThrowIOExceptionOnClear() throws Exception {
167      SshjSshClient ssh1 = createClient();
168      SSHClient ssh = createMock(SSHClient.class);
169      expect(ssh.isConnected()).andReturn(true);
170      ssh.disconnect();
171      expectLastCall().andThrow(new ConnectionException("disconnected"));
172      replay(ssh);
173      ssh1.ssh = ssh;
174      ssh1.sshConnection.clear();
175      verify(ssh);
176   }
177
178   public void testRetryNotOnToStringCustomMismatch() {
179      Exception nex = new ExceptionWithStrangeToString();
180      Properties props = new Properties();
181      props.setProperty("jclouds.ssh.retryable-messages", "foo-baR");
182      SshjSshClient ssh1 = createClient(props);
183      assert !ssh1.shouldRetry(new RuntimeException(nex));
184   }
185
186   public void testRetriesLoggedAtInfoWithCount() throws Exception {
187      @SuppressWarnings("unchecked")
188      SshjSshClient.Connection<net.schmizz.sshj.SSHClient> mockConnection = createMock(SshjSshClient.Connection.class);
189      net.schmizz.sshj.SSHClient mockClient = createMock(net.schmizz.sshj.SSHClient.class);
190      
191      mockConnection.clear(); expectLastCall();
192      mockConnection.create(); expectLastCall().andThrow(new ConnectionException("test1"));
193      mockConnection.clear(); expectLastCall();
194      //currently does two clears, one on failure (above) and one on next iteration (below)
195      mockConnection.clear(); expectLastCall();
196      mockConnection.create(); expectLastCall().andReturn(mockClient);
197      replay(mockConnection);
198      replay(mockClient);
199      
200      ssh.sshConnection = mockConnection;
201      BufferLogger logcheck = new BufferLogger(ssh.getClass().getCanonicalName()); 
202      ssh.logger = logcheck;
203      logcheck.setLevel(Level.INFO);
204      
205      ssh.connect();
206      
207      Assert.assertEquals(ssh.ssh, mockClient);
208      verify(mockConnection);
209      verify(mockClient);
210      Record r = logcheck.assertLogContains("attempt 1 of 5");
211      logcheck.assertLogDoesntContain("attempt 2 of 5");
212      Assert.assertEquals(Level.INFO, r.getLevel());
213   }
214
215}