diff options
author | Ben Murdoch <benm@google.com> | 2010-03-29 11:55:47 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-03-30 18:14:19 +0100 |
commit | e902e1a71a4bb31b9db665a7ecdb853d1538eb39 (patch) | |
tree | 3b34617500a6c026d1d58526ba6cedd4344efee4 | |
parent | 5149c7b1a265fe8e97fc6f2d372cdc18d7c96d42 (diff) | |
download | android_packages_apps_Gello-e902e1a71a4bb31b9db665a7ecdb853d1538eb39.tar.gz android_packages_apps_Gello-e902e1a71a4bb31b9db665a7ecdb853d1538eb39.tar.bz2 android_packages_apps_Gello-e902e1a71a4bb31b9db665a7ecdb853d1538eb39.zip |
Add a test for verifying the JS -> Java bindings.
Change-Id: I7d15efd5cc1c40d9c0c5b7cf1a5a7f9775a709d7
-rwxr-xr-x | tests/assets/bindings_test.html | 231 | ||||
-rw-r--r-- | tests/src/com/android/browser/JNIBindingsTest.java | 267 | ||||
-rw-r--r-- | tests/src/com/android/browser/JNIBindingsTestApp.java | 222 |
3 files changed, 720 insertions, 0 deletions
diff --git a/tests/assets/bindings_test.html b/tests/assets/bindings_test.html new file mode 100755 index 00000000..93dbff1c --- /dev/null +++ b/tests/assets/bindings_test.html @@ -0,0 +1,231 @@ +<html> +<head> +<script type="text/javascript"> + +function testPrimitiveTypes() { + return JNIBindingsTest.testPrimitiveTypes(100, 'c', 123.34567890, 456.789, 1234567, 1234567890, 6000, true); +} + +function testObjectTypes() { + return JNIBindingsTest.testObjectTypes("Foo", "", {"foo":"bar"}, {}); +} + +function testArray() { + return JNIBindingsTest.testArray([1,2,3], ['d', 'o', 'g'], [1.2, 2.3, 3.4], [4.5,5.6,6.7], [1,2,3], [4,5,6], [7,8,9], [true, false]); +} + +function testObjectArray() { + return JNIBindingsTest.testObjectArray(['Hello', 'World', '!'], [], [{"foo":"bar"}]); +} + +function testObjectMembers() { + var foo = {"bool":true, + "byte":101, + "char":'d', + "double":123.456, + "float":456.789, + "int":102, + "long":103, + "short":104, + "string":"Hello World", + "array": [1,2,3], + "objArray":["foo", "bar", "baz"], + "object": {"foo":1} + }; + return JNIBindingsTest.testObjectMembers(foo.bool, foo.byte, foo.char, foo.double, foo.float, foo.int, foo.long, foo.short, foo.string, foo.array, foo.objArray, foo.object); +} + +function testJSPrimitivesToStringsInJava() { + return JNIBindingsTest.testJSPrimitivesToStringsInJava(123, null, 456.789, true, 'd', undefined); +} + +function testJavaReturnTypes() { + var expectedBoolReturn = true; + var expectedByteReturn = 1; + var expectedCharReturn = 98; // 'b'; Currently bindings in JSC and V8 return chars as their ASCII equivalent. + var expectedDoubleReturn = 123.456; + var expectedFloatReturn = 456.789; + var expectedIntReturn = 123; + var expectedLongReturn = 1234; + var expectedShortReturn = 12345; + var expectedStringReturn = "Hello World!"; + + var returned = JNIBindingsTest.returnBool(); + if (returned != expectedBoolReturn) { + appendLog("returnBool() failed: expected "+ expectedBoolReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnByte(); + if (returned != expectedByteReturn) { + appendLog("returnByte() failed: expected "+ expectedByteReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnChar(); + if (returned != expectedCharReturn) { + appendLog("returnChar() failed: expected "+ expectedCharReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnDouble(); + if (returned != expectedDoubleReturn) { + appendLog("returnDouble() failed: expected "+ expectedDoubleReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnFloat(); + if (Math.abs(returned - expectedFloatReturn) > 0.001) { + appendLog("returnFloat() failed: expected "+ expectedFloatReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnInt(); + if (returned != expectedIntReturn) { + appendLog("returnInt() failed: expected "+ expectedIntReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnLong(); + if (returned != expectedLongReturn) { + appendLog("returnLong() failed: expected "+ expectedLongReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnShort(); + if (returned != expectedShortReturn) { + appendLog("returnShort() failed: expected "+ expectedShortReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnString(); + if (returned != expectedStringReturn) { + appendLog("returnString() failed: expected "+ expectedStringReturn +", got " + returned); + return false; + } + + returned = JNIBindingsTest.returnObject(); + if (returned == null) { + appendLog("returnObject() failed: expected non-null, got " + returned); + return false; + } else if (returned.x != 0) { + // EMULATE_JSC_BINDINGS + // Note: the Java sets the x property to 123. JSC and V8 do not support object + // members in the bindings though. + appendLog("returnObject() failed: expected 'x' property 0, got " + returned.x) + return false; + } else if (returned.s != undefined) { + // EMULATE_JSC_BINDINGS + // Note that the java class returned has s set to Hello World. JSC and V8 do not support + // getting properties. + appendLog("returnObject() failed: expected 's' property undefined, got " + returned.s); + return false; + } else if (!returned.aMethod()) { + appendLog("returnObject() failed: expected 'aMethod' method to return true, got " + returned.aMethod()); + return false; + } else if (returned.anotherMethod() != "Hello World") { + appendLog("returnObject() failed: expected 'anotherMethod' to return 'Hello World' got "+ returned.anotherMethod()); + return false; + } + + returned = JNIBindingsTest.returnArray(); + if (returned != null) { + appendLog("returnArray() failed: expected null, got " + returned); + return false; + } + + returned = JNIBindingsTest.returnVoid(); + if (returned != null) { + appendLog("returnVoid() failed: expected null, got " + returned); + return false; + } + + return true; +} + +function getIfaceProperties() { + if (JNIBindingsTest.mInt != 0) { + // EMULATE_JSC_BINDINGS + // Note: the Java sets the mInt property to 123. JSC and V8 do not support object + // members in the bindings though. + appendLog("getIfaceProperties() failed: expected mInt = 0, got " + JNIBindingsTest.mInt); + return false; + } + + if (JNIBindingsTest.mString != undefined) { + // EMULATE_JSC_BINDINGS + // Note that the java class returned has s set to Hello World. JSC and V8 do not support + // getting properties. + appendLog("getIfaceProperties() failed: expected mString = 'Hello World', got " + JNIBindingsTest.mString); + return false; + } + + return true; +} + +function appendLog(msg) { + var log = document.getElementById("status"); + log.innerHTML += "<br/>" + msg; +} + +function runTests() { + + // Assume that if the test isn't done after 10s that we failed. + window.setTimeout(function() { JNIBindingsTest.testComplete(); }, 10000); + + if (testPrimitiveTypes()) { + appendLog("testPrimitiveTypes passed!"); + } else { + appendLog("testPrimtiveTypes failed!"); + } + + if (testObjectTypes()) { + appendLog("testObjectTypes passed!"); + } else { + appendLog("testObjectTypes failed!"); + } + + if (testArray()) { + appendLog("testArray passed!"); + } else { + appendLog("testArray failed!"); + } + + if (testObjectArray()) { + appendLog("testObjectArray passed!"); + } else { + appendLog("testObjectArray failed!"); + } + + if (testObjectMembers()) { + appendLog("testObjectMembers passed!"); + } else { + appendLog("<br/>testObjectMembers failed!"); + } + + if (testJSPrimitivesToStringsInJava()) { + appendLog("testJSPrimitivesToStringsInJava passed!"); + } else { + appendLog("testJSPrimitivesToStringsInJava failed!"); + } + + if (testJavaReturnTypes()) { + appendLog("testJavaReturnTypes passed!"); + } else { + appendLog("testJavaReturnTypes failed!"); + } + + if (getIfaceProperties()) { + appendLog("getIfaceProperties passed!"); + } else { + appendLog("getIfaceProperties failed!"); + } + + JNIBindingsTest.testComplete(); +} +</script> + +<body onload="runTests();"> +<p id="status">Running JNI Bindings test...</p> +</body> +</html> diff --git a/tests/src/com/android/browser/JNIBindingsTest.java b/tests/src/com/android/browser/JNIBindingsTest.java new file mode 100644 index 00000000..d2220f6f --- /dev/null +++ b/tests/src/com/android/browser/JNIBindingsTest.java @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.browser; + +import android.test.AndroidTestCase; +import android.util.Log; + +import java.util.Arrays; +import junit.framework.AssertionFailedError; + +public class JNIBindingsTest extends AndroidTestCase { + + private final static String LOGTAG = "JNIBindingsTest"; + private JNIBindingsTestApp mTestApp; + + public int mInt = 123; + public String mString = "Hello World"; + + public JNIBindingsTest(JNIBindingsTestApp testApp) { + mTestApp = testApp; + } + + public void testComplete() { + Log.v(LOGTAG, "Completing the test."); + mTestApp.testComplete(); + } + + public void printAssertionFailed(AssertionFailedError e) { + Log.e(LOGTAG, ""); + Log.e(LOGTAG, "*** ASSERTION FAILED: " + e.getMessage()); + Log.e(LOGTAG, "*** Stack trace:"); + StackTraceElement[] trace = e.getStackTrace(); + for(StackTraceElement elem : trace) { + Log.e(LOGTAG, "***\t" + elem.toString()); + } + Log.e(LOGTAG, ""); + } + + public boolean testPrimitiveTypes(byte byteParam, char charParam, double doubleParam, + float floatParam, int intParam, long longParam, short shortParam, + boolean booleanParam) { + byte expectedByteParam = 100; + char expectedCharParam = 'c'; + double expectedDoubleParam = 123.34567890; + float expectedFloatParam = 456.789f; + int expectedIntParam = 1234567; + long expectedLongParam = 1234567890L; + short expectedShortParam = 6000; + boolean expectedBooleanParam = true; + + try { + assertEquals(expectedByteParam, byteParam); + + // EMULATE_JSC_BINDINGS: JSC does not pass chars correctly + // assertEquals(expectedCharParam, charParam); + + assertEquals(expectedDoubleParam, doubleParam); + assertEquals(expectedFloatParam, floatParam); + assertEquals(expectedIntParam, intParam); + assertEquals(expectedLongParam, longParam); + assertEquals(expectedShortParam, shortParam); + assertEquals(expectedBooleanParam, booleanParam); + } catch (AssertionFailedError e) { + printAssertionFailed(e); + return false; + } + return true; + } + + public boolean testObjectTypes(String stringParam, String emptyString, Object objectParam, + Object emptyObject) { + String expectedString = "Foo"; + String expectedEmptyString = ""; + + try { + assertNotNull(stringParam); + assertNotNull(emptyString); + assertEquals(expectedString, stringParam); + assertEquals(expectedEmptyString, emptyString); + assertNull(objectParam); + assertNull(emptyObject); + } catch (AssertionFailedError e) { + printAssertionFailed(e); + return false; + } + return true; + } + + public boolean testArray(byte[] byteArray, char[] charArray, double[] doubleArray, + float[] floatArray, int[] intArray, long[] longArray, short[] shortArray, + boolean[] booleanArray) { + byte[] expectedByteArray = { 1,2,3}; + char[] expectedCharArray = {'d', 'o', 'g'}; + double[] expectedDoubleArray = {1.2,2.3,3.4}; + float[] expectedFloatArray = {4.5F,5.6F,6.7F}; + int[] expectedIntArray = {1,2,3}; + long[] expectedLongArray = {4L,5L,6L}; + short[] expectedShortArray = {7,8,9}; + boolean[] expectedBooleanArray = {true, false}; + + try { + assertNotNull(byteArray); + assertNotNull(charArray); + assertNotNull(doubleArray); + assertNotNull(floatArray); + assertNotNull(intArray); + assertNotNull(longArray); + assertNotNull(shortArray); + assertNotNull(booleanArray); + assertEquals(Arrays.toString(expectedByteArray), Arrays.toString(byteArray)); + assertEquals(Arrays.toString(expectedCharArray), Arrays.toString(charArray)); + assertEquals(Arrays.toString(expectedDoubleArray), Arrays.toString(doubleArray)); + assertEquals(Arrays.toString(expectedFloatArray), Arrays.toString(floatArray)); + assertEquals(Arrays.toString(expectedIntArray), Arrays.toString(intArray)); + assertEquals(Arrays.toString(expectedLongArray), Arrays.toString(longArray)); + assertEquals(Arrays.toString(expectedShortArray), Arrays.toString(shortArray)); + assertEquals(Arrays.toString(expectedBooleanArray), Arrays.toString(booleanArray)); + } catch (AssertionFailedError e) { + printAssertionFailed(e); + return false; + } + return true; + } + + public boolean testObjectArray(String[] stringArray, Object[] emptyArray, + Object[] objectArray) { + String[] expectedStringArray = {"Hello", "World", "!"}; + Object[] expectedObjectArray = {}; + + try { + assertNotNull(stringArray); + + // EMULATE_JSC_BINDINGS JSC pass null for object arrays that are not strings. + // Should be an empty array? + assertNull(emptyArray); + assertNull(objectArray); + + assertEquals(Arrays.toString(expectedStringArray), Arrays.toString(stringArray)); + + // EMULATE_JSC_BINDINGS + // assertEquals(Arrays.toString(expectedObjectArray), Arrays.toString(emptyArray)); + // assertEquals(Arrays.toString(expectedObjectArray), Arrays.toString(objectArray)); + + } catch (AssertionFailedError e) { + printAssertionFailed(e); + return false; + } + return true; + } + + public boolean testObjectMembers(boolean boolParam, byte byteParam, char charParam, + double doubleParam, float floatParam, int intParam, long longParam, short shortParam, + String stringParam, int[] intArrayParam, String[] stringArrayParam, + Object objectParam) { + boolean expectedBoolParam = true; + byte expectedByteParam = 101; + char expectedCharParam = 'd'; + double expectedDoubleParam = 123.456; + float expectedFloatParam = 456.789F; + int expectedIntParam = 102; + long expectedLongParam = 103L; + short expectedShortParam = 104; + String expectedStringParam = "Hello World"; + int[] expectedIntArray = {1,2,3}; + String[] expectedStringArrayParam = {"foo", "bar", "baz"}; + + try { + assertEquals(expectedBoolParam, boolParam); + assertEquals(expectedByteParam, byteParam); + + // EMULATE_JSC_BINDINGS: JSC does not pass chars correctly. (chars are strings in JS) + // assertEquals(expectedCharParam, charParam); + + assertEquals(expectedDoubleParam, doubleParam); + assertEquals(expectedFloatParam, floatParam); + assertEquals(expectedIntParam, intParam); + assertEquals(expectedLongParam, longParam); + assertEquals(expectedShortParam, shortParam); + assertEquals(expectedStringParam, stringParam); + assertEquals(Arrays.toString(expectedIntArray), Arrays.toString(intArrayParam)); + assertEquals(Arrays.toString(expectedStringArrayParam), + Arrays.toString(stringArrayParam)); + assertNull(objectParam); + } catch (AssertionFailedError e) { + printAssertionFailed(e); + return false; + } + return true; + } + + public boolean testJSPrimitivesToStringsInJava(String intParam, String nullParam, + String doubleParam, String booleanParam, String charParam, + String undefinedParam) { + String expectedIntParam = "123"; + String expectedDoubleParam = "456.789"; + String expectedBooleanParam = "true"; + String expectedCharParam = "d"; + + // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types. Should be null? + String expectedUndefinedParam = "undefined"; + + try { + assertNotNull(intParam); + assertNull(nullParam); + assertNotNull(doubleParam); + assertNotNull(booleanParam); + assertNotNull(charParam); + + // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types. + assertNotNull(undefinedParam); + + assertEquals(expectedIntParam, intParam); + assertEquals(expectedDoubleParam, doubleParam); + assertEquals(expectedBooleanParam, booleanParam); + assertEquals(expectedCharParam, charParam);; + + // EMULATE_JSC_BINDINGS JSC passes "undefined" for undefined types. + assertEquals(expectedUndefinedParam, undefinedParam); + + } catch (AssertionFailedError e) { + printAssertionFailed(e); + return false; + } + return true; + } + + public boolean returnBool() { return true; } + public byte returnByte() { return 1; } + public char returnChar() { return 'b'; } + public double returnDouble() { return 123.456; } + public float returnFloat() { return 456.789F; } + public int returnInt() { return 123; } + public long returnLong() { return 1234L; } + public short returnShort() { return 12345; } + public String returnString() { return "Hello World!"; } + + public class TestObject { + public int x = 123; + public String s = "Hello World!"; + + public boolean aMethod() { return true; } + public String anotherMethod() { return "Hello World"; } + } + + public TestObject returnObject() { return new TestObject(); } + + public int[] returnArray() { + int[] array = {1,2,3,4,5}; + return array; + } + + public void returnVoid() { } +} diff --git a/tests/src/com/android/browser/JNIBindingsTestApp.java b/tests/src/com/android/browser/JNIBindingsTestApp.java new file mode 100644 index 00000000..cb38cbcc --- /dev/null +++ b/tests/src/com/android/browser/JNIBindingsTestApp.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.browser; + +import android.app.Instrumentation; +import android.net.http.SslError; +import android.os.Environment; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; +import android.webkit.SslErrorHandler; +import android.webkit.WebView; + +/** + * Adds a JavaScript interface to the webview and calls functions on it to verify variables + * are passed from JS to Java correctly. + */ +public class JNIBindingsTestApp extends ActivityInstrumentationTestCase2<BrowserActivity> { + + private final static String TAG = "JNIBindingsTest"; + + private static final int MSG_WEBKIT_DATA_READY = 101; + + private BrowserActivity mActivity = null; + private Instrumentation mInst = null; + + private boolean mTestDone = false; + private String mWebKitResult; + + private String mExpectedWebKitResult = "Running JNI Bindings test...\n" + + "testPrimitiveTypes passed!\n" + + "testObjectTypes passed!\n" + + "testArray passed!\n" + + "testObjectArray passed!\n" + + "testObjectMembers passed!\n" + + "testJSPrimitivesToStringsInJava passed!\n" + + "testJavaReturnTypes passed!\n" + + "getIfaceProperties passed!\n"; + + + private class GetWebKitDataThread extends Thread { + private JNIBindingsTestApp mTestApp; + private WebView mWebView; + private Handler mHandler; + + GetWebKitDataThread(JNIBindingsTestApp testApp, WebView webView) { + mTestApp = testApp; + mWebView = webView; + } + + public void run() { + Looper.prepare(); + mHandler = new Handler() { + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_WEBKIT_DATA_READY: { + mTestApp.setWebKitResult((String)msg.obj); + Looper.myLooper().quit(); + } + default: super.handleMessage(msg); break; + } + } + }; + mWebView.documentAsText(mHandler.obtainMessage(MSG_WEBKIT_DATA_READY)); + Looper.loop(); + } + } + + public synchronized void setWebKitResult(String result) { + mWebKitResult = result; + notify(); + } + + public JNIBindingsTestApp() { + super(BrowserActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mActivity = getActivity(); + mInst = getInstrumentation(); + mInst.waitForIdleSync(); + + } + + /** + * Gets the browser ready for testing by starting the application + * and wrapping the WebView's helper clients. + */ + void setUpBrowser() { + Tab tab = mActivity.getTabControl().getCurrentTab(); + WebView webView = tab.getWebView(); + webView.addJavascriptInterface(new JNIBindingsTest(this), "JNIBindingsTest"); + + webView.setWebChromeClient(new TestWebChromeClient(webView.getWebChromeClient()) { + + /** + * Dismisses and logs Javascript alerts. + */ + @Override + public boolean onJsAlert(WebView view, String url, String message, + JsResult result) { + String logMsg = String.format("JS Alert '%s' received from %s", message, url); + Log.w(TAG, logMsg); + result.confirm(); + + return true; + } + + /** + * Confirms and logs Javascript alerts. + */ + @Override + public boolean onJsConfirm(WebView view, String url, String message, + JsResult result) { + String logMsg = String.format("JS Confirmation '%s' received from %s", + message, url); + Log.w(TAG, logMsg); + result.confirm(); + + return true; + } + + /** + * Confirms and logs Javascript alerts, providing the default value. + */ + @Override + public boolean onJsPrompt(WebView view, String url, String message, + String defaultValue, JsPromptResult result) { + String logMsg = String.format("JS Prompt '%s' received from %s; " + + "Giving default value '%s'", message, url, defaultValue); + Log.w(TAG, logMsg); + result.confirm(defaultValue); + + return true; + } + }); + + webView.setWebViewClient(new TestWebViewClient(webView.getWebViewClient()) { + + /** + * Bypasses and logs errors. + */ + @Override + public void onReceivedError(WebView view, int errorCode, + String description, String failingUrl) { + String message = String.format("Error '%s' (%d) loading url: %s", + description, errorCode, failingUrl); + Log.w(TAG, message); + } + + /** + * Ignores and logs SSL errors. + */ + @Override + public void onReceivedSslError(WebView view, SslErrorHandler handler, + SslError error) { + Log.w(TAG, "SSL error: " + error); + handler.proceed(); + } + + }); + } + + public synchronized void testComplete() { + mTestDone = true; + notify(); + } + + public void testJNIBindings() { + setUpBrowser(); + + Tab tab = mActivity.getTabControl().getCurrentTab(); + WebView webView = tab.getWebView(); + webView.loadUrl("file:///sdcard/bindings_test.html"); + synchronized(this) { + while(!mTestDone) { + try { + wait(); + } catch (InterruptedException e) {} + } + } + + // Now the tests are complete grab the DOM content and compare to the reference. + GetWebKitDataThread getWKData = new GetWebKitDataThread(this, webView); + mWebKitResult = null; + getWKData.start(); + + synchronized(this) { + while(mWebKitResult == null) { + try { + wait(); + } catch (InterruptedException e) {} + } + } + + Log.v(TAG, "WebKit result:"); + Log.v(TAG, mWebKitResult); + assertEquals("Bindings test failed! See logcat for more details!", mExpectedWebKitResult, + mWebKitResult); + } +} |