package hudson.cli;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.TopLevelItem;
import hudson.model.ViewTest.CompositeView;
import hudson.model.View;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import jenkins.model.Jenkins;
import jenkins.model.ModifiableTopLevelItemGroup;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Jenkins.class)
@SuppressStaticInitializationFor("hudson.cli.CLICommand")
public class ListJobsCommandTest {
private /*final*/ Jenkins jenkins;
private /*final*/ ListJobsCommand command;
private final ByteArrayOutputStream stdout = new ByteArrayOutputStream();
private final ByteArrayOutputStream stderr = new ByteArrayOutputStream();
@Before
public void setUp() {
jenkins = mock(Jenkins.class);
mockStatic(Jenkins.class);
when(Jenkins.getInstance()).thenReturn(jenkins);
when(Jenkins.getActiveInstance()).thenReturn(jenkins);
command = mock(ListJobsCommand.class, Mockito.CALLS_REAL_METHODS);
command.stdout = new PrintStream(stdout);
command.stderr = new PrintStream(stderr);
}
@Test
public void failForNonexistingName() throws Exception {
when(jenkins.getView("NoSuchViewOrItemGroup")).thenReturn(null);
when(jenkins.getItemByFullName("NoSuchViewOrItemGroup")).thenReturn(null);
try {
runWith("NoSuchViewOrItemGroup");
fail("Exception should be thrown in the previous call.");
} catch (IllegalArgumentException e) { // Expected
assertThat(e.getMessage(), containsString("No view or item group with the given name 'NoSuchViewOrItemGroup' found."));
}
assertThat(stdout, is(empty()));
}
/*
@Test
@Issue("JENKINS-18393")
public void failForMatrixProject() throws Exception {
final MatrixProject matrix = mock(MatrixProject.class);
final MatrixConfiguration config = mock(MatrixConfiguration.class);
when(matrix.getItems()).thenReturn(Arrays.asList(config));
when(jenkins.getView("MatrixJob")).thenReturn(null);
when(jenkins.getItemByFullName("MatrixJob")).thenReturn(matrix);
assertThat(runWith("MatrixJob"), equalTo(-1));
assertThat(stdout, is(empty()));
assertThat(stderr.toString(), containsString("No view or item group with the given name found"));
}
*/
@Test
public void getAllJobsFromFolders() throws Exception {
abstract class Folder implements ModifiableTopLevelItemGroup, TopLevelItem {
}
final Folder folder = mock(Folder.class);
final Folder nestedFolder = mock(Folder.class);
when(folder.getDisplayName()).thenReturn("Folder");
when(nestedFolder.getDisplayName()).thenReturn("NestedFolder");
final TopLevelItem job = job("job");
final TopLevelItem nestedJob = job("nestedJob");
when(job.hasPermission(Item.READ)).thenReturn(true);
when(nestedJob.hasPermission(Item.READ)).thenReturn(true);
when(job.getRelativeNameFrom((ItemGroup<TopLevelItem>) folder)).thenReturn("job");
when(nestedJob.getRelativeNameFrom((ItemGroup<TopLevelItem>) folder)).thenReturn("nestedJob");
when(folder.getItems()).thenReturn(Arrays.asList(nestedFolder, job));
when(nestedFolder.getItems()).thenReturn(Arrays.asList(nestedJob));
when(jenkins.getView("OuterFolder")).thenReturn(null);
when(jenkins.getItemByFullName("OuterFolder")).thenReturn(folder);
assertThat(runWith("OuterFolder"), equalTo(0));
assertThat(stdout, listsJobs("job", "nestedJob"));
assertThat(stderr, is(empty()));
}
@Test
public void getAllJobsForEmptyName() throws Exception {
final Collection<TopLevelItem> jenkinsJobs = Arrays.asList(
job("some-job"), job("some-other-job")
);
when(jenkins.getItems()).thenReturn((List<TopLevelItem>) jenkinsJobs);
assertThat(runWith(null), equalTo(0));
assertThat(stderr, is(empty()));
assertThat(stdout, listsJobs("some-job", "some-other-job"));
}
@Test
public void getJobsFromView() throws Exception {
final Collection<TopLevelItem> viewJobs = Arrays.asList(
job("some-job"), job("some-other-job")
);
final View customView = view();
when(customView.getItems()).thenReturn(viewJobs);
when(jenkins.getView("CustomView")).thenReturn(customView);
assertThat(runWith("CustomView"), equalTo(0));
assertThat(stderr, is(empty()));
assertThat(stdout, listsJobs("some-job", "some-other-job"));
}
@Test
public void getJobsRecursivelyFromViewGroup() throws Exception {
final CompositeView rootView = mock(CompositeView.class);
when(rootView.getAllItems()).thenCallRealMethod();
final View leftView = view();
final View rightView = view();
final TopLevelItem rootJob = job("rootJob");
final TopLevelItem leftJob = job("leftJob");
final TopLevelItem rightJob = job("rightJob");
final TopLevelItem sharedJob = job("sharedJob");
when(rootView.getViews()).thenReturn(Arrays.asList(leftView, rightView));
when(rootView.getItems()).thenReturn(Arrays.asList(rootJob, sharedJob));
when(leftView.getItems()).thenReturn(Arrays.asList(leftJob, sharedJob));
when(rightView.getItems()).thenReturn(Arrays.asList(rightJob));
when(jenkins.getView("Root")).thenReturn(rootView);
assertThat(runWith("Root"), equalTo(0));
assertThat(stderr, is(empty()));
assertThat(stdout, listsJobs("rootJob", "leftJob", "rightJob", "sharedJob"));
}
private View view() {
final View view = mock(View.class);
when(view.getAllItems()).thenCallRealMethod();
return view;
}
private TopLevelItem job(final String name) {
final TopLevelItem item = mock(TopLevelItem.class);
when(item.getName()).thenReturn(name);
when(item.getDisplayName()).thenReturn(name);
return item;
}
private int runWith(final String name) throws Exception {
command.name = name;
return command.run();
}
private TypeSafeMatcher<ByteArrayOutputStream> empty() {
return new TypeSafeMatcher<ByteArrayOutputStream>() {
@Override
protected boolean matchesSafely(ByteArrayOutputStream item) {
return item.toString().isEmpty();
}
@Override
public void describeTo(Description description) {
description.appendText("Empty output");
}
};
}
private TypeSafeMatcher<ByteArrayOutputStream> listsJobs(final String... expected) {
return new TypeSafeMatcher<ByteArrayOutputStream>() {
@Override
protected boolean matchesSafely(ByteArrayOutputStream item) {
final HashSet<String> jobs = new HashSet<String>(
Arrays.asList(item.toString().split(System.getProperty("line.separator")))
);
return new HashSet<String>(Arrays.asList(expected)).equals(jobs);
}
@Override
public void describeTo(Description description) {
description.appendText("Job listing of " + Arrays.toString(expected));
}
};
}
}