services = target.getServices();
- assertTrue(!services.isEmpty());
+ @Test
+ public void testUnknownHostServices() throws Exception {
+ ClientRequests client = cloudfoundry.client;
+ when(client.getServices()).thenThrow(new UnknownHostException("api.run.pivotal.io"));
+ CFTarget target = targetCache.getOrCreate().get(0);
+ assertError(() -> target.getServices(), ConnectionException.class, expectedMessages.noNetworkConnection());
+ }
+
+ @Test
+ public void testUnknownHostBuildpacks() throws Exception {
+ ClientRequests client = cloudfoundry.client;
+ when(client.getBuildpacks()).thenThrow(new UnknownHostException("api.run.pivotal.io"));
+ CFTarget target = targetCache.getOrCreate().get(0);
+ assertError(() -> target.getBuildpacks(), ConnectionException.class, expectedMessages.noNetworkConnection());
+ }
+
+ @Test
+ public void testAbortedExceptionServices() throws Exception {
+ ClientRequests client = cloudfoundry.client;
+ when(client.getServices()).thenThrow(new AbortedException("connection aborted"));
+ CFTarget target = targetCache.getOrCreate().get(0);
+ assertError(() -> target.getServices(), UnauthorizedException.class, expectedMessages.unauthorised());
+ }
+
+ @Test
+ public void testAbortedExceptionBuildpacks() throws Exception {
+ ClientRequests client = cloudfoundry.client;
+ when(client.getBuildpacks()).thenThrow(new AbortedException("connection aborted"));
+ CFTarget target = targetCache.getOrCreate().get(0);
+ assertError(() -> target.getBuildpacks(), UnauthorizedException.class, expectedMessages.unauthorised());
+ }
+
+ @Test
+ public void testUaaExceptionServices() throws Exception {
+ ClientRequests client = cloudfoundry.client;
+ when(client.getServices()).thenThrow(new UaaException(401, "unauthorized", "Bad credentials"));
+ CFTarget target = targetCache.getOrCreate().get(0);
+ assertError(() -> target.getServices(), UnauthorizedException.class, expectedMessages.unauthorised());
+ }
+
+ @Test
+ public void testUaaExceptionBuildpacks() throws Exception {
+ ClientRequests client = cloudfoundry.client;
+ when(client.getBuildpacks()).thenThrow(new UaaException(401, "unauthorized", "Bad credentials"));
+ CFTarget target = targetCache.getOrCreate().get(0);
+ assertError(() -> target.getBuildpacks(), UnauthorizedException.class, expectedMessages.unauthorised());
+ }
+
+ protected void assertError(Callable> callable, Class extends Throwable> expected, String expectedMessage)
+ throws Exception {
+ Throwable error = null;
+
+ try {
+ callable.call();
+ } catch (Exception e) {
+ error = ExceptionUtil.getDeepestCause(e);
+ }
+ assertEquals(expected, error.getClass());
+ assertTrue(ExceptionUtil.getMessageNoAppendedInformation(error).contains(expectedMessage));
}
}
diff --git a/vscode-extensions/commons/commons-cf/src/test/java/org/springframework/ide/vscode/commons/cloudfoundry/client/MockCfCli.java b/vscode-extensions/commons/commons-cf/src/test/java/org/springframework/ide/vscode/commons/cloudfoundry/client/MockCfCli.java
new file mode 100644
index 000000000..16b09712e
--- /dev/null
+++ b/vscode-extensions/commons/commons-cf/src/test/java/org/springframework/ide/vscode/commons/cloudfoundry/client/MockCfCli.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Pivotal, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Pivotal, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.springframework.ide.vscode.commons.cloudfoundry.client;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.mockito.Mockito;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.CloudFoundryClientFactory;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFClientParams;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFCredentials;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CfCliProviderMessages;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ClientParamsProvider;
+import org.springframework.ide.vscode.commons.util.ExceptionUtil;
+
+import com.google.common.collect.ImmutableList;
+
+public class MockCfCli {
+
+ public final static CFClientParams DEFAULT_PARAMS = new CFClientParams("test.io", "testuser",
+ CFCredentials.fromRefreshToken("refreshtoken"), false);
+
+ public final CloudFoundryClientFactory factory = mock(CloudFoundryClientFactory.class);
+ public final ClientRequests client = mock(ClientRequests.class);
+ public final ClientParamsProvider paramsProvider = mock(ClientParamsProvider.class);
+ public final CfCliProviderMessages actualCfCliMessages = new CfCliProviderMessages();
+
+ public MockCfCli() {
+ try {
+ //program some default behavior into mocks... most tests will use this.
+ //other tests should 'reset' the mocks and reprogram them as needed.
+ when(factory.getClient(any(), any())).thenReturn(client);
+ when(paramsProvider.getParams()).thenReturn(ImmutableList.of(DEFAULT_PARAMS));
+ when(paramsProvider.getMessages()).thenReturn(actualCfCliMessages);
+
+ } catch (Exception e) {
+ throw ExceptionUtil.unchecked(e);
+ }
+ }
+
+ /**
+ * Reset the mocks. Use this if the default's programmed into the mocks don't suite your test case.
+ *
+ * Note: you may also choose to call {@link Mockito}.mock directly if you do not want to
+ * reset all of the mocks.
+ */
+ public void reset() throws Exception {
+ Mockito.reset(factory, client, paramsProvider);
+ }
+
+}
diff --git a/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/ExceptionUtil.java b/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/ExceptionUtil.java
index 6a8b1fc12..d12fcefb4 100644
--- a/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/ExceptionUtil.java
+++ b/vscode-extensions/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/ExceptionUtil.java
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.commons.util;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
+import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
@@ -56,6 +57,22 @@ public class ExceptionUtil {
}
return null;
}
+
+ /**
+ * Given an exception, find if any of the exception types to look for is contained in the given exception
+ * @param e
+ * @param toLookFor non-null list of exception types to look for
+ * @return exception of specified type, if found, or null if not found
+ */
+ public static Throwable findThrowable(Throwable e, List> toLookFor) {
+ for (Class extends Throwable> klass : toLookFor) {
+ Throwable found = getThrowable(e, klass);
+ if (found != null) {
+ return found;
+ }
+ }
+ return null;
+ }
public static String getMessage(Throwable e) {
// The message of nested exception is usually more interesting than the
diff --git a/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/AbstractCFHintsProvider.java b/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/AbstractCFHintsProvider.java
index 0a143bad3..b26ca6c88 100644
--- a/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/AbstractCFHintsProvider.java
+++ b/vscode-extensions/vscode-manifest-yaml/src/main/java/org/springframework/ide/vscode/manifest/yaml/AbstractCFHintsProvider.java
@@ -19,11 +19,15 @@ import java.util.logging.Logger;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTarget;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.CFTargetCache;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.UnauthorizedException;
+import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.ConnectionException;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
import org.springframework.ide.vscode.commons.util.ValueParseException;
import org.springframework.ide.vscode.commons.yaml.schema.YValueHint;
+import com.google.common.collect.ImmutableList;
+
public abstract class AbstractCFHintsProvider implements Callable> {
public static final String EMPTY_VALUE = "";
@@ -59,12 +63,12 @@ public abstract class AbstractCFHintsProvider implements Callable