diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-13 13:04:22 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-13 13:04:22 -0700 |
commit | ba87e3e6c985e7175152993b5efcc7dd2f0e1c93 (patch) | |
tree | ee35f76532767dc29411a8738a434d1d88d330f2 /tests | |
parent | c39a6e0c51e182338deb8b63d07933b585134929 (diff) | |
download | frameworks_base-ba87e3e6c985e7175152993b5efcc7dd2f0e1c93.zip frameworks_base-ba87e3e6c985e7175152993b5efcc7dd2f0e1c93.tar.gz frameworks_base-ba87e3e6c985e7175152993b5efcc7dd2f0e1c93.tar.bz2 |
auto import from //branches/cupcake_rel/...@138607
Diffstat (limited to 'tests')
14 files changed, 1064 insertions, 916 deletions
diff --git a/tests/CoreTests/android/webkit/CookieTest.java b/tests/CoreTests/android/webkit/CookieTest.java index 1c3d671..ea4422f 100644 --- a/tests/CoreTests/android/webkit/CookieTest.java +++ b/tests/CoreTests/android/webkit/CookieTest.java @@ -55,6 +55,11 @@ public class CookieTest extends AndroidTestCase { mCookieManager.setCookie(url, "c=\"d;\""); cookie = mCookieManager.getCookie(url); assertTrue(cookie.equals("a=b; c=\"d;\"")); + + // empty + mCookieManager.setCookie(url, "; path=/"); + cookie = mCookieManager.getCookie(url); + assertTrue(cookie.equals("a=b; c=\"d;\"")); } public void testDomain() { diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml index 8e06cc8..17c44ad 100644 --- a/tests/DumpRenderTree/AndroidManifest.xml +++ b/tests/DumpRenderTree/AndroidManifest.xml @@ -23,7 +23,7 @@ <category android:name="android.intent.category.TEST" /> </intent-filter> </activity> - <activity android:name="HTMLHostActivity"> + <activity android:name="TestShellActivity" android:launchMode="singleTop"> </activity> </application> diff --git a/tests/DumpRenderTree/compare_layout_results.py b/tests/DumpRenderTree/compare_layout_results.py deleted file mode 100644 index c4285f1..0000000 --- a/tests/DumpRenderTree/compare_layout_results.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/python -""" -Compares results of two webkit layout test runs and writes -results to a file. -""" - -import optparse -import os -import sys - -def DiffResults(marker, new_results, old_results, diff_results, strip_reason): - """ Given two result files, generate diff and - write to diff_results file. All arguments are absolute paths - to files. - """ - old_file = open(old_results, "r") - new_file = open(new_results, "r") - diff_file = open(diff_results, "a") - - # Read lines from each file - ndict = new_file.readlines() - cdict = old_file.readlines() - - # Write marker to diff file - diff_file.writelines(marker + "\n") - diff_file.writelines("###############\n") - - # Strip reason from result lines - if strip_reason is True: - for i in range(0, len(ndict)): - ndict[i] = ndict[i].split(' ')[0] + "\n" - for i in range(0, len(cdict)): - cdict[i] = cdict[i].split(' ')[0] + "\n" - - # Find results in new_results missing in old_results - new_count=0 - for line in ndict: - if line not in cdict: - diff_file.writelines("+ " + line) - new_count += 1 - - # Find results in old_results missing in new_results - missing_count=0 - for line in cdict: - if line not in ndict: - diff_file.writelines("- " + line) - missing_count += 1 - - print marker + " >>> added " + str(new_count) + " tests, removed " + str(missing_count) + " tests" - - diff_file.writelines("\n\n") - - old_file.close() - new_file.close() - diff_file.close() - return - -def main(options, args): - results_dir = os.path.abspath(options.results_directory) - ref_dir = options.ref_directory - - # if ref_dir is null, cannonify ref_dir to the script dir. - if not ref_dir: - script_self = sys.argv[0] - script_dir = os.path.dirname(script_self) - ref_dir = os.path.join(script_dir, "results") - - ref_dir = os.path.abspath(ref_dir) - - diff_result = os.path.join(results_dir, "layout_tests_diff.txt") - if os.path.exists(diff_result): - os.remove(diff_result) - - files=["passed", "failed", "nontext", "crashed"] - for f in files: - result_file_name = "layout_tests_" + f + ".txt" - DiffResults(f, os.path.join(results_dir, result_file_name), - os.path.join(ref_dir, result_file_name), diff_result, - f == "failed") - -if '__main__' == __name__: - option_parser = optparse.OptionParser() - option_parser.add_option("", "--ref-directory", - default=None, - dest="ref_directory", - help="directory name under which results are stored.") - - option_parser.add_option("", "--results-directory", - default="layout-test-results/", - dest="results_directory", - help="directory name under which results are stored.") - options, args = option_parser.parse_args() - main(options, args) diff --git a/tests/DumpRenderTree/run_layout_tests.py b/tests/DumpRenderTree/run_layout_tests.py index 433271e..5409a0c 100755 --- a/tests/DumpRenderTree/run_layout_tests.py +++ b/tests/DumpRenderTree/run_layout_tests.py @@ -22,6 +22,7 @@ use --refresh-test-list option *once* to re-generate test list on the card. Some other options are: + --rebaseline generates expected layout tests results under /sdcard/android/expected_result/ --time-out-ms (default is 8000 millis) for each test --adb-options="-e" passes option string to adb --results-directory=..., (default is ./layout-test-results) directory name under which results are stored. @@ -55,8 +56,8 @@ def DumpRenderTreeFinished(adb_cmd): output: adb_cmd string """ - # pull /sdcard/running_test.txt, if the content is "#DONE", it's done - shell_cmd_str = adb_cmd + " shell cat /sdcard/running_test.txt" + # pull /sdcard/android/running_test.txt, if the content is "#DONE", it's done + shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt" adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] return adb_output.strip() == "#DONE" @@ -145,7 +146,7 @@ def main(options, args): # Include all tests if none are specified. if not args: - path = 'fast'; + path = '/'; else: path = ' '.join(args); @@ -156,8 +157,8 @@ def main(options, args): # Re-generate the test list if --refresh-test-list is on if options.refresh_test_list: logging.info("Generating test list."); - shell_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#generateTestList -e path fast -w com.android.dumprendertree/.LayoutTestsAutoRunner" - adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] + generate_test_list_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#generateTestList -e path \"" + path + "\" -w com.android.dumprendertree/.LayoutTestsAutoRunner" + adb_output = subprocess.Popen(generate_test_list_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] if adb_output.find('Process crashed') != -1: logging.info("Aborting because cannot generate test list.\n" + adb_output) @@ -169,20 +170,28 @@ def main(options, args): # Count crashed tests. crashed_tests = [] - timeout_ms = '8000' + timeout_ms = '5000' if options.time_out_ms: timeout_ms = options.time_out_ms # Run test until it's done + run_layout_test_cmd_prefix = adb_cmd + " shell am instrument" + + run_layout_test_cmd_postfix = " -e path \"" + path + "\" -e timeout " + timeout_ms + if options.rebaseline: + run_layout_test_cmd_postfix += " -e rebaseline true" + run_layout_test_cmd_postfix += " -w com.android.dumprendertree/.LayoutTestsAutoRunner" + # Call LayoutTestsAutoTest::startLayoutTests. - shell_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#startLayoutTests -e path \"" + path + "\" -e timeout " + timeout_ms + " -w com.android.dumprendertree/.LayoutTestsAutoRunner" - adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] + run_layout_test_cmd = run_layout_test_cmd_prefix + " -e class com.android.dumprendertree.LayoutTestsAutoTest#startLayoutTests" + run_layout_test_cmd_postfix + + adb_output = subprocess.Popen(run_layout_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] while not DumpRenderTreeFinished(adb_cmd): # Get the running_test.txt logging.error("DumpRenderTree crashed, output:\n" + adb_output) - shell_cmd_str = adb_cmd + " shell cat /sdcard/running_test.txt" + shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt" crashed_test = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE).communicate()[0] logging.info(crashed_test + " CRASHED"); @@ -190,9 +199,9 @@ def main(options, args): logging.info("Resuming layout test runner..."); # Call LayoutTestsAutoTest::resumeLayoutTests - shell_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#resumeLayoutTests -e path \"" + path + "\" -e timeout " + timeout_ms + " -w com.android.dumprendertree/.LayoutTestsAutoRunner" + run_layout_test_cmd = run_layout_test_cmd_prefix + " -e class com.android.dumprendertree.LayoutTestsAutoTest#resumeLayoutTests" + run_layout_test_cmd_postfix - adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] + adb_output = subprocess.Popen(run_layout_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] if adb_output.find('INSTRUMENTATION_FAILED') != -1: logging.error("Error happened : " + adb_output) @@ -219,7 +228,7 @@ def main(options, args): # Create the crash list. fp = open(results_dir + "/layout_tests_crashed.txt", "w"); - fp.writelines(crashed_tests) + fp.writelines('\n'.join(crashed_tests)) fp.close() # Count the number of tests in each category. @@ -250,6 +259,9 @@ def main(options, args): if '__main__' == __name__: option_parser = optparse.OptionParser() + option_parser.add_option("", "--rebaseline", action="store_true", + default=False, + help="generate expected results for those tests not having one") option_parser.add_option("", "--time-out-ms", default=None, help="set the timeout for each test") diff --git a/tests/DumpRenderTree/run_page_cycler.py b/tests/DumpRenderTree/run_page_cycler.py new file mode 100755 index 0000000..9a099b5 --- /dev/null +++ b/tests/DumpRenderTree/run_page_cycler.py @@ -0,0 +1,101 @@ +#!/usr/bin/python + +"""Run page cycler tests using Android instrumentation. + + First, you need to get an SD card or sdcard image that has page cycler tests. + + Usage: + Run a single page cycler test: + run_page_cycler.py "file:///sdcard/android/page_cycler/moz/start.html?auto=1\&iterations=10" +""" + +import logging +import optparse +import os +import subprocess +import sys +import time + + + +def main(options, args): + """Run the tests. Will call sys.exit when complete. + + """ + + # Set up logging format. + log_level = logging.INFO + if options.verbose: + log_level = logging.DEBUG + logging.basicConfig(level=log_level, + format='%(message)s') + + # Include all tests if none are specified. + if not args: + print "need a URL, e.g. file:///sdcard/android/page_cycler/moz/start.html" + sys.exit(1) + else: + path = ' '.join(args); + + adb_cmd = "adb "; + if options.adb_options: + adb_cmd += options.adb_options + + logging.info("Running the test ...") + + # Count crashed tests. + crashed_tests = [] + + timeout_ms = '0' + if options.time_out_ms: + timeout_ms = options.time_out_ms + + # Run test until it's done + + run_load_test_cmd_prefix = adb_cmd + " shell am instrument" + run_load_test_cmd_postfix = " -w com.android.dumprendertree/.LayoutTestsAutoRunner" + + # Call LoadTestsAutoTest::runTest. + run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runTest -e path \"" + path + "\" -e timeout " + timeout_ms + run_load_test_cmd_postfix + + (adb_output, adb_error) = subprocess.Popen(run_load_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + if adb_output.find('INSTRUMENTATION_FAILED') != -1: + logging.error("Error happened : " + adb_output) + sys.exit(1) + + logging.info(adb_output); + logging.info(adb_error); + logging.info("Done\n"); + + # Pull results from /sdcard/load_test_result.txt + results_dir = options.results_directory + if not os.path.exists(results_dir): + os.makedirs(results_dir) + if not os.path.isdir(results_dir): + logging.error("Cannot create results dir: " + results_dir) + sys.exit(1) + + result_file = "/sdcard/load_test_result.txt" + shell_cmd_str = adb_cmd + " pull " + result_file + " " + results_dir + adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] + logging.info(adb_output) + + logging.info("Results are stored under: " + results_dir + "/load_test_result.txt\n") + +if '__main__' == __name__: + option_parser = optparse.OptionParser() + option_parser.add_option("", "--time-out-ms", + default=None, + help="set the timeout for each test") + option_parser.add_option("", "--verbose", action="store_true", + default=False, + help="include debug-level logging") + option_parser.add_option("", "--adb-options", + default=None, + help="pass options to adb, such as -d -e, etc"); + option_parser.add_option("", "--results-directory", + default="layout-test-results", + help="directory which results are stored.") + + options, args = option_parser.parse_args(); + main(options, args) diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java index 9be33db..4f162b3 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java @@ -75,31 +75,14 @@ public class FileFilter { ".", // ignore hidden directories and files "resources", // ignore resource directories "AppleScript", // AppleScript not supported - "xpath", // xpath requires libxml2, not supported - "xsl", //xsl requires libxml2 & libxslt, not sup. - "kde", // don't run kde tests. ".svn", // don't run anything under .svn folder - "gradients", // known crash - "profiler" // profiler is not supported + "profiler", // profiler is not supported + "svg", // svg is not supported + "platform", // platform specific + "http" // requires local http(s) server }; static final String [] ignoreTestList = { - "toString-stack-overflow.html", // Crashes #606688 - "frame-limit.html", // generates too many GREFs - "css-insert-import-rule.html", // Crashes, #717414 - "input-text-enter.html", // Crashes. #735088 - "text-shadow-extreme-value.html", // Crashes #571671 - "reflection-masks.html", - "frame-creation-removal.html", - "large-expressions.html", - "null-page-show-modal-dialog-crash.html", - "font-face-implicit-local-font.html", - "font-face-locally-installed.html", - "beforeSelectorOnCodeElement.html", - "cssTarget-crash.html", - "searchfield-heights.html", // Bug 1570692 - "tabindex-focus-blur-all.html", - "search-rtl.html" // fast/forms/search-rtl.html }; static void fillIgnoreResultSet() { diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java index d685f5d..0218317 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileList.java @@ -17,6 +17,7 @@ package com.android.dumprendertree; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -84,7 +85,8 @@ public abstract class FileList extends ListActivity return myData; } String[] files = f.list(); - + Arrays.sort(files); + for (int i = 0; i < files.length; i++) { StringBuilder sb = new StringBuilder(mPath); sb.append(File.separatorChar); diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java deleted file mode 100644 index 86bfad7..0000000 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java +++ /dev/null @@ -1,726 +0,0 @@ -/* - * Copyright (C) 2007 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.dumprendertree; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.BufferedOutputStream; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.util.List; -import java.util.Vector; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.KeyEvent; -import android.view.ViewGroup; -import android.webkit.JsPromptResult; -import android.webkit.JsResult; -import android.webkit.WebChromeClient; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.widget.LinearLayout; -import android.os.*; - -// TestRecorder creates two files, one for passing tests -// and another for failing tests and writes the paths to -// layout tests one line at a time. TestRecorder does not -// have ability to clear the results. -class TestRecorder { - public void passed(String layout_file) { - try { - mBufferedOutputPassedStream.write(layout_file.getBytes()); - mBufferedOutputPassedStream.write('\n'); - mBufferedOutputPassedStream.flush(); - } catch(Exception e) { - e.printStackTrace(); - } - } - - public void failed(String layout_file, String reason) { - try { - mBufferedOutputFailedStream.write(layout_file.getBytes()); - mBufferedOutputFailedStream.write(" : ".getBytes()); - mBufferedOutputFailedStream.write(reason.getBytes()); - mBufferedOutputFailedStream.write('\n'); - mBufferedOutputFailedStream.flush(); - } catch(Exception e) { - e.printStackTrace(); - } - } - - public void nontext(String layout_file, boolean has_results) { - try { - mBufferedOutputNontextStream.write(layout_file.getBytes()); - if (has_results) { - mBufferedOutputNontextStream.write(" : has expected results".getBytes()); - } - mBufferedOutputNontextStream.write('\n'); - mBufferedOutputNontextStream.flush(); - } catch(Exception e) { - e.printStackTrace(); - } - } - - public TestRecorder(boolean resume) { - try { - File resultsPassedFile = new File("/sdcard/layout_tests_passed.txt"); - File resultsFailedFile = new File("/sdcard/layout_tests_failed.txt"); - File resultsNontextFile = new File("/sdcard/layout_tests_nontext.txt"); - - mBufferedOutputPassedStream = - new BufferedOutputStream(new FileOutputStream(resultsPassedFile, resume)); - mBufferedOutputFailedStream = - new BufferedOutputStream(new FileOutputStream(resultsFailedFile, resume)); - mBufferedOutputNontextStream = - new BufferedOutputStream(new FileOutputStream(resultsNontextFile, resume)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - public void close() { - try { - mBufferedOutputPassedStream.close(); - mBufferedOutputFailedStream.close(); - mBufferedOutputNontextStream.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - private BufferedOutputStream mBufferedOutputPassedStream; - private BufferedOutputStream mBufferedOutputFailedStream; - private BufferedOutputStream mBufferedOutputNontextStream; -} - -public class HTMLHostActivity extends Activity - implements LayoutTestController { - - public class AsyncHandler extends Handler { - @Override - public void handleMessage(Message msg) { - if (msg.what == MSG_TIMEOUT) { - mTimedOut = true; - requestWebKitData(); - return; - } else if (msg.what == MSG_WEBKIT_DATA) { - HTMLHostActivity.this.dump(mTimedOut, (String)msg.obj); - return; - } - - super.handleMessage(msg); - } - } - - public void requestWebKitData() { - Message callback = mHandler.obtainMessage(MSG_WEBKIT_DATA); - - if (mRequestedWebKitData) - throw new AssertionError("Requested webkit data twice: " + mWebView.getUrl()); - - mRequestedWebKitData = true; - if (mDumpAsText) { - mWebView.documentAsText(callback); - } else { - mWebView.externalRepresentation(callback); - } - } - // Activity methods - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - LinearLayout contentView = new LinearLayout(this); - contentView.setOrientation(LinearLayout.VERTICAL); - setContentView(contentView); - - mWebView = new WebView(this); - mWebView.getSettings().setJavaScriptEnabled(true); - mWebView.setWebChromeClient(mChromeClient); - mEventSender = new WebViewEventSender(mWebView); - mCallbackProxy = new CallbackProxy(mEventSender, this); - mFinishedRunning = false; - - mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController"); - mWebView.addJavascriptInterface(mCallbackProxy, "eventSender"); - contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.0f)); - - mHandler = new AsyncHandler(); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - } - - private void getTestList() { - // Read test list. - try { - BufferedReader inReader = new BufferedReader(new FileReader(LAYOUT_TESTS_LIST_FILE)); - String line = inReader.readLine(); - while (line != null) { - if (line.startsWith(mTestPathPrefix)) - mTestList.add(line); - line = inReader.readLine(); - } - inReader.close(); - Log.v(LOGTAG, "Test list has " + mTestList.size() + " test(s)."); - } catch (Exception e) { - Log.e(LOGTAG, "Error while reading test list : " + e.getMessage()); - } - } - - private void resumeTestList() { - // read out the test name it stoped last time. - try { - BufferedReader inReader = new BufferedReader(new FileReader(TEST_STATUS_FILE)); - String line = inReader.readLine(); - for (int i = 0; i < mTestList.size(); i++) { - if (mTestList.elementAt(i).equals(line)) { - mTestList = new Vector<String>(mTestList.subList(i+1, mTestList.size())); - break; - } - } - inReader.close(); - } catch (Exception e) { - Log.e(LOGTAG, "Error reading " + TEST_STATUS_FILE); - } - } - - private void clearTestStatus() { - // Delete TEST_STATUS_FILE - try { - File f = new File(TEST_STATUS_FILE); - if (f.delete()) - Log.v(LOGTAG, "Deleted " + TEST_STATUS_FILE); - else - Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE); - } catch (Exception e) { - Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE + " : " + e.getMessage()); - } - } - - private void updateTestStatus(String s) { - // Write TEST_STATUS_FILE - try { - BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(TEST_STATUS_FILE)); - bos.write(s.getBytes()); - bos.close(); - } catch (Exception e) { - Log.e(LOGTAG, "Cannot update file " + TEST_STATUS_FILE); - } - } - - protected void onResume() { - super.onResume(); - if (mTestList == null) - mTestList = new Vector<String>(); - - if (mTestList.isEmpty()) { - // Read settings - Intent intent = getIntent(); - mTestPathPrefix = intent.getStringExtra(TEST_PATH_PREFIX); - mSingleTestMode = intent.getBooleanExtra(SINGLE_TEST_MODE, false); - boolean resume = intent.getBooleanExtra(RESUME_FROM_CRASH, false); - mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 8000); - - mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); - - if (mTestPathPrefix == null) - throw new AssertionError("mTestPathPrefix cannot be null"); - - Log.v(LOGTAG, "Run tests with prefix: " + mTestPathPrefix); - - mResultRecorder = new TestRecorder(resume); - - if (!resume) - clearTestStatus(); - - if (!mSingleTestMode) { - getTestList(); - if (resume) - resumeTestList(); - } else { - mTestList.add(mTestPathPrefix); - } - - if (!mTestList.isEmpty()) - runTestAtIndex(0); - else - mWebView.loadUrl("about:"); - } - } - - protected void onStop() { - super.onStop(); - mWebView.stopLoading(); - } - - protected void onDestroy() { - super.onDestroy(); - mResultRecorder.close(); - mWebView.destroy(); - mWebView = null; - } - - public void onLowMemory() { - super.onLowMemory(); - // Simulate a crash - Log.e(LOGTAG, "Low memory, killing self"); - System.exit(1); - } - - public boolean dispatchKeyEvent(KeyEvent event) { - // Log key strokes as they don't seem to be matched - //Log.e(LOGTAG, "Event: "+event); - return super.dispatchKeyEvent(event); - } - - // Run a test at specified index in the test list. - // Stops activity if run out of tests. - protected void runTestAtIndex(int testIndex) { - mTestIndex = testIndex; - - resetTestStatus(); - - if (testIndex == mTestList.size()) { - if (!mSingleTestMode) { - updateTestStatus("#DONE"); - } - finished(); - return; - } - String s = mTestList.elementAt(testIndex); - if (!mSingleTestMode) - updateTestStatus(s); - - Log.v(LOGTAG, " Running test: "+s); - mWebView.loadUrl("file://"+s); - - if (!mSingleTestMode) { - // Create a timeout timer - Message m = mHandler.obtainMessage(MSG_TIMEOUT); - mHandler.sendMessageDelayed(m, mTimeoutInMillis); - } - } - - // Dump the page - public void dump(boolean timeout, String webkitData) { - String currentTest = mTestList.elementAt(mTestIndex); - String resultFile = currentTest.substring(0, currentTest.lastIndexOf('.')); - - // dumpAsText version can be directly compared to expected results - if (mDumpAsText) { - resultFile += "-results.txt"; - } else { - resultFile += "-android-results.txt"; - } - - try { - FileOutputStream os = new FileOutputStream(resultFile); - if (timeout) { - Log.w("Layout test: Timeout", resultFile); - os.write(TIMEOUT_STR.getBytes()); - os.write('\n'); - } - if (mDumpTitleChanges) - os.write(mTitleChanges.toString().getBytes()); - if (mDialogStrings != null) - os.write(mDialogStrings.toString().getBytes()); - mDialogStrings = null; - os.write(webkitData.getBytes()); - os.flush(); - os.close(); - } catch (FileNotFoundException ex) { - ex.printStackTrace(); - } catch (IOException ex) { - ex.printStackTrace(); - } - - processResult(timeout, currentTest); - runTestAtIndex(mTestIndex + 1); - } - - // Wrap up - public void failedCase(String file, String reason) { - Log.w("Layout test: ", file + " failed " + reason); - mResultRecorder.failed(file, reason); - - String bugNumber = FileFilter.isKnownBug(file); - if (bugNumber != null) { - System.out.println("FAIL known:"+bugNumber+ " "+file+reason); - return; - } - if (FileFilter.ignoreResults(file)) { - return; - } - System.out.println("FAIL: "+file+reason); - } - - public void passedCase(String file) { - Log.v("Layout test:", file + " passed"); - mResultRecorder.passed(file); - - String bugNumber = FileFilter.isKnownBug(file); - if (bugNumber != null) { - System.out.println("Bug Fixed: "+bugNumber+ " "+file); - return; - } - - if (FileFilter.ignoreResults(file)) { - System.out.println("Ignored test passed: "+file); - return; - } - } - - public void nontextCase(String file, boolean has_expected_results) { - Log.v("Layout test:", file + " nontext"); - mResultRecorder.nontext(file, has_expected_results); - } - - public void setCallback(HTMLHostCallbackInterface callback) { - mCallback = callback; - } - - public void processResult(boolean timeout, String test_path) { - Log.v(LOGTAG, " Processing result: " + test_path); - // remove the extension - String short_file = test_path.substring(0, test_path.lastIndexOf('.')); - if (timeout) { - failedCase(test_path, "TIMEDOUT"); - return; - } - // Only check results that we can check, ie dumpAsText results - String dumpFile = short_file + "-results.txt"; - File f = new File(dumpFile); - if (f.exists()) { - try { - FileInputStream fr = new FileInputStream(short_file+"-results.txt"); - FileInputStream fe = new FileInputStream(short_file+"-expected.txt"); - - // If the length is different then they are different - int diff = fe.available() - fr.available(); - if (diff > 1 || diff < 0) { - failedCase(test_path, " different length"); - fr.close(); - fe.close(); - return; - } - byte[] br = new byte[fr.available()]; - byte[] be = new byte[fe.available()]; - fr.read(br); - fe.read(be); - boolean fail = false; - for (int i = 0; i < br.length; i++) { - if (br[i] != be[i]) { - failedCase(test_path, " @offset: "+i); - fr.close(); - fe.close(); - return; - } - } - if (br.length != be.length && be[be.length-1] == '\n') { - Log.d(LOGTAG, "Extra new line being ignore:" + test_path); - } - fr.close(); - fe.close(); - passedCase(test_path); - } catch (FileNotFoundException ex) { - // TODO do something here - } catch (IOException ex) { - // Failed on available() or read() - } - - return; - } - - File nontext_result = new File(short_file + "-android-results.txt"); - if (nontext_result.exists()) { - // Check if the test has expected results. - File expected = new File(short_file + "-expected.txt"); - nontextCase(test_path, expected.exists()); - } - } - - public void finished() { - if (mCallback != null) { - mCallback.waitForFinish(); - } - - mFinishedRunning = true; - finish(); - } - - // LayoutTestController Functions - public void dumpAsText() { - mDumpAsText = true; - if (mWebView != null) { - String url = mWebView.getUrl(); - Log.v(LOGTAG, "dumpAsText called: "+url); - } - } - - public void waitUntilDone() { - mWaitUntilDone = true; - String url = mWebView.getUrl(); - Log.v(LOGTAG, "waitUntilDone called: " + url); - } - public void notifyDone() { - String url = mWebView.getUrl(); - Log.v(LOGTAG, "notifyDone called: " + url); - if (mWaitUntilDone) { - mWaitUntilDone = false; - mChromeClient.onProgressChanged(mWebView, 100); - } - } - - public void display() { - mWebView.invalidate(); - } - - public void clearBackForwardList() { - mWebView.clearHistory(); - - } - - public void dumpBackForwardList() { - //printf("\n============== Back Forward List ==============\n"); - // mWebHistory - //printf("===============================================\n"); - - } - - public void dumpChildFrameScrollPositions() { - // TODO Auto-generated method stub - - } - - public void dumpEditingCallbacks() { - // TODO Auto-generated method stub - - } - - public void dumpSelectionRect() { - // TODO Auto-generated method stub - - } - - public void dumpTitleChanges() { - if (!mDumpTitleChanges) { - mTitleChanges = new StringBuffer(); - } - mDumpTitleChanges = true; - } - - public void keepWebHistory() { - if (!mKeepWebHistory) { - mWebHistory = new Vector(); - } - mKeepWebHistory = true; - } - - public void queueBackNavigation(int howfar) { - // TODO Auto-generated method stub - - } - - public void queueForwardNavigation(int howfar) { - // TODO Auto-generated method stub - - } - - public void queueLoad(String Url, String frameTarget) { - // TODO Auto-generated method stub - - } - - public void queueReload() { - mWebView.reload(); - } - - public void queueScript(String scriptToRunInCurrentContext) { - mWebView.loadUrl("javascript:"+scriptToRunInCurrentContext); - } - - public void repaintSweepHorizontally() { - // TODO Auto-generated method stub - - } - - public void setAcceptsEditing(boolean b) { - // TODO Auto-generated method stub - - } - - public void setMainFrameIsFirstResponder(boolean b) { - // TODO Auto-generated method stub - - } - - public void setWindowIsKey(boolean b) { - // This is meant to show/hide the window. The best I can find - // is setEnabled() - mWebView.setEnabled(b); - } - - public void testRepaint() { - mWebView.invalidate(); - } - - // Instrumentation calls this to find - // if the activity has finished running the layout tests - // TODO(fqian): need to sync on mFinisheRunning - public boolean hasFinishedRunning() { - return mFinishedRunning; - } - - private final WebChromeClient mChromeClient = new WebChromeClient() { - @Override - public void onProgressChanged(WebView view, int newProgress) { - if (newProgress == 100) { - if (!mSingleTestMode && !mTimedOut && !mWaitUntilDone && !mRequestedWebKitData) { - String url = mWebView.getUrl(); - Log.v(LOGTAG, "Finished: "+ url); - mHandler.removeMessages(MSG_TIMEOUT); - requestWebKitData(); - } else { - String url = mWebView.getUrl(); - if (mSingleTestMode) { - Log.v(LOGTAG, "Single test mode: " + url); - } else if (mTimedOut) { - Log.v(LOGTAG, "Timed out before finishing: " + url); - } else if (mWaitUntilDone) { - Log.v(LOGTAG, "Waiting for notifyDone: " + url); - } else if (mRequestedWebKitData) { - Log.v(LOGTAG, "Requested webkit data ready: " + url); - } - } - } - } - - @Override - public void onReceivedTitle(WebView view, String title) { - if (title.length() > 30) - title = "..."+title.substring(title.length()-30); - setTitle(title); - if (mDumpTitleChanges) { - mTitleChanges.append("TITLE CHANGED: "); - mTitleChanges.append(title); - mTitleChanges.append("\n"); - } - } - - @Override - public boolean onJsAlert(WebView view, String url, String message, - JsResult result) { - if (mDialogStrings == null) { - mDialogStrings = new StringBuffer(); - } - mDialogStrings.append("ALERT: "); - mDialogStrings.append(message); - mDialogStrings.append('\n'); - result.confirm(); - return true; - } - - @Override - public boolean onJsConfirm(WebView view, String url, String message, - JsResult result) { - if (mDialogStrings == null) { - mDialogStrings = new StringBuffer(); - } - mDialogStrings.append("CONFIRM: "); - mDialogStrings.append(message); - mDialogStrings.append('\n'); - result.confirm(); - return true; - } - - @Override - public boolean onJsPrompt(WebView view, String url, String message, - String defaultValue, JsPromptResult result) { - if (mDialogStrings == null) { - mDialogStrings = new StringBuffer(); - } - mDialogStrings.append("PROMPT: "); - mDialogStrings.append(message); - mDialogStrings.append(", default text: "); - mDialogStrings.append(defaultValue); - mDialogStrings.append('\n'); - result.confirm(); - return true; - } - }; - - private void resetTestStatus() { - mWaitUntilDone = false; - mDumpAsText = false; - mTimedOut = false; - mDumpTitleChanges = false; - mRequestedWebKitData = false; - mEventSender.resetMouse(); - } - - private TestRecorder mResultRecorder; - private HTMLHostCallbackInterface mCallback = null; - private CallbackProxy mCallbackProxy; - - private WebView mWebView; - private WebViewEventSender mEventSender; - - private Vector<String> mTestList; - private int mTestIndex; - - private int mTimeoutInMillis; - private String mTestPathPrefix; - private boolean mSingleTestMode; - - private AsyncHandler mHandler; - private boolean mFinishedRunning; - - private boolean mTimedOut; - private boolean mRequestedWebKitData; - private boolean mDumpAsText; - private boolean mWaitUntilDone; - private boolean mDumpTitleChanges; - - private StringBuffer mTitleChanges; - private StringBuffer mDialogStrings; - - private boolean mKeepWebHistory; - private Vector mWebHistory; - - static final String TIMEOUT_STR = "**Test timeout"; - - static final int MSG_TIMEOUT = 0; - static final int MSG_WEBKIT_DATA = 1; - - static final String LOGTAG="DumpRenderTree"; - - static final String LAYOUT_TESTS_ROOT = "/sdcard/android/layout_tests/"; - static final String LAYOUT_TESTS_LIST_FILE = "/sdcard/layout_tests_list.txt"; - static final String TEST_STATUS_FILE = "/sdcard/running_test.txt"; - - static final String RESUME_FROM_CRASH = "ResumeFromCrash"; - static final String TEST_PATH_PREFIX = "TestPathPrefix"; - static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis"; - static final String SINGLE_TEST_MODE = "SingleTestMode"; -} diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java index 1f37405..8f968b4 100755 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java @@ -27,7 +27,7 @@ import android.os.Bundle; /** - * Instrumentation Test Runner for all MediaPlayer tests. + * Instrumentation Test Runner for all DumpRenderTree tests. * * Running all tests: * @@ -40,6 +40,7 @@ public class LayoutTestsAutoRunner extends InstrumentationTestRunner { public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); suite.addTestSuite(LayoutTestsAutoTest.class); + suite.addTestSuite(LoadTestsAutoTest.class); return suite; } @@ -51,18 +52,22 @@ public class LayoutTestsAutoRunner extends InstrumentationTestRunner { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - String path = (String) icicle.get("path"); - LayoutTestsAutoTest.setLayoutTestDir(path); + this.mTestPath = (String) icicle.get("path"); String timeout_str = (String) icicle.get("timeout"); - int timeout = 0; // default value if (timeout_str != null) { try { - timeout = Integer.parseInt(timeout_str); + this.mTimeoutInMillis = Integer.parseInt(timeout_str); } catch (Exception e) { e.printStackTrace(); } } - LayoutTestsAutoTest.setTimeoutInMillis(timeout); + + String r = (String)icicle.get("rebaseline"); + this.mRebaseline = (r != null && r.toLowerCase().equals("true")); } + + public String mTestPath = null; + public int mTimeoutInMillis = 0; + public boolean mRebaseline = false; } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java index 3e65f03..a857e68 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java @@ -25,92 +25,375 @@ import android.content.Intent; import android.util.Log; import android.view.KeyEvent; +import android.webkit.WebSettings; import android.os.Bundle; import android.os.Message; -import android.test.ActivityInstrumentationTestCase; +import android.test.ActivityInstrumentationTestCase2; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; -import com.android.dumprendertree.HTMLHostActivity; +import com.android.dumprendertree.TestShellActivity; import java.io.BufferedOutputStream; +import java.io.BufferedReader; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; +import java.util.Vector; + +//TestRecorder creates two files, one for passing tests +//and another for failing tests and writes the paths to +//layout tests one line at a time. TestRecorder does not +//have ability to clear the results. +class MyTestRecorder { + private BufferedOutputStream mBufferedOutputPassedStream; + private BufferedOutputStream mBufferedOutputFailedStream; + private BufferedOutputStream mBufferedOutputNoresultStream; + + public void passed(String layout_file) { + try { + mBufferedOutputPassedStream.write(layout_file.getBytes()); + mBufferedOutputPassedStream.write('\n'); + mBufferedOutputPassedStream.flush(); + } catch(Exception e) { + e.printStackTrace(); + } + } + + public void failed(String layout_file) { + try { + mBufferedOutputFailedStream.write(layout_file.getBytes()); + mBufferedOutputFailedStream.write('\n'); + mBufferedOutputFailedStream.flush(); + } catch(Exception e) { + e.printStackTrace(); + } + } + + public void noresult(String layout_file) { + try { + mBufferedOutputNoresultStream.write(layout_file.getBytes()); + mBufferedOutputNoresultStream.write('\n'); + mBufferedOutputNoresultStream.flush(); + } catch(Exception e) { + e.printStackTrace(); + } + } + + public MyTestRecorder(boolean resume) { + try { + File resultsPassedFile = new File("/sdcard/layout_tests_passed.txt"); + File resultsFailedFile = new File("/sdcard/layout_tests_failed.txt"); + File noExpectedResultFile = new File("/sdcard/layout_tests_nontext.txt"); + + mBufferedOutputPassedStream = + new BufferedOutputStream(new FileOutputStream(resultsPassedFile, resume)); + mBufferedOutputFailedStream = + new BufferedOutputStream(new FileOutputStream(resultsFailedFile, resume)); + mBufferedOutputNoresultStream = + new BufferedOutputStream(new FileOutputStream(noExpectedResultFile, resume)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void close() { + try { + mBufferedOutputPassedStream.close(); + mBufferedOutputFailedStream.close(); + mBufferedOutputNoresultStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} -public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase<Menu> { - private final static String LOGTAG = "LayoutTests"; - private final static int DEFAULT_TIMEOUT_IN_MILLIS = 6000; - private static String layoutTestDir = null; - private static int mTimeoutInMillis = 0; +public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> { + + private static final String LOGTAG = "LayoutTests"; + static final int DEFAULT_TIMEOUT_IN_MILLIS = 5000; + + static final String LAYOUT_TESTS_ROOT = "/sdcard/android/layout_tests/"; + static final String LAYOUT_TESTS_RESULT_DIR = "/sdcard/android/layout_tests_results/"; + static final String ANDROID_EXPECTED_RESULT_DIR = "/sdcard/android/expected_results/"; + static final String LAYOUT_TESTS_LIST_FILE = "/sdcard/android/layout_tests_list.txt"; + static final String TEST_STATUS_FILE = "/sdcard/android/running_test.txt"; + + private MyTestRecorder mResultRecorder; + private Vector<String> mTestList; + private boolean mRebaselineResults; + private String mTestPathPrefix; public LayoutTestsAutoTest() { - super("com.android.dumprendertree", Menu.class); + super("com.android.dumprendertree", TestShellActivity.class); } // This function writes the result of the layout test to // Am status so that it can be picked up from a script. - public void passOrFailCallback(String file, boolean result) { + private void passOrFailCallback(String file, boolean result) { Instrumentation inst = getInstrumentation(); Bundle bundle = new Bundle(); bundle.putBoolean(file, result); inst.sendStatus(0, bundle); } + + private void getTestList() { + // Read test list. + try { + BufferedReader inReader = new BufferedReader(new FileReader(LAYOUT_TESTS_LIST_FILE)); + String line = inReader.readLine(); + while (line != null) { + if (line.startsWith(mTestPathPrefix)) + mTestList.add(line); + line = inReader.readLine(); + } + inReader.close(); + Log.v(LOGTAG, "Test list has " + mTestList.size() + " test(s)."); + } catch (Exception e) { + Log.e(LOGTAG, "Error while reading test list : " + e.getMessage()); + } + } + + private void resumeTestList() { + // read out the test name it stoped last time. + try { + BufferedReader inReader = new BufferedReader(new FileReader(TEST_STATUS_FILE)); + String line = inReader.readLine(); + for (int i = 0; i < mTestList.size(); i++) { + if (mTestList.elementAt(i).equals(line)) { + mTestList = new Vector<String>(mTestList.subList(i+1, mTestList.size())); + break; + } + } + inReader.close(); + } catch (Exception e) { + Log.e(LOGTAG, "Error reading " + TEST_STATUS_FILE); + } + } + + private void clearTestStatus() { + // Delete TEST_STATUS_FILE + try { + File f = new File(TEST_STATUS_FILE); + if (f.delete()) + Log.v(LOGTAG, "Deleted " + TEST_STATUS_FILE); + else + Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE); + } catch (Exception e) { + Log.e(LOGTAG, "Fail to delete " + TEST_STATUS_FILE + " : " + e.getMessage()); + } + } + + private void updateTestStatus(String s) { + // Write TEST_STATUS_FILE + try { + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(TEST_STATUS_FILE)); + bos.write(s.getBytes()); + bos.close(); + } catch (Exception e) { + Log.e(LOGTAG, "Cannot update file " + TEST_STATUS_FILE); + } + } + + private String getResultFile(String test) { + String shortName = test.substring(0, test.lastIndexOf('.')); + // Write actual results to result directory. + return shortName.replaceFirst(LAYOUT_TESTS_ROOT, LAYOUT_TESTS_RESULT_DIR) + "-result.txt"; + } + + private String getExpectedResultFile(String test) { + String shortName = test.substring(0, test.lastIndexOf('.')); + return shortName + "-expected.txt"; + } + + private String getAndroidExpectedResultFile(String expectedResultFile) { + return expectedResultFile.replaceFirst(LAYOUT_TESTS_ROOT, ANDROID_EXPECTED_RESULT_DIR); + } + + // Wrap up + private void failedCase(String file) { + Log.w("Layout test: ", file + " failed"); + mResultRecorder.failed(file); + } - public static void setTimeoutInMillis(int millis) { - mTimeoutInMillis = (millis > 0) ? millis : DEFAULT_TIMEOUT_IN_MILLIS; + private void passedCase(String file) { + Log.v("Layout test:", file + " passed"); + mResultRecorder.passed(file); } - public static void setLayoutTestDir(String name) { - if (name == null) - throw new AssertionError("Layout test directory cannot be null."); - layoutTestDir = HTMLHostActivity.LAYOUT_TESTS_ROOT + name; - Log.v("LayoutTestsAutoTest", " Only running the layout tests : " + layoutTestDir); + private void noresultCase(String file) { + Log.v("Layout test:", file + " no expected result"); + mResultRecorder.noresult(file); } + + private void processResult(String testFile, String actualResultFile, String expectedResultFile) { + Log.v(LOGTAG, " Processing result: " + testFile); + File actual = new File(actualResultFile); + File expected = new File(expectedResultFile); + if (actual.exists() && expected.exists()) { + try { + boolean passing = true; + BufferedReader fr = new BufferedReader(new FileReader(actual)); + BufferedReader fe = new BufferedReader(new FileReader(expected)); + while (true) { + String s1 = fr.readLine(); + String s2 = fe.readLine(); + if (s1 == null && s2 == null) + break; // both files are the same + if (s1 == null || s2 == null || !s1.equals(s2)) { + passing = false; + break; + } + } + + if (passing) { + passedCase(testFile); + } else { + failedCase(testFile); + } + + fe.close(); + fr.close(); + } catch (FileNotFoundException ex) { + Log.e(LOGTAG, "File not found : " + ex.getMessage()); + } catch (IOException ex) { + Log.e(LOGTAG, "IO Error : " + ex.getMessage()); + } + return; + } + + if (!expected.exists()) { + noresultCase(testFile); + } + } + + private void runTestAndWaitUntilDone(TestShellActivity activity, String test, int timeout) { + activity.setCallback(new TestShellCallback() { + public void finished() { + synchronized (LayoutTestsAutoTest.this) { + LayoutTestsAutoTest.this.notifyAll(); + } + } + }); + + String resultFile = getResultFile(test); + if (mRebaselineResults) { + String expectedResultFile = getExpectedResultFile(test); + File f = new File(expectedResultFile); + if (f.exists()) { + return; // don't run test and don't overwrite default tests. + } + + resultFile = getAndroidExpectedResultFile(expectedResultFile); + } + + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setClass(activity, TestShellActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(TestShellActivity.TEST_URL, "file://" + test); + intent.putExtra(TestShellActivity.RESULT_FILE, resultFile); + intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout); + activity.startActivity(intent); + + // Wait until done. + synchronized (this) { + try { + this.wait(); + } catch (InterruptedException e) { } + } + + if (!mRebaselineResults) { + String expectedResultFile = getExpectedResultFile(test); + File f = new File(expectedResultFile); + if (!f.exists()) { + expectedResultFile = getAndroidExpectedResultFile(expectedResultFile); + } + + processResult(test, resultFile, expectedResultFile); + } + } + // Invokes running of layout tests // and waits till it has finished running. public void executeLayoutTests(boolean resume) { - Instrumentation inst = getInstrumentation(); - - { - Activity activity = getActivity(); - Intent intent = new Intent(); - intent.setClass(activity, HTMLHostActivity.class); - intent.putExtra(HTMLHostActivity.RESUME_FROM_CRASH, resume); - intent.putExtra(HTMLHostActivity.SINGLE_TEST_MODE, false); - intent.putExtra(HTMLHostActivity.TEST_PATH_PREFIX, layoutTestDir); - intent.putExtra(HTMLHostActivity.TIMEOUT_IN_MILLIS, mTimeoutInMillis); - activity.startActivity(intent); - } + LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation(); + // A convenient method to be called by another activity. + + if (runner.mTestPath == null) { + Log.e(LOGTAG, "No test specified"); + return; + } + + this.mTestList = new Vector<String>(); - ActivityMonitor htmlHostActivityMonitor = - inst.addMonitor("com.android.dumprendertree.HTMLHostActivity", null, false); + // Read settings + try { + this.mTestPathPrefix = + (new File(LAYOUT_TESTS_ROOT + runner.mTestPath)).getCanonicalPath(); + } catch (IOException e) { + Log.e(LOGTAG, "Cannot find test path prefix: " + e.getMessage()); + return; + } + + this.mRebaselineResults = runner.mRebaseline; + + int timeout = runner.mTimeoutInMillis; + if (timeout <= 0) { + timeout = DEFAULT_TIMEOUT_IN_MILLIS; + } + + this.mResultRecorder = new MyTestRecorder(resume); + + if (!resume) + clearTestStatus(); + + getTestList(); + if (resume) + resumeTestList(); + + TestShellActivity activity = (TestShellActivity) getActivity(); - HTMLHostActivity activity = - (HTMLHostActivity) htmlHostActivityMonitor.waitForActivity(); + // Run tests. + for (int i = 0; i < mTestList.size(); i++) { + String s = mTestList.elementAt(i); + updateTestStatus(s); + // Run tests + runTestAndWaitUntilDone(activity, s, runner.mTimeoutInMillis); + } - while (!activity.hasFinishedRunning()) { - // Poll every 5 seconds to determine if the layout - // tests have finished running - try {Thread.sleep(5000); } catch(Exception e){} - } + updateTestStatus("#DONE"); + + activity.finish(); + } - // Wait few more seconds so that results are - // flushed to the /sdcard - try {Thread.sleep(5000); } catch(Exception e){} - // Clean up the HTMLHostActivity activity - activity.finish(); + private String getTestPath() { + LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation(); + + String test_path = LAYOUT_TESTS_ROOT; + if (runner.mTestPath != null) { + test_path += runner.mTestPath; + } + try { + test_path = new File(test_path).getCanonicalPath(); + } catch (IOException e) { + Log.e("LayoutTestsAutoTest", "Cannot get cannonical path " + e.getMessage()); + } + Log.v("LayoutTestsAutoTest", " Test path : " + test_path); + + return test_path; } public void generateTestList() { try { - File tests_list = new File(HTMLHostActivity.LAYOUT_TESTS_LIST_FILE); + File tests_list = new File(LAYOUT_TESTS_LIST_FILE); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tests_list, false)); - findTestsRecursively(bos, layoutTestDir); + findTestsRecursively(bos, getTestPath()); bos.flush(); bos.close(); } catch (Exception e) { @@ -156,7 +439,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase<Menu> { // in chunks. public void startLayoutTests() { try { - File tests_list = new File(HTMLHostActivity.LAYOUT_TESTS_LIST_FILE); + File tests_list = new File(LAYOUT_TESTS_LIST_FILE); if (!tests_list.exists()) generateTestList(); } catch (Exception e) { diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java new file mode 100644 index 0000000..b064dbb --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2008 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.dumprendertree; + +import android.app.Activity; +import android.app.Instrumentation; +import android.app.Instrumentation.ActivityMonitor; +import android.content.Intent; + +import android.util.Log; + +import android.os.Bundle; +import android.test.ActivityInstrumentationTestCase2; + +import com.android.dumprendertree.TestShellActivity; +import com.android.dumprendertree.TestShellCallback; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +class StreamPipe extends Thread { + InputStream in; + OutputStream out; + + StreamPipe(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + public void run() { + try { + byte[] buf = new byte[1024]; + int nofb = this.in.read(buf); + while (nofb != -1) { + this.out.write(buf, 0, nofb); + nofb = this.in.read(buf); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} + +public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> { + + private final static String LOGTAG = "LoadTest"; + private final static String LOAD_TEST_RESULT = "/sdcard/load_test_result.txt"; + + public LoadTestsAutoTest() { + super("com.android.dumprendertree", TestShellActivity.class); + } + + // This function writes the result of the layout test to + // Am status so that it can be picked up from a script. + public void passOrFailCallback(String file, boolean result) { + Instrumentation inst = getInstrumentation(); + Bundle bundle = new Bundle(); + bundle.putBoolean(file, result); + inst.sendStatus(0, bundle); + } + + // Invokes running of layout tests + // and waits till it has finished running. + public void runTest() { + LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation(); + + if (runner.mTestPath == null) { + Log.e(LOGTAG, "No test specified"); + return; + } + + TestShellActivity activity = (TestShellActivity) getActivity(); + + // Run tests + runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis); + + // TODO(fqian): let am instrumentation pass in the command line, currently + // am instrument does not allow spaces in the command. + runPostShellCommand("/system/bin/dumpsys meminfo"); + + // Kill activity + activity.finish(); + } + + private void runPostShellCommand(String cmd) { + if (cmd == null || cmd.length() == 0) + return; + + try { + // Call dumpsys meminfo + Process proc = Runtime.getRuntime().exec(cmd); + // Append output to LOAD_TEST_RESULT + InputStream input = proc.getInputStream(); + InputStream error = proc.getErrorStream(); + FileOutputStream out = new FileOutputStream(LOAD_TEST_RESULT, true); + + StreamPipe p_in = new StreamPipe(input, out); + StreamPipe p_err = new StreamPipe(error, System.err); + + p_in.start(); + p_err.start(); + + proc.waitFor(); + } catch (IOException e) { + Log.e(LOGTAG, e.getMessage()); + } catch (InterruptedException e) { + Log.e(LOGTAG, e.getMessage()); + } + } + + // A convenient method to be called by another activity. + private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout) { + activity.setCallback(new TestShellCallback() { + public void finished() { + synchronized (LoadTestsAutoTest.this) { + LoadTestsAutoTest.this.notifyAll(); + } + } + }); + + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setClass(activity, TestShellActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(TestShellActivity.TEST_URL, url); + intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout); + intent.putExtra(TestShellActivity.RESULT_FILE, LOAD_TEST_RESULT); + activity.startActivity(intent); + + // Wait until done. + synchronized (this) { + try { + this.wait(); + } catch (InterruptedException e) { } + } + } +} diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java index de0da61..00e0f89 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/Menu.java @@ -19,6 +19,7 @@ package com.android.dumprendertree; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.util.Log; import java.io.File; @@ -42,15 +43,12 @@ public class Menu extends FileList { } void processFile(String filename, boolean selection) - { - Intent result = new Intent(); - result.setClass(this, HTMLHostActivity.class); - result.putExtra(HTMLHostActivity.RESUME_FROM_CRASH, false); - result.putExtra(HTMLHostActivity.SINGLE_TEST_MODE, true); - result.putExtra(HTMLHostActivity.TEST_PATH_PREFIX, filename); - result.putExtra(HTMLHostActivity.TIMEOUT_IN_MILLIS, 8000); - startActivity(result); + { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setClass(this, TestShellActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(TestShellActivity.TEST_URL, "file://" + filename); + startActivity(intent); } - } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java new file mode 100644 index 0000000..bf8a3b3 --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java @@ -0,0 +1,426 @@ +/* + * Copyright (C) 2007 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.dumprendertree; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Vector; + +import android.app.Activity; +import android.content.Intent; +import android.util.Log; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; +import android.view.ViewGroup; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.widget.LinearLayout; +import android.os.*; + +public class TestShellActivity extends Activity implements LayoutTestController { + public class AsyncHandler extends Handler { + @Override + public void handleMessage(Message msg) { + if (msg.what == MSG_TIMEOUT) { + mTimedOut = true; + requestWebKitData(); + return; + } else if (msg.what == MSG_WEBKIT_DATA) { + TestShellActivity.this.dump(mTimedOut, (String)msg.obj); + return; + } + + super.handleMessage(msg); + } + } + + public void requestWebKitData() { + Message callback = mHandler.obtainMessage(MSG_WEBKIT_DATA); + + if (mRequestedWebKitData) + throw new AssertionError("Requested webkit data twice: " + mWebView.getUrl()); + + mRequestedWebKitData = true; + if (mDumpAsText) { + mWebView.documentAsText(callback); + } else { + mWebView.externalRepresentation(callback); + } + } + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + + LinearLayout contentView = new LinearLayout(this); + contentView.setOrientation(LinearLayout.VERTICAL); + setContentView(contentView); + + mWebView = new WebView(this); + mWebView.getSettings().setJavaScriptEnabled(true); + mWebView.setWebChromeClient(mChromeClient); + mEventSender = new WebViewEventSender(mWebView); + mCallbackProxy = new CallbackProxy(mEventSender, this); + + mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController"); + mWebView.addJavascriptInterface(mCallbackProxy, "eventSender"); + contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.0f)); + + mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); + + mHandler = new AsyncHandler(); + + Intent intent = getIntent(); + if (intent != null) { + executeIntent(intent); + } + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + executeIntent(intent); + } + + private void executeIntent(Intent intent) { + resetTestStatus(); + if (!Intent.ACTION_VIEW.equals(intent.getAction())) { + return; + } + + mTestUrl = intent.getStringExtra(TEST_URL); + if (mTestUrl == null) + return; + + mResultFile = intent.getStringExtra(RESULT_FILE); + mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 0); + + Log.v(LOGTAG, " Loading " + mTestUrl); + mWebView.loadUrl(mTestUrl); + + if (mTimeoutInMillis > 0) { + // Create a timeout timer + Message m = mHandler.obtainMessage(MSG_TIMEOUT); + mHandler.sendMessageDelayed(m, mTimeoutInMillis); + } + } + + @Override + protected void onStop() { + super.onStop(); + mWebView.stopLoading(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mWebView.destroy(); + mWebView = null; + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + Log.e(LOGTAG, "Low memory, kill self"); + System.exit(1); + } + + // Dump the page + public void dump(boolean timeout, String webkitData) { + if (mResultFile == null || mResultFile.length() == 0) { + finished(); + return; + } + + try { + File parentDir = new File(mResultFile).getParentFile(); + if (!parentDir.exists()) { + parentDir.mkdirs(); + } + + FileOutputStream os = new FileOutputStream(mResultFile); + if (timeout) { + Log.w("Layout test: Timeout", mResultFile); + os.write(TIMEOUT_STR.getBytes()); + os.write('\n'); + } + if (mDumpTitleChanges) + os.write(mTitleChanges.toString().getBytes()); + if (mDialogStrings != null) + os.write(mDialogStrings.toString().getBytes()); + mDialogStrings = null; + os.write(webkitData.getBytes()); + os.flush(); + os.close(); + } catch (IOException ex) { + Log.e(LOGTAG, "Cannot write to " + mResultFile + ", " + ex.getMessage()); + } + + finished(); + } + + public void setCallback(TestShellCallback callback) { + mCallback = callback; + } + + public void finished() { + if (mCallback != null) { + mCallback.finished(); + } + } + + // ....................................... + // LayoutTestController Functions + public void dumpAsText() { + mDumpAsText = true; + if (mWebView != null) { + String url = mWebView.getUrl(); + Log.v(LOGTAG, "dumpAsText called: "+url); + } + } + + public void waitUntilDone() { + mWaitUntilDone = true; + String url = mWebView.getUrl(); + Log.v(LOGTAG, "waitUntilDone called: " + url); + } + + public void notifyDone() { + String url = mWebView.getUrl(); + Log.v(LOGTAG, "notifyDone called: " + url); + if (mWaitUntilDone) { + mWaitUntilDone = false; + mChromeClient.onProgressChanged(mWebView, 100); + } + } + + public void display() { + mWebView.invalidate(); + } + + public void clearBackForwardList() { + mWebView.clearHistory(); + + } + + public void dumpBackForwardList() { + //printf("\n============== Back Forward List ==============\n"); + // mWebHistory + //printf("===============================================\n"); + + } + + public void dumpChildFrameScrollPositions() { + // TODO Auto-generated method stub + + } + + public void dumpEditingCallbacks() { + // TODO Auto-generated method stub + + } + + public void dumpSelectionRect() { + // TODO Auto-generated method stub + + } + + public void dumpTitleChanges() { + if (!mDumpTitleChanges) { + mTitleChanges = new StringBuffer(); + } + mDumpTitleChanges = true; + } + + public void keepWebHistory() { + if (!mKeepWebHistory) { + mWebHistory = new Vector(); + } + mKeepWebHistory = true; + } + + public void queueBackNavigation(int howfar) { + // TODO Auto-generated method stub + + } + + public void queueForwardNavigation(int howfar) { + // TODO Auto-generated method stub + + } + + public void queueLoad(String Url, String frameTarget) { + // TODO Auto-generated method stub + + } + + public void queueReload() { + mWebView.reload(); + } + + public void queueScript(String scriptToRunInCurrentContext) { + mWebView.loadUrl("javascript:"+scriptToRunInCurrentContext); + } + + public void repaintSweepHorizontally() { + // TODO Auto-generated method stub + + } + + public void setAcceptsEditing(boolean b) { + // TODO Auto-generated method stub + + } + + public void setMainFrameIsFirstResponder(boolean b) { + // TODO Auto-generated method stub + + } + + public void setWindowIsKey(boolean b) { + // This is meant to show/hide the window. The best I can find + // is setEnabled() + mWebView.setEnabled(b); + } + + public void testRepaint() { + mWebView.invalidate(); + } + + private final WebChromeClient mChromeClient = new WebChromeClient() { + @Override + public void onProgressChanged(WebView view, int newProgress) { + if (newProgress == 100) { + if (!mTimedOut && !mWaitUntilDone && !mRequestedWebKitData) { + String url = mWebView.getUrl(); + Log.v(LOGTAG, "Finished: "+ url); + mHandler.removeMessages(MSG_TIMEOUT); + requestWebKitData(); + } else { + String url = mWebView.getUrl(); + if (mTimedOut) { + Log.v(LOGTAG, "Timed out before finishing: " + url); + } else if (mWaitUntilDone) { + Log.v(LOGTAG, "Waiting for notifyDone: " + url); + } else if (mRequestedWebKitData) { + Log.v(LOGTAG, "Requested webkit data ready: " + url); + } + } + } + } + + @Override + public void onReceivedTitle(WebView view, String title) { + if (title.length() > 30) + title = "..."+title.substring(title.length()-30); + setTitle(title); + if (mDumpTitleChanges) { + mTitleChanges.append("TITLE CHANGED: "); + mTitleChanges.append(title); + mTitleChanges.append("\n"); + } + } + + @Override + public boolean onJsAlert(WebView view, String url, String message, + JsResult result) { + if (mDialogStrings == null) { + mDialogStrings = new StringBuffer(); + } + mDialogStrings.append("ALERT: "); + mDialogStrings.append(message); + mDialogStrings.append('\n'); + result.confirm(); + return true; + } + + @Override + public boolean onJsConfirm(WebView view, String url, String message, + JsResult result) { + if (mDialogStrings == null) { + mDialogStrings = new StringBuffer(); + } + mDialogStrings.append("CONFIRM: "); + mDialogStrings.append(message); + mDialogStrings.append('\n'); + result.confirm(); + return true; + } + + @Override + public boolean onJsPrompt(WebView view, String url, String message, + String defaultValue, JsPromptResult result) { + if (mDialogStrings == null) { + mDialogStrings = new StringBuffer(); + } + mDialogStrings.append("PROMPT: "); + mDialogStrings.append(message); + mDialogStrings.append(", default text: "); + mDialogStrings.append(defaultValue); + mDialogStrings.append('\n'); + result.confirm(); + return true; + } + }; + + private void resetTestStatus() { + mWaitUntilDone = false; + mDumpAsText = false; + mTimedOut = false; + mDumpTitleChanges = false; + mRequestedWebKitData = false; + mEventSender.resetMouse(); + } + + private WebView mWebView; + private WebViewEventSender mEventSender; + private AsyncHandler mHandler; + private TestShellCallback mCallback; + + private CallbackProxy mCallbackProxy; + + private String mTestUrl; + private String mResultFile; + private int mTimeoutInMillis; + + // States + private boolean mTimedOut; + private boolean mRequestedWebKitData; + private boolean mFinishedRunning; + + // Layout test controller variables. + private boolean mDumpAsText; + private boolean mWaitUntilDone; + private boolean mDumpTitleChanges; + private StringBuffer mTitleChanges; + private StringBuffer mDialogStrings; + private boolean mKeepWebHistory; + private Vector mWebHistory; + + static final String TIMEOUT_STR = "**Test timeout"; + + static final int MSG_TIMEOUT = 0; + static final int MSG_WEBKIT_DATA = 1; + + static final String LOGTAG="TestShell"; + + static final String TEST_URL = "TestUrl"; + static final String RESULT_FILE = "ResultFile"; + static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis"; +} diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java index 60a2915..759c443 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostCallbackInterface.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java @@ -16,6 +16,6 @@ package com.android.dumprendertree; -public interface HTMLHostCallbackInterface { - public void waitForFinish(); +public interface TestShellCallback { + public void finished(); } |