diff options
7 files changed, 365 insertions, 8 deletions
diff --git a/tests/DumpRenderTree2/AndroidManifest.xml b/tests/DumpRenderTree2/AndroidManifest.xml index a5199e708df8..14df611c4ff5 100644 --- a/tests/DumpRenderTree2/AndroidManifest.xml +++ b/tests/DumpRenderTree2/AndroidManifest.xml @@ -28,6 +28,14 @@ limitations under the License. <activity android:name=".LayoutTestsRunner" android:label="Layout tests' runner"> </activity> + + <activity android:name=".LayoutTestsExecuter" + android:label="Layout tests' executer" + android:process=":executer"> + </activity> + + <service android:name="ManagerService"> + </service> </application> <uses-permission android:name="android.permission.INTERNET" /> diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java index 880a5cbd8fe7..3c7dee2415bf 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java @@ -16,6 +16,7 @@ package com.android.dumprendertree2; +import android.os.Bundle; import android.os.Message; import android.webkit.WebView; @@ -50,15 +51,15 @@ public abstract class AbstractResult { } /** - * Makes the result object obtain the result of the test from the webview - * and store it in the format that suits itself bests. This method is asynchronous. + * Makes the result object obtain the results of the test from the webview + * and store them in the format that suits itself bests. This method is asynchronous. * The message passed as a parameter is a message that should be sent to its target * when the result finishes obtaining the result. * * @param webview * @param resultObtainedMsg */ - public abstract void obtainActualResult(WebView webview, Message resultObtainedMsg); + public abstract void obtainActualResults(WebView webview, Message resultObtainedMsg); public abstract void setExpectedImageResult(byte[] expectedResult); @@ -108,4 +109,6 @@ public abstract class AbstractResult { * a piece of HTML code with a visual diff between the result and the expected result */ public abstract String getDiffAsHtml(); + + public abstract Bundle getBundle(); }
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTest.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTest.java index aa505b70ed64..1312ef900cd7 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTest.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTest.java @@ -54,8 +54,10 @@ public class LayoutTest { @Override public void handleMessage(Message msg) { if (msg.what == MSG_ACTUAL_RESULT_OBTAINED) { - mResult.setExpectedTextResult(LayoutTestsRunnerThread.getExpectedTextResult(mRelativePath)); - mResult.setExpectedImageResult(LayoutTestsRunnerThread.getExpectedImageResult(mRelativePath)); + mResult.setExpectedTextResult(LayoutTestsRunnerThread + .getExpectedTextResult(mRelativePath)); + mResult.setExpectedImageResult(LayoutTestsRunnerThread + .getExpectedImageResult(mRelativePath)); mTestFinishedMsg.sendToTarget(); } } @@ -114,6 +116,11 @@ public class LayoutTest { mActivity = activity; } + public LayoutTest(AbstractResult result, String relativePath) { + mResult = result; + mRelativePath = relativePath; + } + public void run() { mWebView = new WebView(mActivity); mActivity.setContentView(mWebView); @@ -143,7 +150,7 @@ public class LayoutTest { /** TODO: Implement waitUntilDone */ - mResult.obtainActualResult(mWebView, + mResult.obtainActualResults(mWebView, mResultHandler.obtainMessage(MSG_ACTUAL_RESULT_OBTAINED)); } diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecuter.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecuter.java new file mode 100644 index 000000000000..6fd3085feee7 --- /dev/null +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecuter.java @@ -0,0 +1,240 @@ +/* + * 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.dumprendertree2; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.util.Log; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.webkit.WebStorage.QuotaUpdater; + +import java.io.File; +import java.util.List; + +/** + * This activity executes the test. It contains WebView and logic of LayoutTestController + * functions. It runs in a separate process and sends the results of running the test + * to ManagerService. The reason why is to handle crashing (test that crashes brings down + * whole process with it). + */ +public class LayoutTestsExecuter extends Activity { + + /** TODO: make it a setting */ + static final String TESTS_ROOT_DIR_PATH = + Environment.getExternalStorageDirectory() + + File.separator + "android" + + File.separator + "LayoutTests"; + + private static final String LOG_TAG = "LayoutTestExecuter"; + + public static final String EXTRA_TESTS_LIST = "TestsList"; + + private static final int MSG_ACTUAL_RESULT_OBTAINED = 0; + + private List<String> mTestsList; + private int mCurrentTestCount = 0; + + private WebView mCurrentWebView; + private String mCurrentTestRelativePath; + private String mCurrentTestUri; + + private boolean mOnTestFinishedCalled; + private AbstractResult mCurrentResult; + + /** COMMUNICATION WITH ManagerService */ + + private Messenger mManagerServiceMessenger; + + private ServiceConnection mServiceConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + mManagerServiceMessenger = new Messenger(service); + runNextTest(); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + /** TODO */ + } + }; + + private final Handler mResultHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == MSG_ACTUAL_RESULT_OBTAINED) { + reportResultToService(); + runNextTest(); + } + } + }; + + /** WEBVIEW CONFIGURATION */ + + private WebViewClient mWebViewClient = new WebViewClient() { + @Override + public void onPageFinished(WebView view, String url) { + /** Some tests fire up many page loads, we don't want to detect them */ + if (!url.equals(mCurrentTestUri)) { + return; + } + + /** TODO: Implement waitUntilDone */ + onTestFinished(); + } + }; + + private WebChromeClient mWebChromeClient = new WebChromeClient() { + @Override + public void onExceededDatabaseQuota(String url, String databaseIdentifier, + long currentQuota, long estimatedSize, long totalUsedQuota, + QuotaUpdater quotaUpdater) { + /** TODO: This should be recorded as part of the text result */ + quotaUpdater.updateQuota(currentQuota + 5 * 1024 * 1024); + } + + @Override + public boolean onJsAlert(WebView view, String url, String message, JsResult result) { + /** TODO: Alerts should be recorded as part of text result */ + result.confirm(); + return true; + } + + @Override + public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { + /** TODO: Alerts should be recorded as part of text result */ + result.confirm(); + return true; + } + + @Override + public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, + JsPromptResult result) { + /** TODO: Alerts should be recorded as part of text result */ + result.confirm(); + return true; + } + + }; + + /** IMPLEMENTATION */ + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + mTestsList = intent.getStringArrayListExtra(EXTRA_TESTS_LIST); + + bindService(new Intent(this, ManagerService.class), mServiceConnection, + Context.BIND_AUTO_CREATE); + } + + private void reset() { + mOnTestFinishedCalled = false; + mCurrentResult = null; + + mCurrentWebView = new WebView(this); + mCurrentWebView.setWebViewClient(mWebViewClient); + mCurrentWebView.setWebChromeClient(mWebChromeClient); + + WebSettings webViewSettings = mCurrentWebView.getSettings(); + webViewSettings.setAppCacheEnabled(true); + webViewSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath()); + webViewSettings.setAppCacheMaxSize(Long.MAX_VALUE); + webViewSettings.setJavaScriptEnabled(true); + webViewSettings.setJavaScriptCanOpenWindowsAutomatically(true); + webViewSettings.setSupportMultipleWindows(true); + webViewSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); + webViewSettings.setDatabaseEnabled(true); + webViewSettings.setDatabasePath(getDir("databases", 0).getAbsolutePath()); + webViewSettings.setDomStorageEnabled(true); + webViewSettings.setWorkersEnabled(false); + webViewSettings.setXSSAuditorEnabled(false); + + setContentView(mCurrentWebView); + } + + private void runNextTest() { + if (mTestsList.isEmpty()) { + onAllTestsFinished(); + return; + } + + mCurrentTestCount++; + mCurrentTestRelativePath = mTestsList.remove(0); + mCurrentTestUri = + Uri.fromFile(new File(TESTS_ROOT_DIR_PATH, mCurrentTestRelativePath)).toString(); + + reset(); + /** TODO: Implement timeout */ + mCurrentWebView.loadUrl(mCurrentTestUri); + } + + private void onTestFinished() { + if (mOnTestFinishedCalled) { + return; + } + + mOnTestFinishedCalled = true; + + /** + * If the result has not been set by the time the test finishes we create + * a default type of result. + */ + if (mCurrentResult == null) { + /** TODO: Default type should be RenderTreeResult. We don't support it now. */ + mCurrentResult = new TextResult(mCurrentTestRelativePath); + } + + mCurrentResult.obtainActualResults(mCurrentWebView, + mResultHandler.obtainMessage(MSG_ACTUAL_RESULT_OBTAINED)); + } + + private void reportResultToService() { + try { + Message serviceMsg = + Message.obtain(null, ManagerService.MSG_PROCESS_ACTUAL_RESULTS); + Bundle bundle = mCurrentResult.getBundle(); + /** TODO: Add timeout info to bundle */ + serviceMsg.setData(bundle); + mManagerServiceMessenger.send(serviceMsg); + } catch (RemoteException e) { + Log.e(LOG_TAG + "::reportResultToService", e.getMessage()); + } + } + + private void onAllTestsFinished() { + Log.d(LOG_TAG + "::onAllTestsFisnihed", "Begin."); + } +}
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsRunnerThread.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsRunnerThread.java index 8c72e3b90898..ac814cbf2783 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsRunnerThread.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsRunnerThread.java @@ -16,6 +16,7 @@ package com.android.dumprendertree2; +import android.content.Intent; import android.os.Environment; import android.os.Handler; import android.os.Looper; @@ -23,6 +24,7 @@ import android.os.Message; import android.util.Log; import java.io.File; +import java.util.ArrayList; import java.util.LinkedList; /** @@ -154,7 +156,17 @@ public class LayoutTestsRunnerThread extends Thread { mTotalTestCount = 1; } - runNextTest(); + /** + * Instead of running next test here, we send a tests' list to Executer activity. + * Rest of the code is never executed and will be gradually moved to the service. + */ + Intent intent = new Intent(); + intent.setClass(mActivity, LayoutTestsExecuter.class); + intent.setAction(Intent.ACTION_RUN); + intent.putStringArrayListExtra(LayoutTestsExecuter.EXTRA_TESTS_LIST, + new ArrayList<String>(mTestsList)); + mActivity.startActivity(intent); + Looper.loop(); } diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java new file mode 100644 index 000000000000..e452a38953b4 --- /dev/null +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java @@ -0,0 +1,60 @@ +/* + * 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.dumprendertree2; + +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.util.Log; + +/** + * A service that handles managing the results of tests, informing of crashes, generating + * summaries, etc. + */ +public class ManagerService extends Service { + + private static final String LOG_TAG = "ManagerService"; + + static final int MSG_PROCESS_ACTUAL_RESULTS = 0; + + private Handler mIncomingHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_PROCESS_ACTUAL_RESULTS: + Log.d(LOG_TAG + ".mIncomingHandler", msg.getData().getString("relativePath")); + break; + } + } + }; + + private Messenger mMessenger = new Messenger(mIncomingHandler); + + @Override + public void onCreate() { + super.onCreate(); + /** TODO: */ + } + + @Override + public IBinder onBind(Intent intent) { + return mMessenger.getBinder(); + } +}
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java index e3dcef03deb8..7bab4aed601a 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java @@ -16,6 +16,7 @@ package com.android.dumprendertree2; +import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.webkit.WebView; @@ -50,6 +51,19 @@ public class TextResult extends AbstractResult { mRelativePath = relativePath; } + /** + * Used to recreate the Result when received by the service. + * + * @param bundle + * bundle with data used to recreate the result + */ + public TextResult(Bundle bundle) { + mExpectedResult = bundle.getString("expectedTextualResult"); + mActualResult = bundle.getString("actualTextualResult"); + mRelativePath = bundle.getString("relativePath"); + mResultCode = ResultCode.valueOf(bundle.getString("resultCode")); + } + @Override public ResultCode getResultCode() { if (mResultCode != null) { @@ -141,7 +155,7 @@ public class TextResult extends AbstractResult { } @Override - public void obtainActualResult(WebView webview, Message resultObtainedMsg) { + public void obtainActualResults(WebView webview, Message resultObtainedMsg) { mResultObtainedMsg = resultObtainedMsg; Message msg = mHandler.obtainMessage(MSG_DOCUMENT_AS_TEXT); @@ -150,4 +164,17 @@ public class TextResult extends AbstractResult { msg.arg2 = 0; webview.documentAsText(msg); } + + @Override + public Bundle getBundle() { + Bundle bundle = new Bundle(); + bundle.putString("expectedTextualResult", mExpectedResult); + bundle.putString("actualTextualResult", mActualResult); + bundle.putString("relativePath", mRelativePath); + if (mResultCode != null) { + bundle.putString("resultCode", mResultCode.name()); + } + bundle.putString("type", getType().name()); + return bundle; + } }
\ No newline at end of file |