blob: 6a5541f2054cf6788e49910605fd3f3536b804ed [file] [log] [blame]
/*******************************************************************************
* 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 {
}
}