diff options
author | Steve Block <steveblock@google.com> | 2011-11-03 12:41:27 -0700 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-11-07 15:00:39 +0000 |
commit | d100cdbcc8033e59c405e0ce6855e81778f29132 (patch) | |
tree | 5b576f93aca73e6382f23bf3f042152b28738ccc /tests/WebViewTests | |
parent | 2d803903af6158722c846ad8c605a7e8f7e4fd6d (diff) | |
download | frameworks_base-d100cdbcc8033e59c405e0ce6855e81778f29132.zip frameworks_base-d100cdbcc8033e59c405e0ce6855e81778f29132.tar.gz frameworks_base-d100cdbcc8033e59c405e0ce6855e81778f29132.tar.bz2 |
Add tests for returning values from WebView's Java Bridge
Bug: 5140673
Change-Id: I62b45f8b35be3ce9c76766e39e8867c028f94ac1
Diffstat (limited to 'tests/WebViewTests')
3 files changed, 314 insertions, 87 deletions
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java index 77dd284..34b3432 100644 --- a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java +++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java @@ -33,58 +33,7 @@ package com.android.webviewtests; -import android.test.ActivityInstrumentationTestCase2; -import android.util.Log; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -import junit.framework.Assert; - -public class JavaBridgeCoercionTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> { - private class TestWebViewClient extends WebViewClient { - private boolean mIsPageFinished; - @Override - public synchronized void onPageFinished(WebView webView, String url) { - mIsPageFinished = true; - notify(); - } - public synchronized void waitForOnPageFinished() throws RuntimeException { - while (!mIsPageFinished) { - try { - wait(5000); - } catch (Exception e) { - continue; - } - if (!mIsPageFinished) { - throw new RuntimeException("Timed out waiting for onPageFinished()"); - } - } - mIsPageFinished = false; - } - } - - private class Controller { - private boolean mIsResultReady; - - protected synchronized void notifyResultIsReady() { - mIsResultReady = true; - notify(); - } - protected synchronized void waitForResult() { - while (!mIsResultReady) { - try { - wait(5000); - } catch (Exception e) { - continue; - } - if (!mIsResultReady) { - Assert.fail("Wait timed out"); - } - } - mIsResultReady = false; - } - } - +public class JavaBridgeCoercionTest extends JavaBridgeTestBase { private class TestObject extends Controller { private Object objectInstance; private CustomType customTypeInstance; @@ -220,45 +169,11 @@ public class JavaBridgeCoercionTest extends ActivityInstrumentationTestCase2<Web private TestObject mTestObject; - public JavaBridgeCoercionTest() { - super(WebViewStubActivity.class); - } - @Override protected void setUp() throws Exception { super.setUp(); - // ActivityInstrumentationTestCase2 kills the activity after each test, - // so each test gets a new WebView. mTestObject = new TestObject(); - // This starts the activity, so muct be called on the test thread. - final WebViewStubActivity activity = getActivity(); - // On the UI thread, load an empty page and wait for it to finish - // loading so that the Java object is injected. - final TestWebViewClient webViewClient = new TestWebViewClient(); - try { - runTestOnUiThread(new Runnable() { - @Override - public void run() { - WebView webView = activity.getWebView(); - webView.addJavascriptInterface(mTestObject, "testObject"); - webView.getSettings().setJavaScriptEnabled(true); - webView.setWebViewClient(webViewClient); - webView.loadData("<html><head></head><body></body></html>", "text/html", null); - } - }); - webViewClient.waitForOnPageFinished(); - } catch (Throwable e) { - throw new RuntimeException("Failed to set up WebView: " + Log.getStackTraceString(e)); - } - } - - private void executeJavaScript(final String script) throws Throwable { - runTestOnUiThread(new Runnable() { - @Override - public void run() { - getActivity().getWebView().loadUrl("javascript:" + script); - } - }); + setUpWebView(mTestObject, "testObject"); } // Test passing a JavaScript number in the int32 range to a method of an diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeReturnValuesTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeReturnValuesTest.java new file mode 100644 index 0000000..44d5cc6 --- /dev/null +++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeReturnValuesTest.java @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * 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. + */ + +/** + * Part of the test suite for the WebView's Java Bridge. This test checks that + * we correctly convert Java values to JavaScript values when returning them + * from the methods of injected Java objects. + * + * The conversions should follow + * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in + * which the implementation differs from the spec are marked with + * LIVECONNECT_COMPLIANCE. + * FIXME: Consider making our implementation more compliant, if it will not + * break backwards-compatibility. See b/4408210. + * + * To run this test ... + * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeReturnValuesTest \ + * com.android.webviewtests/android.test.InstrumentationTestRunner + */ + +package com.android.webviewtests; + +public class JavaBridgeReturnValuesTest extends JavaBridgeTestBase { + // An instance of this class is injected into the page to test returning + // Java values to JavaScript. + private class TestObject extends Controller { + private String mStringValue; + private boolean mBooleanValue; + + // These four methods are used to control the test. + public synchronized void setStringValue(String x) { + mStringValue = x; + notifyResultIsReady(); + } + public synchronized String waitForStringValue() { + waitForResult(); + return mStringValue; + } + public synchronized void setBooleanValue(boolean x) { + mBooleanValue = x; + notifyResultIsReady(); + } + public synchronized boolean waitForBooleanValue() { + waitForResult(); + return mBooleanValue; + } + + public boolean getBooleanValue() { + return true; + } + public byte getByteValue() { + return 42; + } + public char getCharValue() { + return '\u002A'; + } + public short getShortValue() { + return 42; + } + public int getIntValue() { + return 42; + } + public long getLongValue() { + return 42L; + } + public float getFloatValue() { + return 42.1f; + } + public float getFloatValueNoDecimal() { + return 42.0f; + } + public double getDoubleValue() { + return 42.1; + } + public double getDoubleValueNoDecimal() { + return 42.0; + } + public String getStringValue() { + return "foo"; + } + public String getEmptyStringValue() { + return ""; + } + public String getNullStringValue() { + return null; + } + public Object getObjectValue() { + return new Object(); + } + public Object getNullObjectValue() { + return null; + } + public CustomType getCustomTypeValue() { + return new CustomType(); + } + public void getVoidValue() { + } + } + + // A custom type used when testing passing objects. + private class CustomType { + } + + TestObject mTestObject; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTestObject = new TestObject(); + setUpWebView(mTestObject, "testObject"); + } + + // Note that this requires that we can pass a JavaScript string to Java. + protected String executeJavaScriptAndGetStringResult(String script) throws Throwable { + executeJavaScript("testObject.setStringValue(" + script + ");"); + return mTestObject.waitForStringValue(); + } + + // Note that this requires that we can pass a JavaScript boolean to Java. + private boolean executeJavaScriptAndGetBooleanResult(String script) throws Throwable { + executeJavaScript("testObject.setBooleanValue(" + script + ");"); + return mTestObject.waitForBooleanValue(); + } + + public void testMethodReturnTypes() throws Throwable { + assertEquals("boolean", + executeJavaScriptAndGetStringResult("typeof testObject.getBooleanValue()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getByteValue()")); + // char values are returned to JavaScript as numbers. + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getCharValue()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getShortValue()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getIntValue()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getLongValue()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getFloatValue()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getFloatValueNoDecimal()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValue()")); + assertEquals("number", + executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValueNoDecimal()")); + assertEquals("string", + executeJavaScriptAndGetStringResult("typeof testObject.getStringValue()")); + assertEquals("string", + executeJavaScriptAndGetStringResult("typeof testObject.getEmptyStringValue()")); + // LIVECONNECT_COMPLIANCE: This should have type object. + assertEquals("undefined", + executeJavaScriptAndGetStringResult("typeof testObject.getNullStringValue()")); + assertEquals("object", + executeJavaScriptAndGetStringResult("typeof testObject.getObjectValue()")); + assertEquals("object", + executeJavaScriptAndGetStringResult("typeof testObject.getNullObjectValue()")); + assertEquals("object", + executeJavaScriptAndGetStringResult("typeof testObject.getCustomTypeValue()")); + assertEquals("undefined", + executeJavaScriptAndGetStringResult("typeof testObject.getVoidValue()")); + } + + public void testMethodReturnValues() throws Throwable { + // We do the string comparison in JavaScript, to avoid relying on the + // coercion algorithm from JavaScript to Java. + assertTrue(executeJavaScriptAndGetBooleanResult("testObject.getBooleanValue()")); + assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getByteValue()")); + // char values are returned to JavaScript as numbers. + assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getCharValue()")); + assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getShortValue()")); + assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getIntValue()")); + assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getLongValue()")); + assertTrue(executeJavaScriptAndGetBooleanResult( + "Math.abs(42.1 - testObject.getFloatValue()) < 0.001")); + assertTrue(executeJavaScriptAndGetBooleanResult( + "42.0 === testObject.getFloatValueNoDecimal()")); + assertTrue(executeJavaScriptAndGetBooleanResult( + "Math.abs(42.1 - testObject.getDoubleValue()) < 0.001")); + assertTrue(executeJavaScriptAndGetBooleanResult( + "42.0 === testObject.getDoubleValueNoDecimal()")); + assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.getStringValue()")); + assertEquals("", executeJavaScriptAndGetStringResult("testObject.getEmptyStringValue()")); + assertTrue(executeJavaScriptAndGetBooleanResult("undefined === testObject.getVoidValue()")); + } +} diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java new file mode 100644 index 0000000..8b9e425 --- /dev/null +++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * 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. + */ + +/** + * Common functionality for testing the WebView's Java Bridge. + */ + +package com.android.webviewtests; + +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +import junit.framework.Assert; + +public class JavaBridgeTestBase extends ActivityInstrumentationTestCase2<WebViewStubActivity> { + private class TestWebViewClient extends WebViewClient { + private boolean mIsPageFinished; + @Override + public synchronized void onPageFinished(WebView webView, String url) { + mIsPageFinished = true; + notify(); + } + public synchronized void waitForOnPageFinished() throws RuntimeException { + while (!mIsPageFinished) { + try { + wait(5000); + } catch (Exception e) { + continue; + } + if (!mIsPageFinished) { + throw new RuntimeException("Timed out waiting for onPageFinished()"); + } + } + mIsPageFinished = false; + } + } + + protected class Controller { + private boolean mIsResultReady; + + protected synchronized void notifyResultIsReady() { + mIsResultReady = true; + notify(); + } + protected synchronized void waitForResult() { + while (!mIsResultReady) { + try { + wait(5000); + } catch (Exception e) { + continue; + } + if (!mIsResultReady) { + Assert.fail("Wait timed out"); + } + } + mIsResultReady = false; + } + } + + private TestWebViewClient mWebViewClient; + + public JavaBridgeTestBase() { + super(WebViewStubActivity.class); + } + + // Sets up the WebView and injects the supplied object. Intended to be called from setUp(). + protected void setUpWebView(final Object object, final String name) throws Exception { + mWebViewClient = new TestWebViewClient(); + // This starts the activity, so must be called on the test thread. + final WebViewStubActivity activity = getActivity(); + // On the UI thread, load an empty page and wait for it to finish + // loading so that the Java object is injected. + try { + runTestOnUiThread(new Runnable() { + @Override + public void run() { + WebView webView = activity.getWebView(); + webView.addJavascriptInterface(object, name); + webView.getSettings().setJavaScriptEnabled(true); + webView.setWebViewClient(mWebViewClient); + webView.loadData("<html><head></head><body></body></html>", "text/html", null); + } + }); + mWebViewClient.waitForOnPageFinished(); + } catch (Throwable e) { + throw new RuntimeException("Failed to set up WebView: " + Log.getStackTraceString(e)); + } + } + + protected void executeJavaScript(final String script) throws Throwable { + runTestOnUiThread(new Runnable() { + @Override + public void run() { + getActivity().getWebView().loadUrl("javascript:" + script); + } + }); + } +} |