| /* |
| * Copyright 2008 Google Inc. |
| * |
| * 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 com.google.gwt.dev.jjs.test; |
| |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.core.client.GWT.UncaughtExceptionHandler; |
| import com.google.gwt.core.client.RunAsyncCallback; |
| import com.google.gwt.core.client.Scheduler; |
| import com.google.gwt.core.client.Scheduler.RepeatingCommand; |
| import com.google.gwt.junit.client.GWTTestCase; |
| |
| import javaemul.internal.annotations.DoNotInline; |
| |
| /** |
| * Tests runAsync in various ways. |
| */ |
| public class RunAsyncTest extends GWTTestCase { |
| private static final String HELLO = "hello"; |
| |
| private static final String LONG_INTERNED_STRING = "abcdefghijklmnopqrstuvwxyz"; |
| |
| private static final int RUNASYNC_TIMEOUT = 10000; |
| |
| private static String staticWrittenInBaseButReadLater; |
| |
| private static int staticWrittenByAsync; |
| |
| @Override |
| public String getModuleName() { |
| return "com.google.gwt.dev.jjs.CompilerSuite"; |
| } |
| |
| @DoNotInline |
| public String getTestString() { |
| return LONG_INTERNED_STRING; |
| } |
| |
| public void testBasic() { |
| delayTestFinish(RUNASYNC_TIMEOUT); |
| |
| GWT.runAsync(new RunAsyncCallback() { |
| @Override |
| public void onFailure(Throwable caught) { |
| throw new RuntimeException(caught); |
| } |
| |
| @Override |
| public void onSuccess() { |
| finishTest(); |
| } |
| }); |
| } |
| |
| /** |
| * Only tests the XSLinker/CrossSiteRunAsyncSuite. |
| * A string which is only referenced in > 0 fragment which gets interned needs to be |
| * processed by HandleCrossFragmentReferences, but JsLiteralInterner was running after |
| * HandleCrossFragmentReferences. |
| */ |
| public void testHandleCrossFragmentReference() { |
| delayTestFinish(RUNASYNC_TIMEOUT); |
| |
| GWT.runAsync(new RunAsyncCallback() { |
| @Override |
| public void onFailure(Throwable caught) { |
| throw new RuntimeException(caught); |
| } |
| |
| @Override |
| public void onSuccess() { |
| assertEquals(LONG_INTERNED_STRING, getTestString()); |
| GWT.runAsync(new RunAsyncCallback() { |
| @Override |
| public void onFailure(Throwable caught) { |
| throw new RuntimeException(caught); |
| } |
| |
| @Override |
| public void onSuccess() { |
| assertEquals(LONG_INTERNED_STRING, getTestString()); |
| finishTest(); |
| } |
| }); |
| } |
| }); |
| } |
| /** |
| * Unlike with pruning, writing to a field should rescue it for code-splitting |
| * purposes. |
| */ |
| public void testFieldWrittenButNotRead() { |
| delayTestFinish(RUNASYNC_TIMEOUT); |
| |
| // This write happens in the base fragment |
| staticWrittenInBaseButReadLater = HELLO; |
| |
| GWT.runAsync(new RunAsyncCallback() { |
| @Override |
| public void onFailure(Throwable caught) { |
| throw new RuntimeException(caught); |
| } |
| |
| @Override |
| public void onSuccess() { |
| // This read happens later |
| assertEquals(HELLO, staticWrittenInBaseButReadLater); |
| finishTest(); |
| } |
| }); |
| } |
| |
| /** |
| * Test runAsync always runs async. |
| */ |
| public void testAsyncIsAlwaysAsync() { |
| delayTestFinish(RUNASYNC_TIMEOUT); |
| staticWrittenByAsync = 0; |
| |
| assertRunAsyncIsAsync(); |
| |
| // Give it little bit more time to loaded and try runAsync again |
| Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() { |
| @Override public boolean execute() { |
| if (staticWrittenByAsync == 0) { |
| return true; |
| } |
| |
| // Code is loaded, let's assert it still runs async |
| assertRunAsyncIsAsync(); |
| |
| finishTest(); |
| return false; |
| } |
| }, 100); |
| } |
| |
| private void assertRunAsyncIsAsync() { |
| final int lastValue = staticWrittenByAsync; |
| GWT.runAsync(RunAsyncTest.class, new RunAsyncCallback() { |
| @Override |
| public void onFailure(Throwable caught) { |
| throw new RuntimeException(caught); |
| } |
| @Override |
| public void onSuccess() { |
| staticWrittenByAsync++; |
| } |
| }); |
| assertEquals(lastValue, staticWrittenByAsync); |
| } |
| |
| /** |
| * Test that callbacks are called in the order they are posted. |
| */ |
| public void testOrder() { |
| class Util { |
| int callNumber = 0; |
| int seen = 0; |
| |
| void scheduleCallback() { |
| final int thisCallNumber = callNumber++; |
| |
| GWT.runAsync(new RunAsyncCallback() { |
| |
| @Override |
| public void onFailure(Throwable caught) { |
| throw new RuntimeException(caught); |
| } |
| |
| @Override |
| public void onSuccess() { |
| assertEquals(seen, thisCallNumber); |
| seen++; |
| if (seen == 3) { |
| finishTest(); |
| } |
| } |
| }); |
| } |
| } |
| Util util = new Util(); |
| |
| delayTestFinish(RUNASYNC_TIMEOUT); |
| |
| util.scheduleCallback(); |
| util.scheduleCallback(); |
| util.scheduleCallback(); |
| } |
| |
| @Override |
| protected void reportUncaughtException(Throwable ex) { |
| if (!(ex.getMessage().equals("_expected_"))) { |
| super.reportUncaughtException(ex); |
| } |
| } |
| |
| public void testExceptionsThrownFromOnSuccessReported() { |
| // Create an exception that will be thrown from an onSuccess method |
| final RuntimeException toThrow = new RuntimeException("_expected_"); |
| |
| // set a handler that looks for toThrow |
| GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { |
| @Override |
| public void onUncaughtException(Throwable e) { |
| if (e == toThrow) { |
| // expected |
| finishTest(); |
| } |
| } |
| }); |
| delayTestFinish(RUNASYNC_TIMEOUT); |
| |
| GWT.runAsync(new RunAsyncCallback() { |
| @Override |
| public void onFailure(Throwable caught) { |
| } |
| |
| @Override |
| public void onSuccess() { |
| throw toThrow; |
| } |
| }); |
| } |
| } |