/* * Copyright (c) 2010 Lockheed Martin Corporation * * 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 org.eurekastreams.web.client.ui; import java.util.Date; import org.eurekastreams.commons.client.ActionProcessor; import org.eurekastreams.web.client.AnonymousClassInterceptor; import org.eurekastreams.web.client.ui.TimerFactory.EventedTimer; import org.jmock.Expectations; import org.jmock.States; import org.jmock.integration.junit4.JUnit4Mockery; import org.jmock.lib.legacy.ClassImposteriser; import org.junit.Before; import org.junit.Test; import com.google.gwt.junit.GWTMockUtilities; /** * Tests {@link PeriodicEventManager}. */ public class PeriodicEventManagerTest { /** Test data. */ private static final int IDLE_TIMEOUT = 15; /** Obvious to everyone but checkstyle. */ private static final long MS_PER_S = 1000; /** Used for mocking objects. */ private JUnit4Mockery context = new JUnit4Mockery() { { setImposteriser(ClassImposteriser.INSTANCE); GWTMockUtilities.disarm(); } }; /** Fixture: timer factory. */ private TimerFactory timerFactory = context.mock(TimerFactory.class); /** Fixture: timer. */ private EventedTimer timer = context.mock(EventedTimer.class); /** Fixture: action processor. */ private ActionProcessor actionProcessor = context.mock(ActionProcessor.class); /** Fixture: registered action. */ private TimerHandler action1 = context.mock(TimerHandler.class, "action1"); /** Fixture: registered action. */ private TimerHandler action2 = context.mock(TimerHandler.class, "action2"); /** Interceptor. */ private AnonymousClassInterceptor<TimerHandler> timerHandlerInt; /** SUT. */ private PeriodicEventManager sut; /** Time to use for "now". */ private Date now; /** * Simulates time passing by one second. */ private void incrementTime() { now = new Date(now.getTime() + MS_PER_S); } /** * Setup before each test. */ @Before public void setUp() { now = new Date(); timerHandlerInt = new AnonymousClassInterceptor<TimerHandler>(); context.checking(new Expectations() { { oneOf(timerFactory).createTimer(with(any(TimerHandler.class))); will(doAll(timerHandlerInt, returnValue(timer))); } }); sut = new PeriodicEventManager(IDLE_TIMEOUT, timerFactory, actionProcessor) { @Override protected Date timeNow() { return now; } }; } /** * Starts the timer. */ private void setupToRun() { final States state = context.states("setupSegregator").startsAs("setup"); context.checking(new Expectations() { { oneOf(timer).scheduleRepeating(with(any(Integer.class))); when(state.is("setup")); } }); sut.start(); state.become(""); incrementTime(); } /** * Tests registration (by seeing handler invoked on timer). */ @Test public void testRegister() { sut.register(action1, 0); setupToRun(); context.checking(new Expectations() { { oneOf(action1).run(); oneOf(actionProcessor).setQueueRequests(true); oneOf(actionProcessor).fireQueuedRequests(); oneOf(actionProcessor).setQueueRequests(false); } }); timerHandlerInt.getObject().run(); context.assertIsSatisfied(); } /** * Tests deregistration (by seeing handler not invoked on timer). */ @Test public void testDeregister() { sut.register(action1, 0); sut.register(action2, 0); setupToRun(); sut.deregister(action1); sut.deregister(action2); timerHandlerInt.getObject().run(); context.assertIsSatisfied(); } /** * Tests timing of periodic actions. */ @Test public void testTiming() { setupToRun(); // At this point, time = 1 // So action1 should run at: 3, 5, 7, etc. // So action2 should run at: 4, 7, 10 sut.register(action1, 2); sut.register(action2, 3); TimerHandler hdlr = timerHandlerInt.getObject(); final States state = context.states("time").startsAs("1"); context.checking(new Expectations() { { oneOf(action1).run(); when(state.is("3")); oneOf(action1).run(); when(state.is("5")); oneOf(action1).run(); when(state.is("7")); oneOf(action1).run(); when(state.is("9")); oneOf(action1).run(); when(state.is("11")); oneOf(action2).run(); when(state.is("4")); oneOf(action2).run(); when(state.is("7")); oneOf(action2).run(); when(state.is("10")); allowing(actionProcessor).setQueueRequests(true); allowing(actionProcessor).fireQueuedRequests(); allowing(actionProcessor).setQueueRequests(false); } }); for (int i = 2; i <= 9 + 3; i++) { incrementTime(); state.become(Integer.toString(i)); hdlr.run(); } context.assertIsSatisfied(); } /** * Tests system becoming idle. */ @Test public void testBecomingIdle() { setupToRun(); // At this point, time = 1 // So action1 should run at: 1, 2, 3, etc. // Will become idle at time = 15 sut.register(action1, 0); TimerHandler hdlr = timerHandlerInt.getObject(); final States state = context.states("time").startsAs("notLast"); context.checking(new Expectations() { { exactly(IDLE_TIMEOUT - 1).of(action1).run(); when(state.is("notLast")); oneOf(timer).cancel(); when(state.is("last")); allowing(actionProcessor).setQueueRequests(true); allowing(actionProcessor).fireQueuedRequests(); allowing(actionProcessor).setQueueRequests(false); } }); for (int i = 1; i <= IDLE_TIMEOUT; i++) { if (i == IDLE_TIMEOUT) { state.become("last"); } hdlr.run(); incrementTime(); } context.assertIsSatisfied(); } /** * Tests activity preventing idleness. */ @Test public void testActivityPreventIdle() { setupToRun(); final int activityAtTime = 3; // At this point, time = 1 // Will become idle at time = 15, except activty at 3 will bump it to 18 TimerHandler hdlr = timerHandlerInt.getObject(); final States state = context.states("time").startsAs("notLast"); context.checking(new Expectations() { { oneOf(timer).cancel(); when(state.is("last")); } }); for (int i = 1; i <= IDLE_TIMEOUT + activityAtTime; i++) { if (i == IDLE_TIMEOUT + activityAtTime) { state.become("last"); } if (i == activityAtTime) { sut.userActivityDetected(); } hdlr.run(); incrementTime(); } context.assertIsSatisfied(); } /** * Tests activity restarting from idleness. */ @Test public void testActivityRestartFromIdle() { setupToRun(); TimerHandler hdlr = timerHandlerInt.getObject(); // At this point, time = 1 // Will become idle at time = 15 final States state = context.states("time").startsAs("makeIdle"); context.checking(new Expectations() { { oneOf(timer).cancel(); when(state.is("makeIdle")); } }); for (int i = 1; i <= IDLE_TIMEOUT; i++) { if (i == IDLE_TIMEOUT) { state.become("makeIdle"); } hdlr.run(); incrementTime(); } // Now time = 16 and system is idle context.checking(new Expectations() { { oneOf(timer).scheduleRepeating(with(any(Integer.class))); } }); sut.userActivityDetected(); context.assertIsSatisfied(); } }