/*
* The MIT License
*
* Copyright (c) 2013-2014, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package jenkins.widgets;
import hudson.model.Job;
import hudson.model.MockItem;
import hudson.model.ModelObject;
import hudson.model.Queue;
import hudson.model.Result;
import hudson.model.Run;
import jenkins.widgets.HistoryPageEntry;
import jenkins.widgets.HistoryPageFilter;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:tom.fennelly@gmail.com">tom.fennelly@gmail.com</a>
*/
public class HistoryPageFilterTest {
/**
* No items.
*/
@Test
public void test_latest_empty_page() {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, null);
List<ModelObject> itemList = new ArrayList<>();
historyPageFilter.add(itemList);
Assert.assertEquals(false, historyPageFilter.hasUpPage);
Assert.assertEquals(false, historyPageFilter.hasDownPage);
Assert.assertEquals(true, historyPageFilter.queueItems.isEmpty());
Assert.assertEquals(true, historyPageFilter.runs.isEmpty());
}
/**
* Latest/top page where total number of items less than the max page size.
*/
@Test
public void test_latest_partial_page() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, null);
List<ModelObject> runs = newRuns(1, 2);
List<Queue.Item> queueItems = newQueueItems(3, 4);
historyPageFilter.add(runs, queueItems);
Assert.assertEquals(false, historyPageFilter.hasUpPage);
Assert.assertEquals(false, historyPageFilter.hasDownPage);
Assert.assertEquals(2, historyPageFilter.queueItems.size());
Assert.assertEquals(2, historyPageFilter.runs.size());
Assert.assertEquals(4, historyPageFilter.queueItems.get(0).getEntryId());
Assert.assertEquals(4, historyPageFilter.newestOnPage);
Assert.assertEquals(3, historyPageFilter.queueItems.get(1).getEntryId());
Assert.assertEquals(HistoryPageEntry.getEntryId(2), historyPageFilter.runs.get(0).getEntryId());
Assert.assertEquals(HistoryPageEntry.getEntryId(1), historyPageFilter.runs.get(1).getEntryId());
Assert.assertEquals(HistoryPageEntry.getEntryId(1), historyPageFilter.oldestOnPage);
}
/**
* Latest/top page where total number of items greater than the max page size.
*/
@Test
public void test_latest_longer_list() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, null);
List<ModelObject> runs = newRuns(1, 10);
List<Queue.Item> queueItems = newQueueItems(11, 12);
historyPageFilter.add(runs, queueItems);
Assert.assertEquals(false, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(2, historyPageFilter.queueItems.size());
Assert.assertEquals(3, historyPageFilter.runs.size());
Assert.assertEquals(12, historyPageFilter.queueItems.get(0).getEntryId());
Assert.assertEquals(12, historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(10), historyPageFilter.runs.get(0).getEntryId());
}
/**
* Test olderThan (page down) when set to id greater than newest (should never happen). Should be same as not
* specifying newerThan/olderThan.
*/
@Test
public void test_olderThan_gt_newest() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, 11L);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(false, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(5, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(10), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(6), historyPageFilter.oldestOnPage);
}
/**
* Test olderThan (page down) when set to id less than the oldest (should never happen). Should just give an
* empty list of builds.
*/
@Test
public void test_olderThan_lt_oldest() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, 0L);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(true, historyPageFilter.hasUpPage);
Assert.assertEquals(false, historyPageFilter.hasDownPage);
Assert.assertEquals(0, historyPageFilter.runs.size());
}
/**
* Test olderThan (page down) when set to an id close to the oldest in the list (where
* there's less than a full page older than the supplied olderThan arg).
*/
@Test
public void test_olderThan_leaving_part_page() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, 4L);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(true, historyPageFilter.hasUpPage);
Assert.assertEquals(false, historyPageFilter.hasDownPage);
// Should only be 3 runs on the page (oldest 3)
Assert.assertEquals(3, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(3), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(1), historyPageFilter.oldestOnPage);
}
/**
* Test olderThan (page down) when set to an id in the middle. Should be a page up and a page down.
*/
@Test
public void test_olderThan_mid_page() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, 8L);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(true, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(5, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(7), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(3), historyPageFilter.oldestOnPage);
}
/**
* Test newerThan (page up) when set to id greater than newest (should never happen). Should be an empty list.
*/
@Test
public void test_newerThan_gt_newest() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, 11L, null);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(false, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(0, historyPageFilter.runs.size());
}
/**
* Test newerThan (page up) when set to id less than the oldest (should never happen). Should give the oldest
* set of builds.
*/
@Test
public void test_newerThan_lt_oldest() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, 0L, null);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(true, historyPageFilter.hasUpPage);
Assert.assertEquals(false, historyPageFilter.hasDownPage);
Assert.assertEquals(5, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(5), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(1), historyPageFilter.oldestOnPage);
}
/**
* Test newerThan (page up) mid range nearer the oldest build in the list.
*/
@Test
public void test_newerThan_near_oldest() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, 3L, null);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(true, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(5, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(8), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(4), historyPageFilter.oldestOnPage);
}
/**
* Test newerThan (page up) mid range nearer the newest build in the list. This works a little different
* in that it will put the 2 builds newer than newerThan on the page and then fill the remaining slots on the
* page with builds equal to and older i.e. it return the newest/latest builds.
*/
@Test
public void test_newerThan_near_newest() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, 8L, null);
List<ModelObject> itemList = newRuns(1, 10);
historyPageFilter.add(itemList);
Assert.assertEquals(false, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(5, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(10), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(6), historyPageFilter.oldestOnPage);
}
/**
* Test newerThan (page up) mid range when there are queued builds that are new enough to
* not show up.
*/
@Test
public void test_newerThan_doesntIncludeQueuedItems() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, 5L, null);
List<ModelObject> runs = newRuns(1, 10);
List<Queue.Item> queueItems = newQueueItems(11, 12);
historyPageFilter.add(runs, queueItems);
Assert.assertEquals(true, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(0, historyPageFilter.queueItems.size());
Assert.assertEquals(5, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(10), historyPageFilter.runs.get(0).getEntryId());
Assert.assertEquals(HistoryPageEntry.getEntryId(10), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(6), historyPageFilter.oldestOnPage);
}
/**
* Test that later items in the list that are not needed for display are not evaluated at all (for performance).
*/
@Test
public void test_laterItemsNotEvaluated() throws IOException {
HistoryPageFilter<ModelObject> historyPageFilter = newPage(5, null, null);
List<ModelObject> itemList = newRuns(6, 10);
for (int queueId = 5; queueId >= 1; queueId--) {
itemList.add(new ExplodingMockRun(queueId));
}
historyPageFilter.add(itemList);
Assert.assertEquals(false, historyPageFilter.hasUpPage);
Assert.assertEquals(true, historyPageFilter.hasDownPage);
Assert.assertEquals(5, historyPageFilter.runs.size());
Assert.assertEquals(HistoryPageEntry.getEntryId(10), historyPageFilter.newestOnPage);
Assert.assertEquals(HistoryPageEntry.getEntryId(6), historyPageFilter.oldestOnPage);
}
private List<Queue.Item> newQueueItems(long startId, long endId) {
List<Queue.Item> items = new ArrayList<>();
for (long queueId = startId; queueId <= endId; queueId++) {
items.add(new MockItem(queueId));
}
return items;
}
private List<ModelObject> newRuns(long startId, long endId) throws IOException {
// Runs should be in reverse order, newest first.
List<ModelObject> runs = new ArrayList<>();
for (long queueId = endId; queueId >= startId; queueId--) {
runs.add(new MockRun(queueId));
}
return runs;
}
private HistoryPageFilter<ModelObject> newPage(int maxEntries, Long newerThan, Long olderThan) {
HistoryPageFilter<ModelObject> pageFilter = new HistoryPageFilter<>(maxEntries);
if (newerThan != null) {
pageFilter.setNewerThan(HistoryPageEntry.getEntryId(newerThan));
} else if (olderThan != null) {
pageFilter.setOlderThan(HistoryPageEntry.getEntryId(olderThan));
}
return pageFilter;
}
@SuppressWarnings("unchecked")
private static class MockRun extends Run {
private final long queueId;
public MockRun(long queueId) throws IOException {
super(Mockito.mock(Job.class));
this.queueId = queueId;
}
@Override
public int compareTo(Run o) {
return 0;
}
@Override
public Result getResult() {
return result;
}
@Override
public boolean isBuilding() {
return false;
}
@Override
public long getQueueId() {
return queueId;
}
@Override
public int getNumber() {
return (int) queueId;
}
}
// A version of MockRun that will throw an exception if getQueueId or getNumber is called
private static class ExplodingMockRun extends MockRun {
public ExplodingMockRun(long queueId) throws IOException {
super(queueId);
}
@Override
public long getQueueId() {
Assert.fail("Should not get called");
return super.getQueueId();
}
@Override
public int getNumber() {
Assert.fail("Should not get called");
return super.getNumber();
}
}
}