Merge branch 'master' of github.com:spring-projects/sts4

This commit is contained in:
Kris De Volder
2017-01-25 14:59:57 -08:00
10 changed files with 493 additions and 215 deletions

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
* 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;
/**
* Package-private.
* <p/>
* Use {@link CFEntities} public API to create instance
*
*/
class CFBuildpackImpl implements CFBuildpack {
private final String name;
public CFBuildpackImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CFBuildpackImpl other = (CFBuildpackImpl) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}

View File

@@ -0,0 +1,27 @@
/*******************************************************************************
* 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;
/**
* Factory to create CF "Entities" like CF services, buildpacks, etc..
*/
public class CFEntities {
public static CFBuildpack createBuildpack(String name) {
return new CFBuildpackImpl(name);
}
public static CFServiceInstance createServiceInstance(String name, String service, String plan,
String documentationUrl, String description, String dashboardUrl) {
return new CFServiceInstanceImpl(name, service, plan, documentationUrl, description, dashboardUrl);
}
}

View File

@@ -0,0 +1,123 @@
/*******************************************************************************
* 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;
/**
* Package-private.
* <p/>
* Use {@link CFEntities} public API to create instance
*
*/
class CFServiceInstanceImpl implements CFServiceInstance {
private String service;
private String plan;
private String name;
private String documentationUrl;
private String description;
private String dashboardUrl;
public CFServiceInstanceImpl(String name, String service, String plan, String documentationUrl, String description,
String dashboardUrl) {
this.name = name;
this.service = service;
this.plan = plan;
this.documentationUrl = documentationUrl;
this.description = description;
this.dashboardUrl = dashboardUrl;
}
@Override
public String getService() {
return service;
}
@Override
public String getPlan() {
return plan;
}
@Override
public String getName() {
return name;
}
@Override
public String getDocumentationUrl() {
return documentationUrl;
}
@Override
public String getDescription() {
return description;
}
@Override
public String getDashboardUrl() {
return dashboardUrl;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dashboardUrl == null) ? 0 : dashboardUrl.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((documentationUrl == null) ? 0 : documentationUrl.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((plan == null) ? 0 : plan.hashCode());
result = prime * result + ((service == null) ? 0 : service.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CFServiceInstanceImpl other = (CFServiceInstanceImpl) obj;
if (dashboardUrl == null) {
if (other.dashboardUrl != null)
return false;
} else if (!dashboardUrl.equals(other.dashboardUrl))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (documentationUrl == null) {
if (other.documentationUrl != null)
return false;
} else if (!documentationUrl.equals(other.documentationUrl))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (plan == null) {
if (other.plan != null)
return false;
} else if (!plan.equals(other.plan))
return false;
if (service == null) {
if (other.service != null)
return false;
} else if (!service.equals(other.service))
return false;
return true;
}
}

View File

@@ -14,6 +14,7 @@ import org.cloudfoundry.operations.buildpacks.Buildpack;
import org.cloudfoundry.operations.services.ServiceInstance;
import org.cloudfoundry.operations.services.ServiceInstanceType;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFEntities;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
/**
@@ -27,159 +28,18 @@ public class CFWrappingV2 {
public static CFBuildpack wrap(Buildpack buildpack) {
String name = buildpack.getName();
return new CFBuildpackImpl(name);
return CFEntities.createBuildpack(name);
}
public static CFServiceInstance wrap(ServiceInstance service) {
return new CFServiceInstanceImpl(service);
public static CFServiceInstance wrap(ServiceInstance serviceInstance) {
String name = serviceInstance.getName();
String plan = serviceInstance.getPlan();
String dashboardUrl = serviceInstance.getDashboardUrl();
String service = serviceInstance.getType() == ServiceInstanceType.USER_PROVIDED ? "user-provided"
: serviceInstance.getService();
String description = serviceInstance.getDescription();
String documentationUrl = serviceInstance.getDocumentationUrl();
return CFEntities.createServiceInstance(name, service, plan, documentationUrl, description, dashboardUrl);
}
public static CFBuildpack buildpack(String name) {
return new CFBuildpackImpl(name);
}
public static class CFBuildpackImpl implements CFBuildpack {
private final String name;
public CFBuildpackImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CFBuildpackImpl other = (CFBuildpackImpl) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public static class CFServiceInstanceImpl implements CFServiceInstance {
private final String name;
private final String plan;
private final String dashboardUrl;
private final String service;
private final String description;
private final String documentationUrl;
public CFServiceInstanceImpl(ServiceInstance serviceInstance) {
this.name = serviceInstance.getName();
this.plan = serviceInstance.getPlan();
this.dashboardUrl = serviceInstance.getDashboardUrl();
this.service = serviceInstance.getType() == ServiceInstanceType.USER_PROVIDED ? "user-provided"
: serviceInstance.getService();
this.description = serviceInstance.getDescription();
this.documentationUrl = serviceInstance.getDocumentationUrl();
}
@Override
public String getName() {
return this.name;
}
@Override
public String getPlan() {
return this.plan;
}
@Override
public String getDashboardUrl() {
return this.dashboardUrl;
}
@Override
public String getService() {
return this.service;
}
@Override
public String getDescription() {
return this.description;
}
@Override
public String getDocumentationUrl() {
return this.documentationUrl;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dashboardUrl == null) ? 0 : dashboardUrl.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((documentationUrl == null) ? 0 : documentationUrl.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((plan == null) ? 0 : plan.hashCode());
result = prime * result + ((service == null) ? 0 : service.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CFServiceInstanceImpl other = (CFServiceInstanceImpl) obj;
if (dashboardUrl == null) {
if (other.dashboardUrl != null)
return false;
} else if (!dashboardUrl.equals(other.dashboardUrl))
return false;
if (description == null) {
if (other.description != null)
return false;
} else if (!description.equals(other.description))
return false;
if (documentationUrl == null) {
if (other.documentationUrl != null)
return false;
} else if (!documentationUrl.equals(other.documentationUrl))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (plan == null) {
if (other.plan != null)
return false;
} else if (!plan.equals(other.plan))
return false;
if (service == null) {
if (other.service != null)
return false;
} else if (!service.equals(other.service))
return false;
return true;
}
}
}

View File

@@ -14,7 +14,7 @@ package org.springframework.ide.vscode.languageserver.testharness;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.assertContains;
import static org.springframework.ide.vscode.languageserver.testharness.TestAsserts.*;
import java.util.ArrayList;
import java.util.Collections;
@@ -264,6 +264,22 @@ public class Editor {
}
}
public void assertDoesNotContainCompletions(String... notToBeFound) throws Exception {
StringBuilder actual = new StringBuilder();
for (CompletionItem completion : getCompletions()) {
Editor editor = this.clone();
editor.apply(completion);
actual.append(editor.getText());
actual.append("\n-------------------\n");
}
String actualText = actual.toString();
for (String after : notToBeFound) {
assertDoesNotContain(after, actualText);
}
}
public void apply(CompletionItem completion) throws Exception {
TextEdit edit = completion.getTextEdit();
String docText = document.getText();

View File

@@ -21,4 +21,9 @@ public class TestAsserts {
}
}
public static void assertDoesNotContain(String needle, String haystack) {
if (haystack!=null && haystack.contains(needle)) {
fail("Found: "+needle+"\n in \n"+haystack);
}
}
}

View File

@@ -0,0 +1,148 @@
/*******************************************************************************
* 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.manifest.yaml;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFBuildpack;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFEntities;
import org.springframework.ide.vscode.commons.cloudfoundry.client.CFServiceInstance;
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientRequests;
import org.springframework.ide.vscode.commons.cloudfoundry.client.ClientTimeouts;
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.ClientParamsProvider;
import org.springframework.ide.vscode.commons.cloudfoundry.client.cftarget.NoTargetsException;
import com.google.common.collect.ImmutableList;
/**
* An alternative to using mockito for mocking the CF client, as the mockito
* version of the CF client seems to fail when run on OpenJDK (which is used for
* the sts4 concourse ci build).
* <p/>
* This also allows additional testing of the general manifest-yaml vscode
* framework, as the framework should be able to take any client factory,
* including the basic one below, and still produce correct results for content
* assist as well as reconcile
*
*/
public class BasicCfClientHarness {
private BasicCFClientFactory clientFactory = new BasicCFClientFactory();
private ClientParamsProvider paramsProvider = new BasicClientParamsProvider(ImmutableList.of(DEFAULT_PARAMS));
public static CFClientParams DEFAULT_PARAMS = new CFClientParams("test.io", "testuser",
CFCredentials.fromRefreshToken("refreshtoken"), false);
public BasicCFClientFactory getBasicClientFactory() {
return clientFactory;
}
public ClientParamsProvider getParamsProvider() {
return paramsProvider;
}
public void addBuildpacks(String... buildpacks) {
// Allow testing of null condition when vscode asks for buildpacks from
// the client and
// client returns null instead of empty list
List<CFBuildpack> asList = null;
if (buildpacks != null) {
asList = new ArrayList<CFBuildpack>();
for (String name : buildpacks) {
asList.add(CFEntities.createBuildpack(name));
}
}
getBasicClientFactory().getExistingClientInHarness().setBuildPacks(asList);
}
public static final class BasicCFClientFactory implements CloudFoundryClientFactory {
/*
* Create the client "ahead of time" so that it can be configured before
* the language server is tested
*/
private BasicClientRequests preexistingClient = new BasicClientRequests(DEFAULT_PARAMS, new ClientTimeouts());
@Override
public ClientRequests getClient(CFClientParams params, ClientTimeouts timeouts) throws Exception {
return this.preexistingClient;
}
/**
* Convenient non-framework method to fetch the existing client so that
* values can be set to simulate values from CF.
*
* @return
*/
public BasicClientRequests getExistingClientInHarness() {
return this.preexistingClient;
}
}
static class BasicClientParamsProvider implements ClientParamsProvider {
private List<CFClientParams> params;
public BasicClientParamsProvider(List<CFClientParams> defaultParams) {
this.params = defaultParams;
}
public void setParams(List<CFClientParams> params) {
this.params = params;
}
@Override
public List<CFClientParams> getParams() throws NoTargetsException, ExecutionException {
return this.params;
}
}
static class BasicClientRequests implements ClientRequests {
private List<CFBuildpack> buildpacks;
private List<CFServiceInstance> serviceInstances;
private CFClientParams params;
private ClientTimeouts timeouts;
public BasicClientRequests(CFClientParams params, ClientTimeouts timeouts) {
this.params = params;
this.timeouts = timeouts;
}
@Override
public List<CFBuildpack> getBuildpacks() throws Exception {
return this.buildpacks;
}
@Override
public List<CFServiceInstance> getServices() throws Exception {
return this.serviceInstances;
}
public void setBuildPacks(List<CFBuildpack> buildpacks) {
this.buildpacks = buildpacks;
}
public void setServices(List<CFServiceInstance> serviceInstances) {
this.serviceInstances = serviceInstances;
}
}
}

View File

@@ -0,0 +1,100 @@
/*******************************************************************************
* 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.manifest.yaml;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
public class ManifestYamlEditorCFBasicTest {
LanguageServerHarness harness;
BasicCfClientHarness basicCfClientHarness = new BasicCfClientHarness();
@Before
public void setup() throws Exception {
harness = new LanguageServerHarness(() -> new ManifestYamlLanguageServer(
basicCfClientHarness.getBasicClientFactory(), basicCfClientHarness.getParamsProvider()));
harness.intialize(null);
}
@Test
public void contentAssistBuildpack() throws Exception {
basicCfClientHarness.addBuildpacks("java_buildpack");
assertContainsCompletions("buildpack: <*>", "buildpack: java_buildpack<*>");
}
@Test
public void contentAssistDoesNotContainBuildpack() throws Exception {
basicCfClientHarness.addBuildpacks("java_buildpack");
assertDoesNotContainCompletions("buildpack: <*>", "buildpack: wrong_buildpack<*>");
}
// @Test
// public void contentAssistServices() throws Exception {
// basicCfClientHarness.addServices("mysql");
// assertContainsCompletions("services:\n" + " - <*>", "mysql");
// }
//
// @Test
// public void reconcileCFService() throws Exception {
// basicCfClientHarness.addServices("myservice");
// Editor editor = harness.newEditor("applications:\n" //
// + "- name: foo\n" //
// + " services:\n" //
// + " - myservice\n" //
// );
// // Should have no problems
// editor.assertProblems(/* none */);
// }
//
// @Test
// public void reconcileShowsWarningOnUnknownService() throws Exception {
// basicCfClientHarness.addServices("myservice");
// Editor editor = harness.newEditor("applications:\n" //
// + "- name: foo\n" //
// + " services:\n" //
// + " - bad-service\n" //
//
// );
// editor.assertProblems("bad-service|There is no service instance called");
//
// Diagnostic problem = editor.assertProblem("bad-service");
// assertEquals(DiagnosticSeverity.Warning, problem.getSeverity());
// }
//
// @Test
// public void reconcileShowsWarningOnEmptyServices() throws Exception {
// // Add empty list of services
// basicCfClientHarness.addServices();
// Editor editor = harness.newEditor("applications:\n" //
// + "- name: foo\n" //
// + " services:\n" //
// + " - bad-service\n");//
// editor.assertProblems("bad-service|There is no service instance called");
//
// Diagnostic problem = editor.assertProblem("bad-service");
// assertEquals(DiagnosticSeverity.Warning, problem.getSeverity());
// }
//////////////////////////////////////////////////////////////////////////////
private void assertContainsCompletions(String textBefore, String... textAfter) throws Exception {
Editor editor = harness.newEditor(textBefore);
editor.assertContainsCompletions(textAfter);
}
private void assertDoesNotContainCompletions(String textBefore, String... notToBeFound) throws Exception {
Editor editor = harness.newEditor(textBefore);
editor.assertDoesNotContainCompletions(notToBeFound);
}
}

View File

@@ -1,63 +0,0 @@
/*******************************************************************************
* 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.manifest.yaml;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
public class ManifestYamlEditorCFTest {
LanguageServerHarness harness;
@Before
public void setup() throws Exception {
harness = new LanguageServerHarness(()-> new ManifestYamlLanguageServer());
harness.intialize(null);
}
/*
* Optional test that is here only to be run in certain conditions. Tests if
* buildpack completion values are actually fetched from PWS if the test env
* also has a CLI that is alread connected to PWS. Enable only if underlying
* conditions for CF connection from vscode are present. For example, CLI is
* installed.
*/
@Ignore
@Test
public void optionalDynamicBuildpacksPWSUsingCliParams() throws Exception {
// No special test harness setup to use CLI. It is a "default" CF client params
// provider in the CF vscode framework.
// Just have to make sure the test env has a CLI that is connected to
// PWS
assertContainsCompletions("buildpack: <*>", "buildpack: java_buildpack<*>");
}
@Ignore
@Test
public void optionalDynamicServicesPWSUsingCliParams() throws Exception {
// No special test harness setup to use CLI. It is a "default" CF client params
// provider in the CF vscode framework.
// Just have to make sure the test env has a CLI that is connected to
// PWS
assertContainsCompletions( "services:\n"+
" - <*>", "sql");
}
//////////////////////////////////////////////////////////////////////////////
private void assertContainsCompletions(String textBefore, String... textAfter) throws Exception {
Editor editor = harness.newEditor(textBefore);
editor.assertContainsCompletions(textAfter);
}
}

View File

@@ -790,6 +790,11 @@ public class ManifestYamlEditorTest {
editor.assertProblems("bogus|Unknown property");
}
//////////////////////////////////////////////////////////////////////////////
// These tests are on ignore because they fail in the concourse ci build that uses OpenJDK.
// Possible issue is with mockito does not behave as expected using OpenJDK vs Oracle JVM
// These tests pass when running on an Oracle JVM.
@Ignore
@Test
public void reconcileCFService() throws Exception {