/*******************************************************************************
* Copyright (c) 2012, 2015 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.internal.resources;
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.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.rap.json.JsonArray;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.client.WebClient;
import org.eclipse.rap.rwt.internal.protocol.Operation;
import org.eclipse.rap.rwt.internal.protocol.Operation.CallOperation;
import org.eclipse.rap.rwt.internal.protocol.Operation.CreateOperation;
import org.eclipse.rap.rwt.internal.service.ContextProvider;
import org.eclipse.rap.rwt.service.ResourceManager;
import org.eclipse.rap.rwt.testfixture.internal.Fixture;
import org.eclipse.rap.rwt.testfixture.internal.TestMessage;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class JavaScriptModuleLoaderImpl_Test {
private static final String JS_FILE_1 = "resourcetest1.js";
private static final String JS_FILE_2 = "utf-8-resource.js";
private final JavaScriptModuleLoader loader = new JavaScriptModuleLoaderImpl();
private ResourceManager resourceManager;
private Display display;
@Before
public void setUp() {
Fixture.setUp();
display = new Display();
Fixture.fakeNewRequest();
resourceManager = RWT.getResourceManager();
}
@After
public void tearDown() {
Fixture.tearDown();
}
@Test
public void testRegisterOnce() {
ensureFiles( new String[]{ JS_FILE_1 } );
String expected = getRegistryPath() + "/resourcetest1.js";
assertTrue( resourceManager.isRegistered( expected ) );
}
@Test
public void testDoNotRegisterTwice() {
ensureFiles( new String[]{ JS_FILE_1 } );
ensureFiles( new String[]{ JS_FILE_2 } );
// Same module, different return value: not a valid use case!
// Used to check for repeated registration
String expected = getRegistryPath() + "/" + JS_FILE_1;
String notExpected = getRegistryPath() + "/" + JS_FILE_2;
assertTrue( resourceManager.isRegistered( expected ) );
assertFalse( resourceManager.isRegistered( notExpected ) );
}
@Test
public void testRegisterMultipleFiles() {
ensureFiles( new String[]{ JS_FILE_1, JS_FILE_2 } );
String expectedOne = getRegistryPath() + "/" + JS_FILE_1;
String expectedTwo = getRegistryPath() + "/" + JS_FILE_2;
assertTrue( resourceManager.isRegistered( expectedOne ) );
assertTrue( resourceManager.isRegistered( expectedTwo ) );
}
@Test
public void testRegisterMultipleModules() {
ensureFiles( new String[]{ JS_FILE_1 } );
ensureFiles( new String[]{ JS_FILE_2 }, true );
String expectedOne = getRegistryPath( false ) + "/" + JS_FILE_1;
String expectedTwo = getRegistryPath( true ) + "/" + JS_FILE_2;
assertTrue( resourceManager.isRegistered( expectedOne ) );
assertTrue( resourceManager.isRegistered( expectedTwo ) );
}
@Test
public void testFileNotFound() {
try {
ensureFiles( new String[]{ "this-file-does-not-exist.js" } );
fail();
} catch( Exception ex ) {
// expected
}
}
@Test
public void testNoFilesGiven() {
try {
ensureFiles( new String[]{} );
fail();
} catch( Exception ex ) {
// expected
}
}
@Test
public void testLoadOnce() {
ensureFiles( new String[]{ JS_FILE_1 } );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
assertNotNull( findLoadOperation( message, expected ) );
}
@Test
public void testLoadBeforeCreateWidget() {
ensureFiles( new String[]{ JS_FILE_1 } );
Shell shell = new Shell( display );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
CreateOperation createOperation = message.findCreateOperation( shell );
String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
CallOperation loadOperation = findLoadOperation( message, expected );
List<Operation> operations = message.getOperations();
assertTrue( operations.indexOf( loadOperation ) < operations.indexOf( createOperation ) );
}
@Test
public void testDoNotLoadTwiceForSameRequest() {
ensureFiles( new String[]{ JS_FILE_1 } );
ensureFiles( new String[]{ JS_FILE_1 } );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String file = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
assertEquals( 1, findLoadOperations( message, file ).length );
}
@Test
public void testDoNotLoadTwiceForSameSession() {
ensureFiles( new String[]{ JS_FILE_1 } );
Fixture.executeLifeCycleFromServerThread();
Fixture.fakeNewRequest();
ensureFiles( new String[]{ JS_FILE_1 } );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
assertNull( findLoadOperation( message, expected ) );
}
@Test
public void testDoLoadTwiceForSameApplication() {
ensureFiles( new String[]{ JS_FILE_1 } );
Fixture.executeLifeCycleFromServerThread();
newSession();
ensureFiles( new String[]{ JS_FILE_1 } );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
assertNotNull( findLoadOperation( message, expected ) );
}
@Test
public void testLoadMultipleFiles() {
ensureFiles( new String[]{ JS_FILE_1, JS_FILE_2 } );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String expectedOne = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
String expectedTwo = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_2;
CallOperation operationOne = findLoadOperation( message, expectedOne );
CallOperation operationTwo = findLoadOperation( message, expectedTwo );
assertNotNull( operationOne );
List<Operation> operations = message.getOperations();
assertEquals( operations.indexOf( operationOne ), operations.indexOf( operationTwo ) );
}
@Test
public void testLoadMultipleFilesInOrder() {
ensureFiles( new String[]{ JS_FILE_1, JS_FILE_2 } );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String expectedOne = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
String expectedTwo = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_2;
CallOperation operation = findLoadOperation( message, expectedOne );
JsonArray files = operation.getParameters().get( "files" ).asArray();
assertEquals( expectedOne, files.get( 0 ).asString() );
assertEquals( expectedTwo, files.get( 1 ).asString() );
}
@Test
public void testLoadMultipleModulesInSameRequest() {
ensureFiles( new String[]{ JS_FILE_1 }, false );
ensureFiles( new String[]{ JS_FILE_2 }, true );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String expectedOne = "rwt-resources/" + getRegistryPath( false ) + "/" + JS_FILE_1;
String expectedTwo = "rwt-resources/" + getRegistryPath( true ) + "/" + JS_FILE_2;
CallOperation operationOne = findLoadOperation( message, expectedOne );
CallOperation operationTwo = findLoadOperation( message, expectedTwo );
List<Operation> operations = message.getOperations();
assertTrue( operations.indexOf( operationOne ) < operations.indexOf( operationTwo ) );
}
@Test
public void testLoadMultipleModulesInMultipleRequest() {
ensureFiles( new String[]{ JS_FILE_1 }, false );
Fixture.executeLifeCycleFromServerThread();
Fixture.fakeNewRequest();
ensureFiles( new String[]{ JS_FILE_2 }, true );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String notExpected = "rwt-resources/" + getRegistryPath( false ) + "/" + JS_FILE_1;
String expected = "rwt-resources/" + getRegistryPath( true ) + "/" + JS_FILE_2;
assertNotNull( findLoadOperation( message, expected ) );
assertNull( findLoadOperation( message, notExpected ) );
}
@Test
public void testFileNamesChangeAtRuntime() {
ensureFiles( new String[]{ JS_FILE_1 } );
Fixture.executeLifeCycleFromServerThread();
newSession();
ensureFiles( new String[]{ JS_FILE_2 } );
Fixture.executeLifeCycleFromServerThread();
TestMessage message = Fixture.getProtocolMessage();
String expected = "rwt-resources/" + getRegistryPath() + "/" + JS_FILE_1;
assertNotNull( findLoadOperation( message, expected ) );
}
private void ensureFiles( String[] files ) {
ensureFiles( files, false );
}
private void ensureFiles( String[] files, boolean secondModule ) {
if( secondModule ) {
DummyModuleTwo.files = files;
loader.ensureModule( DummyModuleTwo.class );
} else {
DummyModule.files = files;
loader.ensureModule( DummyModule.class );
}
}
private String getRegistryPath() {
return getRegistryPath( false );
}
private String getRegistryPath( boolean secondModule ) {
String result;
if( secondModule ) {
result = "DummyModuleTwo" + String.valueOf( DummyModuleTwo.class.hashCode() );
} else {
result = "DummyModule" + String.valueOf( DummyModule.class.hashCode() );
}
return result;
}
private CallOperation findLoadOperation( TestMessage message, String file ) {
CallOperation[] operations = findLoadOperations( message, file );
return operations.length == 0 ? null : operations[ 0 ];
}
private CallOperation[] findLoadOperations( TestMessage message, String file ) {
List<CallOperation> result = new ArrayList<CallOperation>();
for( int i = 0; i < message.getOperationCount(); i++ ) {
if( message.getOperation( i ) instanceof CallOperation ) {
CallOperation operation = ( CallOperation )message.getOperation( i );
if( operation.getTarget().equals( "rwt.client.JavaScriptLoader" )
&& "load".equals( operation.getMethodName() )
) {
JsonArray files = operation.getParameters().get( "files" ).asArray();
for( int j = 0; j < files.size(); j++ ) {
if( files.get( j ).asString().equals( file ) ) {
result.add( operation );
}
}
}
}
}
return result.toArray( new CallOperation[ 0 ] );
}
private void newSession() {
ContextProvider.disposeContext();
Fixture.createServiceContext();
Fixture.fakeClient( new WebClient() );
display = new Display();
Fixture.fakeNewRequest();
resourceManager = RWT.getResourceManager();
}
static public class DummyModule implements JavaScriptModule {
public static String[] files;
public String getDirectory() {
return "org/eclipse/rap/rwt/internal/resources";
}
public String[] getFileNames() {
return files;
}
public ClassLoader getLoader() {
return this.getClass().getClassLoader();
}
}
static public class DummyModuleTwo implements JavaScriptModule {
public static String[] files;
public String getDirectory() {
return "org/eclipse/rap/rwt/internal/resources";
}
public String[] getFileNames() {
return files;
}
public ClassLoader getLoader() {
return this.getClass().getClassLoader();
}
}
}