Update from chromium https://crrev.com/302282 Updates based on chromium https://crrev.com/302282 / 30228db41b946899ce33f284da0adf2b35188d552de47. Contains updates for https://crrev.com/301916 and https://crrev.com/301795. TBR=ben@chromium.org Review URL: https://codereview.chromium.org/683113005
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 4e9e64b..4b366d9 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -46,17 +46,3 @@ results = [] results.extend(_CommonChecks(input_api, output_api)) return results - - -def GetPreferredTryMasters(project, change): - return { - 'tryserver.chromium.linux': { - 'linux_chromium_rel': set(['defaulttests']), - }, - 'tryserver.chromium.mac': { - 'mac_chromium_rel': set(['defaulttests']), - }, - 'tryserver.chromium.win': { - 'win_chromium_rel': set(['defaulttests']), - } - }
diff --git a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index c56d76c..e429026 100644 --- a/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -30,6 +30,9 @@ public class LibraryLoader { private static final String TAG = "LibraryLoader"; + // Set to true to enable debug logs. + private static final boolean DEBUG = false; + // Guards all access to the libraries private static final Object sLock = new Object(); @@ -54,6 +57,10 @@ // directly. private static boolean sLibraryWasLoadedFromApk = false; + // One-way switch becomes false if the Chromium library should be loaded + // directly from the APK file but it was not aligned. + private static boolean sLibraryWasAlignedInApk = true; + // One-way switch becomes true if the system library loading failed, // and the right native library was found and loaded by the hack. // The flag is used to report UMA stats later. @@ -165,9 +172,19 @@ Linker.prepareLibraryLoad(); for (String library : NativeLibraries.LIBRARIES) { + // Don't self-load the linker. This is because the build system is + // not clever enough to understand that all the libraries packaged + // in the final .apk don't need to be explicitly loaded. + if (Linker.isChromiumLinkerLibrary(library)) { + if (DEBUG) Log.i(TAG, "ignoring self-linker load"); + continue; + } + String zipfile = null; if (Linker.isInZipFile()) { zipfile = context.getApplicationInfo().sourceDir; + sLibraryWasAlignedInApk = Linker.checkLibraryAlignedInApk( + zipfile, System.mapLibraryName(library)); Log.i(TAG, "Loading " + library + " from within " + zipfile); } else { Log.i(TAG, "Loading: " + library); @@ -185,8 +202,8 @@ } isLoaded = true; } catch (UnsatisfiedLinkError e) { - Log.w(TAG, "Failed to load native library with shared RELRO, " + - "retrying without"); + Log.w(TAG, "Failed to load native library with shared RELRO, " + + "retrying without"); Linker.disableSharedRelros(); sLoadAtFixedAddressFailed = true; } @@ -209,7 +226,7 @@ System.loadLibrary(library); } catch (UnsatisfiedLinkError e) { if (context != null - && LibraryLoaderHelper.tryLoadLibraryUsingWorkaround(context, + && LibraryLoaderHelper.tryLoadLibraryUsingWorkaround(context, library)) { sNativeLibraryHackWasUsed = true; } else { @@ -220,10 +237,10 @@ } if (context != null - && shouldDeleteOldWorkaroundLibraries - && !sNativeLibraryHackWasUsed) { + && shouldDeleteOldWorkaroundLibraries + && !sNativeLibraryHackWasUsed) { LibraryLoaderHelper.deleteWorkaroundLibrariesAsynchronously( - context); + context); } long stopTime = SystemClock.uptimeMillis(); @@ -239,8 +256,8 @@ } // Check that the version of the library we have loaded matches the version we expect Log.i(TAG, String.format( - "Expected native library version number \"%s\"," + - "actual native library version number \"%s\"", + "Expected native library version number \"%s\"," + + "actual native library version number \"%s\"", NativeLibraries.sVersionNumber, nativeGetVersionNumber())); if (!NativeLibraries.sVersionNumber.equals(nativeGetVersionNumber())) { @@ -326,14 +343,18 @@ return LibraryLoadFromApkStatusCodes.SUCCESSFUL; } + if (!sLibraryWasAlignedInApk) { + return LibraryLoadFromApkStatusCodes.NOT_ALIGNED; + } + if (context == null) { Log.w(TAG, "Unknown APK filename due to null context"); return LibraryLoadFromApkStatusCodes.UNKNOWN; } - return Linker.checkLibraryLoadFromApkSupport(context.getApplicationInfo().sourceDir) ? - LibraryLoadFromApkStatusCodes.SUPPORTED : - LibraryLoadFromApkStatusCodes.NOT_SUPPORTED; + return Linker.checkLibraryLoadFromApkSupport(context.getApplicationInfo().sourceDir) + ? LibraryLoadFromApkStatusCodes.SUPPORTED + : LibraryLoadFromApkStatusCodes.NOT_SUPPORTED; } // Register pending Chromium linker histogram state for renderer processes. This cannot be
diff --git a/android/java/src/org/chromium/base/library_loader/Linker.java b/android/java/src/org/chromium/base/library_loader/Linker.java index 997b67c..dbd780b 100644 --- a/android/java/src/org/chromium/base/library_loader/Linker.java +++ b/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -243,8 +243,8 @@ } if (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT) { - sMemoryDeviceConfig = SysUtils.isLowEndDevice() ? - MEMORY_DEVICE_CONFIG_LOW : MEMORY_DEVICE_CONFIG_NORMAL; + sMemoryDeviceConfig = SysUtils.isLowEndDevice() + ? MEMORY_DEVICE_CONFIG_LOW : MEMORY_DEVICE_CONFIG_NORMAL; } switch (BROWSER_SHARED_RELRO_CONFIG) { @@ -341,8 +341,8 @@ assert NativeLibraries.sEnableLinkerTests; synchronized (Linker.class) { assert sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT; - assert memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW || - memoryDeviceConfig == MEMORY_DEVICE_CONFIG_NORMAL; + assert memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW + || memoryDeviceConfig == MEMORY_DEVICE_CONFIG_NORMAL; if (DEBUG) { if (memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW) Log.i(TAG, "Simulating a low-memory device"); @@ -507,8 +507,8 @@ parcel.recycle(); } if (DEBUG) { - Log.i(TAG, "useSharedRelros() called with " + bundle + - ", cloned " + clonedBundle); + Log.i(TAG, "useSharedRelros() called with " + bundle + + ", cloned " + clonedBundle); } synchronized (Linker.class) { // Note that in certain cases, this can be called before @@ -640,8 +640,7 @@ final long maxExpectedBytes = 192 * 1024 * 1024; final long address = nativeGetRandomBaseLoadAddress(maxExpectedBytes); if (DEBUG) { - Log.i(TAG, - String.format(Locale.US, "Random native base load address: 0x%x", address)); + Log.i(TAG, String.format(Locale.US, "Random native base load address: 0x%x", address)); } return address; } @@ -703,7 +702,8 @@ * Load a native shared library with the Chromium linker. * The shared library is uncompressed and page aligned inside the zipfile. * Note the crazy linker treats libraries and files as equivalent, - * so you can only open one library in a given zip file. + * so you can only open one library in a given zip file. The library must + * not be the Chromium linker library. * * @param zipfile The filename of the zipfile contain the library. * @param library The library's base name. @@ -713,7 +713,8 @@ } /** - * Load a native shared library with the Chromium linker. + * Load a native shared library with the Chromium linker. The library must + * not be the Chromium linker library. * * @param library The library's base name. */ @@ -724,15 +725,7 @@ private static void loadLibraryMaybeInZipFile( @Nullable String zipFile, String library) { if (DEBUG) Log.i(TAG, "loadLibrary: " + library); - - // Don't self-load the linker. This is because the build system is - // not clever enough to understand that all the libraries packaged - // in the final .apk don't need to be explicitly loaded. - // Also deal with the component build that adds a .cr suffix to the name. - if (library.equals(TAG) || library.equals(TAG + ".cr")) { - if (DEBUG) Log.i(TAG, "ignoring self-linker load"); - return; - } + assert !isChromiumLinkerLibrary(library); synchronized (Linker.class) { ensureInitializedLocked(); @@ -762,8 +755,8 @@ String sharedRelRoName = libName; if (zipFile != null) { if (!nativeLoadLibraryInZipFile(zipFile, libName, loadAddress, libInfo)) { - String errorMessage = "Unable to load library: " + libName + - ", in: " + zipFile; + String errorMessage = "Unable to load library: " + libName + + ", in: " + zipFile; Log.e(TAG, errorMessage); throw new UnsatisfiedLinkError(errorMessage); } @@ -822,6 +815,14 @@ } /** + * Determine whether a library is the linker library. Also deal with the + * component build that adds a .cr suffix to the name. + */ + public static boolean isChromiumLinkerLibrary(String library) { + return library.equals(TAG) || library.equals(TAG + ".cr"); + } + + /** * Check whether the device supports loading a library directly from the APK file. * * @param apkFile Filename of the APK. @@ -834,13 +835,32 @@ if (DEBUG) Log.i(TAG, "checkLibraryLoadFromApkSupported: " + apkFile); boolean supported = nativeCheckLibraryLoadFromApkSupport(apkFile); - if (DEBUG) Log.i(TAG, "Loading a library directly from the APK file " + - (supported ? "" : "NOT ") + "supported"); + if (DEBUG) Log.i(TAG, "Loading a library directly from the APK file " + + (supported ? "" : "NOT ") + "supported"); return supported; } } /** + * Check whether a library is page aligned in the APK file. + * + * @param apkFile Filename of the APK. + * @param library The library's base name. + * @return true if page aligned. + */ + public static boolean checkLibraryAlignedInApk(String apkFile, String library) { + synchronized (Linker.class) { + ensureInitializedLocked(); + + if (DEBUG) Log.i(TAG, "checkLibraryAlignedInApk: " + apkFile + ", " + library); + boolean aligned = nativeCheckLibraryAlignedInApk(apkFile, library); + if (DEBUG) Log.i(TAG, library + " is " + (aligned ? "" : "NOT ") + + "page aligned in " + apkFile); + return aligned; + } + } + + /** * Move activity from the native thread to the main UI thread. * Called from native code on its own thread. Posts a callback from * the UI thread back to native code. @@ -885,11 +905,10 @@ * of this LibInfo instance will set on success. * @return true for success, false otherwise. */ - private static native boolean nativeLoadLibraryInZipFile( - String zipfileName, - String libraryName, - long loadAddress, - LibInfo libInfo); + private static native boolean nativeLoadLibraryInZipFile(String zipfileName, + String libraryName, + long loadAddress, + LibInfo libInfo); /** * Native method used to create a shared RELRO section. @@ -943,11 +962,19 @@ * * @param apkFile Filename of the APK. * @return true if supported. - * */ private static native boolean nativeCheckLibraryLoadFromApkSupport(String apkFile); /** + * Native method which checks whether a library is page aligned in the APK file. + * + * @param apkFile Filename of the APK. + * @param library The library's base name. + * @return true if page aligned. + */ + private static native boolean nativeCheckLibraryAlignedInApk(String apkFile, String library); + + /** * Record information for a given library. * IMPORTANT: Native code knows about this class's fields, so * don't change them without modifying the corresponding C++ sources. @@ -1080,5 +1107,5 @@ // Used to pass the shared RELRO Bundle through Binder. public static final String EXTRA_LINKER_SHARED_RELROS = - "org.chromium.base.android.linker.shared_relros"; + "org.chromium.base.android.linker.shared_relros"; }
diff --git a/android/library_loader/library_load_from_apk_status_codes.h b/android/library_loader/library_load_from_apk_status_codes.h index 73ddbd5..21f40bc 100644 --- a/android/library_loader/library_load_from_apk_status_codes.h +++ b/android/library_loader/library_load_from_apk_status_codes.h
@@ -21,11 +21,14 @@ // The device supports loading a library directly from the APK file. LIBRARY_LOAD_FROM_APK_STATUS_CODES_SUPPORTED = 2, - // A library was successfully loaded directly from the APK file. + // The Chromium library was successfully loaded directly from the APK file. LIBRARY_LOAD_FROM_APK_STATUS_CODES_SUCCESSFUL = 3, + // The Chromium library was not page aligned in the APK file. + LIBRARY_LOAD_FROM_APK_STATUS_CODES_NOT_ALIGNED = 4, + // End sentinel. - LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX = 4, + LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX = 5, }; } // namespace
diff --git a/android/linker/linker_jni.cc b/android/linker/linker_jni.cc index a545c52..30aced1 100644 --- a/android/linker/linker_jni.cc +++ b/android/linker/linker_jni.cc
@@ -584,7 +584,7 @@ // |apkfile_name| is the filename of the APK. // Returns true if supported. jboolean CheckLibraryLoadFromApkSupport(JNIEnv* env, jclass clazz, - jstring apkfile_name) { + jstring apkfile_name) { String apkfile_name_str(env, apkfile_name); const char* apkfile_name_c_str = apkfile_name_str.c_str(); @@ -613,6 +613,29 @@ return status; } +// Check whether a library is page aligned in the APK file. +// +// |env| is the current JNI environment handle. +// |clazz| is the static class handle which is not used here. +// |apkfile_name| is the filename of the APK. +// |library_name| is the library base name. +// Returns true if page aligned. +jboolean CheckLibraryAlignedInApk(JNIEnv* env, jclass clazz, + jstring apkfile_name, jstring library_name) { + String apkfile_name_str(env, apkfile_name); + const char* apkfile_name_c_str = apkfile_name_str.c_str(); + String library_name_str(env, library_name); + const char* library_name_c_str = library_name_str.c_str(); + + LOG_INFO("%s: Checking if %s is page-aligned in %s\n", __FUNCTION__, + library_name_c_str, apkfile_name_c_str); + jboolean aligned = crazy_linker_check_library_aligned_in_zip_file( + apkfile_name_c_str, library_name_c_str) == CRAZY_STATUS_SUCCESS; + LOG_INFO("%s: %s\n", __FUNCTION__, aligned ? "Aligned" : "NOT aligned"); + + return aligned; +} + const JNINativeMethod kNativeMethods[] = { {"nativeLoadLibrary", "(" @@ -668,7 +691,14 @@ "Ljava/lang/String;" ")" "Z", - reinterpret_cast<void*>(&CheckLibraryLoadFromApkSupport)}, }; + reinterpret_cast<void*>(&CheckLibraryLoadFromApkSupport)}, + {"nativeCheckLibraryAlignedInApk", + "(" + "Ljava/lang/String;" + "Ljava/lang/String;" + ")" + "Z", + reinterpret_cast<void*>(&CheckLibraryAlignedInApk)}, }; } // namespace
diff --git a/base.gyp b/base.gyp index 42e270f..ad4dd22 100644 --- a/base.gyp +++ b/base.gyp
@@ -216,7 +216,7 @@ ], }, }], - ['OS != "win" and OS != "ios"', { + ['OS != "win" and (OS != "ios" or _toolset == "host")', { 'dependencies': ['../third_party/libevent/libevent.gyp:libevent'], },], ['component=="shared_library"', { @@ -295,6 +295,9 @@ }], ], }], + ['OS == "ios"', { + 'toolsets': ['host', 'target'], + }], ], 'export_dependent_settings': [ 'base', @@ -887,6 +890,9 @@ 'base_java_unittest_support', ], }], + ['OS == "ios"', { + 'toolsets': ['host', 'target'], + }], ], 'sources': [ 'test/expectations/expectation.cc', @@ -986,11 +992,20 @@ # by file name rules). ['include', '^test/test_file_util_mac\\.cc$'], ], + }], + ['OS == "ios" and _toolset == "target"', { 'sources!': [ # iOS uses its own unit test launcher. 'test/launcher/unit_test_launcher.cc', ], }], + ['OS == "ios" and _toolset == "host"', { + 'sources!': [ + 'test/launcher/unit_test_launcher_ios.cc', + 'test/test_support_ios.h', + 'test/test_support_ios.mm', + ], + }], ], # target_conditions }, { @@ -1012,6 +1027,21 @@ }, ], 'conditions': [ + ['OS=="ios" and "<(GENERATOR)"=="ninja"', { + 'targets': [ + { + 'target_name': 'test_launcher', + 'toolsets': ['host'], + 'type': 'executable', + 'dependencies': [ + 'test_support_base', + ], + 'sources': [ + 'test/launcher/test_launcher_ios.cc', + ], + }, + ], + }], ['OS!="ios"', { 'targets': [ { @@ -1381,7 +1411,6 @@ { # GN: //base:base_android_java_enums_srcjar 'target_name': 'base_java_library_load_from_apk_status_codes', - 'toolsets': ['host', 'target'], 'type': 'none', 'variables': { 'source_file': 'android/library_loader/library_load_from_apk_status_codes.h'
diff --git a/files/file_path_watcher_win.cc b/files/file_path_watcher_win.cc index 98169ab..73f9cfb 100644 --- a/files/file_path_watcher_win.cc +++ b/files/file_path_watcher_win.cc
@@ -11,7 +11,7 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/message_loop/message_loop_proxy.h" -#include "base/profiler/scoped_profile.h" +#include "base/profiler/scoped_tracker.h" #include "base/time/time.h" #include "base/win/object_watcher.h" @@ -39,7 +39,7 @@ virtual void WillDestroyCurrentMessageLoop() override; // Callback from MessageLoopForIO. - virtual void OnObjectSignaled(HANDLE object); + virtual void OnObjectSignaled(HANDLE object) override; private: virtual ~FilePathWatcherImpl() {} @@ -147,10 +147,9 @@ } void FilePathWatcherImpl::OnObjectSignaled(HANDLE object) { - // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed. - tracked_objects::ScopedProfile tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "FilePathWatcherImpl_OnObjectSignaled")); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("FilePathWatcherImpl_OnObjectSignaled")); DCHECK(object == handle_); // Make sure we stay alive through the body of this function.
diff --git a/mac/sdk_forward_declarations.h b/mac/sdk_forward_declarations.h index 234b268..fde0fcc 100644 --- a/mac/sdk_forward_declarations.h +++ b/mac/sdk_forward_declarations.h
@@ -210,6 +210,8 @@ BASE_EXPORT extern "C" NSString* const NSWindowWillExitFullScreenNotification; BASE_EXPORT extern "C" NSString* const NSWindowDidEnterFullScreenNotification; BASE_EXPORT extern "C" NSString* const NSWindowDidExitFullScreenNotification; +BASE_EXPORT extern "C" NSString* const + NSWindowDidChangeBackingPropertiesNotification; @protocol NSWindowDelegateFullScreenAdditions - (void)windowDidFailToEnterFullScreen:(NSWindow*)window; @@ -293,6 +295,10 @@ - (NSWindowOcclusionState)occlusionState; @end + +BASE_EXPORT extern "C" NSString* const + NSWindowDidChangeOcclusionStateNotification; + enum { NSWorkspaceLaunchWithErrorPresentation = 0x00000040 }; @@ -325,6 +331,7 @@ @interface NSUserActivity : NSObject @property (readonly, copy) NSString* activityType; +@property (copy) NSDictionary* userInfo; @property (copy) NSURL* webPageURL; @end
diff --git a/mac/sdk_forward_declarations.mm b/mac/sdk_forward_declarations.mm index 8f77422..7a57032 100644 --- a/mac/sdk_forward_declarations.mm +++ b/mac/sdk_forward_declarations.mm
@@ -20,8 +20,20 @@ NSString* const NSWindowDidExitFullScreenNotification = @"NSWindowDidExitFullScreenNotification"; +NSString* const NSWindowDidChangeBackingPropertiesNotification = + @"NSWindowDidChangeBackingPropertiesNotification"; + #endif // MAC_OS_X_VERSION_10_7 +// Replicate specific 10.9 SDK declarations for building with prior SDKs. +#if !defined(MAC_OS_X_VERSION_10_9) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9 + +NSString* const NSWindowDidChangeOcclusionStateNotification = + @"NSWindowDidChangeOcclusionStateNotification"; + +#endif // MAC_OS_X_VERSION_10_9 + // Replicate specific 10.10 SDK declarations for building with prior SDKs. #if !defined(MAC_OS_X_VERSION_10_10) || \ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
diff --git a/process/kill_win.cc b/process/kill_win.cc index f5fb859..b102a87 100644 --- a/process/kill_win.cc +++ b/process/kill_win.cc
@@ -12,7 +12,7 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/process/process_iterator.h" -#include "base/profiler/scoped_profile.h" +#include "base/profiler/scoped_tracker.h" #include "base/win/object_watcher.h" namespace base { @@ -72,10 +72,9 @@ } void TimerExpiredTask::OnObjectSignaled(HANDLE object) { - // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed. - tracked_objects::ScopedProfile tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "TimerExpiredTask_OnObjectSignaled")); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("TimerExpiredTask_OnObjectSignaled")); CloseHandle(process_); process_ = NULL;
diff --git a/synchronization/waitable_event_watcher_win.cc b/synchronization/waitable_event_watcher_win.cc index dc14e64..f5218f1 100644 --- a/synchronization/waitable_event_watcher_win.cc +++ b/synchronization/waitable_event_watcher_win.cc
@@ -5,7 +5,7 @@ #include "base/synchronization/waitable_event_watcher.h" #include "base/compiler_specific.h" -#include "base/profiler/scoped_profile.h" +#include "base/profiler/scoped_tracker.h" #include "base/synchronization/waitable_event.h" #include "base/win/object_watcher.h" @@ -37,10 +37,9 @@ } void WaitableEventWatcher::OnObjectSignaled(HANDLE h) { - // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed. - tracked_objects::ScopedProfile tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "WaitableEventWatche_OnObjectSignaled")); + // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("WaitableEventWatche_OnObjectSignaled")); WaitableEvent* event = event_; EventCallback callback = callback_;
diff --git a/test/android/OWNERS b/test/android/OWNERS index 25c1d80..3c9067c 100644 --- a/test/android/OWNERS +++ b/test/android/OWNERS
@@ -1,2 +1,3 @@ +feng@chromium.org nyquist@chromium.org yfriedman@chromium.org
diff --git a/test/android/javatests/src/org/chromium/base/test/util/Manual.java b/test/android/javatests/src/org/chromium/base/test/util/Manual.java new file mode 100644 index 0000000..31f3977 --- /dev/null +++ b/test/android/javatests/src/org/chromium/base/test/util/Manual.java
@@ -0,0 +1,21 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation can be used to mark a test that should only be run manually. + * <p> + * Tests with this annotation will not be run on bots, because they take too long + * or need manual monitoring. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Manual { +}
diff --git a/test/android/javatests/src/org/chromium/base/test/util/PerfTest.java b/test/android/javatests/src/org/chromium/base/test/util/PerfTest.java new file mode 100644 index 0000000..9b3495c --- /dev/null +++ b/test/android/javatests/src/org/chromium/base/test/util/PerfTest.java
@@ -0,0 +1,88 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation tells the test harness that this method will be used in a performance test. + * This means that the test harness will use the parameters here to figure out which trace calls + * to track specifically for this test. + * <p> + * Each of the lists ({@link #traceNames()}, {@link #graphNames()}, + * and {@link #seriesNames()}) should have the same number of + * elements. + * <p> + * To write a performance test, you need to do the following: + * <p><ol> + * <li>Add TraceEvent calls to the code that you want to track. + * <ul> + * <li> For FPS, add a TraceEvent.instant call where you want to time and detect calls. + * <li> For code segment timing, add {@link org.chromium.base.TraceEvent#begin()}/ + * {@link org.chromium.base.TraceEvent#end()} calls around the code + * segment (does not have to be in the same method). + * </ul> + * <li> Write a Java Automated UI Test that instruments this code. + * <li> Add this PerfTest annotation to the test method. + * <ul> + * <li> traceNames must be a list of the names of all of the TraceEvent calls you want to track. + * <li> graphNames must be a list, one for each traceName, of which graph the trace data should be + * placed in (does not have to be unique). + * <li> seriesNames must be a list, one for each traceName, of what the series should be called + * for this trace data (has to be unique per graphName). + * <li> When checked in, the buildbots will automatically run this test and the results will show up + * under the Java Automation UI Performance graph, where there will be tabs for each graphName + * specified. + * <li> To test your performance test, run the following command and you should see the performance + * numbers printed to the console. + * </ol> + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface PerfTest { + /** + * @return A list of the trace calls to track. + */ + public String[] traceNames(); + + /** + * @return A list, one for each traceName, that represents which graph this trace call should + * be output on. This does not have to be unique if there are multiple series per + * graph. + */ + public String[] graphNames(); + + /** + * @return A list, one for each traceName, that represents the series this trace call should be + * on the corresponding graph. This should be unique. + */ + public String[] seriesNames(); + + /** + * @return Whether or not we should automatically start and stop tracing for the test. This + * makes it easier to run some tests where tracing is started and stopped at the + * beginning and end of that particular test. + */ + public boolean autoTrace() default false; + + /** + * @return Whether this performance test should track memory usage in addition to time. If + * true, this will track memory usage when tracking time deltas or instants. With each + * graph defined in the annotation for tracking time, this will add an additional graph + * suffixed with a memory identifier containing the same series as those tracking the + * timing performance but instead will be tracking memory consumption. + */ + public boolean traceMemory() default true; + + /** + * @return Whether this performance test should track time or (optionally) only memory. If + * false, this will not automatically track time deltas or instants when logging + * memory info. + */ + public boolean traceTiming() default true; +}
diff --git a/test/launcher/test_launcher_ios.cc b/test/launcher/test_launcher_ios.cc new file mode 100644 index 0000000..38e4ef9 --- /dev/null +++ b/test/launcher/test_launcher_ios.cc
@@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/launcher/test_launcher.h" + +#include "base/bind.h" +#include "base/test/launcher/unit_test_launcher.h" + +namespace { + +int DummyRunTestSuite(void) { + return -1; +} + +} // namespace + +int main(int argc, char** argv) { + return base::LaunchUnitTests(argc, argv, base::Bind(&DummyRunTestSuite)); +}
diff --git a/time/time.cc b/time/time.cc index f731356..ce9d12c 100644 --- a/time/time.cc +++ b/time/time.cc
@@ -4,12 +4,15 @@ #include "base/time/time.h" +#include <ios> #include <limits> #include <ostream> +#include <sstream> #include "base/float_util.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/strings/stringprintf.h" #include "base/third_party/nspr/prtime.h" namespace base { @@ -94,6 +97,10 @@ return delta_; } +std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { + return os << time_delta.InSecondsF() << "s"; +} + // Time ----------------------------------------------------------------------- // static @@ -230,6 +237,20 @@ return true; } +std::ostream& operator<<(std::ostream& os, Time time) { + Time::Exploded exploded; + time.UTCExplode(&exploded); + // Use StringPrintf because iostreams formatting is painful. + return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC", + exploded.year, + exploded.month, + exploded.day_of_month, + exploded.hour, + exploded.minute, + exploded.second, + exploded.millisecond); +} + // Local helper class to hold the conversion from Time to TickTime at the // time of the Unix epoch. class UnixEpochSingleton { @@ -253,6 +274,16 @@ return leaky_unix_epoch_singleton_instance.Get().unix_epoch(); } +std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) { + // This function formats a TimeTicks object as "bogo-microseconds". + // The origin and granularity of the count are platform-specific, and may very + // from run to run. Although bogo-microseconds usually roughly correspond to + // real microseconds, the only real guarantee is that the number never goes + // down during a single run. + const TimeDelta as_time_delta = time_ticks - TimeTicks(); + return os << as_time_delta.InMicroseconds() << " bogo-microseconds"; +} + // Time::Exploded ------------------------------------------------------------- inline bool is_in_range(int value, int lo, int hi) {
diff --git a/time/time.h b/time/time.h index 3cf3746..641f465 100644 --- a/time/time.h +++ b/time/time.h
@@ -19,12 +19,18 @@ // // These classes are represented as only a 64-bit value, so they can be // efficiently passed by value. +// +// Definitions of operator<< are provided to make these types work with +// DCHECK_EQ() and other log macros. For human-readable formatting, see +// "base/i18n/time_formatting.h". #ifndef BASE_TIME_TIME_H_ #define BASE_TIME_TIME_H_ #include <time.h> +#include <iosfwd> + #include "base/base_export.h" #include "base/basictypes.h" #include "build/build_config.h" @@ -206,6 +212,9 @@ return TimeDelta(a * td.delta_); } +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeDelta time_delta); + // Time ----------------------------------------------------------------------- // Represents a wall clock time in UTC. @@ -561,6 +570,9 @@ return Time(t.us_ + delta_); } +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, Time time); + // TimeTicks ------------------------------------------------------------------ class BASE_EXPORT TimeTicks { @@ -723,6 +735,9 @@ return TimeTicks(t.ticks_ + delta_); } +// For logging use only. +BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks); + } // namespace base #endif // BASE_TIME_TIME_H_
diff --git a/time/time_unittest.cc b/time/time_unittest.cc index d8f1e5e..ef80e43 100644 --- a/time/time_unittest.cc +++ b/time/time_unittest.cc
@@ -6,6 +6,8 @@ #include <time.h> +#include <string> + #include "base/compiler_specific.h" #include "base/logging.h" #include "base/strings/stringprintf.h" @@ -13,9 +15,9 @@ #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" -using base::Time; -using base::TimeDelta; -using base::TimeTicks; +namespace base { + +namespace { // Specialized test fixture allowing time strings without timezones to be // tested by comparing them to a known time in the local zone. @@ -780,3 +782,100 @@ // We can't test 1601 epoch, since the system time functions on Linux // only compute years starting from 1900. } + +// We could define this separately for Time, TimeTicks and TimeDelta but the +// definitions would be identical anyway. +template <class Any> +std::string AnyToString(Any any) { + std::ostringstream oss; + oss << any; + return oss.str(); +} + +TEST(TimeDeltaLogging, DCheckEqCompiles) { + DCHECK_EQ(TimeDelta(), TimeDelta()); +} + +TEST(TimeDeltaLogging, EmptyIsZero) { + TimeDelta zero; + EXPECT_EQ("0s", AnyToString(zero)); +} + +TEST(TimeDeltaLogging, FiveHundredMs) { + TimeDelta five_hundred_ms = TimeDelta::FromMilliseconds(500); + EXPECT_EQ("0.5s", AnyToString(five_hundred_ms)); +} + +TEST(TimeDeltaLogging, MinusTenSeconds) { + TimeDelta minus_ten_seconds = TimeDelta::FromSeconds(-10); + EXPECT_EQ("-10s", AnyToString(minus_ten_seconds)); +} + +TEST(TimeDeltaLogging, DoesNotMessUpFormattingFlags) { + std::ostringstream oss; + std::ios_base::fmtflags flags_before = oss.flags(); + oss << TimeDelta(); + EXPECT_EQ(flags_before, oss.flags()); +} + +TEST(TimeDeltaLogging, DoesNotMakeStreamBad) { + std::ostringstream oss; + oss << TimeDelta(); + EXPECT_TRUE(oss.good()); +} + +TEST(TimeLogging, DCheckEqCompiles) { + DCHECK_EQ(Time(), Time()); +} + +TEST(TimeLogging, ChromeBirthdate) { + Time birthdate; + ASSERT_TRUE(Time::FromString("Tue, 02 Sep 2008 09:42:18 GMT", &birthdate)); + EXPECT_EQ("2008-09-02 09:42:18.000 UTC", AnyToString(birthdate)); +} + +TEST(TimeLogging, DoesNotMessUpFormattingFlags) { + std::ostringstream oss; + std::ios_base::fmtflags flags_before = oss.flags(); + oss << Time(); + EXPECT_EQ(flags_before, oss.flags()); +} + +TEST(TimeLogging, DoesNotMakeStreamBad) { + std::ostringstream oss; + oss << Time(); + EXPECT_TRUE(oss.good()); +} + +TEST(TimeTicksLogging, DCheckEqCompiles) { + DCHECK_EQ(TimeTicks(), TimeTicks()); +} + +TEST(TimeTicksLogging, ZeroTime) { + TimeTicks zero; + EXPECT_EQ("0 bogo-microseconds", AnyToString(zero)); +} + +TEST(TimeTicksLogging, FortyYearsLater) { + TimeTicks forty_years_later = + TimeTicks() + TimeDelta::FromDays(365.25 * 40); + EXPECT_EQ("1262304000000000 bogo-microseconds", + AnyToString(forty_years_later)); +} + +TEST(TimeTicksLogging, DoesNotMessUpFormattingFlags) { + std::ostringstream oss; + std::ios_base::fmtflags flags_before = oss.flags(); + oss << TimeTicks(); + EXPECT_EQ(flags_before, oss.flags()); +} + +TEST(TimeTicksLogging, DoesNotMakeStreamBad) { + std::ostringstream oss; + oss << TimeTicks(); + EXPECT_TRUE(oss.good()); +} + +} // namespace + +} // namespace base
diff --git a/win/enum_variant.h b/win/enum_variant.h index 030f7fd..d978eaa 100644 --- a/win/enum_variant.h +++ b/win/enum_variant.h
@@ -33,10 +33,10 @@ // IEnumVARIANT. STDMETHODIMP Next(ULONG requested_count, VARIANT* out_elements, - ULONG* out_elements_received); - STDMETHODIMP Skip(ULONG skip_count); - STDMETHODIMP Reset(); - STDMETHODIMP Clone(IEnumVARIANT** out_cloned_object); + ULONG* out_elements_received) override; + STDMETHODIMP Skip(ULONG skip_count) override; + STDMETHODIMP Reset() override; + STDMETHODIMP Clone(IEnumVARIANT** out_cloned_object) override; private: ~EnumVariant();