diff options
11 files changed, 321 insertions, 544 deletions
diff --git a/tests/DumpRenderTree2/AndroidManifest.xml b/tests/DumpRenderTree2/AndroidManifest.xml index 14df611c4ff5..1213674b6eb9 100644 --- a/tests/DumpRenderTree2/AndroidManifest.xml +++ b/tests/DumpRenderTree2/AndroidManifest.xml @@ -25,13 +25,13 @@ limitations under the License. </intent-filter> </activity> - <activity android:name=".LayoutTestsRunner" - android:label="Layout tests' runner"> + <activity android:name=".TestsListActivity" + android:label="Tests' list activity"> </activity> - <activity android:name=".LayoutTestsExecuter" - android:label="Layout tests' executer" - android:process=":executer"> + <activity android:name=".LayoutTestsExecutor" + android:label="Layout tests' executor" + android:process=":executor"> </activity> <service android:name="ManagerService"> diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java index 3c7dee2415bf..0a80ed4b4888 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java @@ -27,8 +27,21 @@ import android.webkit.WebView; public abstract class AbstractResult { public enum TestType { - TEXT, - PIXEL + TEXT { + @Override + public AbstractResult createResult(Bundle bundle) { + return new TextResult(bundle); + } + }, + RENDER_TREE { + @Override + public AbstractResult createResult(Bundle bundle) { + /** TODO: RenderTree tests are not yet supported */ + return null; + } + }; + + public abstract AbstractResult createResult(Bundle bundle); } public enum ResultCode { @@ -101,6 +114,8 @@ public abstract class AbstractResult { */ public abstract TestType getType(); + public abstract String getRelativePath(); + /** * Returns a piece of HTML code that presents a visual diff between a result and * the expected result. diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTest.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTest.java deleted file mode 100644 index 1312ef900cd7..000000000000 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTest.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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.net.Uri; -import android.os.Handler; -import android.os.Message; -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; - -/** - * A class that represents a single layout test. It is responsible for running the test, - * checking its result and creating an AbstractResult object. - */ -public class LayoutTest { - - private static final String LOG_TAG = "LayoutTest"; - - public static final int MSG_ACTUAL_RESULT_OBTAINED = 0; - - private String mRelativePath; - private String mTestsRootDirPath; - private String mUrl; - private boolean mOnTestFinishedCalled; - private Message mTestFinishedMsg; - private AbstractResult mResult; - - private WebView mWebView; - private Activity mActivity; - - private final Handler mResultHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - if (msg.what == MSG_ACTUAL_RESULT_OBTAINED) { - mResult.setExpectedTextResult(LayoutTestsRunnerThread - .getExpectedTextResult(mRelativePath)); - mResult.setExpectedImageResult(LayoutTestsRunnerThread - .getExpectedImageResult(mRelativePath)); - mTestFinishedMsg.sendToTarget(); - } - } - }; - - 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(mUrl)) { - return; - } - - 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; - } - - }; - - public LayoutTest(String relativePath, String testsRootDirPath, Message testFinishedMsg, - LayoutTestsRunner activity) { - mRelativePath = relativePath; - mTestsRootDirPath = testsRootDirPath; - mTestFinishedMsg = testFinishedMsg; - mActivity = activity; - } - - public LayoutTest(AbstractResult result, String relativePath) { - mResult = result; - mRelativePath = relativePath; - } - - public void run() { - mWebView = new WebView(mActivity); - mActivity.setContentView(mWebView); - - setupWebView(); - - /** TODO: Add timeout msg */ - mUrl = Uri.fromFile(new File(mTestsRootDirPath, mRelativePath)).toString(); - mWebView.loadUrl(mUrl); - } - - 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 (mResult == null) { - /** TODO: Default type should be RenderTreeResult. We don't support it now. */ - mResult = new TextResult(mRelativePath); - } - - /** TODO: Implement waitUntilDone */ - - mResult.obtainActualResults(mWebView, - mResultHandler.obtainMessage(MSG_ACTUAL_RESULT_OBTAINED)); - } - - private void setupWebView() { - WebSettings webViewSettings = mWebView.getSettings(); - webViewSettings.setAppCacheEnabled(true); - webViewSettings.setAppCachePath(mActivity.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(mActivity.getDir("databases", 0).getAbsolutePath()); - webViewSettings.setDomStorageEnabled(true); - webViewSettings.setWorkersEnabled(false); - webViewSettings.setXSSAuditorEnabled(false); - - mWebView.setWebViewClient(mWebViewClient); - mWebView.setWebChromeClient(mWebChromeClient); - } - - public AbstractResult getResult() { - return mResult; - } - - public String getRelativePath() { - return mRelativePath; - } -}
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecuter.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java index 6fd3085feee7..608b14e44b18 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecuter.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java @@ -30,6 +30,7 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; +import android.view.Window; import android.webkit.JsPromptResult; import android.webkit.JsResult; import android.webkit.WebChromeClient; @@ -47,7 +48,7 @@ import java.util.List; * to ManagerService. The reason why is to handle crashing (test that crashes brings down * whole process with it). */ -public class LayoutTestsExecuter extends Activity { +public class LayoutTestsExecutor extends Activity { /** TODO: make it a setting */ static final String TESTS_ROOT_DIR_PATH = @@ -55,14 +56,23 @@ public class LayoutTestsExecuter extends Activity { File.separator + "android" + File.separator + "LayoutTests"; - private static final String LOG_TAG = "LayoutTestExecuter"; + private static final String LOG_TAG = "LayoutTestExecutor"; public static final String EXTRA_TESTS_LIST = "TestsList"; + public static final String EXTRA_TEST_INDEX = "TestIndex"; private static final int MSG_ACTUAL_RESULT_OBTAINED = 0; private List<String> mTestsList; - private int mCurrentTestCount = 0; + + /** + * This is a number of currently running test. It is 0-based and doesn't reset after + * the crash. Initial index is passed to LayoutTestsExecuter in the intent that starts + * it. + */ + private int mCurrentTestIndex; + + private int mTotalTestCount; private WebView mCurrentWebView; private String mCurrentTestRelativePath; @@ -94,6 +104,8 @@ public class LayoutTestsExecuter extends Activity { public void handleMessage(Message msg) { if (msg.what == MSG_ACTUAL_RESULT_OBTAINED) { reportResultToService(); + mCurrentTestIndex++; + updateProgressBar(); runNextTest(); } } @@ -153,8 +165,12 @@ public class LayoutTestsExecuter extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_PROGRESS); + Intent intent = getIntent(); mTestsList = intent.getStringArrayListExtra(EXTRA_TESTS_LIST); + mCurrentTestIndex = intent.getIntExtra(EXTRA_TEST_INDEX, -1); + mTotalTestCount = mCurrentTestIndex + mTestsList.size(); bindService(new Intent(this, ManagerService.class), mServiceConnection, Context.BIND_AUTO_CREATE); @@ -191,7 +207,6 @@ public class LayoutTestsExecuter extends Activity { return; } - mCurrentTestCount++; mCurrentTestRelativePath = mTestsList.remove(0); mCurrentTestUri = Uri.fromFile(new File(TESTS_ROOT_DIR_PATH, mCurrentTestRelativePath)).toString(); @@ -226,6 +241,7 @@ public class LayoutTestsExecuter extends Activity { Message serviceMsg = Message.obtain(null, ManagerService.MSG_PROCESS_ACTUAL_RESULTS); Bundle bundle = mCurrentResult.getBundle(); + bundle.putInt("testIndex", mCurrentTestIndex); /** TODO: Add timeout info to bundle */ serviceMsg.setData(bundle); mManagerServiceMessenger.send(serviceMsg); @@ -234,7 +250,20 @@ public class LayoutTestsExecuter extends Activity { } } + private void updateProgressBar() { + getWindow().setFeatureInt(Window.FEATURE_PROGRESS, + mCurrentTestIndex * Window.PROGRESS_END / mTotalTestCount); + setTitle(mCurrentTestIndex * 100 / mTotalTestCount + "% " + + "(" + mCurrentTestIndex + "/" + mTotalTestCount + ")"); + } + private void onAllTestsFinished() { - Log.d(LOG_TAG + "::onAllTestsFisnihed", "Begin."); + try { + Message serviceMsg = + Message.obtain(null, ManagerService.MSG_ALL_TESTS_FINISHED); + mManagerServiceMessenger.send(serviceMsg); + } catch (RemoteException e) { + Log.e(LOG_TAG + "::onAllTestsFinished", e.getMessage()); + } } }
\ 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 deleted file mode 100644 index ac814cbf2783..000000000000 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsRunnerThread.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * 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.content.Intent; -import android.os.Environment; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import java.io.File; -import java.util.ArrayList; -import java.util.LinkedList; - -/** - * A Thread that is responsible for finding and loading the tests, starting them and - * generating summaries. The actual running of the test is delegated to LayoutTestsRunner - * activity (a UI thread) because of a WebView object that need to be created in UI thread - * so it can be displayed on the screen. However, the logic for doing this remains in - * this class (in handler created in constructor). - */ -public class LayoutTestsRunnerThread extends Thread { - - private static final String LOG_TAG = "LayoutTestsRunnerThread"; - - /** Messages for handler on this thread */ - public static final int MSG_TEST_FINISHED = 0; - - /** Messages for our handler running on UI thread */ - public static final int MSG_RUN_TEST = 0; - - /** TODO: make it a setting */ - private static final String TESTS_ROOT_DIR_PATH = - Environment.getExternalStorageDirectory() + - File.separator + "android" + - File.separator + "LayoutTests"; - - /** TODO: make it a setting */ - private static final String RESULTS_ROOT_DIR_PATH = - Environment.getExternalStorageDirectory() + - File.separator + "android" + - File.separator + "LayoutTests-results"; - - /** TODO: Make it a setting */ - private static final String EXPECTED_RESULT_SECONDARY_LOCATION_RELATIVE_DIR_PREFIX = - "platform" + File.separator + - "android-v8" + File.separator; - - /** TODO: Make these settings */ - private static final String TEXT_RESULT_EXTENSION = "txt"; - private static final String IMAGE_RESULT_EXTENSION = "png"; - - /** A list containing relative paths of tests to run */ - private LinkedList<String> mTestsList = new LinkedList<String>(); - - private FileFilter mFileFilter; - private Summarizer mSummarizer; - - /** Our handler running on this thread. Created in run() method. */ - private Handler mHandler; - - /** Our handler running on UI thread. Created in constructor of this thread. */ - private Handler mHandlerOnUiThread; - - /** - * A relative path to the folder with the tests we want to run or particular test. - * Used up to and including preloadTests(). - */ - private String mRelativePath; - - private LayoutTestsRunner mActivity; - - private LayoutTest mCurrentTest; - private String mCurrentTestPath; - private int mCurrentTestCount = 0; - private int mTotalTestCount; - - /** - * The given path must be relative to the root dir. The given handler must be - * able to handle messages that update the display (UI thread). - * - * @param path - * @param uiDisplayHandler - */ - public LayoutTestsRunnerThread(String path, LayoutTestsRunner activity) { - mFileFilter = new FileFilter(TESTS_ROOT_DIR_PATH); - mRelativePath = path; - mActivity = activity; - - /** This creates a handler that runs on the thread that _created_ this thread */ - mHandlerOnUiThread = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_RUN_TEST: - ((LayoutTest) msg.obj).run(); - break; - } - } - }; - } - - @Override - public void run() { - Looper.prepare(); - - mSummarizer = new Summarizer(mFileFilter, RESULTS_ROOT_DIR_PATH); - - /** A handler obtained from UI thread to handle messages concerning updating the display */ - final Handler uiDisplayHandler = mActivity.getHandler(); - - /** Creates a new handler in _this_ thread */ - mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_TEST_FINISHED: - onTestFinished(mCurrentTest); - uiDisplayHandler.obtainMessage(LayoutTestsRunner.MSG_UPDATE_PROGRESS, - mCurrentTestCount, mTotalTestCount).sendToTarget(); - runNextTest(); - break; - } - } - }; - - /** Check if the path is correct */ - File file = new File(TESTS_ROOT_DIR_PATH, mRelativePath); - if (!file.exists()) { - Log.e(LOG_TAG + "::run", "Path does not exist: " + mRelativePath); - return; - } - - /** Populate the tests' list accordingly */ - if (file.isDirectory()) { - uiDisplayHandler.sendEmptyMessage(LayoutTestsRunner.MSG_SHOW_PROGRESS_DIALOG); - preloadTests(mRelativePath); - uiDisplayHandler.sendEmptyMessage(LayoutTestsRunner.MSG_DISMISS_PROGRESS_DIALOG); - } else { - mTestsList.addLast(mRelativePath); - mTotalTestCount = 1; - } - - /** - * 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(); - } - - /** - * Loads all the tests from the given folders and all the subfolders - * into mTestsList. - * - * @param dirRelativePath - */ - private void preloadTests(String dirRelativePath) { - LinkedList<String> foldersList = new LinkedList<String>(); - foldersList.add(dirRelativePath); - - String relativePath; - String currentDirRelativePath; - String itemName; - File[] items; - while (!foldersList.isEmpty()) { - currentDirRelativePath = foldersList.removeFirst(); - items = new File(TESTS_ROOT_DIR_PATH, currentDirRelativePath).listFiles(); - for (File item : items) { - itemName = item.getName(); - relativePath = currentDirRelativePath + File.separator + itemName; - - if (item.isDirectory() && FileFilter.isTestDir(itemName)) { - foldersList.add(relativePath); - continue; - } - - if (FileFilter.isTestFile(itemName)) { - if (!mFileFilter.isSkip(relativePath)) { - mTestsList.addLast(relativePath); - } else { - mSummarizer.addSkippedTest(relativePath); - } - } - } - } - - mTotalTestCount = mTestsList.size(); - } - - private void runNextTest() { - if (mTestsList.isEmpty()) { - onFinishedTests(); - return; - } - - mCurrentTestCount++; - mCurrentTestPath = mTestsList.removeFirst(); - mCurrentTest = new LayoutTest(mCurrentTestPath, TESTS_ROOT_DIR_PATH, - mHandler.obtainMessage(MSG_TEST_FINISHED), mActivity); - - /** - * This will run the test on UI thread. The reason why we need to run the test - * on UI thread is because of the WebView. If we want to display the webview on - * the screen it needs to be in the UI thread. WebView should be created as - * part of the LayoutTest.run() method. - */ - mHandlerOnUiThread.obtainMessage(MSG_RUN_TEST, mCurrentTest).sendToTarget(); - } - - private void onTestFinished(LayoutTest test) { - String testPath = test.getRelativePath(); - - /** Obtain the result */ - AbstractResult result = test.getResult(); - if (result == null) { - Log.e(LOG_TAG + "::runTests", testPath + ": result NULL!!"); - return; - } - - dumpResultData(result, testPath); - - mSummarizer.appendTest(test); - } - - private void dumpResultData(AbstractResult result, String testPath) { - dumpActualTextResult(result, testPath); - dumpActualImageResult(result, testPath); - } - - private void dumpActualTextResult(AbstractResult result, String testPath) { - String actualTextResult = result.getActualTextResult(); - if (actualTextResult == null) { - return; - } - - String resultPath = FileFilter.setPathEnding(testPath, "-actual." + TEXT_RESULT_EXTENSION); - FsUtils.writeDataToStorage(new File(RESULTS_ROOT_DIR_PATH, resultPath), - actualTextResult.getBytes(), false); - } - - private void dumpActualImageResult(AbstractResult result, String testPath) { - byte[] actualImageResult = result.getActualImageResult(); - if (actualImageResult == null) { - return; - } - - String resultPath = FileFilter.setPathEnding(testPath, "-actual." + IMAGE_RESULT_EXTENSION); - FsUtils.writeDataToStorage(new File(RESULTS_ROOT_DIR_PATH, resultPath), - actualImageResult, false); - } - - private void onFinishedTests() { - Log.d(LOG_TAG + "::onFinishedTests", "Begin."); - Looper.myLooper().quit(); - mSummarizer.summarize(); - /** TODO: Present some kind of notification to the user that - * allows to chose next action, e.g: - * - go to html view of results - * - zip results - * - run more tests before zipping */ - } - - public static String getExpectedTextResult(String relativePath) { - return new String(getExpectedResult(relativePath, TEXT_RESULT_EXTENSION)); - } - - public static byte[] getExpectedImageResult(String relativePath) { - return getExpectedResult(relativePath, IMAGE_RESULT_EXTENSION); - } - - private static byte[] getExpectedResult(String relativePath, String extension) { - relativePath = FileFilter.setPathEnding(relativePath, "-expected." + extension); - - byte[] bytes = FsUtils.readDataFromStorage(new File(TESTS_ROOT_DIR_PATH, relativePath)); - if (bytes == null) { - relativePath = EXPECTED_RESULT_SECONDARY_LOCATION_RELATIVE_DIR_PREFIX + relativePath; - bytes = FsUtils.readDataFromStorage(new File(TESTS_ROOT_DIR_PATH, relativePath)); - } - - return bytes; - } -}
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java index e452a38953b4..e32247c3e02b 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java @@ -18,12 +18,16 @@ package com.android.dumprendertree2; import android.app.Service; import android.content.Intent; +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.util.Log; +import java.io.File; + /** * A service that handles managing the results of tests, informing of crashes, generating * summaries, etc. @@ -32,7 +36,29 @@ public class ManagerService extends Service { private static final String LOG_TAG = "ManagerService"; + /** TODO: make it a setting */ + static final String TESTS_ROOT_DIR_PATH = + Environment.getExternalStorageDirectory() + + File.separator + "android" + + File.separator + "LayoutTests"; + + /** TODO: make it a setting */ + static final String RESULTS_ROOT_DIR_PATH = + Environment.getExternalStorageDirectory() + + File.separator + "android" + + File.separator + "LayoutTests-results"; + + /** TODO: Make it a setting */ + private static final String EXPECTED_RESULT_SECONDARY_LOCATION_RELATIVE_DIR_PREFIX = + "platform" + File.separator + + "android-v8" + File.separator; + + /** TODO: Make these settings */ + private static final String TEXT_RESULT_EXTENSION = "txt"; + private static final String IMAGE_RESULT_EXTENSION = "png"; + static final int MSG_PROCESS_ACTUAL_RESULTS = 0; + static final int MSG_ALL_TESTS_FINISHED = 1; private Handler mIncomingHandler = new Handler() { @Override @@ -40,6 +66,11 @@ public class ManagerService extends Service { switch (msg.what) { case MSG_PROCESS_ACTUAL_RESULTS: Log.d(LOG_TAG + ".mIncomingHandler", msg.getData().getString("relativePath")); + onActualResultsObtained(msg.getData()); + break; + + case MSG_ALL_TESTS_FINISHED: + mSummarizer.summarize(); break; } } @@ -47,14 +78,76 @@ public class ManagerService extends Service { private Messenger mMessenger = new Messenger(mIncomingHandler); + private FileFilter mFileFilter; + private Summarizer mSummarizer; + @Override public void onCreate() { super.onCreate(); - /** TODO: */ + + mFileFilter = new FileFilter(TESTS_ROOT_DIR_PATH); + mSummarizer = new Summarizer(mFileFilter, RESULTS_ROOT_DIR_PATH); } @Override public IBinder onBind(Intent intent) { return mMessenger.getBinder(); } + + private void onActualResultsObtained(Bundle bundle) { + AbstractResult results = + AbstractResult.TestType.valueOf(bundle.getString("type")).createResult(bundle); + String relativePath = results.getRelativePath(); + results.setExpectedTextResult(getExpectedTextResult(relativePath)); + results.setExpectedImageResult(getExpectedImageResult(relativePath)); + + dumpActualTextResult(results); + dumpActualImageResult(results); + + mSummarizer.appendTest(results); + } + + private void dumpActualTextResult(AbstractResult result) { + String testPath = result.getRelativePath(); + String actualTextResult = result.getActualTextResult(); + if (actualTextResult == null) { + return; + } + + String resultPath = FileFilter.setPathEnding(testPath, "-actual." + TEXT_RESULT_EXTENSION); + FsUtils.writeDataToStorage(new File(RESULTS_ROOT_DIR_PATH, resultPath), + actualTextResult.getBytes(), false); + } + + private void dumpActualImageResult(AbstractResult result) { + String testPath = result.getRelativePath(); + byte[] actualImageResult = result.getActualImageResult(); + if (actualImageResult == null) { + return; + } + + String resultPath = FileFilter.setPathEnding(testPath, "-actual." + IMAGE_RESULT_EXTENSION); + FsUtils.writeDataToStorage(new File(RESULTS_ROOT_DIR_PATH, resultPath), + actualImageResult, false); + } + + public static String getExpectedTextResult(String relativePath) { + return new String(getExpectedResult(relativePath, TEXT_RESULT_EXTENSION)); + } + + public static byte[] getExpectedImageResult(String relativePath) { + return getExpectedResult(relativePath, IMAGE_RESULT_EXTENSION); + } + + private static byte[] getExpectedResult(String relativePath, String extension) { + relativePath = FileFilter.setPathEnding(relativePath, "-expected." + extension); + + byte[] bytes = FsUtils.readDataFromStorage(new File(TESTS_ROOT_DIR_PATH, relativePath)); + if (bytes == null) { + relativePath = EXPECTED_RESULT_SECONDARY_LOCATION_RELATIVE_DIR_PREFIX + relativePath; + bytes = FsUtils.readDataFromStorage(new File(TESTS_ROOT_DIR_PATH, relativePath)); + } + + return bytes; + } }
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java index 4d15bb5a3dcd..36cde86fc067 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java @@ -16,8 +16,6 @@ package com.android.dumprendertree2; -import android.util.Log; - import java.io.File; import java.util.EnumMap; import java.util.HashSet; @@ -155,15 +153,8 @@ public class Summarizer { mSkippedTestsList.addLast(relativePath); } - public void appendTest(LayoutTest test) { - String testPath = test.getRelativePath(); - - /** Obtain the result */ - AbstractResult result = test.getResult(); - if (result == null) { - Log.e(LOG_TAG + "::appendTest", testPath + ": result NULL!!"); - return; - } + public void appendTest(AbstractResult result) { + String testPath = result.getRelativePath(); AbstractResult.ResultCode resultCode = result.getResultCode(); diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsRunner.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListActivity.java index 4421aba44191..a402ae124a40 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsRunner.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListActivity.java @@ -24,18 +24,16 @@ import android.os.Handler; import android.os.Message; import android.view.Window; +import java.util.ArrayList; + /** - * An Activity that is responsible only for updating the UI features, like titles, progress bars, - * etc. - * - * <p>Also, the webview form the test must be running in this activity's thread if we want - * to be able to display it on the screen. + * An Activity that generates a list of tests and sends the intent to + * LayoutTestsExecuter to run them. It also restarts the LayoutTestsExecuter + * after it crashes (TODO). */ -public class LayoutTestsRunner extends Activity { +public class TestsListActivity extends Activity { - public static final int MSG_UPDATE_PROGRESS = 1; - public static final int MSG_SHOW_PROGRESS_DIALOG = 2; - public static final int MSG_DISMISS_PROGRESS_DIALOG = 3; + private static final int MSG_TEST_LIST_PRELOADER_DONE = 0; /** Constants for adding extras to an intent */ public static final String EXTRA_TEST_PATH = "TestPath"; @@ -46,31 +44,25 @@ public class LayoutTestsRunner extends Activity { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_UPDATE_PROGRESS: - int i = msg.arg1; - int size = msg.arg2; - getWindow().setFeatureInt(Window.FEATURE_PROGRESS, - i * Window.PROGRESS_END / size); - setTitle(i * 100 / size + "% (" + i + "/" + size + ")"); - break; - - case MSG_SHOW_PROGRESS_DIALOG: - sProgressDialog.show(); - break; - - case MSG_DISMISS_PROGRESS_DIALOG: + case MSG_TEST_LIST_PRELOADER_DONE: sProgressDialog.dismiss(); + mTestsList = (ArrayList<String>)msg.obj; + mTotalTestCount = mTestsList.size(); + restartExecutor(0); break; } } }; + private ArrayList<String> mTestsList; + private int mTotalTestCount; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** Prepare the progress dialog */ - sProgressDialog = new ProgressDialog(LayoutTestsRunner.this); + sProgressDialog = new ProgressDialog(TestsListActivity.this); sProgressDialog.setCancelable(false); sProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); sProgressDialog.setTitle(R.string.dialog_progress_title); @@ -78,17 +70,32 @@ public class LayoutTestsRunner extends Activity { requestWindowFeature(Window.FEATURE_PROGRESS); - /** Execute the intent */ Intent intent = getIntent(); if (!intent.getAction().equals(Intent.ACTION_RUN)) { return; } String path = intent.getStringExtra(EXTRA_TEST_PATH); - new LayoutTestsRunnerThread(path, this).start(); + sProgressDialog.show(); + Message doneMsg = Message.obtain(mHandler, MSG_TEST_LIST_PRELOADER_DONE); + + new TestsListPreloaderThread(path, doneMsg).start(); } - public Handler getHandler() { - return mHandler; + /** + * (Re)starts the executer activity from the given test number (inclusive, 0-based). + * This number is an index in mTestsList, not the sublist passed in the intent. + * + * @param startFrom + * test index in mTestsList to start the tests from (inclusive, 0-based) + */ + private void restartExecutor(int startFrom) { + Intent intent = new Intent(); + intent.setClass(this, LayoutTestsExecutor.class); + intent.setAction(Intent.ACTION_RUN); + intent.putStringArrayListExtra(LayoutTestsExecutor.EXTRA_TESTS_LIST, + new ArrayList<String>(mTestsList.subList(startFrom, mTotalTestCount))); + intent.putExtra(LayoutTestsExecutor.EXTRA_TEST_INDEX, startFrom); + startActivity(intent); } }
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListPreloaderThread.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListPreloaderThread.java new file mode 100644 index 000000000000..f76105d0fc56 --- /dev/null +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListPreloaderThread.java @@ -0,0 +1,121 @@ +/* + * 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.os.Environment; +import android.os.Message; +import android.util.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * A Thread that is responsible for generating a lists of tests to run. + */ +public class TestsListPreloaderThread extends Thread { + + private static final String LOG_TAG = "TestsListPreloaderThread"; + + /** TODO: make it a setting */ + private static final String TESTS_ROOT_DIR_PATH = + Environment.getExternalStorageDirectory() + + File.separator + "android" + + File.separator + "LayoutTests"; + + /** A list containing relative paths of tests to run */ + private ArrayList<String> mTestsList = new ArrayList<String>(); + + private FileFilter mFileFilter; + + /** + * A relative path to the folder with the tests we want to run or particular test. + * Used up to and including preloadTests(). + */ + private String mRelativePath; + + private Message mDoneMsg; + + /** + * The given path must be relative to the root dir. + * + * @param path + * @param doneMsg + */ + public TestsListPreloaderThread(String path, Message doneMsg) { + mFileFilter = new FileFilter(TESTS_ROOT_DIR_PATH); + mRelativePath = path; + mDoneMsg = doneMsg; + } + + @Override + public void run() { + /** Check if the path is correct */ + File file = new File(TESTS_ROOT_DIR_PATH, mRelativePath); + if (!file.exists()) { + Log.e(LOG_TAG + "::run", "Path does not exist: " + mRelativePath); + return; + } + + /** Populate the tests' list accordingly */ + if (file.isDirectory()) { + preloadTests(mRelativePath); + } else { + mTestsList.add(mRelativePath); + } + mDoneMsg.obj = mTestsList; + mDoneMsg.sendToTarget(); + } + + /** + * Loads all the tests from the given folders and all the subfolders + * into mTestsList. + * + * @param dirRelativePath + */ + private void preloadTests(String dirRelativePath) { + LinkedList<String> foldersList = new LinkedList<String>(); + foldersList.add(dirRelativePath); + + String relativePath; + String currentDirRelativePath; + String itemName; + File[] items; + while (!foldersList.isEmpty()) { + currentDirRelativePath = foldersList.removeFirst(); + items = new File(TESTS_ROOT_DIR_PATH, currentDirRelativePath).listFiles(); + for (File item : items) { + itemName = item.getName(); + relativePath = currentDirRelativePath + File.separator + itemName; + + if (item.isDirectory() && FileFilter.isTestDir(itemName)) { + foldersList.add(relativePath); + continue; + } + + if (FileFilter.isTestFile(itemName)) { + if (!mFileFilter.isSkip(relativePath)) { + mTestsList.add(relativePath); + } else { + //mSummarizer.addSkippedTest(relativePath); + /** TODO: Summarizer is now in service - figure out how to send the info */ + } + } + } + } + } +}
\ 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 7bab4aed601a..33ee4c79bfb9 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java @@ -61,7 +61,10 @@ public class TextResult extends AbstractResult { mExpectedResult = bundle.getString("expectedTextualResult"); mActualResult = bundle.getString("actualTextualResult"); mRelativePath = bundle.getString("relativePath"); - mResultCode = ResultCode.valueOf(bundle.getString("resultCode")); + String resultCode = bundle.getString("resultCode"); + if (resultCode != null) { + mResultCode = ResultCode.valueOf(resultCode); + } } @Override @@ -177,4 +180,9 @@ public class TextResult extends AbstractResult { bundle.putString("type", getType().name()); return bundle; } + + @Override + public String getRelativePath() { + return mRelativePath; + } }
\ No newline at end of file diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java index 790d1d36429b..661a8ec02fb9 100644 --- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java +++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java @@ -17,7 +17,7 @@ package com.android.dumprendertree2.ui; import com.android.dumprendertree2.FileFilter; -import com.android.dumprendertree2.LayoutTestsRunner; +import com.android.dumprendertree2.TestsListActivity; import com.android.dumprendertree2.R; import android.app.Activity; @@ -203,9 +203,9 @@ public class DirListActivity extends ListActivity { } else { /** Run the test */ Intent intent = new Intent(); - intent.setClass(DirListActivity.this, LayoutTestsRunner.class); + intent.setClass(DirListActivity.this, TestsListActivity.class); intent.setAction(Intent.ACTION_RUN); - intent.putExtra(LayoutTestsRunner.EXTRA_TEST_PATH, item.getRelativePath()); + intent.putExtra(TestsListActivity.EXTRA_TEST_PATH, item.getRelativePath()); startActivity(intent); } } @@ -277,9 +277,9 @@ public class DirListActivity extends ListActivity { removeDialog(DIALOG_RUN_ABORT_DIR); /** Run the tests */ Intent intent = new Intent(); - intent.setClass(DirListActivity.this, LayoutTestsRunner.class); + intent.setClass(DirListActivity.this, TestsListActivity.class); intent.setAction(Intent.ACTION_RUN); - intent.putExtra(LayoutTestsRunner.EXTRA_TEST_PATH, + intent.putExtra(TestsListActivity.EXTRA_TEST_PATH, args.getString("relativePath")); startActivity(intent); } |