Title: [128181] trunk
Revision
128181
Author
[email protected]
Date
2012-09-11 07:10:48 -0700 (Tue, 11 Sep 2012)

Log Message

Tools: Support LayoutTests on non-rooted devices for Chromium Android.
https://bugs.webkit.org/show_bug.cgi?id=95346

Patch by Philippe Liard <[email protected]> on 2012-09-11
Reviewed by Dirk Pranke.

We were requiring root permissions to sync resource files with the
device by comparing host and device files' timestamp after we
synchronized the device and host clocks.
We now rely on md5sum provided by Chromium to handle data files
synchronization.

* Scripts/webkitpy/layout_tests/port/chromium.py:
(ChromiumPort._check_driver_build_up_to_date):
* Scripts/webkitpy/layout_tests/port/chromium_android.py:
(ChromiumAndroidDriver.__init__):
(ChromiumAndroidDriver._setup_test):
(ChromiumAndroidDriver._push_executable):
(ChromiumAndroidDriver._push_test_resources):
(ChromiumAndroidDriver._read_prompt):

LayoutTests: Support LayoutTests on non-rooted Android devices.
https://bugs.webkit.org/show_bug.cgi?id=95346

Patch by Philippe Liard <[email protected]> on 2012-09-11
Reviewed by Dirk Pranke.

http/tests/cache/resources/subresource-test.js was assuming that the
client and server clocks are the same which is no longer true since we
are getting rid of host/device clock synchronization.

* http/tests/cache/resources/cache-simulator.cgi:
* http/tests/cache/resources/current-time.cgi: Added.
* http/tests/cache/resources/subresource-test.js:
(getServerDate):
(nextTest):
(testComplete):
(runTests):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (128180 => 128181)


--- trunk/LayoutTests/ChangeLog	2012-09-11 14:04:32 UTC (rev 128180)
+++ trunk/LayoutTests/ChangeLog	2012-09-11 14:10:48 UTC (rev 128181)
@@ -1,3 +1,22 @@
+2012-09-11  Philippe Liard  <[email protected]>
+
+        Support LayoutTests on non-rooted Android devices.
+        https://bugs.webkit.org/show_bug.cgi?id=95346
+
+        Reviewed by Dirk Pranke.
+
+        http/tests/cache/resources/subresource-test.js was assuming that the
+        client and server clocks are the same which is no longer true since we
+        are getting rid of host/device clock synchronization.
+
+        * http/tests/cache/resources/cache-simulator.cgi:
+        * http/tests/cache/resources/current-time.cgi: Added.
+        * http/tests/cache/resources/subresource-test.js:
+        (getServerDate):
+        (nextTest):
+        (testComplete):
+        (runTests):
+
 2012-09-11  Sergio Villar Senin  <[email protected]>
 
         [GTK] WebKitGtk+ crashes with non-UTF8 HTTP header names

Added: trunk/LayoutTests/http/tests/cache/resources/current-time.cgi (0 => 128181)


--- trunk/LayoutTests/http/tests/cache/resources/current-time.cgi	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/current-time.cgi	2012-09-11 14:10:48 UTC (rev 128181)
@@ -0,0 +1,5 @@
+#!/usr/bin/perl -w
+
+print "Content-type: text/plain\n";
+print "\n";
+print time();
Property changes on: trunk/LayoutTests/http/tests/cache/resources/current-time.cgi
___________________________________________________________________

Added: svn:executable

Modified: trunk/LayoutTests/http/tests/cache/resources/subresource-test.js (128180 => 128181)


--- trunk/LayoutTests/http/tests/cache/resources/subresource-test.js	2012-09-11 14:04:32 UTC (rev 128180)
+++ trunk/LayoutTests/http/tests/cache/resources/subresource-test.js	2012-09-11 14:10:48 UTC (rev 128181)
@@ -25,6 +25,22 @@
 document.body.appendChild(consoleDiv);
 frame2._onload_ = function () { loadedFrameCount++; }
 
+function getServerDate()
+{
+    var req = new XMLHttpRequest();
+    var t0 = new Date().getTime();
+    req.open('GET', "/cache/resources/current-time.cgi", false /* blocking */);
+    req.send();
+    var serverToClientTime = (new Date().getTime() - t0) / 2;
+    if (req.status != 200) {
+        console.log("unexpected status code " + req.status + ", expected 200.");
+        return new Date();
+    }
+    return new Date((parseInt(req.responseText) * 1000) + serverToClientTime);
+}
+
+var serverClientTimeDelta = getServerDate().getTime() - new Date().getTime();
+
 function loadTestFrame(frame, testSpec)
 {
     var first = true;
@@ -67,7 +83,7 @@
 {
     var testSpec = tests[currentTest];
     uniqueId = Math.floor(100000000 * Math.random());
-    now = new Date();
+    now = new Date(new Date().getTime() + serverClientTimeDelta);
     if (!testSpec) {
         if (window.testRunner)
             testRunner.notifyDone();
@@ -80,22 +96,22 @@
 function testComplete(testSpec)
 {
     var line = document.createElement('div');
-    var result = frame1.contentWindow.randomNumber == frame2.contentWindow.randomNumber ? 'Cached' : 'Uncached';    
+    var result = frame1.contentWindow.randomNumber == frame2.contentWindow.randomNumber ? 'Cached' : 'Uncached';
     var passed = result == testSpec.expectedResult;
 
     if (testSpec.description)
         line.innerHTML += testSpec.description;
     else {
-        for (var header in testSpec.testHeaders) 
+        for (var header in testSpec.testHeaders)
             line.innerHTML += header + ": " + testSpec.testHeaders[header] + "; ";
     }
     if (testSpec.delay)
         line.innerHTML += "[delay=" + testSpec.delay + "s] "
     line.innerHTML += "  (result=" + result + " expected=" + testSpec.expectedResult + ") ";
     line.innerHTML += passed ? "<font color=green>PASS</font> " : "<font color=red>FAIL</font> "
-        
+
     consoleDiv.appendChild(line);
-    
+
     nextTest();
 }
 
@@ -106,5 +122,4 @@
         nextTest();
     else
         setTimeout(runTests, 100);
-
 }

Modified: trunk/Tools/ChangeLog (128180 => 128181)


--- trunk/Tools/ChangeLog	2012-09-11 14:04:32 UTC (rev 128180)
+++ trunk/Tools/ChangeLog	2012-09-11 14:10:48 UTC (rev 128181)
@@ -1,3 +1,25 @@
+2012-09-11  Philippe Liard  <[email protected]>
+
+        Support LayoutTests on non-rooted devices for Chromium Android.
+        https://bugs.webkit.org/show_bug.cgi?id=95346
+
+        Reviewed by Dirk Pranke.
+
+        We were requiring root permissions to sync resource files with the
+        device by comparing host and device files' timestamp after we
+        synchronized the device and host clocks.
+        We now rely on md5sum provided by Chromium to handle data files
+        synchronization.
+
+        * Scripts/webkitpy/layout_tests/port/chromium.py:
+        (ChromiumPort._check_driver_build_up_to_date):
+        * Scripts/webkitpy/layout_tests/port/chromium_android.py:
+        (ChromiumAndroidDriver.__init__):
+        (ChromiumAndroidDriver._setup_test):
+        (ChromiumAndroidDriver._push_executable):
+        (ChromiumAndroidDriver._push_test_resources):
+        (ChromiumAndroidDriver._read_prompt):
+
 2012-09-11  Simon Hausmann  <[email protected]>
 
         [Qt] Fix output paths on Windows

Modified: trunk/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp (128180 => 128181)


--- trunk/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp	2012-09-11 14:04:32 UTC (rev 128180)
+++ trunk/Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp	2012-09-11 14:10:48 UTC (rev 128181)
@@ -121,11 +121,11 @@
                 '<(source_dir)/WebKit/chromium/WebKit.gyp:inspector_resources',
                 '<(source_dir)/WebKit/chromium/WebKit.gyp:webkit',
                 '<(source_dir)/WTF/WTF.gyp/WTF.gyp:wtf',
+                '<(chromium_src_dir)/base/base.gyp:test_support_base',
                 '<(chromium_src_dir)/build/temp_gyp/googleurl.gyp:googleurl',
                 '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
                 '<(chromium_src_dir)/third_party/mesa/mesa.gyp:osmesa',
                 '<(chromium_src_dir)/v8/tools/gyp/v8.gyp:v8',
-                '<(chromium_src_dir)/base/base.gyp:test_support_base',
                 '<(chromium_src_dir)/webkit/support/webkit_support.gyp:blob',
                 '<(chromium_src_dir)/webkit/support/webkit_support.gyp:webkit_support',
             ],
@@ -282,8 +282,9 @@
                     'type': 'shared_library',
                     'dependencies': [
                         '<(chromium_src_dir)/base/base.gyp:test_support_base',
+                        '<(chromium_src_dir)/testing/android/native_test.gyp:native_test_native_code',
                         '<(chromium_src_dir)/tools/android/forwarder/forwarder.gyp:forwarder',
-                        '<(chromium_src_dir)/testing/android/native_test.gyp:native_test_native_code',
+                        '<(chromium_src_dir)/tools/android/md5sum/md5sum.gyp:md5sum',
                     ],
                     'dependencies!': [
                         'ImageDiff',

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py (128180 => 128181)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py	2012-09-11 14:04:32 UTC (rev 128180)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium.py	2012-09-11 14:10:48 UTC (rev 128181)
@@ -405,10 +405,9 @@
 
                 if (debug_mtime > release_mtime and configuration == 'Release' or
                     release_mtime > debug_mtime and configuration == 'Debug'):
-                    _log.warning('You are not running the most '
-                                 'recent DumpRenderTree binary. You need to '
-                                 'pass --debug or not to select between '
-                                 'Debug and Release.')
+                    most_recent_binary = 'Release' if configuration == 'Debug' else 'Debug'
+                    _log.warning('You are running the %s binary. However the %s binary appears to be more recent. '
+                                 'Please pass --%s.', configuration, most_recent_binary, most_recent_binary.lower())
                     _log.warning('')
             # This will fail if we don't have both a debug and release binary.
             # That's fine because, in this case, we must already be running the

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py (128180 => 128181)


--- trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py	2012-09-11 14:04:32 UTC (rev 128180)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py	2012-09-11 14:10:48 UTC (rev 128181)
@@ -31,6 +31,8 @@
 import logging
 import os
 import re
+import sets
+import subprocess
 import threading
 import time
 
@@ -54,7 +56,6 @@
 # and Chromium's webkit/support/platform_support_android.cc.
 DEVICE_DRT_DIR = DEVICE_SOURCE_ROOT_DIR + 'drt/'
 DEVICE_FORWARDER_PATH = DEVICE_DRT_DIR + 'forwarder'
-DEVICE_DRT_STAMP_PATH = DEVICE_DRT_DIR + 'DumpRenderTree.stamp'
 
 DRT_APP_PACKAGE = 'org.chromium.native_test'
 DRT_ACTIVITY_FULL_NAME = DRT_APP_PACKAGE + '/.ChromeNativeTestActivity'
@@ -137,6 +138,8 @@
     'compositing/resources/video.mp4',
 ]
 
+MD5SUM_DEVICE_FILE_NAME = 'md5sum_bin'
+MD5SUM_DEVICE_PATH = '/data/local/tmp/' + MD5SUM_DEVICE_FILE_NAME
 
 class ChromiumAndroidPort(chromium.ChromiumPort):
     port_name = 'chromium-android'
@@ -306,6 +309,8 @@
 
 
 class ChromiumAndroidDriver(driver.Driver):
+    _data_already_pushed_for_worker = sets.Set()
+
     def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
         super(ChromiumAndroidDriver, self).__init__(port, worker_number, pixel_tests, no_timeout)
         self._cmd_line = None
@@ -319,11 +324,26 @@
         self._original_governors = {}
         self._device_serial = port._get_device_serial(worker_number)
         self._adb_command = ['adb', '-s', self._device_serial]
+        self._setup_md5sum()
+        if not worker_number in ChromiumAndroidDriver._data_already_pushed_for_worker:
+            self._push_executable()
+            self._push_fonts()
+            self._push_test_resources()
+            ChromiumAndroidDriver._data_already_pushed_for_worker.add(worker_number)
 
     def __del__(self):
         self._teardown_performance()
         super(ChromiumAndroidDriver, self).__del__()
 
+    def _setup_md5sum(self):
+        self._md5sum_path = self._port._build_path_with_configuration(self._port.get_option('configuration'), MD5SUM_DEVICE_FILE_NAME)
+        assert os.path.exists(self._md5sum_path)
+
+        if self._file_exists_on_device(MD5SUM_DEVICE_PATH):
+            return
+        if not self._push_to_device(self._md5sum_path, MD5SUM_DEVICE_PATH):
+            _log.error('Could not push md5sum to device')
+
     def _setup_test(self):
         if self._has_setup:
             return
@@ -340,10 +360,6 @@
         self._run_adb_command(['shell', 'mkdir', '-p', DEVICE_DRT_DIR])
         self._run_adb_command(['shell', 'chmod', '777', DEVICE_DRT_DIR])
 
-        self._push_executable()
-        self._push_fonts()
-        self._synchronize_datetime()
-
         # Delete the disk cache if any to ensure a clean test run.
         # This is like what's done in ChromiumPort.setup_test_run but on the device.
         self._run_adb_command(['shell', 'rm', '-r', DRT_APP_CACHE_DIR])
@@ -357,29 +373,34 @@
     def _abort(self, message):
         raise AssertionError('[%s] %s' % (self._device_serial, message))
 
+    @staticmethod
+    def _extract_hashes_from_md5sum_output(md5sum_output):
+        assert md5sum_output
+        return [line.split('  ')[0] for line in md5sum_output]
+
+    def _push_file_if_needed(self, host_file, device_file):
+        assert os.path.exists(host_file)
+        device_hashes = self._extract_hashes_from_md5sum_output(
+                self._port.host.executive.popen(self._adb_command + ['shell', MD5SUM_DEVICE_PATH, device_file],
+                                                stdout=subprocess.PIPE).stdout)
+        host_hashes = self._extract_hashes_from_md5sum_output(
+                self._port.host.executive.popen(args=['%s_host' % self._md5sum_path, host_file],
+                                                stdout=subprocess.PIPE).stdout)
+        if host_hashes and device_hashes == host_hashes:
+            return
+        self._push_to_device(host_file, device_file)
+
     def _push_executable(self):
+        self._push_file_if_needed(self._port._path_to_forwarder(), DEVICE_FORWARDER_PATH)
+        self._push_file_if_needed(self._port._build_path('DumpRenderTree.pak'), DEVICE_DRT_DIR + 'DumpRenderTree.pak')
+        self._push_file_if_needed(self._port._build_path('DumpRenderTree_resources'), DEVICE_DRT_DIR + 'DumpRenderTree_resources')
+        self._push_file_if_needed(self._port._build_path('android_main_fonts.xml'), DEVICE_DRT_DIR + 'android_main_fonts.xml')
+        self._push_file_if_needed(self._port._build_path('android_fallback_fonts.xml'), DEVICE_DRT_DIR + 'android_fallback_fonts.xml')
+        self._run_adb_command(['uninstall', DRT_APP_PACKAGE])
         drt_host_path = self._port._path_to_driver()
-        forwarder_host_path = self._port._path_to_forwarder()
-        host_stamp = int(float(max(os.stat(drt_host_path).st_mtime,
-                                   os.stat(forwarder_host_path).st_mtime)))
-        device_stamp = int(float(self._run_adb_command([
-            'shell', 'cat %s 2>/dev/null || echo 0' % DEVICE_DRT_STAMP_PATH])))
-        if device_stamp != host_stamp:
-            self._log_debug('Pushing executable')
-            self._push_to_device(forwarder_host_path, DEVICE_FORWARDER_PATH)
-            self._run_adb_command(['uninstall', DRT_APP_PACKAGE])
-            install_result = self._run_adb_command(['install', drt_host_path])
-            if install_result.find('Success') == -1:
-                self._abort('Failed to install %s onto device: %s' % (drt_host_path, install_result))
-            self._push_to_device(self._port._build_path('DumpRenderTree.pak'), DEVICE_DRT_DIR + 'DumpRenderTree.pak')
-            self._push_to_device(self._port._build_path('DumpRenderTree_resources'), DEVICE_DRT_DIR + 'DumpRenderTree_resources')
-            self._push_to_device(self._port._build_path('android_main_fonts.xml'), DEVICE_DRT_DIR + 'android_main_fonts.xml')
-            self._push_to_device(self._port._build_path('android_fallback_fonts.xml'), DEVICE_DRT_DIR + 'android_fallback_fonts.xml')
-            # Version control of test resources is dependent on executables,
-            # because we will always rebuild executables when resources are
-            # updated.
-            self._push_test_resources()
-            self._run_adb_command(['shell', 'echo %d >%s' % (host_stamp, DEVICE_DRT_STAMP_PATH)])
+        install_result = self._run_adb_command(['install', drt_host_path])
+        if install_result.find('Success') == -1:
+            self._abort('Failed to install %s onto device: %s' % (drt_host_path, install_result))
 
     def _push_fonts(self):
         if not self._check_version(DEVICE_FONTS_DIR, FONT_FILES_VERSION):
@@ -394,19 +415,8 @@
     def _push_test_resources(self):
         self._log_debug('Pushing test resources')
         for resource in TEST_RESOURCES_TO_PUSH:
-            self._push_to_device(self._port.layout_tests_dir() + '/' + resource, DEVICE_LAYOUT_TESTS_DIR + resource)
+            self._push_file_if_needed(self._port.layout_tests_dir() + '/' + resource, DEVICE_LAYOUT_TESTS_DIR + resource)
 
-    def _synchronize_datetime(self):
-        # The date/time between host and device may not be synchronized.
-        # We need to make them synchronized, otherwise tests might fail.
-        try:
-            # Get seconds since 1970-01-01 00:00:00 UTC.
-            host_datetime = self._port._executive.run_command(['date', '-u', '+%s'])
-        except:
-            # Reset to 1970-01-01 00:00:00 UTC.
-            host_datetime = 0
-        self._run_adb_command(['shell', 'date -u %s' % (host_datetime)])
-
     def _check_version(self, dir, version):
         assert(dir.endswith('/'))
         try:
@@ -664,8 +674,6 @@
         while True:
             current_char = self._server_process.read_stdout(deadline, 1)
             if current_char == ' ':
-                if last_char == '#':
+                if last_char in ('#', '$'):
                     return
-                if last_char == '$':
-                    raise AssertionError('Adbd is not running as root')
             last_char = current_char
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to