DefaultBuildInvocationTest.java
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.internal.build;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.maven.api.BuildInvocation;
import org.apache.maven.api.MakeBehavior;
import org.apache.maven.api.ReactorFailureBehavior;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenSession;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class DefaultBuildInvocationTest {
private static MavenExecutionRequest newRequest() {
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
request.setLocalRepositoryPath(new File("/tmp/test-repo"));
return request;
}
@Test
void fromBasicRequest() {
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
request.setGoals(List.of("clean", "install"));
request.setOffline(true);
request.setUpdateSnapshots(true);
request.setInteractiveMode(false);
request.setReactorFailureBehavior(MavenExecutionRequest.REACTOR_FAIL_AT_END);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals(List.of("clean", "install"), inv.goals());
assertTrue(inv.offline());
assertTrue(inv.updateSnapshots());
assertTrue(inv.batchMode());
assertEquals(ReactorFailureBehavior.FAIL_AT_END, inv.reactorFailureBehavior());
assertTrue(inv.recursive());
assertFalse(inv.resume());
assertNull(inv.makeBehavior());
assertTrue(inv.excludedProjects().isEmpty());
}
@Test
void fromNullGoals() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertNotNull(inv.goals());
assertTrue(inv.goals().isEmpty());
}
@Test
void fromNullActiveProfiles() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertNotNull(inv.activeProfiles());
assertTrue(inv.activeProfiles().isEmpty());
}
@Test
void fromNullSelectedProjects() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertNotNull(inv.selectedProjects());
assertTrue(inv.selectedProjects().isEmpty());
}
@Test
void fromNullReactorFailureBehaviorDefaultsToFailFast() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals(ReactorFailureBehavior.FAIL_FAST, inv.reactorFailureBehavior());
}
@Test
void resumeFrom() {
MavenExecutionRequest request = newRequest();
request.setResumeFrom(":my-module");
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals(":my-module", inv.resumeFrom());
}
@Test
void resumeFromNull() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertNull(inv.resumeFrom());
}
@Test
void sensitiveKeyRedaction() {
MavenExecutionRequest request = newRequest();
Properties userProps = new Properties();
userProps.setProperty("my.password", "secret123");
userProps.setProperty("api_key", "key123");
userProps.setProperty("auth.token", "tok123");
userProps.setProperty("safe.property", "visible");
request.setUserProperties(userProps);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals("***", inv.userProperties().get("my.password"));
assertEquals("***", inv.userProperties().get("api_key"));
assertEquals("***", inv.userProperties().get("auth.token"));
assertEquals("visible", inv.userProperties().get("safe.property"));
}
@ParameterizedTest
@ValueSource(
strings = {
"password",
"PASSWORD",
"my.passwd",
"db_secret",
"auth_token",
"APIKEY",
"my.api_key",
"credential",
"ssh.passphrase"
})
void sensitiveKeyFragments(String key) {
assertTrue(DefaultBuildInvocation.isSensitiveKey(key));
}
@ParameterizedTest
@ValueSource(strings = {"safe.property", "skip.tests", "maven.compiler.source", "project.build.outputDirectory"})
void nonSensitiveKeys(String key) {
assertFalse(DefaultBuildInvocation.isSensitiveKey(key));
}
@Test
void systemInfoCapturesExpectedKeys() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
Map<String, String> sysInfo = inv.systemInfo();
assertNotNull(sysInfo.get("os.name"));
assertNotNull(sysInfo.get("os.arch"));
assertNotNull(sysInfo.get("java.vm.version"));
assertNotNull(sysInfo.get("available.processors"));
}
@Test
void collectionsAreImmutable() {
DefaultBuildInvocation inv = new DefaultBuildInvocation(
List.of("compile"),
Map.of("key", "val"),
Map.of("os.name", "Linux"),
List.of("profile1"),
List.of(":module1"),
List.of(":excluded"),
null,
null,
ReactorFailureBehavior.FAIL_FAST,
false,
false,
false,
true,
false,
1);
assertThrows(UnsupportedOperationException.class, () -> inv.goals().add("test"));
assertThrows(
UnsupportedOperationException.class, () -> inv.userProperties().put("new", "val"));
assertThrows(
UnsupportedOperationException.class, () -> inv.activeProfiles().add("p2"));
assertThrows(
UnsupportedOperationException.class,
() -> inv.selectedProjects().add(":m2"));
assertThrows(
UnsupportedOperationException.class,
() -> inv.excludedProjects().add(":m3"));
assertThrows(UnsupportedOperationException.class, () -> inv.systemInfo().put("k", "v"));
}
@Test
void reactorFailureBehaviorValues() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
request.setReactorFailureBehavior(MavenExecutionRequest.REACTOR_FAIL_FAST);
assertEquals(
ReactorFailureBehavior.FAIL_FAST,
DefaultBuildInvocation.from(session).reactorFailureBehavior());
request.setReactorFailureBehavior(MavenExecutionRequest.REACTOR_FAIL_AT_END);
assertEquals(
ReactorFailureBehavior.FAIL_AT_END,
DefaultBuildInvocation.from(session).reactorFailureBehavior());
request.setReactorFailureBehavior(MavenExecutionRequest.REACTOR_FAIL_NEVER);
assertEquals(
ReactorFailureBehavior.FAIL_NEVER,
DefaultBuildInvocation.from(session).reactorFailureBehavior());
}
@Test
void unrecognizedReactorFailureBehaviorDefaultsToFailFast() {
MavenExecutionRequest request = newRequest();
request.setReactorFailureBehavior("UNKNOWN_VALUE");
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals(ReactorFailureBehavior.FAIL_FAST, inv.reactorFailureBehavior());
}
@Test
void threadsDefault() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals(1, inv.threads());
}
@Test
void threadsExplicit() {
MavenExecutionRequest request = newRequest();
request.setDegreeOfConcurrency(4);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals(4, inv.threads());
}
@Test
void excludedProjects() {
MavenExecutionRequest request = newRequest();
request.setExcludedProjects(List.of(":slow-module", ":flaky-module"));
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
BuildInvocation inv = DefaultBuildInvocation.from(session);
assertEquals(2, inv.excludedProjects().size());
assertTrue(inv.excludedProjects().contains(":slow-module"));
assertTrue(inv.excludedProjects().contains(":flaky-module"));
}
@Test
void makeBehaviorUpstream() {
MavenExecutionRequest request = newRequest();
request.setMakeBehavior(MavenExecutionRequest.REACTOR_MAKE_UPSTREAM);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
assertEquals(MakeBehavior.UPSTREAM, DefaultBuildInvocation.from(session).makeBehavior());
}
@Test
void makeBehaviorDownstream() {
MavenExecutionRequest request = newRequest();
request.setMakeBehavior(MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
assertEquals(
MakeBehavior.DOWNSTREAM, DefaultBuildInvocation.from(session).makeBehavior());
}
@Test
void makeBehaviorBoth() {
MavenExecutionRequest request = newRequest();
request.setMakeBehavior(MavenExecutionRequest.REACTOR_MAKE_BOTH);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
assertEquals(MakeBehavior.BOTH, DefaultBuildInvocation.from(session).makeBehavior());
}
@Test
void makeBehaviorNull() {
MavenExecutionRequest request = newRequest();
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
assertNull(DefaultBuildInvocation.from(session).makeBehavior());
}
@Test
void makeBehaviorUnknownStringReturnsNull() {
MavenExecutionRequest request = newRequest();
request.setMakeBehavior("invalid-value");
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
assertNull(DefaultBuildInvocation.from(session).makeBehavior());
}
@Test
void nonRecursive() {
MavenExecutionRequest request = newRequest();
request.setRecursive(false);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
assertFalse(DefaultBuildInvocation.from(session).recursive());
}
@Test
void resume() {
MavenExecutionRequest request = newRequest();
request.setResume(true);
MavenSession session = mock(MavenSession.class);
when(session.getRequest()).thenReturn(request);
assertTrue(DefaultBuildInvocation.from(session).resume());
}
}