Tools/ChangeLog

 12012-05-18 Xianzhu Wang <wangxianzhu@chromium.org>
 2
 3 [Chromium-Android] Run DumpRenderTree as an apk
 4 https://bugs.webkit.org/show_bug.cgi?id=86862
 5
 6 chromium_android.py is modified to support running DumpRenderTree as
 7 an apk, so that we can run the tests (e.g. video) requiring features
 8 implemented in Java on Android.
 9
 10 BTW split TestShellLinux.cpp into TestShellPosix.cpp and
 11 TestShellX11.cpp. TestShellPosix.cpp and TestShellAndroid.cpp are
 12 compiled for Android.
 13
 14 Reviewed by NOBODY (OOPS!).
 15
 16 * DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp:
 17 * DumpRenderTree/DumpRenderTree.gypi:
 18 * DumpRenderTree/chromium/TestShellAndroid.cpp: Added. Directs stdin/stdout/stderr to fifos and files.
 19 * DumpRenderTree/chromium/TestShellGtk.cpp:
 20 * DumpRenderTree/chromium/TestShellLinux.cpp: Removed. Split into TestShellX11.cpp and TestShellPosix.cpp.
 21 * DumpRenderTree/chromium/TestShellPosix.cpp: The posix part (used on Linux and Android) of the original TestShellLinux.cpp.
 22 * DumpRenderTree/chromium/TestShellX11.cpp: The X11 (fontconfig) part of the original TestShellLinux.cpp.
 23 (setupFontconfig):
 24 (platformInit):
 25 * Scripts/webkitpy/layout_tests/port/chromium_android.py:
 26 (ChromiumAndroidPort.__init__):
 27 (ChromiumAndroidPort.default_child_processes):
 28 (ChromiumAndroidPort.check_wdiff):
 29 (ChromiumAndroidPort.check_build):
 30 (ChromiumAndroidPort.start_helper):
 31 (ChromiumAndroidPort.skipped_layout_tests):
 32 (ChromiumAndroidPort):
 33 (ChromiumAndroidPort._path_to_driver):
 34 (ChromiumAndroidPort._get_crash_log):
 35 (ChromiumAndroidPort._push_executable):
 36 (ChromiumAndroidPort._run_adb_command):
 37 (ChromiumAndroidPort._get_last_stacktrace):
 38 (ChromiumAndroidPort._get_logcat):
 39 (ChromiumAndroidDriver):
 40 (ChromiumAndroidDriver.__init__):
 41 (ChromiumAndroidDriver._command_wrapper):
 42 (ChromiumAndroidDriver.cmd_line):
 43 (ChromiumAndroidDriver._file_exists_on_device):
 44 (ChromiumAndroidDriver._timeout_killer):
 45 (ChromiumAndroidDriver._start):
 46 (ChromiumAndroidDriver.run_test):
 47 (ChromiumAndroidDriver.stop):
 48 (ChromiumAndroidDriver._write_command_and_read_line):
 49 (ChromiumAndroidDriver._output_image):
 50 (ChromiumAndroidDriver._get_stderr):
 51
1522012-05-18 Thiago Marcos P. Santos <thiago.santos@intel.com>
253
354 [EFL] Buildbot output does not print result stats anymore
117639

Tools/DumpRenderTree/DumpRenderTree.gypi

3434 'chromium/TestNavigationController.h',
3535 'chromium/TestShell.cpp',
3636 'chromium/TestShell.h',
37  'chromium/TestShellLinux.cpp',
 37 'chromium/TestShellAndroid.cpp',
3838 'chromium/TestShellGtk.cpp',
3939 'chromium/TestShellMac.mm',
 40 'chromium/TestShellPosix.cpp',
4041 'chromium/TestShellWin.cpp',
 42 'chromium/TestShellX11.cpp',
4143 'chromium/TestWebPlugin.cpp',
4244 'chromium/TestWebPlugin.h',
4345 'chromium/TextInputController.cpp',
117639

Tools/DumpRenderTree/DumpRenderTree.gyp/DumpRenderTree.gyp

7878 'type': 'executable',
7979 'mac_bundle': 1,
8080 'dependencies': [
 81 'ImageDiff',
 82 'TestNetscapePlugIn',
 83 'copy_TestNetscapePlugIn',
8184 '<(source_dir)/WebKit/chromium/WebKit.gyp:inspector_resources',
8285 '<(source_dir)/WebKit/chromium/WebKit.gyp:webkit',
8386 '<(source_dir)/WTF/WTF.gyp/WTF.gyp:wtf',
8487 '<(chromium_src_dir)/build/temp_gyp/googleurl.gyp:googleurl',
8588 '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
 89 '<(chromium_src_dir)/third_party/mesa/mesa.gyp:osmesa',
8690 '<(chromium_src_dir)/v8/tools/gyp/v8.gyp:v8',
8791 '<(chromium_src_dir)/base/base.gyp:test_support_base',
8892 '<(chromium_src_dir)/webkit/support/webkit_support.gyp:blob',

187191 ['exclude', 'Mac\\.cpp$'],
188192 ],
189193 }],
 194 ['os_posix!=1 or OS=="mac"', {
 195 'sources/': [
 196 ['exclude', 'Posix\\.cpp$'],
 197 ],
 198 }],
190199 ['use_x11 == 1', {
191200 'dependencies': [
192201 '<(chromium_src_dir)/build/linux/system.gyp:fontconfig',

212221 ],
213222 },{ # use_x11 != 1
214223 'sources/': [
215  ['exclude', 'Linux\\.cpp$']
 224 ['exclude', 'X11\\.cpp$'],
216225 ]
217226 }],
218227 ['toolkit_uses_gtk == 1', {

231240 ]
232241 }],
233242 ['OS=="android"', {
 243 'type': 'shared_library',
234244 'dependencies': [
235245 'ImageDiff#host',
 246 '<(chromium_src_dir)/base/base.gyp:test_support_base',
 247 '<(chromium_src_dir)/tools/android/forwarder/forwarder.gyp:forwarder',
 248 '<(chromium_src_dir)/testing/android/native_test.gyp:native_test_native_code',
236249 ],
237  'sources/': [
238  ['include', 'chromium/TestShellLinux\\.cpp$'],
239  ],
240  },{ # OS!="android"
241  'sources/': [
242  ['exclude', '(Android)\\.cpp$']
243  ],
244  'dependencies': [
 250 'dependencies!': [
245251 'ImageDiff',
 252 'TestNetscapePlugIn',
246253 'copy_TestNetscapePlugIn',
247254 '<(chromium_src_dir)/third_party/mesa/mesa.gyp:osmesa',
248255 ],
 256 'copies': [{
 257 'destination': '<(PRODUCT_DIR)',
 258 'files': [
 259 '<(ahem_path)',
 260 '<(INTERMEDIATE_DIR)/repack/DumpRenderTree.pak',
 261 ]
 262 }],
 263 }, { # OS!="android"
 264 'sources/': [
 265 ['exclude', 'Android\\.cpp$'],
 266 ],
249267 }],
250268 ['inside_chromium_build==1 and component=="shared_library"', {
251269 'sources': [

383401 'cflags_cc': ['-Wno-c++0x-compat'],
384402 },
385403 }],
 404 ['OS=="android"', {
 405 # Wrap libDumpRenderTree.so into an android apk for execution.
 406 # See <(chromium_src_dir)/base/base.gyp for TODO(jrg)s about this strategy.
 407 'targets': [{
 408 'target_name': 'DumpRenderTree_apk',
 409 'type': 'none',
 410 'dependencies': [
 411 'DumpRenderTree',
 412 ],
 413 'actions': [{
 414 # Generate apk files (including source and antfile) from
 415 # a template, and builds them.
 416 'action_name': 'generate_and_build',
 417 'inputs': [
 418 '<(chromium_src_dir)/testing/android/generate_native_test.py',
 419 '<(PRODUCT_DIR)/lib.target/libDumpRenderTree.so',
 420 # TODO(wangxianzhu): Build the jar for native tests with SDK.
 421 # For now we are using Android.mk to build the apk.
 422 ],
 423 'outputs': [
 424 '<(PRODUCT_DIR)/DumpRenderTree_apk/ChromeNativeTests-debug.apk',
 425 ],
 426 'action': [
 427 '<(chromium_src_dir)/testing/android/generate_native_test.py',
 428 '--native_library',
 429 '<(PRODUCT_DIR)/lib.target/libDumpRenderTree.so',
 430 # TODO(wangxianzhu): Build the jar for native tests with SDK.
 431 # '--jar',
 432 # 'foo/bar.jar',
 433 '--output',
 434 '<(PRODUCT_DIR)/DumpRenderTree_apk',
 435 '--ant-args',
 436 '-DPRODUCT_DIR=<(PRODUCT_DIR)',
 437 '--ant-compile'
 438 ],
 439 }],
 440 }],
 441 }],
386442 ], # conditions
387443}
117639

Tools/DumpRenderTree/chromium/TestShellAndroid.cpp

 1/*
 2 * Copyright (C) 2012 Google Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions are
 6 * met:
 7 *
 8 * * Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * * Redistributions in binary form must reproduce the above
 11 * copyright notice, this list of conditions and the following disclaimer
 12 * in the documentation and/or other materials provided with the
 13 * distribution.
 14 * * Neither the name of Google Inc. nor the names of its
 15 * contributors may be used to endorse or promote products derived from
 16 * this software without specific prior written permission.
 17 *
 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29 */
 30
 31#include "config.h"
 32#include "TestShell.h"
 33
 34#include <android/log.h>
 35#include <errno.h>
 36#include <stdio.h>
 37#include <sys/stat.h>
 38#include <sys/types.h>
 39#include <unistd.h>
 40#include <wtf/Assertions.h>
 41
 42namespace {
 43
 44const char optionInFifo[] = "--in-fifo=";
 45const char optionOutFifo[] = "--out-fifo=";
 46const char optionErrFile[] = "--err-file=";
 47
 48void androidLogError(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
 49
 50void androidLogError(const char* format, ...)
 51{
 52 va_list args;
 53 va_start(args, format);
 54 __android_log_vprint(ANDROID_LOG_ERROR, "DumpRenderTree", format, args);
 55 va_end(args);
 56}
 57
 58void removeArg(int index, int* argc, char*** argv)
 59{
 60 for (int i = index; i < *argc; ++i)
 61 (*argv)[i] = (*argv)[i + 1];
 62 --*argc;
 63}
 64
 65void createFifo(const char* fifoPath)
 66{
 67 unlink(fifoPath);
 68 if (mkfifo(fifoPath, 0600)) {
 69 androidLogError("Failed to create fifo %s: %s\n", fifoPath, strerror(errno));
 70 exit(EXIT_FAILURE);
 71 }
 72}
 73
 74void redirectToFile(FILE* stream, const char* path, const char* mode)
 75{
 76 if (!freopen(path, mode, stream)) {
 77 androidLogError("Failed to redirect stream to file: %s: %s\n", path, strerror(errno));
 78 exit(EXIT_FAILURE);
 79 }
 80}
 81
 82} // namespace
 83
 84void platformInit(int* argc, char*** argv)
 85{
 86 const char* inFifo = 0;
 87 const char* outFifo = 0;
 88 const char* errFile = 0;
 89 for (int i = 1; i < *argc; ) {
 90 const char* argument = (*argv)[i];
 91 if (strstr(argument, optionInFifo) == argument) {
 92 inFifo = argument + strlen(optionInFifo);
 93 createFifo(inFifo);
 94 removeArg(i, argc, argv);
 95 } else if (strstr(argument, optionOutFifo) == argument) {
 96 outFifo = argument + strlen(optionOutFifo);
 97 createFifo(outFifo);
 98 removeArg(i, argc, argv);
 99 } else if (strstr(argument, optionErrFile) == argument) {
 100 errFile = argument + strlen(optionErrFile);
 101 removeArg(i, argc, argv);
 102 } else
 103 ++i;
 104 }
 105
 106 // The order of createFifo() and redirectToFifo() is important to avoid deadlock.
 107 if (outFifo)
 108 redirectToFile(stdout, outFifo, "w");
 109 if (inFifo)
 110 redirectToFile(stdin, inFifo, "r");
 111 if (errFile)
 112 redirectToFile(stderr, errFile, "w");
 113 else {
 114 // Redirect stderr to stdout.
 115 dup2(1, 2);
 116 }
 117}
0

Tools/DumpRenderTree/chromium/TestShellGtk.cpp

3131#include "config.h"
3232#include "TestShell.h"
3333
34 #include "webkit/support/webkit_support.h"
35 #include <fontconfig/fontconfig.h>
3634#include <gtk/gtk.h>
37 #include <signal.h>
38 
3935
4036void openStartupDialog()
4137{
117639

Tools/DumpRenderTree/chromium/TestShellLinux.cpp

1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  * * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "TestShell.h"
33 
34 #include "SkTypeface.h"
35 #include "WebView.h"
36 #include "webkit/support/webkit_support.h"
37 
38 #if !OS(ANDROID)
39 #include <fontconfig/fontconfig.h>
40 #endif
41 
42 #if USE(GTK)
43 #include <gtk/gtk.h>
44 #endif
45 #include <signal.h>
46 #include <unistd.h>
47 
48 static void AlarmHandler(int)
49 {
50  // If the alarm alarmed, kill the process since we have a really bad hang.
51  puts("\n#TEST_TIMED_OUT\n");
52  puts("#EOF\n");
53  fflush(stdout);
54  exit(0);
55 }
56 
57 void TestShell::waitTestFinished()
58 {
59  ASSERT(!m_testIsPending);
60  m_testIsPending = true;
61 
62  // Install an alarm signal handler that will kill us if we time out.
63  struct sigaction alarmAction;
64  alarmAction.sa_handler = AlarmHandler;
65  sigemptyset(&alarmAction.sa_mask);
66  alarmAction.sa_flags = 0;
67 
68  struct sigaction oldAction;
69  sigaction(SIGALRM, &alarmAction, &oldAction);
70  alarm(layoutTestTimeoutForWatchDog() / 1000);
71 
72  // TestFinished() will post a quit message to break this loop when the page
73  // finishes loading.
74  while (m_testIsPending)
75  webkit_support::RunMessageLoop();
76 
77  // Remove the alarm.
78  alarm(0);
79  sigaction(SIGALRM, &oldAction, 0);
80 }
81 
82 #if !OS(ANDROID)
83 static bool checkAndLoadFontFile(FcConfig* fontcfg, const char* path1, const char* path2)
84 {
85  const char* font = path1;
86  if (access(font, R_OK) < 0) {
87  font = path2;
88  if (access(font, R_OK) < 0) {
89  fprintf(stderr, "You are missing %s or %s. Without this, some layout tests may fail. "
90  "See http://code.google.com/p/chromium/wiki/LayoutTestsLinux "
91  "for more.\n", path1, path2);
92  return false;
93  }
94  }
95  if (!FcConfigAppFontAddFile(fontcfg, (FcChar8 *) font)) {
96  fprintf(stderr, "Failed to load font %s\n", font);
97  return false;
98  }
99  return true;
100 }
101 
102 static void setupFontconfig()
103 {
104  // We wish to make the layout tests reproducable with respect to fonts. Skia
105  // uses fontconfig to resolve font family names from WebKit into actual font
106  // files found on the current system. This means that fonts vary based on the
107  // system and also on the fontconfig configuration.
108  //
109  // To avoid this we initialise fontconfig here and install a configuration
110  // which only knows about a few, select, fonts.
111 
112  // We have fontconfig parse a config file from our resources file. This
113  // sets a number of aliases ("sans"->"Arial" etc), but doesn't include any
114  // font directories.
115  FcInit();
116 
117  char drtPath[PATH_MAX + 1];
118  int drtPathSize = readlink("/proc/self/exe", drtPath, PATH_MAX);
119  if (drtPathSize < 0 || drtPathSize > PATH_MAX) {
120  fputs("Unable to resolve /proc/self/exe.", stderr);
121  exit(1);
122  }
123  drtPath[drtPathSize] = 0;
124  std::string drtDirPath(drtPath);
125  size_t lastPathPos = drtDirPath.rfind("/");
126  ASSERT(lastPathPos != std::string::npos);
127  drtDirPath.erase(lastPathPos + 1);
128 
129  FcConfig* fontcfg = FcConfigCreate();
130  std::string fontconfigPath = drtDirPath + "fonts.conf";
131  if (!FcConfigParseAndLoad(fontcfg, reinterpret_cast<const FcChar8*>(fontconfigPath.c_str()), true)) {
132  fputs("Failed to parse fontconfig config file\n", stderr);
133  exit(1);
134  }
135 
136  // This is the list of fonts that fontconfig will know about. It
137  // will try its best to match based only on the fonts here in. The
138  // paths are where these fonts are found on our Ubuntu boxes.
139  static const char *const fonts[] = {
140  "/usr/share/fonts/truetype/kochi/kochi-gothic.ttf",
141  "/usr/share/fonts/truetype/kochi/kochi-mincho.ttf",
142  "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf",
143  "/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf",
144  "/usr/share/fonts/truetype/msttcorefonts/Arial_Bold_Italic.ttf",
145  "/usr/share/fonts/truetype/msttcorefonts/Arial_Italic.ttf",
146  "/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf",
147  "/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS_Bold.ttf",
148  "/usr/share/fonts/truetype/msttcorefonts/Courier_New.ttf",
149  "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold.ttf",
150  "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold_Italic.ttf",
151  "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Italic.ttf",
152  "/usr/share/fonts/truetype/msttcorefonts/Georgia.ttf",
153  "/usr/share/fonts/truetype/msttcorefonts/Georgia_Bold.ttf",
154  "/usr/share/fonts/truetype/msttcorefonts/Georgia_Bold_Italic.ttf",
155  "/usr/share/fonts/truetype/msttcorefonts/Georgia_Italic.ttf",
156  "/usr/share/fonts/truetype/msttcorefonts/Impact.ttf",
157  "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS.ttf",
158  "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Bold.ttf",
159  "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Bold_Italic.ttf",
160  "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Italic.ttf",
161  "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman.ttf",
162  "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Bold.ttf",
163  "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Bold_Italic.ttf",
164  "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Italic.ttf",
165  "/usr/share/fonts/truetype/msttcorefonts/Verdana.ttf",
166  "/usr/share/fonts/truetype/msttcorefonts/Verdana_Bold.ttf",
167  "/usr/share/fonts/truetype/msttcorefonts/Verdana_Bold_Italic.ttf",
168  "/usr/share/fonts/truetype/msttcorefonts/Verdana_Italic.ttf",
169  // The DejaVuSans font is used by the css2.1 tests.
170  "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
171  "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_hi.ttf",
172  "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_ta.ttf",
173  "/usr/share/fonts/truetype/ttf-indic-fonts-core/MuktiNarrow.ttf",
174  };
175  for (size_t i = 0; i < arraysize(fonts); ++i) {
176  if (access(fonts[i], R_OK)) {
177  fprintf(stderr, "You are missing %s. Try re-running build/install-build-deps.sh. Also see "
178  "http://code.google.com/p/chromium/wiki/LayoutTestsLinux",
179  fonts[i]);
180  exit(1);
181  }
182  if (!FcConfigAppFontAddFile(fontcfg, (FcChar8 *) fonts[i])) {
183  fprintf(stderr, "Failed to load font %s\n", fonts[i]);
184  exit(1);
185  }
186  }
187 
188  if (!checkAndLoadFontFile(fontcfg, "/usr/share/fonts/truetype/thai/Garuda.ttf",
189  "/usr/share/fonts/truetype/tlwg/Garuda.ttf"))
190  exit(1);
191 
192  // We special case these fonts because they're only needed in a
193  // few layout tests.
194  checkAndLoadFontFile(fontcfg, "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_pa.ttf",
195  "/usr/share/fonts/truetype/ttf-punjabi-fonts/lohit_pa.ttf");
196 
197  // Also load the layout-test-specific "Ahem" font.
198  std::string ahemPath = drtDirPath + "AHEM____.TTF";
199  if (!FcConfigAppFontAddFile(fontcfg, reinterpret_cast<const FcChar8*>(ahemPath.c_str()))) {
200  fprintf(stderr, "Failed to load font %s\n", ahemPath.c_str());
201  exit(1);
202  }
203 
204  if (!FcConfigSetCurrent(fontcfg)) {
205  fputs("Failed to set the default font configuration\n", stderr);
206  exit(1);
207  }
208 }
209 #endif // !OS(ANDROID)
210 
211 void platformInit(int* argc, char*** argv)
212 {
213  // FIXME: It's better call gtk_init() only when we run plugin tests.
214  // See http://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/633ea167cde196ca#
215 #if USE(GTK)
216  gtk_init(argc, argv);
217 #endif
218 
219 #if !OS(ANDROID)
220  setupFontconfig();
221 #endif
222 }
223 
117639

Tools/DumpRenderTree/chromium/TestShellPosix.cpp

 1/*
 2 * Copyright (C) 2012 Google Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions are
 6 * met:
 7 *
 8 * * Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * * Redistributions in binary form must reproduce the above
 11 * copyright notice, this list of conditions and the following disclaimer
 12 * in the documentation and/or other materials provided with the
 13 * distribution.
 14 * * Neither the name of Google Inc. nor the names of its
 15 * contributors may be used to endorse or promote products derived from
 16 * this software without specific prior written permission.
 17 *
 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29 */
 30
 31#include "config.h"
 32#include "TestShell.h"
 33
 34#include "webkit/support/webkit_support.h"
 35
 36#include <signal.h>
 37#include <unistd.h>
 38
 39static void AlarmHandler(int)
 40{
 41 // If the alarm alarmed, kill the process since we have a really bad hang.
 42 puts("\n#TEST_TIMED_OUT\n");
 43 puts("#EOF\n");
 44 fflush(stdout);
 45 exit(0);
 46}
 47
 48void TestShell::waitTestFinished()
 49{
 50 ASSERT(!m_testIsPending);
 51 m_testIsPending = true;
 52
 53 // Install an alarm signal handler that will kill us if we time out.
 54 struct sigaction alarmAction;
 55 alarmAction.sa_handler = AlarmHandler;
 56 sigemptyset(&alarmAction.sa_mask);
 57 alarmAction.sa_flags = 0;
 58
 59 struct sigaction oldAction;
 60 sigaction(SIGALRM, &alarmAction, &oldAction);
 61 alarm(layoutTestTimeoutForWatchDog() / 1000);
 62
 63 // TestFinished() will post a quit message to break this loop when the page
 64 // finishes loading.
 65 while (m_testIsPending)
 66 webkit_support::RunMessageLoop();
 67
 68 // Remove the alarm.
 69 alarm(0);
 70 sigaction(SIGALRM, &oldAction, 0);
 71}
0

Tools/DumpRenderTree/chromium/TestShellX11.cpp

 1/*
 2 * Copyright (C) 2011 Google Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions are
 6 * met:
 7 *
 8 * * Redistributions of source code must retain the above copyright
 9 * notice, this list of conditions and the following disclaimer.
 10 * * Redistributions in binary form must reproduce the above
 11 * copyright notice, this list of conditions and the following disclaimer
 12 * in the documentation and/or other materials provided with the
 13 * distribution.
 14 * * Neither the name of Google Inc. nor the names of its
 15 * contributors may be used to endorse or promote products derived from
 16 * this software without specific prior written permission.
 17 *
 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29 */
 30
 31#include "config.h"
 32#include "TestShell.h"
 33
 34#include "SkTypeface.h"
 35#include "WebView.h"
 36#include "webkit/support/webkit_support.h"
 37
 38#if !OS(ANDROID)
 39#include <fontconfig/fontconfig.h>
 40#endif
 41
 42#if USE(GTK)
 43#include <gtk/gtk.h>
 44#endif
 45#include <signal.h>
 46#include <unistd.h>
 47
 48static void AlarmHandler(int)
 49{
 50 // If the alarm alarmed, kill the process since we have a really bad hang.
 51 puts("\n#TEST_TIMED_OUT\n");
 52 puts("#EOF\n");
 53 fflush(stdout);
 54 exit(0);
 55}
 56
 57void TestShell::waitTestFinished()
 58{
 59 ASSERT(!m_testIsPending);
 60 m_testIsPending = true;
 61
 62 // Install an alarm signal handler that will kill us if we time out.
 63 struct sigaction alarmAction;
 64 alarmAction.sa_handler = AlarmHandler;
 65 sigemptyset(&alarmAction.sa_mask);
 66 alarmAction.sa_flags = 0;
 67
 68 struct sigaction oldAction;
 69 sigaction(SIGALRM, &alarmAction, &oldAction);
 70 alarm(layoutTestTimeoutForWatchDog() / 1000);
 71
 72 // TestFinished() will post a quit message to break this loop when the page
 73 // finishes loading.
 74 while (m_testIsPending)
 75 webkit_support::RunMessageLoop();
 76
 77 // Remove the alarm.
 78 alarm(0);
 79 sigaction(SIGALRM, &oldAction, 0);
 80}
 81
 82#if !OS(ANDROID)
 83static bool checkAndLoadFontFile(FcConfig* fontcfg, const char* path1, const char* path2)
 84{
 85 const char* font = path1;
 86 if (access(font, R_OK) < 0) {
 87 font = path2;
 88 if (access(font, R_OK) < 0) {
 89 fprintf(stderr, "You are missing %s or %s. Without this, some layout tests may fail. "
 90 "See http://code.google.com/p/chromium/wiki/LayoutTestsLinux "
 91 "for more.\n", path1, path2);
 92 return false;
 93 }
 94 }
 95 if (!FcConfigAppFontAddFile(fontcfg, (FcChar8 *) font)) {
 96 fprintf(stderr, "Failed to load font %s\n", font);
 97 return false;
 98 }
 99 return true;
 100}
 101
 102static void setupFontconfig()
 103{
 104 // We wish to make the layout tests reproducable with respect to fonts. Skia
 105 // uses fontconfig to resolve font family names from WebKit into actual font
 106 // files found on the current system. This means that fonts vary based on the
 107 // system and also on the fontconfig configuration.
 108 //
 109 // To avoid this we initialise fontconfig here and install a configuration
 110 // which only knows about a few, select, fonts.
 111
 112 // We have fontconfig parse a config file from our resources file. This
 113 // sets a number of aliases ("sans"->"Arial" etc), but doesn't include any
 114 // font directories.
 115 FcInit();
 116
 117 char drtPath[PATH_MAX + 1];
 118 int drtPathSize = readlink("/proc/self/exe", drtPath, PATH_MAX);
 119 if (drtPathSize < 0 || drtPathSize > PATH_MAX) {
 120 fputs("Unable to resolve /proc/self/exe.", stderr);
 121 exit(1);
 122 }
 123 drtPath[drtPathSize] = 0;
 124 std::string drtDirPath(drtPath);
 125 size_t lastPathPos = drtDirPath.rfind("/");
 126 ASSERT(lastPathPos != std::string::npos);
 127 drtDirPath.erase(lastPathPos + 1);
 128
 129 FcConfig* fontcfg = FcConfigCreate();
 130 std::string fontconfigPath = drtDirPath + "fonts.conf";
 131 if (!FcConfigParseAndLoad(fontcfg, reinterpret_cast<const FcChar8*>(fontconfigPath.c_str()), true)) {
 132 fputs("Failed to parse fontconfig config file\n", stderr);
 133 exit(1);
 134 }
 135
 136 // This is the list of fonts that fontconfig will know about. It
 137 // will try its best to match based only on the fonts here in. The
 138 // paths are where these fonts are found on our Ubuntu boxes.
 139 static const char *const fonts[] = {
 140 "/usr/share/fonts/truetype/kochi/kochi-gothic.ttf",
 141 "/usr/share/fonts/truetype/kochi/kochi-mincho.ttf",
 142 "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf",
 143 "/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf",
 144 "/usr/share/fonts/truetype/msttcorefonts/Arial_Bold_Italic.ttf",
 145 "/usr/share/fonts/truetype/msttcorefonts/Arial_Italic.ttf",
 146 "/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS.ttf",
 147 "/usr/share/fonts/truetype/msttcorefonts/Comic_Sans_MS_Bold.ttf",
 148 "/usr/share/fonts/truetype/msttcorefonts/Courier_New.ttf",
 149 "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold.ttf",
 150 "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold_Italic.ttf",
 151 "/usr/share/fonts/truetype/msttcorefonts/Courier_New_Italic.ttf",
 152 "/usr/share/fonts/truetype/msttcorefonts/Georgia.ttf",
 153 "/usr/share/fonts/truetype/msttcorefonts/Georgia_Bold.ttf",
 154 "/usr/share/fonts/truetype/msttcorefonts/Georgia_Bold_Italic.ttf",
 155 "/usr/share/fonts/truetype/msttcorefonts/Georgia_Italic.ttf",
 156 "/usr/share/fonts/truetype/msttcorefonts/Impact.ttf",
 157 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS.ttf",
 158 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Bold.ttf",
 159 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Bold_Italic.ttf",
 160 "/usr/share/fonts/truetype/msttcorefonts/Trebuchet_MS_Italic.ttf",
 161 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman.ttf",
 162 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Bold.ttf",
 163 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Bold_Italic.ttf",
 164 "/usr/share/fonts/truetype/msttcorefonts/Times_New_Roman_Italic.ttf",
 165 "/usr/share/fonts/truetype/msttcorefonts/Verdana.ttf",
 166 "/usr/share/fonts/truetype/msttcorefonts/Verdana_Bold.ttf",
 167 "/usr/share/fonts/truetype/msttcorefonts/Verdana_Bold_Italic.ttf",
 168 "/usr/share/fonts/truetype/msttcorefonts/Verdana_Italic.ttf",
 169 // The DejaVuSans font is used by the css2.1 tests.
 170 "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf",
 171 "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_hi.ttf",
 172 "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_ta.ttf",
 173 "/usr/share/fonts/truetype/ttf-indic-fonts-core/MuktiNarrow.ttf",
 174 };
 175 for (size_t i = 0; i < arraysize(fonts); ++i) {
 176 if (access(fonts[i], R_OK)) {
 177 fprintf(stderr, "You are missing %s. Try re-running build/install-build-deps.sh. Also see "
 178 "http://code.google.com/p/chromium/wiki/LayoutTestsLinux",
 179 fonts[i]);
 180 exit(1);
 181 }
 182 if (!FcConfigAppFontAddFile(fontcfg, (FcChar8 *) fonts[i])) {
 183 fprintf(stderr, "Failed to load font %s\n", fonts[i]);
 184 exit(1);
 185 }
 186 }
 187
 188 if (!checkAndLoadFontFile(fontcfg, "/usr/share/fonts/truetype/thai/Garuda.ttf",
 189 "/usr/share/fonts/truetype/tlwg/Garuda.ttf"))
 190 exit(1);
 191
 192 // We special case these fonts because they're only needed in a
 193 // few layout tests.
 194 checkAndLoadFontFile(fontcfg, "/usr/share/fonts/truetype/ttf-indic-fonts-core/lohit_pa.ttf",
 195 "/usr/share/fonts/truetype/ttf-punjabi-fonts/lohit_pa.ttf");
 196
 197 // Also load the layout-test-specific "Ahem" font.
 198 std::string ahemPath = drtDirPath + "AHEM____.TTF";
 199 if (!FcConfigAppFontAddFile(fontcfg, reinterpret_cast<const FcChar8*>(ahemPath.c_str()))) {
 200 fprintf(stderr, "Failed to load font %s\n", ahemPath.c_str());
 201 exit(1);
 202 }
 203
 204 if (!FcConfigSetCurrent(fontcfg)) {
 205 fputs("Failed to set the default font configuration\n", stderr);
 206 exit(1);
 207 }
 208}
 209#endif // !OS(ANDROID)
 210
 211void platformInit(int* argc, char*** argv)
 212{
 213 // FIXME: It's better call gtk_init() only when we run plugin tests.
 214 // See http://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/633ea167cde196ca#
 215#if USE(GTK)
 216 gtk_init(argc, argv);
 217#endif
 218
 219#if !OS(ANDROID)
 220 setupFontconfig();
 221#endif
 222}
 223
117604

Tools/DumpRenderTree/chromium/TestShellX11.cpp

3131#include "config.h"
3232#include "TestShell.h"
3333
34 #include "SkTypeface.h"
35 #include "WebView.h"
36 #include "webkit/support/webkit_support.h"
37 
38 #if !OS(ANDROID)
3934#include <fontconfig/fontconfig.h>
40 #endif
4135
4236#if USE(GTK)
4337#include <gtk/gtk.h>
4438#endif
45 #include <signal.h>
46 #include <unistd.h>
47 
48 static void AlarmHandler(int)
49 {
50  // If the alarm alarmed, kill the process since we have a really bad hang.
51  puts("\n#TEST_TIMED_OUT\n");
52  puts("#EOF\n");
53  fflush(stdout);
54  exit(0);
55 }
5639
57 void TestShell::waitTestFinished()
58 {
59  ASSERT(!m_testIsPending);
60  m_testIsPending = true;
61 
62  // Install an alarm signal handler that will kill us if we time out.
63  struct sigaction alarmAction;
64  alarmAction.sa_handler = AlarmHandler;
65  sigemptyset(&alarmAction.sa_mask);
66  alarmAction.sa_flags = 0;
67 
68  struct sigaction oldAction;
69  sigaction(SIGALRM, &alarmAction, &oldAction);
70  alarm(layoutTestTimeoutForWatchDog() / 1000);
71 
72  // TestFinished() will post a quit message to break this loop when the page
73  // finishes loading.
74  while (m_testIsPending)
75  webkit_support::RunMessageLoop();
76 
77  // Remove the alarm.
78  alarm(0);
79  sigaction(SIGALRM, &oldAction, 0);
80 }
81 
82 #if !OS(ANDROID)
8340static bool checkAndLoadFontFile(FcConfig* fontcfg, const char* path1, const char* path2)
8441{
8542 const char* font = path1;

@@static void setupFontconfig()
206163 exit(1);
207164 }
208165}
209 #endif // !OS(ANDROID)
210166
211167void platformInit(int* argc, char*** argv)
212168{

@@void platformInit(int* argc, char*** arg
216172 gtk_init(argc, argv);
217173#endif
218174
219 #if !OS(ANDROID)
220175 setupFontconfig();
221 #endif
222176}
223177
117604

Tools/Scripts/webkitpy/layout_tests/port/chromium_android.py

2828# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2929
3030import logging
 31import os
3132import re
3233import signal
 34import shlex
 35import shutil
 36import threading
3337import time
3438
35 from webkitpy.layout_tests.port import base
3639from webkitpy.layout_tests.port import chromium
3740from webkitpy.layout_tests.port import factory
3841

@@_log = logging.getLogger(__name__)
4548# This path is defined in base/base_paths_android.cc and
4649# webkit/support/platform_support_android.cc.
4750DEVICE_SOURCE_ROOT_DIR = '/data/local/tmp/'
 51COMMAND_LINE_FILE = DEVICE_SOURCE_ROOT_DIR + 'chrome-native-tests-command-line'
4852
 53# The directory to put tools and resources of DumpRenderTree.
4954DEVICE_DRT_DIR = '/data/drt/'
50 DEVICE_DRT_PATH = DEVICE_DRT_DIR + 'DumpRenderTree'
51 DEVICE_DRT_STDERR = DEVICE_DRT_DIR + 'DumpRenderTree.stderr'
5255DEVICE_FORWARDER_PATH = DEVICE_DRT_DIR + 'forwarder'
5356DEVICE_DRT_STAMP_PATH = DEVICE_DRT_DIR + 'DumpRenderTree.stamp'
5457
 58DRT_APP_PACKAGE = 'org.chromium.native_test'
 59DRT_ACTIVITY_FULL_NAME = DRT_APP_PACKAGE + '/.ChromeNativeTestActivity'
 60DRT_APP_FILE_DIR = '/data/user/0/' + DRT_APP_PACKAGE + '/files/'
 61
5562# This only works for single core devices so far.
5663# FIXME: Find a solution for multi-core devices.
5764SCALING_GOVERNOR = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"

@@FORWARD_PORTS = '8000 8080 8443 8880 932
6976
7077MS_TRUETYPE_FONTS_DIR = '/usr/share/fonts/truetype/msttcorefonts/'
7178
 79# Timeout in seconds to wait for start/stop of DumpRenderTree.
 80DRT_START_STOP_TIMEOUT_SECS = 10
 81
7282# List of fonts that layout tests expect, copied from DumpRenderTree/gtk/TestShellGtk.cpp.
7383HOST_FONT_FILES = [
7484 [MS_TRUETYPE_FONTS_DIR, 'Arial.ttf'],

@@class ChromiumAndroidPort(chromium.Chrom
149159 self._version = 'icecreamsandwich'
150160 self._original_governor = None
151161 self._android_base_dir = None
 162 self._read_fifo_proc = None
152163
153164 self._host_port = factory.PortFactory(host).get('chromium', **kwargs)
154165

@@class ChromiumAndroidPort(chromium.Chrom
165176 return 10 * 1000
166177
167178 def default_child_processes(self):
168  # Currently we only use one process, but it might be helpful to use
169  # more that one process in the future to improve performance.
 179 # Because of the nature of apk, we don't support more than one process.
170180 return 1
171181
172182 def baseline_search_path(self):
173183 return map(self._webkit_baseline_path, self.FALLBACK_PATHS)
174184
 185 def check_wdiff(self, logging=True):
 186 return self._host_port.check_wdiff(logging)
 187
175188 def check_build(self, needs_http):
176  return self._host_port.check_build(needs_http)
 189 result = chromium.ChromiumPort.check_build(self, needs_http)
 190 result = self.check_wdiff() and result
 191 if not result:
 192 _log.error('For complete Android build requirements, please see:')
 193 _log.error('')
 194 _log.error(' http://code.google.com/p/chromium/wiki/AndroidBuildInstructions')
 195
 196 return result
177197
178198 def check_sys_deps(self, needs_http):
179199 for (font_dir, font_file) in HOST_FONT_FILES:

@@class ChromiumAndroidPort(chromium.Chrom
202222 pass
203223
204224 def start_helper(self):
 225 self._run_adb_command(['root'])
205226 self._setup_performance()
206227 # Required by webkit_support::GetWebKitRootDirFilePath().
207228 # Other directories will be created automatically by adb push.
208  self._run_adb_command(['shell', 'mkdir', '-p',
209  DEVICE_SOURCE_ROOT_DIR + 'chrome'])
 229 self._run_adb_command(['shell', 'mkdir', '-p', DEVICE_SOURCE_ROOT_DIR + 'chrome'])
 230 # Allow the DumpRenderTree app to fully access the directory.
 231 # The native code needs the permission to write temporary files here.
 232 self._run_adb_command(['shell', 'chmod', '777', DEVICE_SOURCE_ROOT_DIR])
210233
211234 self._push_executable()
212235 self._push_fonts()

@@class ChromiumAndroidPort(chromium.Chrom
223246 # useful for debugging and do no harm to subsequent tests.
224247 self._teardown_performance()
225248
226  def skipped_tests(self, test_list):
227  return base.Port._real_tests(self, [
 249 def skipped_layout_tests(self, test_list):
 250 return self._real_tests([
228251 # Canvas tests are run as virtual gpu tests.
229252 'fast/canvas',
230253 'canvas/philip',
231254 ])
232255
 256 # Overridden private functions.
 257
233258 def _build_path(self, *comps):
234259 return self._host_port._build_path(*comps)
235260

@@class ChromiumAndroidPort(chromium.Chrom
240265 return self._host_port._path_to_apache_config_file()
241266
242267 def _path_to_driver(self, configuration=None):
243  # Returns the host path to driver which will be pushed to the device.
244268 if not configuration:
245269 configuration = self.get_option('configuration')
246  return self._build_path(configuration, 'DumpRenderTree')
 270 return self._build_path(configuration, 'DumpRenderTree_apk/ChromeNativeTests-debug.apk')
247271
248272 def _path_to_helper(self):
249273 return self._build_path(self.get_option('configuration'), 'forwarder')

@@class ChromiumAndroidPort(chromium.Chrom
269293 def _driver_class(self):
270294 return ChromiumAndroidDriver
271295
 296 def _get_crash_log(self, name, pid, stdout, stderr, newer_than):
 297 if not stdout:
 298 stdout = ''
 299 stdout += '********* Logcat:\n' + self._get_logcat()
 300 if not stderr:
 301 stderr = ''
 302 stderr += '********* Tombstone file:\n' + self._get_last_stacktrace()
 303 return chromium.ChromiumPort._get_crash_log(self, name, pid, stdout, stderr, newer_than)
 304
 305 # Local private functions.
 306
272307 def _push_executable(self):
273308 drt_host_path = self._path_to_driver()
274309 forwarder_host_path = self._path_to_helper()
275  drt_jar_host_path = drt_host_path + '.jar'
276310 host_stamp = int(float(max(os.stat(drt_host_path).st_mtime,
277  os.stat(forwarder_host_path).st_mtime,
278  os.stat(drt_jar_host_path).st_mtime)))
 311 os.stat(forwarder_host_path).st_mtime)))
279312 device_stamp = int(float(self._run_adb_command([
280313 'shell', 'cat %s 2>/dev/null || echo 0' % DEVICE_DRT_STAMP_PATH])))
281314 if device_stamp < host_stamp:
282315 _log.debug('Pushing executable')
283  self._kill_device_process(DEVICE_FORWARDER_PATH)
284316 self._push_to_device(forwarder_host_path, DEVICE_FORWARDER_PATH)
285  self._push_to_device(drt_host_path, DEVICE_DRT_PATH)
286  self._push_to_device(drt_host_path + '.pak', DEVICE_DRT_PATH + '.pak')
287  self._push_to_device(drt_host_path + '_resources', DEVICE_DRT_PATH + '_resources')
288  self._push_to_device(drt_jar_host_path, DEVICE_DRT_PATH + '.jar')
 317 self._run_adb_command(['uninstall', DRT_APP_PACKAGE])
 318 install_result = self._run_adb_command(['install', drt_host_path])
 319 if install_result.find('Success') == -1:
 320 raise AssertionError('Failed to install %s onto device: %s' % (drt_host_path, install_result))
 321 self._push_to_device(self._build_path(self.get_option('configuration'), 'DumpRenderTree.pak'),
 322 DEVICE_DRT_DIR + 'DumpRenderTree.pak')
 323 self._push_to_device(self._build_path(self.get_option('configuration'), 'DumpRenderTree_resources'),
 324 DEVICE_DRT_DIR + 'DumpRenderTree_resources')
289325 # Version control of test resources is dependent on executables,
290326 # because we will always rebuild executables when resources are
291327 # updated.

@@class ChromiumAndroidPort(chromium.Chrom
329365 self._run_adb_command(['shell', 'echo %d > %sVERSION' % (version, dir)])
330366
331367 def _run_adb_command(self, cmd, ignore_error=False):
 368 _log.debug('Run adb command: ' + str(cmd))
332369 if ignore_error:
333370 error_handler = self._executive.ignore_error
334371 else:
335372 error_handler = None
336  return self._executive.run_command(self._adb_command + cmd, error_handler=error_handler)
 373 result = self._executive.run_command(self._adb_command + cmd, error_handler=error_handler)
 374 _log.debug('Run adb result:\n' + result)
 375 return result
337376
338377 def _copy_device_file(self, from_file, to_file, ignore_error=False):
339378 # 'cp' is unavailable on Android, so use 'dd' instead.

@@class ChromiumAndroidPort(chromium.Chrom
345384 def _pull_from_device(self, device_path, host_path, ignore_error=False):
346385 return self._run_adb_command(['pull', device_path, host_path], ignore_error)
347386
348  def _kill_device_process(self, name):
349  ps_result = self._run_adb_command(['shell', 'ps']).split('\n')
350  for line in ps_result:
351  if line.find(name) > 0:
352  pid = line.split()[1]
353  self._run_adb_command(['shell', 'kill', pid])
354 
355  def get_stderr(self):
356  return self._run_adb_command(['shell', 'cat', DEVICE_DRT_STDERR], ignore_error=True)
357 
358  def get_last_stacktrace(self):
 387 def _get_last_stacktrace(self):
359388 tombstones = self._run_adb_command(['shell', 'ls', '-n', '/data/tombstones'])
360389 if not tombstones or tombstones.startswith('/data/tombstones: No such file or directory'):
361390 _log.error('DRT crashed, but no tombstone found!')

@@class ChromiumAndroidPort(chromium.Chrom
376405 # Use Android tool vendor/google/tools/stack to convert the raw
377406 # stack trace into a human readable format, if needed.
378407 # It takes a long time, so don't do it here.
379  return self._run_adb_command(['shell', 'cat', '/data/tombstones/' + last_tombstone[6]])
 408 return '%s\n%s' % (' '.join(last_tombstone),
 409 self._run_adb_command(['shell', 'cat', '/data/tombstones/' + last_tombstone[6]]))
 410
 411 def _get_logcat(self):
 412 return self._run_adb_command(['logcat', '-d'])
380413
381414 def _setup_performance(self):
382415 # Disable CPU scaling and drop ram cache to reduce noise in tests

@@class ChromiumAndroidPort(chromium.Chrom
391424
392425
393426class ChromiumAndroidDriver(chromium.ChromiumDriver):
 427 # The controller may start multiple drivers during test, but for now we
 428 # don't support multiple Android activities, so only one driver can be
 429 # started at a time.
 430 _started_driver = None
 431
394432 def __init__(self, port, worker_number, pixel_tests, no_timeout=False):
395433 chromium.ChromiumDriver.__init__(self, port, worker_number, pixel_tests, no_timeout)
396  self._device_image_path = None
397  self._drt_return_parser = re.compile('#DRT_RETURN (\d+)')
 434 self._in_fifo_path = DRT_APP_FILE_DIR + 'DumpRenderTree.in'
 435 self._out_fifo_path = DRT_APP_FILE_DIR + 'DumpRenderTree.out'
 436 self._err_file_path = DRT_APP_FILE_DIR + 'DumpRenderTree.err'
 437 self._restart_after_killed = False
 438 self._read_fifo_proc = None
 439
 440 def _command_wrapper(cls, wrapper_option):
 441 # Ignore command wrapper which is not applicable on Android.
 442 return []
 443
 444 def cmd_line(self, pixel_tests, per_test_args):
 445 original_cmd = chromium.ChromiumDriver.cmd_line(self, pixel_tests, per_test_args)
 446 cmd = []
 447 for param in original_cmd:
 448 if param.startswith('--pixel-tests='):
 449 self._device_image_path = DRT_APP_FILE_DIR + self._port.host.filesystem.basename(self._image_path)
 450 param = '--pixel-tests=' + self._device_image_path
 451 cmd.append(param)
 452
 453 cmd.append('--in-fifo=' + self._in_fifo_path)
 454 cmd.append('--out-fifo=' + self._out_fifo_path)
 455 cmd.append('--err-file=' + self._err_file_path)
 456 return cmd
 457
 458 def _file_exists_on_device(self, full_file_path):
 459 assert full_file_path.startswith('/')
 460 return self._port._run_adb_command(['shell', 'ls', full_file_path]).strip() == full_file_path
 461
 462 def _timeout_killer(self, pids, stop_event):
 463 time.sleep(DRT_START_STOP_TIMEOUT_SECS)
 464 if not stop_event.is_set():
 465 for i in pids:
 466 self._port._executive.kill_process(i)
398467
399468 def _start(self, pixel_tests, per_test_args):
400  # Convert the original command line into to two parts:
401  # - the 'adb shell' command line to start an interactive adb shell;
402  # - the DumpRenderTree command line to send to the adb shell.
403  original_cmd = self.cmd_line(pixel_tests, per_test_args)
404  shell_cmd = []
405  drt_args = []
406  path_to_driver = self._port._path_to_driver()
407  reading_args_before_driver = True
408  for param in original_cmd:
409  if reading_args_before_driver:
410  if param == path_to_driver:
411  reading_args_before_driver = False
412  else:
413  shell_cmd.append(param)
 469 if ChromiumAndroidDriver._started_driver:
 470 ChromiumAndroidDriver._started_driver.stop()
 471
 472 ChromiumAndroidDriver._started_driver = self
 473
 474 self._port._run_adb_command(['logcat', '-c'])
 475 self._port._run_adb_command(['shell', 'echo'] + self.cmd_line(pixel_tests, per_test_args) + ['>', COMMAND_LINE_FILE])
 476 self._port._run_adb_command(['shell', 'am', 'start', '-n', DRT_ACTIVITY_FULL_NAME])
 477 seconds = 0
 478 while not self._file_exists_on_device(self._in_fifo_path) or not self._file_exists_on_device(self._out_fifo_path):
 479 time.sleep(1)
 480 seconds += 1
 481 if seconds == DRT_START_STOP_TIMEOUT_SECS:
 482 _log.error('Failed to start DumpRenderTreeApplication. Log:\n' + self._port._get_logcat())
 483 raise AssertionError('Failed to start DumpRenderTree application.')
 484
 485 shell_cmd = self._port._adb_command + ['shell']
 486 executive = self._port._executive
 487 # Start a process to send command through the input fifo of the DumpRenderTree app.
 488 # This process must be run as an interactive adb shell because the normal adb shell doesn't support stdin.
 489 self._proc = executive.popen(shell_cmd, stdin=executive.PIPE, stdout=executive.PIPE, universal_newlines=True)
 490 # Read back the shell prompt to ensure adb shell ready.
 491 self._read_prompt()
 492 _log.debug('Interactive shell started')
 493
 494 # Start a process to read from the output fifo of the DumpRenderTree app and print to stdout.
 495 _log.debug('Redirecting stdout to ' + self._out_fifo_path)
 496 self._read_fifo_proc = executive.popen(shell_cmd + ['cat', self._out_fifo_path],
 497 stdout=executive.PIPE, universal_newlines=True)
 498
 499 _log.debug('Redirecting stdin to ' + self._in_fifo_path)
 500 (line, crash) = self._write_command_and_read_line('cat >%s\n' % self._in_fifo_path)
 501
 502 # Combine the two unidirectional pipes into one bidirectional pipe to make _write_command_and_read_line() etc
 503 # work with self._proc.
 504 self._proc.stdout.close()
 505 self._proc.stdout = self._read_fifo_proc.stdout
 506
 507 # Start a thread to kill the pipe reader and writer processes on deadlock of the fifos during startup.
 508 stop_killer_event = threading.Event()
 509 killer_thread = threading.Thread(target=self._timeout_killer,
 510 args=([self._proc.pid, self._read_fifo_proc.pid], stop_killer_event))
 511 killer_thread.start()
 512
 513 output = ''
 514 while not crash and line.rstrip() != '#READY':
 515 if line == '': # EOF or crashed
 516 crash = True
414517 else:
415  if param.startswith('--pixel-tests='):
416  if not self._device_image_path:
417  self._device_image_path = DEVICE_DRT_DIR + self._port.host.filesystem.basename(self._image_path)
418  param = '--pixel-tests=' + self._device_image_path
419  drt_args.append(param)
420 
421  shell_cmd += self._port._adb_command
422  shell_cmd.append('shell')
423  retries = 0
424  while True:
425  _log.debug('Starting adb shell for DumpRenderTree: ' + ' '.join(shell_cmd))
426  executive = self._port.host.executive
427  self._proc = executive.popen(shell_cmd, stdin=executive.PIPE, stdout=executive.PIPE, stderr=executive.STDOUT,
428  close_fds=True, universal_newlines=True)
429  # Read back the shell prompt to ensure adb shell ready.
430  self._read_prompt()
431  # Some tests rely on this to produce proper number format etc.,
432  # e.g. fast/speech/input-appearance-numberandspeech.html.
433  self._write_command_and_read_line("export LC_CTYPE='en_US'\n")
434  self._write_command_and_read_line("export CLASSPATH='/data/drt/DumpRenderTree.jar'\n")
435 
436  # When DumpRenderTree crashes, the Android debuggerd will stop the
437  # process before dumping stack to log/tombstone file and terminating
438  # the process. Sleep 1 second (long enough for debuggerd to dump
439  # stack) before exiting the shell to ensure the process has quit,
440  # otherwise the exit will fail because "You have stopped jobs".
441  drt_cmd = '%s %s 2>%s;echo "#DRT_RETURN $?";sleep 1;exit\n' % (DEVICE_DRT_PATH, ' '.join(drt_args), DEVICE_DRT_STDERR)
442  _log.debug('Starting DumpRenderTree: ' + drt_cmd)
443 
444  # Wait until DRT echos '#READY'.
445  output = ''
446  (line, crash) = self._write_command_and_read_line(drt_cmd)
447  while not crash and line.rstrip() != '#READY':
448  if line == '': # EOF or crashed
449  crash = True
450  else:
451  output += line
452  (line, crash) = self._write_command_and_read_line()
 518 output += line
 519 (line, crash) = self._write_command_and_read_line()
453520
454521 if crash:
455  # Sometimes the device is in unstable state (may be out of
456  # memory?) and kills DumpRenderTree just after it is started.
457  # Try to stop and start it again.
458  _log.error('Failed to start DumpRenderTree: \n%s\n%s\n' % (output, self._port.get_stderr()))
 522 _log.error('Failed to start DumpRenderTree: \n%s\nLog:\n%s' % (output, self._port._get_logcat()))
459523 self.stop()
460  retries += 1
461  if retries > 2:
462  raise AssertionError('Failed multiple times to start DumpRenderTree')
 524 raise AssertionError('Failed to start DumpRenderTree application')
463525 else:
 526 # Startup succeeded.
 527 stop_killer_event.set()
464528 return
465529
466530 def run_test(self, driver_input):
467531 driver_output = chromium.ChromiumDriver.run_test(self, driver_input)
468 
469  drt_return = self._get_drt_return_value(driver_output.error)
470  if drt_return is not None:
471  _log.debug('DumpRenderTree return value: %d' % drt_return)
472  # FIXME: Retrieve stderr from the target.
473532 if driver_output.crash:
474  # When Android is OOM, it sends a SIGKILL signal to DRT. DRT
475  # is stopped silently and regarded as crashed. Re-run the test for
 533 # When Android is OOM, DRT process may be killed by ActivityManager or system OOM.
 534 # It looks like a crash but there is no fatal signal logged. Re-run the test for
476535 # such crash.
477  if drt_return == 128 + signal.SIGKILL:
 536 # To test: adb shell am force-stop org.chromium.native_test,
 537 # or kill -11 pid twice or three times to simulate a fatal crash.
 538 if self._port._get_logcat().find('Fatal signal') == -1:
 539 self._restart_after_killed = True
478540 self._port._drt_retry_after_killed += 1
479541 if self._port._drt_retry_after_killed > 10:
480542 raise AssertionError('DumpRenderTree is killed by Android for too many times!')
481  _log.error('DumpRenderTree is killed by SIGKILL. Retry the test (%d).' % self._port._drt_retry_after_killed)
 543 _log.error('DumpRenderTree is killed by system (%d).' % self._port._drt_retry_after_killed)
482544 self.stop()
483545 # Sleep 10 seconds to let system recover.
484546 time.sleep(10)
485547 return self.run_test(driver_input)
486  # Fetch the stack trace from the tombstone file.
487  # FIXME: sometimes the crash doesn't really happen so that no
488  # tombstone is generated. In that case we fetch the wrong stack
489  # trace.
490  driver_output.error += self._port.get_last_stacktrace().encode('ascii', 'ignore')
491  driver_output.error += self._port._run_adb_command(['logcat', '-d']).encode('ascii', 'ignore')
 548
 549 self._restart_after_killed = False
 550 driver_output.error += self._get_stderr()
492551 return driver_output
493552
494553 def stop(self):
495  _log.debug('Stopping DumpRenderTree')
 554 if ChromiumAndroidDriver._started_driver != self or not self._proc:
 555 return
 556 ChromiumAndroidDriver._started_driver = None
 557
 558 self._port._run_adb_command(['shell', 'am', 'force-stop', DRT_APP_PACKAGE])
 559 seconds = 0
 560 while self._file_exists_on_device(self._in_fifo_path) or self._file_exists_on_device(self._out_fifo_path):
 561 time.sleep(1)
 562 self._port._run_adb_command(['shell', 'rm', self._in_fifo_path])
 563 self._port._run_adb_command(['shell', 'rm', self._out_fifo_path])
 564 seconds += 1
 565 if seconds == DRT_START_STOP_TIMEOUT_SECS:
 566 raise AssertionError('Failed to remove fifo files. May be locked.')
 567
 568 if self._read_fifo_proc:
 569 self._port._executive.kill_process(self._read_fifo_proc.pid)
 570 self._read_fifo_proc = None
 571
 572 # Here duplicate some logic in ChromiumDriver.stop() instead of directly calling it,
 573 # because our DumpRenderTree app process won't quit by itself on close of the pipes.
496574 if self._proc:
497  # Send an explicit QUIT command because closing the pipe can't let
498  # DumpRenderTree on Android quit immediately.
499  try:
500  self._proc.stdin.write('QUIT\n')
501  except IOError:
502  # The pipe has already been closed, indicating abnormal
503  # situation occurred. Wait a while to allow the device to
504  # recover. *fingers crossed*
505  time.sleep(1)
506  chromium.ChromiumDriver.stop(self)
 575 self._proc.stdin.close()
 576 self._proc.stdout.close()
 577 if self._proc.stderr:
 578 self._proc.stderr.close()
 579 self._port._executive.kill_process(self._proc.pid)
 580 if self._proc.poll() is not None:
 581 self._proc.wait()
 582 self._proc = None
507583
508584 def _test_shell_command(self, uri, timeout_ms, checksum):
509585 if uri.startswith('file:///'):

@@class ChromiumAndroidDriver(chromium.Chr
517593 def _write_command_and_read_line(self, input=None):
518594 (line, crash) = chromium.ChromiumDriver._write_command_and_read_line(self, input)
519595 url_marker = '#URL:'
520  if not crash and line.startswith(url_marker) and line.find(FILE_TEST_URI_PREFIX) == len(url_marker):
521  # Convert the device test uri back to host uri otherwise
522  # chromium.ChromiumDriver.run_test() will complain.
523  line = '#URL:file://%s/%s' % (self._port.layout_tests_dir(), line[len(url_marker) + len(FILE_TEST_URI_PREFIX):])
524  if not crash and self._has_crash_hint(line):
525  crash = True
 596 if not crash:
 597 if line.startswith(url_marker) and line.find(FILE_TEST_URI_PREFIX) == len(url_marker):
 598 # Convert the device test uri back to host uri otherwise
 599 # chromium.ChromiumDriver.run_test() will complain.
 600 line = '#URL:file://%s/%s' % (self._port.layout_tests_dir(), line[len(url_marker) + len(FILE_TEST_URI_PREFIX):])
 601 # chromium.py uses "line == '' and self._proc.poll() is not None" to detect crash,
 602 # but we have ever seen "line == '' and self._proc.poll() is None" when the app crashes.
 603 if line == '':
 604 crash = True
526605 return (line, crash)
527606
528607 def _output_image(self):
529608 if self._image_path:
530  _log.debug('pulling from device: %s to %s' % (self._device_image_path, self._image_path))
 609 _log.debug('Pulling from device: %s to %s' % (self._device_image_path, self._image_path))
531610 self._port._pull_from_device(self._device_image_path, self._image_path, ignore_error=True)
532611 return chromium.ChromiumDriver._output_image(self)
533612
534  def _has_crash_hint(self, line):
535  # When DRT crashes, it sends a signal to Android Debuggerd, like
536  # SIGSEGV, SIGFPE, etc. When Debuggerd receives the signal, it stops DRT
537  # (which causes Shell to output a message), and dumps the stack strace.
538  # We use the Shell output as a crash hint.
539  return line is not None and line.find('[1] + Stopped (signal)') >= 0
540 
541  def _get_drt_return_value(self, error):
542  return_match = self._drt_return_parser.search(error)
543  return None if (return_match is None) else int(return_match.group(1))
 613 def _get_stderr(self):
 614 return self._port._run_adb_command(['shell', 'cat', self._err_file_path], ignore_error=True)
544615
545616 def _read_prompt(self):
546617 last_char = ''
117639