/******************************************************************************* * Copyright (c) 2011, 2015 Frank Appel and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Frank Appel - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.rap.rwt.internal.application; import static org.eclipse.rap.rwt.internal.service.StartupPageTestUtil.getStartupPageTemplate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.atomic.AtomicBoolean; import javax.servlet.ServletContext; import org.eclipse.rap.rwt.application.Application; import org.eclipse.rap.rwt.application.ApplicationConfiguration; import org.eclipse.rap.rwt.internal.lifecycle.DefaultEntryPointFactory; import org.eclipse.rap.rwt.internal.lifecycle.TestEntryPoint; import org.eclipse.rap.rwt.internal.resources.ResourceDirectory; import org.eclipse.rap.rwt.internal.serverpush.ServerPushServiceHandler; import org.eclipse.rap.rwt.internal.service.ServiceManagerImpl; import org.eclipse.rap.rwt.internal.service.StartupPageTestUtil; import org.eclipse.rap.rwt.internal.theme.Theme; import org.eclipse.rap.rwt.internal.theme.ThemeManager; import org.eclipse.rap.rwt.service.ApplicationContextEvent; import org.eclipse.rap.rwt.service.ApplicationContextListener; import org.eclipse.rap.rwt.service.ResourceLoader; import org.eclipse.rap.rwt.service.ServiceHandler; import org.eclipse.rap.rwt.service.SettingStoreFactory; import org.eclipse.rap.rwt.service.UISession; import org.eclipse.rap.rwt.service.UISessionEvent; import org.eclipse.rap.rwt.service.UIThreadListener; import org.eclipse.rap.rwt.testfixture.internal.Fixture; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; public class ApplicationContextImpl_Test { private static final String TEST_RESOURCE = "test-resource"; private static final Object ATTRIBUTE_VALUE = new Object(); private static final String ATTRIBUTE_NAME = "name"; private static final String THEME_ID = "TestTheme"; private static final String STYLE_SHEET = "resources/theme/TestExample.css"; private static final String STYLE_SHEET_CONTRIBUTION = "resources/theme/TestExample2.css"; private static final String SERVICE_HANDLER_ID = "SERVICE_HANDLER_ID"; private SettingStoreFactory settingStoreFactory; private ServiceHandler serviceHandler; private ApplicationContextImpl applicationContext; private ApplicationContextListener appContextListener; private UIThreadListener uiThreadListener; @Before public void setUp() { settingStoreFactory = mock( SettingStoreFactory.class ); serviceHandler = mock( ServiceHandler.class ); appContextListener = mock( ApplicationContextListener.class ); uiThreadListener = mock( UIThreadListener.class ); } @Test public void testApplicationContextSingletons() { applicationContext = new ApplicationContextImpl( null, null ); assertNotNull( applicationContext.getThemeManager() ); assertSame( applicationContext.getThemeManager(), applicationContext.getThemeManager() ); assertNotNull( applicationContext.getPhaseListenerManager() ); assertSame( applicationContext.getPhaseListenerManager(), applicationContext.getPhaseListenerManager() ); assertNotNull( applicationContext.getLifeCycleFactory() ); assertSame( applicationContext.getLifeCycleFactory(), applicationContext.getLifeCycleFactory() ); assertNotNull( applicationContext.getEntryPointManager() ); assertSame( applicationContext.getEntryPointManager(), applicationContext.getEntryPointManager() ); assertNotNull( applicationContext.getResourceFactory() ); assertSame( applicationContext.getResourceFactory(), applicationContext.getResourceFactory() ); assertNotNull( applicationContext.getImageFactory() ); assertSame( applicationContext.getImageFactory(), applicationContext.getImageFactory() ); assertNotNull( applicationContext.getInternalImageFactory() ); assertSame( applicationContext.getInternalImageFactory(), applicationContext.getInternalImageFactory() ); assertNotNull( applicationContext.getImageDataFactory() ); assertSame( applicationContext.getImageDataFactory(), applicationContext.getImageDataFactory() ); assertNotNull( applicationContext.getFontDataFactory() ); assertSame( applicationContext.getFontDataFactory(), applicationContext.getFontDataFactory() ); assertNotNull( applicationContext.getSettingStoreManager() ); assertSame( applicationContext.getSettingStoreManager(), applicationContext.getSettingStoreManager() ); assertNotNull( applicationContext.getServiceManager() ); assertSame( applicationContext.getServiceManager(), applicationContext.getServiceManager() ); assertNotNull( applicationContext.getResourceRegistry() ); assertSame( applicationContext.getResourceRegistry(), applicationContext.getResourceRegistry() ); assertNotNull( applicationContext.getResourceDirectory() ); assertSame( applicationContext.getResourceDirectory(), applicationContext.getResourceDirectory() ); assertNotNull( applicationContext.getResourceManager() ); assertSame( applicationContext.getResourceManager(), applicationContext.getResourceManager() ); assertNotNull( applicationContext.getStartupPage() ); assertSame( applicationContext.getStartupPage(), applicationContext.getStartupPage() ); assertNotNull( applicationContext.getDisplaysHolder() ); assertSame( applicationContext.getDisplaysHolder(), applicationContext.getDisplaysHolder() ); assertNotNull( applicationContext.getTextSizeStorage() ); assertSame( applicationContext.getTextSizeStorage(), applicationContext.getTextSizeStorage() ); assertNotNull( applicationContext.getProbeStore() ); assertSame( applicationContext.getProbeStore(), applicationContext.getProbeStore() ); assertNotNull( applicationContext.getClientSelector() ); assertSame( applicationContext.getClientSelector(), applicationContext.getClientSelector() ); } @Test public void testIsActive_isFalseAfterCreation() { applicationContext = new ApplicationContextImpl( null, null ); assertFalse( applicationContext.isActive() ); } @Test public void testIsActive_isTrueAfterActivate() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); assertTrue( applicationContext.isActive() ); } @Test public void testActivate_initializesSubSystems() { ServletContext servletContext = createServletContext(); applicationContext = new ApplicationContextImpl( createConfiguration(), servletContext ); applicationContext.activate(); checkContextDirectoryHasBeenSet(); checkSettingStoreManagerHasBeenSet(); checkEntryPointsHaveBeenAdded(); checkResourceHasBeenAdded(); checkServiceHandlersHaveBeenAdded(); checkThemeHasBeenAdded(); checkThemableWidgetHasBeenAdded(); checkThemeContributionHasBeenAdded(); checkAttributeHasBeenSet(); checkLifeCycleHasBeenCreated(); checkStartupPageTemplateHasBeenCreated(); checkClientSelectorHasBeenActivated(); } @Test public void testActivate_withDifferentResourceLocation() { File tempDirectory = createTempDirectory(); ServletContext servletContext = createServletContext( tempDirectory ); applicationContext = new ApplicationContextImpl( createConfiguration(), servletContext ); applicationContext.activate(); checkContextDirectoryHasBeenSet( tempDirectory ); } @Test public void testActivate_withDefaultSettingStoreFactory() { ApplicationConfiguration configuration = new ApplicationConfiguration() { @Override public void configure( Application application ) { application.addStyleSheet( THEME_ID, STYLE_SHEET ); } }; ServletContext servletContext = createServletContext(); applicationContext = new ApplicationContextImpl( configuration, servletContext ); applicationContext.activate(); assertTrue( applicationContext.getSettingStoreManager().hasFactory() ); } @Test public void testActivate_canBeCalledTwice() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.activate(); assertTrue( applicationContext.isActive() ); verify( applicationContext, times( 1 ) ).doActivate(); } @Test public void testDeactivate_canBeCalledTwice() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.deactivate(); applicationContext.deactivate(); assertFalse( applicationContext.isActive() ); verify( applicationContext, times( 1 ) ).doDeactivate(); } @Test public void testDeactivate_calledTwice_doesNotCallListenersTwice() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.addApplicationContextListener( appContextListener ); applicationContext.deactivate(); applicationContext.deactivate(); verify( appContextListener, times( 1 ) ).beforeDestroy( any( ApplicationContextEvent.class ) ); } @Test public void testDeactivate_resetsSubSystems() { ServletContext servletContext = createServletContext(); applicationContext = new ApplicationContextImpl( createConfiguration(), servletContext ); applicationContext.activate(); applicationContext.deactivate(); checkEntryPointsHaveBeenRemoved(); checkPhaseListenerHasBeenRemoved(); checkResourceHasBeenRemoved(); checkConfigurationHasBeenReset(); checkServiceHandlerHasBeenRemoved(); checkSettingStoreFactoryHasBeenRemoved(); checkThemeManagerHasBeenReset(); checkApplicationStoreHasBeenReset(); checkLifeCycleHasBeenReset(); checkStartupPageTemplateHasBeenReset(); } @Test public void testSetToServletContext() { ServletContext servletContext = Fixture.createServletContext(); applicationContext = new ApplicationContextImpl( null, servletContext ); applicationContext.attachToServletContext( ); assertSame( applicationContext, ApplicationContextImpl.getFrom( servletContext ) ); } @Test public void testRemoveFromServletContext() { ServletContext servletContext = Fixture.createServletContext(); applicationContext = new ApplicationContextImpl( null, servletContext ); applicationContext.attachToServletContext( ); applicationContext.removeFromServletContext(); assertNull( ApplicationContextImpl.getFrom( servletContext ) ); } @Test( expected = NullPointerException.class ) public void testAddUIThreadListener_failsWithNullArgument() { applicationContext = new ApplicationContextImpl( null, null ); applicationContext.addUIThreadListener( null ); } @Test public void testAddUIThreadListener_addsListener() { applicationContext = createApplicationContextSpy(); applicationContext.addUIThreadListener( uiThreadListener ); UISession uiSession = mock( UISession.class ); InOrder inOrder = inOrder( uiThreadListener ); ArgumentCaptor<UISessionEvent> captor = ArgumentCaptor.forClass( UISessionEvent.class ); applicationContext.notifyEnterUIThread( uiSession ); applicationContext.notifyLeaveUIThread( uiSession ); inOrder.verify( uiThreadListener ).enterUIThread( captor.capture() ); inOrder.verify( uiThreadListener ).leaveUIThread( captor.capture() ); inOrder.verifyNoMoreInteractions(); for( UISessionEvent event : captor.getAllValues() ) { assertSame( uiSession, event.getUISession() ); } } @Test public void testAddUIThreadListener_doesNotAddListenerTwice() { applicationContext = createApplicationContextSpy(); applicationContext.addUIThreadListener( uiThreadListener ); applicationContext.addUIThreadListener( uiThreadListener ); applicationContext.notifyEnterUIThread( mock( UISession.class ) ); verify( uiThreadListener ).enterUIThread( any( UISessionEvent.class ) ); } @Test( expected = NullPointerException.class ) public void testRemoveUIThreadListener_failsWithNullArgument() { applicationContext = new ApplicationContextImpl( null, null ); applicationContext.removeUIThreadListener( null ); } @Test public void testRemoveUIThreadListener_toleratesMissingListener() { applicationContext = createApplicationContextSpy(); applicationContext.removeUIThreadListener( uiThreadListener ); } @Test public void testRemoveUIThreadListener_removesListener() { applicationContext = createApplicationContextSpy(); applicationContext.addUIThreadListener( uiThreadListener ); applicationContext.addUIThreadListener( uiThreadListener ); applicationContext.removeUIThreadListener( uiThreadListener ); applicationContext.notifyEnterUIThread( mock( UISession.class ) ); applicationContext.notifyLeaveUIThread( mock( UISession.class ) ); verify( uiThreadListener, never() ).enterUIThread( any( UISessionEvent.class ) ); verify( uiThreadListener, never() ).leaveUIThread( any( UISessionEvent.class ) ); } @Test( expected = NullPointerException.class ) public void testAddApplicationContextListener_failsWithNullArgument() { applicationContext = new ApplicationContextImpl( null, null ); applicationContext.addApplicationContextListener( null ); } @Test public void testAddApplicationContextListener_addsListener() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.addApplicationContextListener( appContextListener ); applicationContext.deactivate(); verify( appContextListener ).beforeDestroy( any( ApplicationContextEvent.class ) ); } @Test public void testAddApplicationContextListener_doesNotAddListenerTwice() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.addApplicationContextListener( appContextListener ); applicationContext.addApplicationContextListener( appContextListener ); applicationContext.deactivate(); verify( appContextListener ).beforeDestroy( any( ApplicationContextEvent.class ) ); } @Test public void testAddApplicationContextListener_returnsTrueWhenActive() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); boolean result = applicationContext.addApplicationContextListener( appContextListener ); assertTrue( result ); } @Test public void testAddApplicationContextListener_returnsTrueEvenIfAlreadyAdded() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.addApplicationContextListener( appContextListener ); boolean result = applicationContext.addApplicationContextListener( appContextListener ); assertTrue( result ); } @Test public void testAddApplicationContextListener_returnsFalseWhenInactive() { applicationContext = createApplicationContextSpy(); boolean result = applicationContext.addApplicationContextListener( appContextListener ); assertFalse( result ); } @Test( expected = NullPointerException.class ) public void testRemoveApplicationContextListener_failsWithNullArgument() { applicationContext = new ApplicationContextImpl( null, null ); applicationContext.removeApplicationContextListener( null ); } @Test public void testRemoveApplicationContextListener_toleratesMissingListener() { applicationContext = createApplicationContextSpy(); applicationContext.removeApplicationContextListener( appContextListener ); } @Test public void testRemoveApplicationContextListener_removesListener() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.addApplicationContextListener( appContextListener ); applicationContext.removeApplicationContextListener( appContextListener ); applicationContext.deactivate(); verify( appContextListener, never() ).beforeDestroy( any( ApplicationContextEvent.class ) ); } @Test public void testRemoveApplicationContextListener_returnsTrueWhenActive() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.addApplicationContextListener( appContextListener ); boolean result = applicationContext.removeApplicationContextListener( appContextListener ); assertTrue( result ); } @Test public void testRemoveApplicationContextListener_returnsTrueEvenIfMissing() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); boolean result = applicationContext.removeApplicationContextListener( appContextListener ); assertTrue( result ); } @Test public void testRemoveApplicationContextListener_returnsFalseWhenInActive() { applicationContext = createApplicationContextSpy(); applicationContext.addApplicationContextListener( appContextListener ); boolean result = applicationContext.removeApplicationContextListener( appContextListener ); assertFalse( result ); } @Test public void testBeforeDestroyEvent() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); applicationContext.addApplicationContextListener( appContextListener ); applicationContext.deactivate(); ArgumentCaptor<ApplicationContextEvent> captor = ArgumentCaptor.forClass( ApplicationContextEvent.class ); verify( appContextListener ).beforeDestroy( captor.capture() ); assertSame( applicationContext, captor.getValue().getSource() ); assertSame( applicationContext, captor.getValue().getApplicationContext() ); } @Test public void testBeforeDestroyEvent_hasActiveApplicationContext() { applicationContext = createApplicationContextSpy(); applicationContext.activate(); final AtomicBoolean applicationContextActive = new AtomicBoolean(); ApplicationContextListener listener = new ApplicationContextListener() { @Override public void beforeDestroy( ApplicationContextEvent event ) { boolean active = ( ( ApplicationContextImpl )event.getApplicationContext() ).isActive(); applicationContextActive.set( active ); } }; applicationContext.addApplicationContextListener( listener ); applicationContext.deactivate(); assertTrue( applicationContextActive.get() ); } @Test public void testExceptionHandlingInApplicationContextListeners() { ServletContext servletContext = createServletContext(); applicationContext = new ApplicationContextImpl( createConfiguration(), servletContext ); applicationContext.activate(); applicationContext.addApplicationContextListener( new ApplicationContextListener() { @Override public void beforeDestroy( ApplicationContextEvent event ) { throw new RuntimeException(); } } ); applicationContext.deactivate(); verify( servletContext ).log( anyString(), any( RuntimeException.class ) ); } private File createTempDirectory() { File tempDir = new File( Fixture.TEMP_DIR, ApplicationContextImpl_Test.class.getName() ); if( !tempDir.mkdir() ) { throw new RuntimeException( "Failed to create temp directory" ); } return tempDir; } private ApplicationConfiguration createConfiguration() { return new ApplicationConfiguration() { @Override public void configure( Application application ) { application.addEntryPoint( "/entryPoint", TestEntryPoint.class, null ); DefaultEntryPointFactory factory = new DefaultEntryPointFactory( TestEntryPoint.class ); application.addEntryPoint( "/entryPointViaFactory", factory, null ); application.addResource( TEST_RESOURCE, new TestResourceLoader() ); application.setSettingStoreFactory( settingStoreFactory ); application.addServiceHandler( SERVICE_HANDLER_ID, serviceHandler ); application.addStyleSheet( THEME_ID, STYLE_SHEET ); application.addStyleSheet( THEME_ID, STYLE_SHEET_CONTRIBUTION ); application.addThemeableWidget( TestWidget.class ); application.setAttribute( ATTRIBUTE_NAME, ATTRIBUTE_VALUE ); } }; } private void checkLifeCycleHasBeenCreated() { assertNotNull( applicationContext.getLifeCycleFactory().getLifeCycle() ); } private void checkStartupPageTemplateHasBeenCreated() { assertNotNull( getStartupPageTemplate( applicationContext.getStartupPage() ) ); } private void checkClientSelectorHasBeenActivated() { try { applicationContext.getClientSelector().activate(); fail(); } catch( IllegalStateException expected ) { assertEquals( "ClientSelector already activated", expected.getMessage() ); } } private void checkAttributeHasBeenSet() { Object attribute = applicationContext.getAttribute( ATTRIBUTE_NAME ); assertSame( ATTRIBUTE_VALUE, attribute ); } private void checkThemeContributionHasBeenAdded() { Theme theme = applicationContext.getThemeManager().getTheme( THEME_ID ); assertEquals( 18, theme.getValuesMap().getAllValues().length ); } private void checkThemableWidgetHasBeenAdded() { assertNotNull( applicationContext.getThemeManager().getThemeableWidget( TestWidget.class ) ); } private void checkThemeHasBeenAdded() { assertNotNull( applicationContext.getThemeManager().getTheme( THEME_ID ) ); } private void checkServiceHandlersHaveBeenAdded() { ServiceManagerImpl serviceManager = applicationContext.getServiceManager(); assertSame( serviceHandler, serviceManager.getServiceHandler( SERVICE_HANDLER_ID ) ); assertNotNull( serviceManager.getServiceHandler( ServerPushServiceHandler.HANDLER_ID ) ); } private void checkResourceHasBeenAdded() { assertTrue( applicationContext.getResourceManager().isRegistered( TEST_RESOURCE ) ); } private void checkEntryPointsHaveBeenAdded() { assertEquals( 2, applicationContext.getEntryPointManager().getServletPaths().size() ); } private void checkSettingStoreManagerHasBeenSet() { assertTrue( applicationContext.getSettingStoreManager().hasFactory() ); } private void checkContextDirectoryHasBeenSet() { File webContextDir = Fixture.WEB_CONTEXT_DIR; checkContextDirectoryHasBeenSet( webContextDir ); } private void checkContextDirectoryHasBeenSet( File contextDirectory ) { ResourceDirectory resourceDirectory = applicationContext.getResourceDirectory(); assertEquals( contextDirectory, resourceDirectory.getDirectory().getParentFile() ); } private void checkEntryPointsHaveBeenRemoved() { assertEquals( 0, applicationContext.getEntryPointManager().getServletPaths().size() ); } private void checkPhaseListenerHasBeenRemoved() { assertEquals( 0, applicationContext.getPhaseListenerManager().getPhaseListeners().length ); } private void checkResourceHasBeenRemoved() { assertEquals( 0, applicationContext.getResourceRegistry().getResourceRegistrations().length ); } private void checkConfigurationHasBeenReset() { try { applicationContext.getResourceDirectory().getDirectory(); fail(); } catch( IllegalStateException exception ) { } } private void checkServiceHandlerHasBeenRemoved() { ServiceManagerImpl serviceManager = applicationContext.getServiceManager(); assertNull( serviceManager.getServiceHandler( SERVICE_HANDLER_ID ) ); } private void checkSettingStoreFactoryHasBeenRemoved() { assertFalse( applicationContext.getSettingStoreManager().hasFactory() ); } private void checkThemeManagerHasBeenReset() { ThemeManager themeManager = applicationContext.getThemeManager(); assertEquals( 1, themeManager.getRegisteredThemeIds().length ); assertEquals( ThemeManager.FALLBACK_THEME_ID, themeManager.getRegisteredThemeIds()[ 0 ] ); } private void checkApplicationStoreHasBeenReset() { Object attribute = applicationContext.getAttribute( ATTRIBUTE_NAME ); assertNull( attribute ); } private void checkLifeCycleHasBeenReset() { assertNull( applicationContext.getLifeCycleFactory().getLifeCycle() ); } private void checkStartupPageTemplateHasBeenReset() { assertNull( StartupPageTestUtil.getStartupPageTemplate( applicationContext.getStartupPage() ) ); } private static ApplicationContextImpl createApplicationContextSpy() { return spy( new ApplicationContextImpl( null, null ) { @Override void doActivate() { } @Override void doDeactivate() { } } ); } private static ServletContext createServletContext() { return createServletContext( Fixture.WEB_CONTEXT_DIR ); } private static ServletContext createServletContext( File contextDirectory ) { ServletContext servletContext = mock( ServletContext.class ); if( contextDirectory != null ) { when( servletContext.getAttribute( ApplicationConfiguration.RESOURCE_ROOT_LOCATION ) ) .thenReturn( contextDirectory.toString() ); } return servletContext; } private static class TestWidget extends Composite { TestWidget( Composite parent ) { super( parent, SWT.NONE ); } } private static class TestResourceLoader implements ResourceLoader { @Override public InputStream getResourceAsStream( String resourceName ) throws IOException { return mock( InputStream.class ); } } }