Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unified UI setting for toolchains #1691

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions org.eclipse.m2e.core.tests/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ Require-Bundle: org.eclipse.m2e.tests.common,
org.eclipse.debug.core,
org.eclipse.jdt.core
Import-Package: org.apache.commons.io,
org.hamcrest;version="[2.2.0,3.0.0]",
org.hamcrest.collection;version="[2.2.0,3.0.0]",
org.hamcrest.core;version="[2.2.0,3.0.0]",
org.junit,
org.mockito,
org.mockito.stubbing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<toolchains/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<toolchains/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2024 Georg Tsakumagos and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Georg Tsakumagos - initial declaration
*******************************************************************************/
package org.eclipse.m2e.core;

import java.util.function.Consumer;

import org.eclipse.core.runtime.CoreException;

/**
* Represents an operation that accepts two input arguments, returns no
* result and throws a {@link CoreException}.
* This is the two-arity specialization of {@link Consumer}.
* Unlike most other functional interfaces, {@code BiConsumer} is expected
* to operate via side-effects.
*
*
* @param <T> the type of the first argument to the operation
* @param <U> the type of the second argument to the operation
*
* @see Consumer
* @author Georg Tsakumagos
*/
@FunctionalInterface
public interface CoreBiConsumer<T, U> {

/**
* Performs this operation on the given arguments.
*
* @param t the first input argument
* @param u the second input argument
* @throws CoreException If something went wrong.
*/
void accept(T t, U u) throws CoreException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* Contributors:
* Hannes Wellmann - initial API and implementation
* Konrad Windszus - Add tests for required java runtime version implied by enforcer rule
* Georg Tsakumagos - Add tests for global- & user- settings and toolchains.
*******************************************************************************/

package org.eclipse.m2e.internal.launch;
Expand All @@ -19,21 +20,31 @@

import java.io.File;
import java.util.List;
import java.util.Optional;

import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.cli.CLIManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.Launch;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.jdt.launching.AbstractVMInstall;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMInstallType;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.m2e.actions.MavenLaunchConstants;
import org.eclipse.m2e.core.CoreBiConsumer;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.embedder.IMavenConfiguration;
import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matcher;
import org.hamcrest.MatcherAssert;
import org.junit.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
Expand All @@ -47,6 +58,8 @@ public class MavenLaunchDelegateTest extends AbstractMavenProjectTestCase {
private static final String DEFAULT_VM = "defaultVM";
private static final List<String> AVAILABLE_VM_VERSIONS = List.of("17.0.4", "11.0.7", "13.0.5", "11.0.1", "1.8.0");



@Test
public void testGetBestMatchingVM_majorOnly() throws InvalidVersionSpecificationException {
try (var mock = mockJavaRuntime()) {
Expand Down Expand Up @@ -75,6 +88,63 @@ public void testGetBestMatchingVM_1XversionRange() throws InvalidVersionSpecific
}
}

/**
* Tests rendering of maven cli args for <em>global settings (-gs,--global-settings)</em>.
* @throws Exception On errors.
*/
@Test
public void testGlobalSettings() throws Exception {
assertMavenLaunchFileSetting(IMavenConfiguration::setGlobalSettingsFile, CLIManager.ALTERNATE_GLOBAL_SETTINGS, "./resources/settings/empty_settings/settings_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global settings (-gs,--global-settings)</em>
* if setting is overridden by direct parameterization in the goal input
* @throws Exception On errors.
*/
@Test
public void testGlobalSettings_GoalOverride() throws Exception {
assertMavenLaunchFileSettingGoalOverride(IMavenConfiguration::setGlobalSettingsFile, CLIManager.ALTERNATE_GLOBAL_SETTINGS, "./resources/settings/empty_settings/settings_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global settings (-gs,--global-settings)</em>
* if an invalid path was provided.
* @throws Exception On errors.
*/
@Test
public void testGlobalSettings_Invalid() throws Exception {
assertMavenLaunchFileSettingPathInvalid(IMavenConfiguration::setGlobalSettingsFile);
}

/**
* Tests rendering of maven cli args for <em>global toolchains (-gt,--global-toolchains)</em>.
* @throws Exception On errors.
*/
@Test
public void testGlobalToolchains() throws Exception {
assertMavenLaunchFileSetting(IMavenConfiguration::setGlobalToolchainsFile, CLIManager.ALTERNATE_GLOBAL_TOOLCHAINS, "./resources/settings/empty_settings/toolchains_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global toolchains (-gt,--global-toolchains)</em>
* if setting is overridden by direct parameterization in the goal input
* @throws Exception On errors.
*/
@Test
public void testGlobalToolchains_GoalOverride() throws Exception {
assertMavenLaunchFileSettingGoalOverride(IMavenConfiguration::setGlobalToolchainsFile, CLIManager.ALTERNATE_GLOBAL_TOOLCHAINS, "./resources/settings/empty_settings/toolchains_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global toolchains (-gt,--global-toolchains)</em> if an invalid path was provided.
* @throws Exception On errors.
*/
@Test
public void testGlobalToolchains_Invalid() throws Exception {
assertMavenLaunchFileSettingPathInvalid(IMavenConfiguration::setGlobalToolchainsFile);
}

@Test
public void testRequiredJavaVersionFromEnforcerRule_Version() throws Exception {
IProject project = importProject("resources/projects/enforcerSettingsWithVersion/pom.xml");
Expand All @@ -93,6 +163,179 @@ public void testRequiredJavaVersionFromEnforcerRule_NoVersionRange() throws Exce
assertRequiredJavaBuildVersion(project, null, DEFAULT_VM);
}

/**
* Tests rendering of maven cli args for <em>global settings (-s,--settings)</em>
* @throws Exception On errors.
*/
@Test
public void testUserSettings() throws Exception {
assertMavenLaunchFileSetting(IMavenConfiguration::setUserSettingsFile, String.valueOf(CLIManager.ALTERNATE_USER_SETTINGS), "./resources/settings/empty_settings/settings_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global settings (-s,--settings)</em>
* if setting is overridden by direct parameterization in the goal input
* @throws Exception On errors.
*/
@Test
public void testUserSettings_GoalOverride() throws Exception {
assertMavenLaunchFileSettingGoalOverride(IMavenConfiguration::setUserSettingsFile, String.valueOf(CLIManager.ALTERNATE_USER_SETTINGS), "./resources/settings/empty_settings/settings_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global settings (-s,--settings)</em>
* if an invalid path was provided.
* @throws Exception On errors.
*/
@Test
public void testUserSettings_Invalid() throws Exception {
assertMavenLaunchFileSettingPathInvalid(IMavenConfiguration::setUserSettingsFile);
}


/**
* Tests rendering of maven cli args for <em>global toolchains (-t,--toolchains)</em>.
* @throws Exception On errors.
*/
@Test
public void testUserToolchains() throws Exception {
assertMavenLaunchFileSetting(IMavenConfiguration::setUserToolchainsFile, String.valueOf(CLIManager.ALTERNATE_USER_TOOLCHAINS), "./resources/settings/empty_settings/toolchains_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global toolchains (-t,--toolchains)</em>.
* if setting is overridden by direct parameterization in the goal input
* @throws Exception On errors.
*/
@Test
public void testUserToolchains_GoalOverride() throws Exception {
assertMavenLaunchFileSettingGoalOverride(IMavenConfiguration::setUserToolchainsFile, String.valueOf(CLIManager.ALTERNATE_USER_TOOLCHAINS), "./resources/settings/empty_settings/toolchains_empty.xml");
}

/**
* Tests rendering of maven cli args for <em>global toolchains (-t,--toolchains)</em>
* if an invalid path was provided.
* @throws Exception On errors.
*/
@Test
public void testUserToolchains_Invalid() throws Exception {
assertMavenLaunchFileSettingPathInvalid(IMavenConfiguration::setUserToolchainsFile);
}


/**
* assertion shortcut for launch configuration.
* @param configSetter Setter for the configuration accepting the relativePath. Must not be <code>null</code>.
* @param key Key of the configuration. Must not be <code>null</code>.
* @param relativePath Relative path for the file. Must not be <code>null</code>.
* @throws Exception Usually only on missed assertions.
*/
private void assertMavenLaunchConfig(CoreBiConsumer<IMavenConfiguration, String> configSetter, String goal, CoreBiConsumer<MavenLaunchDelegate, ILaunchConfigurationWorkingCopy> verifier, String relativePath)
throws Exception {

waitForJobsToComplete();
IProject project = importProject("resources/projects/simplePomOK/pom.xml");
String pomDir = "${workspace_loc:/" + project.getName() + "}";

try (var mock = mockJavaRuntime()) {
IMavenConfiguration mavenConfig = MavenPlugin.getMavenConfiguration();

try {
configSetter.accept(mavenConfig, relativePath);
ILaunchConfigurationWorkingCopy config = createMavenLaunchConfig(pomDir);

try {
Optional.ofNullable(goal).ifPresent((g) -> config.setAttribute(MavenLaunchConstants.ATTR_GOALS, g));

// Prepare Mocks to capture VM configuration
Launch launch = new Launch(config, "run", new MavenSourceLocator());
NullProgressMonitor mockMonitor = Mockito.spy(new NullProgressMonitor());
Mockito.doReturn(true).when(mockMonitor).isCanceled();

// mock launch
MavenLaunchDelegate launcher = new MavenLaunchDelegate();
launcher.launch(config, "run", launch, mockMonitor);

verifier.accept(launcher, config);
} finally {
Optional.ofNullable(goal).ifPresent((g) -> config.removeAttribute(MavenLaunchConstants.ATTR_GOALS));
}
} finally {
// Reset property to avoid conflicts with other test cases.
configSetter.accept(mavenConfig, null);
}
}
}

/**
* assertion shortcut for launch configuration.
* @param configSetter Setter for the configuration accepting the relativePath. Must not be <code>null</code>.
* @param key Key of the configuration. Must not be <code>null</code>.
* @param relativePath Relative path for the file. Must not be <code>null</code>.
* @throws Exception Usually only on missed assertions.
*/
private void assertMavenLaunchFileSetting(CoreBiConsumer<IMavenConfiguration, String> configSetter, String key, String relativePath)
throws Exception {
final String param = "-" + key;
this.assertMavenLaunchConfig(configSetter, null, (launcher, config) -> {
String programArguments = launcher.getProgramArguments(config);

// prepare assert
Matcher<String> allSettings = CoreMatchers.allOf(
CoreMatchers.containsString(param),
CoreMatchers.containsString(new File(relativePath).getAbsolutePath())
);

// assert
MatcherAssert.assertThat(programArguments, allSettings);
}, relativePath);
}

/**
* assertion shortcut for launch configuration.
* @param configSetter Setter for the configuration accepting the relativePath. Must not be <code>null</code>.
* @param key Key of the configuration. Must not be <code>null</code>.
* @param relativePath Relative path for the file. Must not be <code>null</code>.
* @throws Exception Usually only on missed assertions.
*/
private void assertMavenLaunchFileSettingGoalOverride(CoreBiConsumer<IMavenConfiguration, String> configSetter, String key, String relativePath)
throws Exception {
final String userDerivedPath = "./resources/settings/empty_settings/this_do_not_exists.xml";
final String param = "-" + key;
final String goalConfig = "clean " + param + " " + userDerivedPath;

this.assertMavenLaunchConfig(configSetter, goalConfig, (launcher, config) -> {
String programArguments = launcher.getProgramArguments(config);

// prepare assert
Matcher<String> allSettings = CoreMatchers.allOf(
CoreMatchers.containsString(param),
CoreMatchers.containsString(userDerivedPath),
CoreMatchers.not(CoreMatchers.containsString(relativePath))
);

// assert
MatcherAssert.assertThat(programArguments, allSettings);
}, relativePath);
}


/**
* assertion shortcut for launch configuration if an invalid path was provided.
* @param configSetter Setter for the configuration accepting the relativePath. Must not be <code>null</code>.
* @param key Key of the configuration. Must not be <code>null</code>.
* @throws Exception Usually only on missed assertions.
*/
private void assertMavenLaunchFileSettingPathInvalid(CoreBiConsumer<IMavenConfiguration, String> configSetter) throws Exception {
final String path = "./resources/settings/empty_settings/this_do_not_exists.xml";
try {
this.assertMavenLaunchConfig(configSetter, null, (launcher, config) -> {}, path);
} catch(IllegalArgumentException expected) {
MatcherAssert.assertThat(expected.getMessage(), CoreMatchers.containsString(path));
}
}


private void assertRequiredJavaBuildVersion(IProject project, String expectedVersionRange, String expectedVMVersion)
throws Exception {

Expand Down
Loading
Loading