| /******************************************************************************* |
| * Copyright (c) 2011, 2012 EclipseSource 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: |
| * EclipseSource - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.rap.rwt.cluster.test; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNotSame; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.Serializable; |
| import java.util.Arrays; |
| import java.util.Collection; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.http.HttpSession; |
| |
| import org.eclipse.rap.rwt.RWT; |
| import org.eclipse.rap.rwt.application.EntryPoint; |
| import org.eclipse.rap.rwt.cluster.test.entrypoints.AsyncExecEntryPoint; |
| import org.eclipse.rap.rwt.cluster.test.entrypoints.ButtonEntryPoint; |
| import org.eclipse.rap.rwt.cluster.test.entrypoints.DNDEntryPoint; |
| import org.eclipse.rap.rwt.cluster.test.entrypoints.DialogEntryPoint; |
| import org.eclipse.rap.rwt.cluster.test.entrypoints.ImageEntryPoint; |
| import org.eclipse.rap.rwt.cluster.test.entrypoints.ResourcesEntryPoint; |
| import org.eclipse.rap.rwt.cluster.test.entrypoints.TimerExecEntryPoint; |
| import org.eclipse.rap.rwt.cluster.testfixture.ClusterTestHelper; |
| import org.eclipse.rap.rwt.cluster.testfixture.client.RWTClient; |
| import org.eclipse.rap.rwt.cluster.testfixture.client.Response; |
| import org.eclipse.rap.rwt.cluster.testfixture.server.IServletEngine; |
| import org.eclipse.rap.rwt.cluster.testfixture.server.IServletEngineCluster; |
| import org.eclipse.rap.rwt.cluster.testfixture.server.IServletEngineFactory; |
| import org.eclipse.rap.rwt.cluster.testfixture.server.JettyFactory; |
| import org.eclipse.rap.rwt.cluster.testfixture.server.TomcatFactory; |
| import org.eclipse.rap.rwt.internal.application.ApplicationContextImpl; |
| import org.eclipse.rap.rwt.internal.application.ApplicationContextUtil; |
| import org.eclipse.rap.rwt.internal.service.UISessionImpl; |
| import org.eclipse.rap.rwt.lifecycle.WidgetUtil; |
| import org.eclipse.rap.rwt.service.UISession; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.ImageData; |
| import org.eclipse.swt.graphics.ImageLoader; |
| import org.eclipse.swt.internal.widgets.IDisplayAdapter; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| |
| @SuppressWarnings("restriction") |
| @RunWith( Parameterized.class ) |
| public class SessionFailover_Test { |
| |
| private final IServletEngineFactory servletEngineFactory; |
| private IServletEngineCluster cluster; |
| private IServletEngine primary; |
| private IServletEngine secondary; |
| private RWTClient client; |
| |
| @Parameters |
| public static Collection<Object[]> getParameters() { |
| return Arrays.asList( new Object[][] { { new JettyFactory() }, { new TomcatFactory() } } ); |
| } |
| |
| public SessionFailover_Test( IServletEngineFactory servletEngineFactory ) { |
| this.servletEngineFactory = servletEngineFactory; |
| } |
| |
| @Before |
| public void setUp() throws Exception { |
| ClusterTestHelper.enableUITests( true ); |
| cluster = servletEngineFactory.createServletEngineCluster(); |
| primary = cluster.addServletEngine(); |
| secondary = cluster.addServletEngine(); |
| client = new RWTClient( primary ); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| cluster.stop(); |
| } |
| |
| @Test |
| public void testButtonEntryPoint() throws Exception { |
| initializeClient( ButtonEntryPoint.class ); |
| // Click center button four times on primary |
| clickCenterButton( 1, 4 ); |
| // Click center button four times on secondary |
| cluster.removeServletEngine( primary ); |
| client.changeServletEngine( secondary ); |
| clickCenterButton( 5, 8 ); |
| // Number of sessions |
| assertEquals( 1, primary.getSessions().length ); |
| assertEquals( 1, secondary.getSessions().length ); |
| // HttpSessions |
| HttpSession primarySession = ClusterTestHelper.getFirstHttpSession( primary ); |
| assertSessionIsIntact( primarySession, client ); |
| HttpSession secondarySession = ClusterTestHelper.getFirstHttpSession( secondary ); |
| assertSessionIsIntact( secondarySession, client ); |
| assertEquals( primarySession.getId(), secondarySession.getId() ); |
| // Displays |
| Display primaryDisplay = ClusterTestHelper.getSessionDisplay( primarySession ); |
| Display secondaryDisplay = ClusterTestHelper.getSessionDisplay( secondarySession ); |
| assertNotSame( primaryDisplay, secondaryDisplay ); |
| } |
| |
| @Test |
| public void testResourcesEntryPoint() throws Exception { |
| initializeClient( ResourcesEntryPoint.class ); |
| |
| client.changeServletEngine( secondary ); |
| client.sendDisplayResizeRequest( 400, 600 ); |
| |
| prepareExamination(); |
| Shell primaryShell = getFirstShell( primary ); |
| Shell secondaryShell = getFirstShell( secondary ); |
| Font primaryFont = primaryShell.getFont(); |
| Font secondaryFont = secondaryShell.getFont(); |
| assertEquals( primaryFont, secondaryFont ); |
| assertNotSame( primaryFont, secondaryFont ); |
| assertSame( primaryShell.getDisplay(), primaryFont.getDevice() ); |
| assertSame( secondaryShell.getDisplay(), secondaryFont.getDevice() ); |
| } |
| |
| @Test |
| public void testImageEntryPoint() throws Exception { |
| initializeClient( ImageEntryPoint.class ); |
| client.sendResourceRequest( ImageEntryPoint.imagePath ); |
| |
| client.changeServletEngine( secondary ); |
| client.sendDisplayResizeRequest( 400, 600 ); |
| |
| prepareExamination(); |
| Shell primaryShell = getFirstShell( primary ); |
| Shell secondaryShell = getFirstShell( secondary ); |
| Image primaryImage = primaryShell.getImage(); |
| Image secondaryImage = secondaryShell.getImage(); |
| assertImageDataEquals( primaryImage.getImageData(), secondaryImage.getImageData() ); |
| assertNotSame( primaryImage, secondaryImage ); |
| assertSame( primaryShell.getDisplay(), primaryImage.getDevice() ); |
| assertSame( secondaryShell.getDisplay(), secondaryImage.getDevice() ); |
| } |
| |
| @Test |
| public void testAsyncExecEntryPoint() throws Exception { |
| initializeClient( AsyncExecEntryPoint.class ); |
| AsyncExecEntryPoint.scheduleAsyncRunnable( getFirstDisplay( primary ) ); |
| |
| cluster.removeServletEngine( primary ); |
| client.changeServletEngine( secondary ); |
| client.sendDisplayResizeRequest( 100, 100 ); |
| |
| prepareExamination(); |
| UISession secondaryUiSession = ClusterTestHelper.getFirstUISession( secondary ); |
| assertTrue( AsyncExecEntryPoint.wasRunnableExecuted( secondaryUiSession ) ); |
| } |
| |
| @Test |
| public void testSyncExecEntryPoint() throws Exception { |
| initializeClient( AsyncExecEntryPoint.class ); |
| AsyncExecEntryPoint.scheduleSyncRunnable( getFirstDisplay( primary ) ); |
| |
| cluster.removeServletEngine( primary ); |
| client.changeServletEngine( secondary ); |
| client.sendDisplayResizeRequest( 100, 100 ); |
| |
| prepareExamination(); |
| UISession secondaryUiSession = ClusterTestHelper.getFirstUISession( secondary ); |
| assertTrue( AsyncExecEntryPoint.wasRunnableExecuted( secondaryUiSession ) ); |
| } |
| |
| @Test |
| public void testTimerExecEntryPoint() throws Exception { |
| initializeClient( TimerExecEntryPoint.class ); |
| |
| cluster.removeServletEngine( primary ); |
| prepareExamination( primary ); |
| disposeDisplay( getFirstDisplay( primary ) ); |
| client.changeServletEngine( secondary ); |
| Thread.sleep( TimerExecEntryPoint.TIMER_DELAY * 2 ); |
| client.sendDisplayResizeRequest( 100, 100 ); |
| |
| prepareExamination( secondary ); |
| UISession primaryUiSession = ClusterTestHelper.getFirstUISession( primary ); |
| UISession secondaryUiSession = ClusterTestHelper.getFirstUISession( secondary ); |
| assertFalse( TimerExecEntryPoint.wasRunnableExecuted( primaryUiSession ) ); |
| assertTrue( TimerExecEntryPoint.wasRunnableExecuted( secondaryUiSession ) ); |
| } |
| |
| @Test |
| public void testDNDEntryPoint() throws Exception { |
| initializeClient( DNDEntryPoint.class ); |
| client.sendDragStartRequest( DNDEntryPoint.ID_SOURCE_LABEL ); |
| |
| cluster.removeServletEngine( primary ); |
| client.changeServletEngine( secondary ); |
| |
| client.sendDragFinishedRequest( DNDEntryPoint.ID_SOURCE_LABEL, DNDEntryPoint.ID_TARGET_LABEL ); |
| |
| prepareExamination( secondary ); |
| UISession secondaryUiSession = ClusterTestHelper.getFirstUISession( secondary ); |
| assertTrue( DNDEntryPoint.isDragFinished( secondaryUiSession ) ); |
| assertTrue( DNDEntryPoint.isDropFinished( secondaryUiSession ) ); |
| } |
| |
| @Test |
| public void testDialogEntryPoint() throws Exception { |
| initializeClient( DialogEntryPoint.class ); |
| cluster.removeServletEngine( primary ); |
| prepareExamination( primary ); |
| Shell dialogShell = getFirstDisplay( primary ).getShells()[ 1 ]; |
| String dialogShellId = WidgetUtil.getId( dialogShell ); |
| |
| client.changeServletEngine( secondary ); |
| client.sendShellCloseRequest( dialogShellId ); |
| |
| prepareExamination( secondary ); |
| UISession uiSession = ClusterTestHelper.getFirstUISession( secondary ); |
| assertEquals( 1, getFirstDisplay( secondary ).getShells().length ); |
| assertEquals( SWT.CANCEL, DialogEntryPoint.getDialogReturnCode( uiSession ) ); |
| } |
| |
| private void initializeClient( Class<? extends EntryPoint> entryPoint ) throws Exception { |
| cluster.start( entryPoint ); |
| client.sendStartupRequest(); |
| client.sendInitializationRequest(); |
| } |
| |
| private static void assertImageDataEquals( ImageData expected, ImageData actual ) { |
| byte[] expectedBytes = getImageBytes( expected ); |
| byte[] actualBytes = getImageBytes( actual ); |
| assertEquals( expectedBytes.length, actualBytes.length ); |
| for( int i = 0; i < actualBytes.length; i++ ) { |
| assertEquals( expectedBytes[ i ], actualBytes[ i ] ); |
| } |
| } |
| |
| private static byte[] getImageBytes( ImageData imageData ) { |
| ImageLoader imageLoader = new ImageLoader(); |
| imageLoader.data = new ImageData[] { imageData }; |
| ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| imageLoader.save( outputStream, SWT.IMAGE_PNG ); |
| return outputStream.toByteArray(); |
| } |
| |
| private void prepareExamination() { |
| prepareExamination( primary ); |
| prepareExamination( secondary ); |
| } |
| |
| private static void prepareExamination( IServletEngine servletEngine ) { |
| attachApplicationContextToSession( servletEngine ); |
| attachCurrentThreadToDisplay( servletEngine ); |
| } |
| |
| private static void disposeDisplay( final Display display ) { |
| if( display != null ) { |
| RWT.getUISession( display ).exec( new Runnable() { |
| public void run() { |
| display.dispose(); |
| } |
| } ); |
| } |
| } |
| |
| private static void attachApplicationContextToSession( IServletEngine servletEngine ) { |
| HttpSession session = ClusterTestHelper.getFirstHttpSession( servletEngine ); |
| UISessionImpl uiSession = UISessionImpl.getInstanceFromSession( session ); |
| ServletContext servletContext = session.getServletContext(); |
| ApplicationContextImpl applicationContext = ApplicationContextUtil.get( servletContext ); |
| ApplicationContextUtil.set( uiSession, applicationContext ); |
| } |
| |
| private static void attachCurrentThreadToDisplay( IServletEngine servletEngine ) { |
| HttpSession session = ClusterTestHelper.getFirstHttpSession( servletEngine ); |
| Display display = ClusterTestHelper.getSessionDisplay( session ); |
| getDisplayAdapter( display ).attachThread(); |
| } |
| |
| private static void assertSessionIsIntact( HttpSession session, RWTClient client ) { |
| assertTrue( client.getSessionId().startsWith( session.getId() ) ); |
| UISession uiSession = ClusterTestHelper.getUISession( session ); |
| Display display = ClusterTestHelper.getSessionDisplay( session ); |
| assertNotNull( uiSession ); |
| assertNotNull( display ); |
| assertSame( uiSession, getDisplayAdapter( display ).getUISession() ); |
| assertNotNull( uiSession.getHttpSession() ); |
| ServletContext servletContext = session.getServletContext(); |
| ApplicationContextImpl applicationContext = ApplicationContextUtil.get( servletContext ); |
| assertNotNull( applicationContext ); |
| } |
| |
| private static IDisplayAdapter getDisplayAdapter( Display display ) { |
| return display.getAdapter( IDisplayAdapter.class ); |
| } |
| |
| private static Display getFirstDisplay( IServletEngine servletEngine ) { |
| HttpSession sessioin = ClusterTestHelper.getFirstHttpSession( servletEngine ); |
| return ClusterTestHelper.getSessionDisplay( sessioin ); |
| } |
| |
| private static Shell getFirstShell( IServletEngine servletEngine ) { |
| HttpSession session = ClusterTestHelper.getFirstHttpSession( servletEngine ); |
| Display display = ClusterTestHelper.getSessionDisplay( session ); |
| return display.getShells()[ 0 ]; |
| } |
| |
| private void clickCenterButton( int start, int end ) throws IOException { |
| for( int i = start; i <= end; i++ ) { |
| Response response = client.sendWidgetSelectedRequest( "w5" ); |
| assertTrue( response.isValidJsonResponse() ); |
| String expectedLabelPart = "relocated " + i + "/1"; |
| String msg = "label update mismatch, missing part: '" + expectedLabelPart + "'"; |
| assertTrue( msg, response.getContentText().contains( expectedLabelPart ) ); |
| } |
| } |
| |
| public interface SerializableRunnable extends Runnable, Serializable { |
| } |
| |
| } |