/*******************************************************************************
* Copyright (c) 2015 Pivotal Software, 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 Software, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.eclipse.boot.launch.test;
import java.util.Arrays;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.jdt.launching.JavaLaunchDelegate;
import org.springframework.ide.eclipse.boot.launch.BootLaunchConfigurationDelegate;
import org.springframework.ide.eclipse.boot.launch.AbstractBootLaunchConfigurationDelegate.PropVal;
import org.springframework.ide.eclipse.boot.launch.livebean.JmxBeanSupport;
import org.springframework.ide.eclipse.boot.test.util.LaunchResult;
import org.springframework.ide.eclipse.boot.test.util.LaunchUtil;
/**
* @author Kris De Volder
*/
@SuppressWarnings("restriction")
public class BootLaunchConfigurationDelegateTest extends BootLaunchTestCase {
private static final String TEST_MAIN_CLASS = "demo.DumpInfoApplication";
private static final String TEST_PROJECT = "dump-info";
@Override
protected void setUp() throws Exception {
super.setUp();
//The following disables some nasty popups that can cause test to hang rather than fail.
//when project has errors upon launching it.
InstanceScope.INSTANCE.getNode(DebugPlugin.getUniqueIdentifier())
.putBoolean(IInternalDebugCoreConstants.PREF_ENABLE_STATUS_HANDLERS, false);
}
public void testGetSetProperties() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
assertProperties(BootLaunchConfigurationDelegate.getProperties(wc)
/*empty*/
);
BootLaunchConfigurationDelegate.setProperties(wc, null); //accepts null in lieu of empty list,
assertProperties(BootLaunchConfigurationDelegate.getProperties(wc)
/*empty*/
);
//store one single property
doGetAndSetProps(wc,
pv("foo", "Hello", true)
);
//store empty property list
doGetAndSetProps(wc
/*empty*/
);
//store a few properties
doGetAndSetProps(wc,
pv("foo.bar", "snuffer.nazz", true),
pv("neala", "nolo", false),
pv("Hohoh", "Santa Claus", false)
);
//store properties with identical keys
doGetAndSetProps(wc,
pv("foo", "snuffer.nazz", true),
pv("foo", "nolo", false),
pv("bar", "Santa Claus", false),
pv("bar", "Santkkk ", false)
);
}
private ILaunchConfigurationWorkingCopy createWorkingCopy() throws CoreException {
return createWorkingCopy(BootLaunchConfigurationDelegate.TYPE_ID);
}
private void doGetAndSetProps(ILaunchConfigurationWorkingCopy wc, PropVal... props) {
BootLaunchConfigurationDelegate.setProperties(wc, Arrays.asList(props));
List<PropVal> retrieved = BootLaunchConfigurationDelegate.getProperties(wc);
assertProperties(retrieved, props);
}
private PropVal pv(String name, String value, boolean isChecked) {
return new PropVal(name, value, isChecked);
}
public void testSetGetProject() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
assertEquals(null, BootLaunchConfigurationDelegate.getProject(wc));
IProject project = getProject("foo");
BootLaunchConfigurationDelegate.setProject(wc, project);
assertEquals(project, BootLaunchConfigurationDelegate.getProject(wc));
}
public void testSetGetProfile() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
assertEquals("", BootLaunchConfigurationDelegate.getProfile(wc));
BootLaunchConfigurationDelegate.setProfile(wc, "deployment");
assertEquals("deployment", BootLaunchConfigurationDelegate.getProfile(wc));
BootLaunchConfigurationDelegate.setProfile(wc, null);
assertEquals("", BootLaunchConfigurationDelegate.getProfile(wc));
}
public void testSetGetAnsiConsoleOutput() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
boolean ideSupportsAnsiConsoleOutput = BootLaunchConfigurationDelegate.supportsAnsiConsoleOutput();
assertEquals(ideSupportsAnsiConsoleOutput, BootLaunchConfigurationDelegate.getEnableAnsiConsoleOutput(wc));
BootLaunchConfigurationDelegate.setEnableAnsiConsoleOutput(wc, true);
assertEquals(true, BootLaunchConfigurationDelegate.getEnableAnsiConsoleOutput(wc));
BootLaunchConfigurationDelegate.setEnableAnsiConsoleOutput(wc, false);
assertEquals(false, BootLaunchConfigurationDelegate.getEnableAnsiConsoleOutput(wc));
}
public void testClearProperties() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
BootLaunchConfigurationDelegate.setProperties(wc, Arrays.asList(
pv("some", "thing", true),
pv("some.other", "thing", false)
));
assertFalse(BootLaunchConfigurationDelegate.getProperties(wc).isEmpty());
BootLaunchConfigurationDelegate.clearProperties(wc);
assertTrue(BootLaunchConfigurationDelegate.getProperties(wc).isEmpty());
}
public void testGetSetDebug() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
boolean deflt = BootLaunchConfigurationDelegate.DEFAULT_ENABLE_DEBUG_OUTPUT;
boolean other = !deflt;
assertEquals(deflt,
BootLaunchConfigurationDelegate.getEnableDebugOutput(wc));
BootLaunchConfigurationDelegate.setEnableDebugOutput(wc, other);
assertEquals(other, BootLaunchConfigurationDelegate.getEnableDebugOutput(wc));
BootLaunchConfigurationDelegate.setEnableDebugOutput(wc, deflt);
assertEquals(deflt, BootLaunchConfigurationDelegate.getEnableDebugOutput(wc));
}
public void testGetSetLiveBean() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
boolean deflt = BootLaunchConfigurationDelegate.DEFAULT_ENABLE_LIVE_BEAN_SUPPORT;
boolean other = !deflt;
assertEquals(deflt, BootLaunchConfigurationDelegate.getEnableLiveBeanSupport(wc));
BootLaunchConfigurationDelegate.setEnableLiveBeanSupport(wc, other);
assertEquals(other, BootLaunchConfigurationDelegate.getEnableLiveBeanSupport(wc));
BootLaunchConfigurationDelegate.setEnableLiveBeanSupport(wc, deflt);
assertEquals(deflt, BootLaunchConfigurationDelegate.getEnableLiveBeanSupport(wc));
}
public void testGetSetJMXPort() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
assertEquals("", BootLaunchConfigurationDelegate.getJMXPort(wc));
BootLaunchConfigurationDelegate.setJMXPort(wc, "something");
assertEquals("something", BootLaunchConfigurationDelegate.getJMXPort(wc));
}
public void testRunAsLaunch() throws Exception {
IProject project = createLaunchReadyProject(TEST_PROJECT);
//Creates a launch conf similar to that created by 'Run As' menu.
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
BootLaunchConfigurationDelegate.setDefaults(wc, project, TEST_MAIN_CLASS);
LaunchResult result = LaunchUtil.synchLaunch(wc);
System.out.println(result); //Great help in debugging this :-)
assertContains(":: Spring Boot ::", result.out);
assertOk(result);
}
public void testLaunchAllOptsDisable() throws Exception {
createLaunchReadyProject(TEST_PROJECT);
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy();
LaunchResult result = LaunchUtil.synchLaunch(wc);
assertContains(":: Spring Boot ::", result.out);
assertOk(result);
}
public void testLaunchWithDebugOutput() throws Exception {
createLaunchReadyProject(TEST_PROJECT);
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy();
BootLaunchConfigurationDelegate.setEnableDebugOutput(wc, true);
LaunchResult result = LaunchUtil.synchLaunch(wc);
assertContains(":: Spring Boot ::", result.out);
assertContains("AUTO-CONFIGURATION REPORT", result.out);
assertOk(result);
}
public void testLaunchWithLiveBeans() throws Exception {
createLaunchReadyProject(TEST_PROJECT);
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy();
BootLaunchConfigurationDelegate.setEnableLiveBeanSupport(wc, true);
int port = JmxBeanSupport.randomPort();
BootLaunchConfigurationDelegate.setJMXPort(wc, ""+port);
LaunchResult result = LaunchUtil.synchLaunch(wc);
System.out.println(result);
assertContains(":: Spring Boot ::", result.out);
//The following check doesn't real prove the live bean graph works, but at least it shows the VM args are
//taking effect.
assertContains("com.sun.management.jmxremote.port='"+port+"'", result.out);
assertOk(result);
}
public void testLaunchWithProperties() throws Exception {
createLaunchReadyProject(TEST_PROJECT);
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy();
BootLaunchConfigurationDelegate.setProperties(wc, Arrays.asList(
pv("foo", "foo is enabled", true),
pv("bar", "bar is not enabled", false),
pv("zor", "zor enabled", true),
pv("zor", "zor disabled", false)
));
int jmxPort = JmxBeanSupport.randomPort(); // must set or it will be generated randomly
// and then we can't make the 'assert' below pass easily.
BootLaunchConfigurationDelegate.setJMXPort(wc, ""+jmxPort);
LaunchResult result = LaunchUtil.synchLaunch(wc);
assertContains(":: Spring Boot ::", result.out);
assertPropertyDump(result.out,
"debug=null\n" +
"zor='zor enabled'\n" +
"foo='foo is enabled'\n" +
"bar=null\n" +
"com.sun.management.jmxremote.port='"+jmxPort+"'"
);
assertOk(result);
}
public void testLaunchWithProfile() throws Exception {
createLaunchReadyProject(TEST_PROJECT);
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy();
BootLaunchConfigurationDelegate.setProfile(wc, "special");
LaunchResult result = LaunchUtil.synchLaunch(wc);
assertContains(":: Spring Boot ::", result.out);
assertContains("foo='special foo'", result.out);
assertOk(result);
}
public void testRuntimeClasspathNoTestStuff() throws Exception {
createLaunchReadyProject(TEST_PROJECT);
ILaunchConfigurationWorkingCopy wc = createBaseWorkingCopy();
String[] cp = getClasspath(new BootLaunchConfigurationDelegate(), wc);
assertClasspath(cp,
"target/classes",
"spring-boot-starter-1.2.1.RELEASE.jar",
"spring-boot-1.2.1.RELEASE.jar",
"spring-context-4.1.4.RELEASE.jar",
"spring-aop-4.1.4.RELEASE.jar",
"aopalliance-1.0.jar",
"spring-beans-4.1.4.RELEASE.jar",
"spring-expression-4.1.4.RELEASE.jar",
"spring-boot-autoconfigure-1.2.1.RELEASE.jar",
"spring-boot-starter-logging-1.2.1.RELEASE.jar",
"jcl-over-slf4j-1.7.8.jar",
"slf4j-api-1.7.8.jar",
"jul-to-slf4j-1.7.8.jar",
"log4j-over-slf4j-1.7.8.jar",
"logback-classic-1.1.2.jar",
"logback-core-1.1.2.jar",
"spring-core-4.1.4.RELEASE.jar",
"snakeyaml-1.14.jar"
);
}
private static void assertClasspath(String[] cp, String... expected) {
for (int i = 0; i < cp.length; i++) {
cp[i]=cp[i].replace('\\', '/');
}
for (String e : expected) {
assertClasspathHasEntry(cp, e);
}
for (String e : cp) {
assertClasspathEntryExpected(e, expected);
}
}
private static void assertClasspathEntryExpected(String e, String[] expected) {
for (String expect : expected) {
if (e.endsWith(expect)) {
return;
}
}
fail("Unexpected classpath entry: "+e);
}
private static void assertClasspathHasEntry(String[] cp, String expect) {
StringBuilder found = new StringBuilder();
for (String actual : cp) {
found.append(actual+"\n");
if (actual.endsWith(expect)) {
return;
}
}
fail("Missing classpath entry: "+expect+"\n"
+ "found: "+found);
}
private String[] getClasspath(JavaLaunchDelegate delegate,
ILaunchConfigurationWorkingCopy wc) throws CoreException {
System.out.println("\n====classpath according to "+delegate.getClass().getSimpleName());
String[] classpath = delegate.getClasspath(wc);
for (String element : classpath) {
int chop = element.lastIndexOf('/');
System.out.println('"'+element.substring(chop+1)+"\",");
}
return classpath;
}
private void assertPropertyDump(String out, String expected) {
String BEG = ">>>properties";
String END = "<<<properties";
int beg = out.indexOf(BEG)+BEG.length();
int end = out.indexOf(END);
String found = out.substring(beg, end);
assertEquals(windozify(expected), windozify(found));
}
/**
* Normalize crlf to just single newline for windoze's sake.
*/
private String windozify(String text) {
text = text.trim();
return text.replaceAll("\r", "");
}
private ILaunchConfigurationWorkingCopy createBaseWorkingCopy() throws Exception {
ILaunchConfigurationWorkingCopy wc = createWorkingCopy();
BootLaunchConfigurationDelegate.setDefaults(wc, getProject(TEST_PROJECT), TEST_MAIN_CLASS);
//Explictly set all options in the config to 'disabled' irrespective of
// their default values (tests will be more robust w.r.t changing of the defaults).
BootLaunchConfigurationDelegate.setEnableDebugOutput(wc, false);
BootLaunchConfigurationDelegate.setEnableLiveBeanSupport(wc, false);
BootLaunchConfigurationDelegate.setJMXPort(wc, "");
BootLaunchConfigurationDelegate.setProfile(wc, "");
BootLaunchConfigurationDelegate.setProperties(wc, null);
return wc;
}
///////////////////////////////////////////////////////////////////////////////
public static void assertProperties(List<PropVal> actual, PropVal... expect) {
assertElements(actual, expect);
}
}