/**
* Copyright (C) 2012-2017 the original author or authors.
*
* Licensed 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 ninja.maven;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import ninja.build.DelayedRestartTrigger;
import ninja.build.RunClassInSeparateJvmMachine;
import ninja.build.WatchAndRestartMachine;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.testing.MojoRule;
import org.apache.maven.project.MavenProject;
import static org.codehaus.plexus.PlexusTestCase.getTestFile;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anySet;
import static org.mockito.Matchers.anyString;
import org.mockito.Mock;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.mockito.runners.MockitoJUnitRunner;
/**
* Unit test a Maven plugin in a modern way.
*/
@RunWith(MockitoJUnitRunner.class)
public class NinjaRunMojoTest {
@Rule
public MojoRule rule = new MojoRule() {
@Override
protected void before() throws Throwable {
}
@Override
protected void after() {
}
};
@Mock
MavenProject project;
@Mock
RunClassInSeparateJvmMachine machine;
@Mock
WatchAndRestartMachine watcher;
@Captor
ArgumentCaptor<String> classNameWithMainToRunCaptor;
@Captor
ArgumentCaptor<ArrayList<String>> classpathCaptor;
@Captor
ArgumentCaptor<ArrayList<String>> jvmArgumentsCaptor;
File pom;
NinjaRunMojo ninjaRunMojo;
@Before
public void before() throws Exception {
pom = getTestFile("src/test/resources/projects/minimal/pom.xml");
assertNotNull(pom);
assertTrue(pom.exists());
NinjaRunMojo mojo = (NinjaRunMojo)rule.lookupMojo("run", pom);
assertNotNull(mojo);
ninjaRunMojo = spy(mojo);
}
private void setupMachineAndWatcherStubs() throws IOException {
doReturn(machine)
.when(ninjaRunMojo)
.buildRunClassInSeparateJvmMachine(anyString(), classNameWithMainToRunCaptor.capture(), classpathCaptor.capture(), jvmArgumentsCaptor.capture(), (File) any());
doReturn(watcher)
.when(ninjaRunMojo)
.buildWatchAndRestartMachine(anySet(), anySet(), anySet(), (DelayedRestartTrigger)any());
}
@Test
public void alertAndStopExecutionIfDirectoryWithCompiledClassesOfThisProjectDoesNotExist() throws Exception {
ninjaRunMojo.buildOutputDirectory = "target/doesnotexist";
try {
ninjaRunMojo.execute();
fail();
} catch (MojoExecutionException e) {
assertThat(e.getMessage(), containsString("Directory with classes does not exist"));
}
}
@Test
public void minimal() throws Exception {
ninjaRunMojo.buildOutputDirectory = "target/classes";
ninjaRunMojo.project = project;
ninjaRunMojo.pluginArtifacts = new ArrayList<>();
ninjaRunMojo.settleDownMillis = 500L;
ninjaRunMojo.mode = "dev";
setupMachineAndWatcherStubs();
ninjaRunMojo.execute();
verify(machine, times(1)).restart();
verify(watcher, times(1)).run();
// verify what actually got to ninja machine
assertThat(jvmArgumentsCaptor.getValue().get(0), is("-Dninja.mode=dev"));
}
@Test
public void portProperty() throws Exception {
ninjaRunMojo.buildOutputDirectory = "target/classes";
ninjaRunMojo.project = project;
ninjaRunMojo.pluginArtifacts = new ArrayList<>();
ninjaRunMojo.settleDownMillis = 500L;
ninjaRunMojo.mode = "dev";
ninjaRunMojo.port = 9000;
setupMachineAndWatcherStubs();
ninjaRunMojo.execute();
verify(machine, times(1)).restart();
verify(watcher, times(1)).run();
// verify what actually got to ninja machine
assertThat(jvmArgumentsCaptor.getValue().get(0), is("-Dninja.mode=dev"));
assertThat(jvmArgumentsCaptor.getValue().get(1), is("-Dninja.port=9000"));
}
@Test
public void contextProperty() throws Exception {
ninjaRunMojo.buildOutputDirectory = "target/classes";
ninjaRunMojo.project = project;
ninjaRunMojo.pluginArtifacts = new ArrayList<>();
ninjaRunMojo.settleDownMillis = 500L;
ninjaRunMojo.mode = "dev";
ninjaRunMojo.context = "/test";
setupMachineAndWatcherStubs();
ninjaRunMojo.execute();
verify(machine, times(1)).restart();
verify(watcher, times(1)).run();
// verify what actually got to ninja machine
assertThat(jvmArgumentsCaptor.getValue().get(0), is("-Dninja.mode=dev"));
assertThat(jvmArgumentsCaptor.getValue().get(1), is("-Dninja.context=/test"));
}
@Test
public void contextPropertyFallbackToContextPath() throws Exception {
ninjaRunMojo.buildOutputDirectory = "target/classes";
ninjaRunMojo.project = project;
ninjaRunMojo.pluginArtifacts = new ArrayList<>();
ninjaRunMojo.settleDownMillis = 500L;
ninjaRunMojo.mode = "dev";
// verify old name still works
ninjaRunMojo.contextPath = "/test";
setupMachineAndWatcherStubs();
ninjaRunMojo.execute();
verify(machine, times(1)).restart();
verify(watcher, times(1)).run();
// verify what actually got to ninja machine
assertThat(jvmArgumentsCaptor.getValue().get(0), is("-Dninja.mode=dev"));
assertThat(jvmArgumentsCaptor.getValue().get(1), is("-Dninja.context=/test"));
}
@Test
public void mainClassProperty() throws Exception {
ninjaRunMojo.buildOutputDirectory = "target/classes";
ninjaRunMojo.project = project;
ninjaRunMojo.pluginArtifacts = new ArrayList<>();
ninjaRunMojo.settleDownMillis = 500L;
ninjaRunMojo.mode = "dev";
ninjaRunMojo.mainClass = "this.is.a.class.to.run";
setupMachineAndWatcherStubs();
ninjaRunMojo.execute();
verify(machine, times(1)).restart();
verify(watcher, times(1)).run();
// verify what actually got to ninja machine
assertThat(classNameWithMainToRunCaptor.getValue(), is("this.is.a.class.to.run"));
}
@Test
public void jvmArgsProperty() throws Exception {
ninjaRunMojo.buildOutputDirectory = "target/classes";
ninjaRunMojo.project = project;
ninjaRunMojo.pluginArtifacts = new ArrayList<>();
ninjaRunMojo.settleDownMillis = 500L;
ninjaRunMojo.mode = "dev";
ninjaRunMojo.jvmArgs = "\"This has spaces\" -Dprop=name -XXXX";
setupMachineAndWatcherStubs();
ninjaRunMojo.execute();
verify(machine, times(1)).restart();
verify(watcher, times(1)).run();
// verify what actually got to ninja machine
ArrayList<String> value = jvmArgumentsCaptor.getValue();
assertThat(value.get(0), is("-Dninja.mode=dev"));
assertThat(value.get(1), is("This has spaces"));
assertThat(value.get(2), is("-Dprop=name"));
assertThat(value.get(3), is("-XXXX"));
}
}