Java tutorial
/** * JBackup is a software managing backups. * * Copyright (C) 2013-2014 Fabien DUMINY (fabien [dot] duminy [at] webmails [dot] com) * * JBackup is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * JBackup is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package fr.duminy.jbackup.swing; import com.google.common.base.Supplier; import fr.duminy.components.swing.AbstractSwingTest; import fr.duminy.jbackup.core.util.LogRule; import org.fest.swing.core.ComponentLookupScope; import org.fest.swing.edt.GuiActionRunner; import org.fest.swing.edt.GuiQuery; import org.fest.swing.edt.GuiTask; import org.fest.swing.exception.ComponentLookupException; import org.fest.swing.fixture.JButtonFixture; import org.fest.swing.fixture.JPanelFixture; import org.fest.swing.fixture.JProgressBarFixture; import org.junit.Rule; import org.junit.Test; import javax.swing.border.TitledBorder; import java.awt.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static java.lang.String.format; import static org.apache.commons.io.FileUtils.byteCountToDisplaySize; import static org.assertj.core.api.Assertions.assertThat; /** * Tests for class {@link ProgressPanel}. */ public class ProgressPanelTest extends AbstractSwingTest { private static final String TITLE = "MyTask"; private static final String CONFIGURATION_NAME = "NotChecked"; private ProgressPanel panel; @Rule public final LogRule logRule = new LogRule(); @Override public void onSetUp() { super.onSetUp(); try { panel = buildAndShowWindow(new Supplier<ProgressPanel>() { @Override public ProgressPanel get() { return new ProgressPanel(TITLE); } }); } catch (Exception e) { throw new RuntimeException(e); } } @Test public void testInit() throws Exception { // check state before call to setTask(Future). checkState(TaskState.NOT_STARTED, null, null, null, null); final TestableTask task = new TestableTask(); panel.setTask(task); // check state after call to setTask(Future). checkState(TaskState.TASK_DEFINED, null, null, null, task); } @Test public void testCancel() throws Exception { final TestableTask task = new TestableTask(); panel.setTask(task); final long actualValue = 1; final long maxValue = 10L; GuiActionRunner.execute(new GuiTask() { protected void executeInEDT() { panel.taskStarted(CONFIGURATION_NAME); panel.totalSizeComputed(CONFIGURATION_NAME, maxValue); panel.progress(CONFIGURATION_NAME, actualValue); } }); checkState(TaskState.PROGRESS, actualValue, maxValue, null, task); } @Test public void testTaskStarted() { GuiActionRunner.execute(new GuiTask() { protected void executeInEDT() { panel.taskStarted(CONFIGURATION_NAME); } }); checkState(TaskState.STARTED, null, null, null, null); } @Test public void testTotalSizeComputed_bigSize() throws Exception { testTotalSizeComputed(Integer.MAX_VALUE + 123L); } @Test public void testTotalSizeComputed_smallSize() throws Exception { testTotalSizeComputed(123); } private void testTotalSizeComputed(final long maxValue) throws Exception { GuiActionRunner.execute(new GuiTask() { protected void executeInEDT() { panel.taskStarted(CONFIGURATION_NAME); panel.totalSizeComputed(CONFIGURATION_NAME, maxValue); } }); checkState(TaskState.TOTAL_SIZE_COMPUTED, 0L, maxValue, null, null); } @Test public void testProgress_bigSize() throws Exception { testProgress(Integer.MAX_VALUE + 1L, 1000L * (Integer.MAX_VALUE + 1L)); } @Test public void testProgress_smallSize() throws Exception { testProgress(10, 123); } private void testProgress(final long value, final long maxValue) throws Exception { GuiActionRunner.execute(new GuiTask() { protected void executeInEDT() { panel.taskStarted(CONFIGURATION_NAME); panel.totalSizeComputed(CONFIGURATION_NAME, maxValue); panel.progress(CONFIGURATION_NAME, value); } }); checkState(TaskState.PROGRESS, value, maxValue, null, null); } @Test public void testTaskFinished_withoutError() { testTaskFinished(null, false); } @Test public void testTaskFinished_withError_afterTotalSizeComputed() { testTaskFinished(new Exception("Something went wrong"), false); } @Test public void testTaskFinished_withError_beforeTotalSizeComputed() { testTaskFinished(new Exception("Something went wrong"), true); } @Test public void testTaskFinished_withErrorAndNullMessage() { testTaskFinished(new Exception(), false); } private void testTaskFinished(final Throwable error, final boolean beforeTotalSizeComputed) { final TestableTask task = GuiActionRunner.execute(new GuiQuery<TestableTask>() { protected TestableTask executeInEDT() { final TestableTask task = new TestableTask(); panel.setTask(task); panel.taskStarted(CONFIGURATION_NAME); if ((error == null) || ((error != null) && !beforeTotalSizeComputed)) { panel.totalSizeComputed(CONFIGURATION_NAME, 10); panel.progress(CONFIGURATION_NAME, 0); } panel.taskFinished(CONFIGURATION_NAME, error); if (error != null) { task.setException(error); } return task; } }); checkState(TaskState.FINISHED, null, null, error, task); } public static void assertThatPanelHasTitle(ProgressPanel panel, String expectedTitle) { assertThat(((TitledBorder) panel.getBorder()).getTitle()).isEqualTo(expectedTitle); } private void checkState(TaskState taskState, Long value, Long maxValue, Throwable error, Future<?> task) { assertThat(panel.getBorder()).isExactlyInstanceOf(TitledBorder.class); assertThatPanelHasTitle(panel, TITLE); JPanelFixture progressPanel = new JPanelFixture(robot(), panel); robot().settings().componentLookupScope(ComponentLookupScope.ALL); JProgressBarFixture progressBar = progressPanel.progressBar(); robot().settings().componentLookupScope(ComponentLookupScope.SHOWING_ONLY); String expectedMessage; final boolean taskInProgress; switch (taskState) { case NOT_STARTED: taskInProgress = false; progressBar.requireIndeterminate().requireText("Not started"); assertThat(panel.isFinished()).as("isFinished").isFalse(); break; case TASK_DEFINED: taskInProgress = false; break; case STARTED: taskInProgress = (task != null); progressBar.requireIndeterminate().requireText("Estimating total size"); assertThat(panel.isFinished()).as("isFinished").isFalse(); break; case TOTAL_SIZE_COMPUTED: case PROGRESS: taskInProgress = (task != null); int iValue; int iMaxValue; if (maxValue > Integer.MAX_VALUE) { iValue = Utils.toInteger(value, maxValue); iMaxValue = Integer.MAX_VALUE; } else { iValue = value.intValue(); iMaxValue = maxValue.intValue(); } expectedMessage = format("%s/%s written (%1.2f %%)", byteCountToDisplaySize(value), byteCountToDisplaySize(maxValue), Utils.percent(value, maxValue)); progressBar.requireDeterminate().requireValue(iValue).requireText(expectedMessage); assertThat(progressBar.component().getMinimum()).isEqualTo(0); assertThat(progressBar.component().getMaximum()).isEqualTo(iMaxValue); assertThat(panel.isFinished()).as("isFinished").isFalse(); break; case FINISHED: default: taskInProgress = false; if (error == null) { progressBar.requireDeterminate().requireText("Finished"); } else { expectedMessage = error.getMessage(); if (expectedMessage == null) { expectedMessage = error.getClass().getSimpleName(); } progressBar.requireDeterminate().requireText("Error : " + expectedMessage); } assertThat(panel.isFinished()).as("isFinished").isTrue(); break; } Container parent = null; if (!TaskState.FINISHED.equals(taskState)) { // checks progress panel is visible parent = panel.getParent(); assertThat(parent).isNotNull(); assertThat(parent.getComponents()).contains(panel); } if (taskInProgress) { assertThat(panel.isFinished()).isFalse(); assertThat(task.isCancelled()).as("task cancelled").isFalse(); // cancel the task JButtonFixture cancelButton = progressPanel.button(); cancelButton.requireText("").requireToolTip("Cancel the task"); assertThat(cancelButton.component().getIcon()).isNotNull(); cancelButton.click(); // checks progress panel is not visible assertThat(panel.isFinished()).isTrue(); assertThat(panel.getParent()).isNull(); assertThat(parent.getComponents()).doesNotContain(panel); assertThat(task.isCancelled()).as("task cancelled").isTrue(); assertThat(((TestableTask) task).getMayInterruptIfRunning()).as("MayInterruptIfRunning").isFalse(); } else { // check no cancel button is visible if the task has been defined requireCancelButton(progressPanel, taskState == TaskState.TASK_DEFINED); } } private void requireCancelButton(JPanelFixture progressPanel, boolean taskDefined) { boolean buttonVisible; try { progressPanel.button(); buttonVisible = true; } catch (ComponentLookupException e) { // ok buttonVisible = false; } assertThat(buttonVisible).as("cancel button visible").isEqualTo(taskDefined); } private static enum TaskState { NOT_STARTED, TASK_DEFINED, STARTED, TOTAL_SIZE_COMPUTED, PROGRESS, FINISHED; } private static class TestableTask implements Future<Object> { private TaskState state = TaskState.NOT_STARTED; private boolean cancelled = false; private Boolean mayInterruptIfRunning; public void setException(Throwable error) { // completeExceptionally(error); } @Override public boolean cancel(boolean mayInterruptIfRunning) { cancelled = true; this.mayInterruptIfRunning = mayInterruptIfRunning; return true; } @Override public boolean isCancelled() { return cancelled; } public Boolean getMayInterruptIfRunning() { return mayInterruptIfRunning; } @Override public boolean isDone() { return false; } @Override public Object get() throws InterruptedException, ExecutionException { return null; } @Override public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return null; } } }