summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:01:02 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-08 16:01:02 +0000
commitc8cca4714027cb44523a3e56c1cf2046b290c3fd (patch)
treeba3df2215e05ba322e270f10862463044c6c32c5
parente8dc1d97cd08ef197dcded3ab6085113817f7f2a (diff)
parentb4233fd961752b80d42ae68e8b42acfb3e99be57 (diff)
downloadlibchrome-aml_tz2_305400100.tar.gz
Change-Id: Iaf6b976428391bc7e96824795b5eda53b01906d1
-rw-r--r--Android.bp620
-rw-r--r--BUILD.IGNORE10
-rw-r--r--BUILD.gn382
-rw-r--r--METADATA3
-rw-r--r--base/android/android_hardware_buffer_abi.h90
-rw-r--r--base/android/android_hardware_buffer_compat.cc129
-rw-r--r--base/android/android_hardware_buffer_compat.h51
-rw-r--r--base/android/android_image_reader_abi.h97
-rw-r--r--base/android/android_image_reader_compat.cc142
-rw-r--r--base/android/android_image_reader_compat.h79
-rw-r--r--base/android/android_image_reader_compat_unittest.cc43
-rw-r--r--base/android/animation_frame_time_histogram.cc26
-rw-r--r--base/android/apk_assets.cc47
-rw-r--r--base/android/apk_assets.h39
-rw-r--r--base/android/application_status_listener.cc78
-rw-r--r--base/android/application_status_listener.h88
-rw-r--r--base/android/application_status_listener_unittest.cc131
-rw-r--r--base/android/base_jni_onload.cc24
-rw-r--r--base/android/callback_android.cc44
-rw-r--r--base/android/callback_android.h38
-rw-r--r--base/android/child_process_binding_types.h25
-rw-r--r--base/android/child_process_service.cc79
-rw-r--r--base/android/command_line_android.cc89
-rw-r--r--base/android/content_uri_utils.cc45
-rw-r--r--base/android/content_uri_utils.h29
-rw-r--r--base/android/content_uri_utils_unittest.cc40
-rw-r--r--base/android/cpu_features.cc22
-rw-r--r--base/android/early_trace_event_binding.cc67
-rw-r--r--base/android/event_log.cc16
-rw-r--r--base/android/event_log.h20
-rw-r--r--base/android/field_trial_list.cc47
-rw-r--r--base/android/important_file_writer_android.cc37
-rw-r--r--base/android/java/src/org/chromium/base/ActivityState.java48
-rw-r--r--base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java145
-rw-r--r--base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java705
-rw-r--r--base/android/java/src/org/chromium/base/ApkAssets.java58
-rw-r--r--base/android/java/src/org/chromium/base/ApplicationStatus.java620
-rw-r--r--base/android/java/src/org/chromium/base/BaseSwitches.java32
-rw-r--r--base/android/java/src/org/chromium/base/Callback.java43
-rw-r--r--base/android/java/src/org/chromium/base/CollectionUtil.java99
-rw-r--r--base/android/java/src/org/chromium/base/CommandLine.java389
-rw-r--r--base/android/java/src/org/chromium/base/CommandLineInitUtil.java103
-rw-r--r--base/android/java/src/org/chromium/base/ContentUriUtils.java251
-rw-r--r--base/android/java/src/org/chromium/base/CpuFeatures.java42
-rw-r--r--base/android/java/src/org/chromium/base/EarlyTraceEvent.java299
-rw-r--r--base/android/java/src/org/chromium/base/EventLog.java20
-rw-r--r--base/android/java/src/org/chromium/base/FieldTrialList.java46
-rw-r--r--base/android/java/src/org/chromium/base/FileUtils.java149
-rw-r--r--base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java31
-rw-r--r--base/android/java/src/org/chromium/base/JNIUtils.java46
-rw-r--r--base/android/java/src/org/chromium/base/JavaHandlerThread.java119
-rw-r--r--base/android/java/src/org/chromium/base/LocaleUtils.java207
-rw-r--r--base/android/java/src/org/chromium/base/MemoryPressureListener.java130
-rw-r--r--base/android/java/src/org/chromium/base/NonThreadSafe.java41
-rw-r--r--base/android/java/src/org/chromium/base/ObserverList.java249
-rw-r--r--base/android/java/src/org/chromium/base/PathService.java26
-rw-r--r--base/android/java/src/org/chromium/base/PathUtils.java263
-rw-r--r--base/android/java/src/org/chromium/base/PowerMonitor.java80
-rw-r--r--base/android/java/src/org/chromium/base/Promise.java294
-rw-r--r--base/android/java/src/org/chromium/base/SecureRandomInitializer.java35
-rw-r--r--base/android/java/src/org/chromium/base/StreamUtil.java28
-rw-r--r--base/android/java/src/org/chromium/base/SysUtils.java199
-rw-r--r--base/android/java/src/org/chromium/base/ThrowUncaughtException.java21
-rw-r--r--base/android/java/src/org/chromium/base/TimeUtils.java18
-rw-r--r--base/android/java/src/org/chromium/base/TraceEvent.java387
-rw-r--r--base/android/java/src/org/chromium/base/UnguessableToken.java91
-rw-r--r--base/android/java/src/org/chromium/base/annotations/DoNotInline.java20
-rw-r--r--base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java829
-rw-r--r--base/android/java/src/org/chromium/base/library_loader/Linker.java1160
-rw-r--r--base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java16
-rw-r--r--base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java20
-rw-r--r--base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java35
-rw-r--r--base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java15
-rw-r--r--base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java301
-rw-r--r--base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java113
-rw-r--r--base/android/java/src/org/chromium/base/metrics/CachedMetrics.java307
-rw-r--r--base/android/java/src/org/chromium/base/metrics/RecordHistogram.java331
-rw-r--r--base/android/java/src/org/chromium/base/metrics/RecordUserAction.java85
-rw-r--r--base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java27
-rw-r--r--base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java78
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java305
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java766
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java27
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java278
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java346
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java76
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.aidl7
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java68
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/ICallbackInt.aidl9
-rw-r--r--base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl26
-rw-r--r--base/android/java/templates/BuildConfig.template70
-rw-r--r--base/android/java/templates/NativeLibraries.template109
-rw-r--r--base/android/java_exception_reporter.cc7
-rw-r--r--base/android/java_handler_thread.cc132
-rw-r--r--base/android/java_handler_thread.h95
-rw-r--r--base/android/javatests/src/org/chromium/base/AdvancedMockContextTest.java77
-rw-r--r--base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java88
-rw-r--r--base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java35
-rw-r--r--base/android/javatests/src/org/chromium/base/CommandLineTest.java141
-rw-r--r--base/android/javatests/src/org/chromium/base/EarlyTraceEventTest.java272
-rw-r--r--base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java262
-rw-r--r--base/android/javatests/src/org/chromium/base/ObserverListTest.java340
-rw-r--r--base/android/javatests/src/org/chromium/base/StrictModeContextTest.java118
-rw-r--r--base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java201
-rw-r--r--base/android/jni_array_unittest.cc389
-rw-r--r--base/android/jni_generator/PRESUBMIT.py37
-rw-r--r--base/android/jni_generator/README.md118
-rw-r--r--base/android/jni_generator/SampleForTests_jni.golden494
-rw-r--r--base/android/jni_generator/testNativeExportsOnlyOption.golden214
-rw-r--r--base/android/jni_registrar.cc30
-rw-r--r--base/android/jni_registrar.h28
-rw-r--r--base/android/jni_utils.cc24
-rw-r--r--base/android/jni_utils.h28
-rw-r--r--base/android/jni_weak_ref.cc79
-rw-r--r--base/android/jni_weak_ref.h51
-rw-r--r--base/android/junit/src/org/chromium/base/ApplicationStatusTest.java70
-rw-r--r--base/android/junit/src/org/chromium/base/LogTest.java87
-rw-r--r--base/android/junit/src/org/chromium/base/NonThreadSafeTest.java63
-rw-r--r--base/android/junit/src/org/chromium/base/PromiseTest.java316
-rw-r--r--base/android/junit/src/org/chromium/base/memory/MemoryPressureMonitorTest.java356
-rw-r--r--base/android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java57
-rw-r--r--base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java332
-rw-r--r--base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java425
-rw-r--r--base/android/library_loader/library_load_from_apk_status_codes.h49
-rw-r--r--base/android/library_loader/library_loader_hooks.cc254
-rw-r--r--base/android/library_loader/library_loader_hooks.h73
-rw-r--r--base/android/library_loader/library_prefetcher.cc333
-rw-r--r--base/android/library_loader/library_prefetcher.h66
-rw-r--r--base/android/library_loader/library_prefetcher_unittest.cc46
-rw-r--r--base/android/linker/config.gni13
-rw-r--r--base/android/linker/linker_jni.cc696
-rw-r--r--base/android/locale_utils.cc27
-rw-r--r--base/android/locale_utils.h25
-rw-r--r--base/android/memory_pressure_listener_android.cc30
-rw-r--r--base/android/memory_pressure_listener_android.h29
-rw-r--r--base/android/orderfile/BUILD.gn34
-rw-r--r--base/android/path_service_android.cc23
-rw-r--r--base/android/path_utils.cc82
-rw-r--r--base/android/path_utils.h55
-rw-r--r--base/android/path_utils_unittest.cc65
-rw-r--r--base/android/proguard/chromium_apk.flags65
-rw-r--r--base/android/proguard/chromium_code.flags75
-rw-r--r--base/android/record_histogram.cc343
-rw-r--r--base/android/record_user_action.cc59
-rw-r--r--base/android/statistics_recorder_android.cc29
-rw-r--r--base/android/sys_utils.cc51
-rw-r--r--base/android/sys_utils.h24
-rw-r--r--base/android/sys_utils_unittest.cc24
-rw-r--r--base/android/throw_uncaught_exception.cc19
-rw-r--r--base/android/throw_uncaught_exception.h20
-rw-r--r--base/android/time_utils.cc20
-rw-r--r--base/android/trace_event_binding.cc155
-rw-r--r--base/android/unguessable_token_android.cc41
-rw-r--r--base/android/unguessable_token_android.h43
-rw-r--r--base/android/unguessable_token_android_unittest.cc42
-rw-r--r--base/barrier_closure_unittest.cc81
-rw-r--r--base/base_paths_android.cc66
-rw-r--r--base/base_paths_android.h25
-rw-r--r--base/bind_unittest.nc322
-rw-r--r--base/bit_cast_unittest.cc31
-rw-r--r--base/build_time.cc4
-rw-r--r--base/callback_list_unittest.nc56
-rw-r--r--base/callback_unittest.nc53
-rw-r--r--base/check_example.cc37
-rw-r--r--base/containers/adapters_unittest.cc52
-rw-r--r--base/containers/flat_map_unittest.cc369
-rw-r--r--base/containers/flat_set_unittest.cc121
-rw-r--r--base/containers/flat_tree_unittest.cc1385
-rw-r--r--base/containers/hash_tables_unittest.cc67
-rw-r--r--base/containers/id_map.h290
-rw-r--r--base/containers/id_map_unittest.cc399
-rw-r--r--base/containers/linked_list_unittest.cc349
-rw-r--r--base/containers/mru_cache_unittest.cc394
-rw-r--r--base/containers/small_map_unittest.cc603
-rw-r--r--base/containers/stack_container_unittest.cc145
-rw-r--r--base/containers/unique_ptr_adapters.h78
-rw-r--r--base/containers/unique_ptr_adapters_unittest.cc134
-rw-r--r--base/debug/activity_analyzer.cc412
-rw-r--r--base/debug/activity_analyzer.h262
-rw-r--r--base/debug/activity_analyzer_unittest.cc546
-rw-r--r--base/debug/asan_invalid_access.cc101
-rw-r--r--base/debug/asan_invalid_access.h46
-rw-r--r--base/debug/crash_logging_unittest.cc17
-rw-r--r--base/debug/proc_maps_linux_unittest.cc328
-rw-r--r--base/debug/stack_trace_unittest.cc320
-rw-r--r--base/debug/thread_heap_usage_tracker.cc340
-rw-r--r--base/debug/thread_heap_usage_tracker_unittest.cc607
-rw-r--r--base/deferred_sequenced_task_runner.cc129
-rw-r--r--base/deferred_sequenced_task_runner.h97
-rw-r--r--base/deferred_sequenced_task_runner_unittest.cc214
-rw-r--r--base/file_descriptor_store.cc73
-rw-r--r--base/file_descriptor_store.h73
-rw-r--r--base/files/file_locking_unittest.cc232
-rw-r--r--base/files/file_path_watcher_fsevents.cc282
-rw-r--r--base/files/file_path_watcher_fsevents.h99
-rw-r--r--base/files/file_path_watcher_kqueue.cc372
-rw-r--r--base/files/file_path_watcher_kqueue.h125
-rw-r--r--base/files/file_path_watcher_stub.cc41
-rw-r--r--base/files/file_proxy.cc358
-rw-r--r--base/files/file_proxy.h142
-rw-r--r--base/files/file_proxy_unittest.cc401
-rw-r--r--base/files/file_util_android.cc16
-rw-r--r--base/files/file_util_posix.cc3
-rw-r--r--base/files/file_util_unittest.cc3749
-rw-r--r--base/files/memory_mapped_file_unittest.cc243
-rw-r--r--base/hash_unittest.cc82
-rw-r--r--base/i18n/base_i18n_switches.cc21
-rw-r--r--base/i18n/base_i18n_switches.h21
-rw-r--r--base/i18n/bidi_line_iterator.cc119
-rw-r--r--base/i18n/bidi_line_iterator.h60
-rw-r--r--base/i18n/bidi_line_iterator_unittest.cc209
-rw-r--r--base/i18n/break_iterator.cc191
-rw-r--r--base/i18n/break_iterator.h182
-rw-r--r--base/i18n/break_iterator_unittest.cc584
-rw-r--r--base/i18n/build_utf8_validator_tables.cc470
-rw-r--r--base/i18n/case_conversion.cc90
-rw-r--r--base/i18n/case_conversion.h48
-rw-r--r--base/i18n/case_conversion_unittest.cc119
-rw-r--r--base/i18n/char_iterator.cc80
-rw-r--r--base/i18n/char_iterator.h134
-rw-r--r--base/i18n/char_iterator_unittest.cc101
-rw-r--r--base/i18n/character_encoding.cc42
-rw-r--r--base/i18n/character_encoding.h20
-rw-r--r--base/i18n/character_encoding_unittest.cc23
-rw-r--r--base/i18n/encoding_detection.cc40
-rw-r--r--base/i18n/encoding_detection.h21
-rw-r--r--base/i18n/file_util_icu.cc179
-rw-r--r--base/i18n/file_util_icu.h58
-rw-r--r--base/i18n/file_util_icu_unittest.cc140
-rw-r--r--base/i18n/i18n_constants.cc13
-rw-r--r--base/i18n/i18n_constants.h21
-rw-r--r--base/i18n/icu_string_conversions.cc223
-rw-r--r--base/i18n/icu_string_conversions.h57
-rw-r--r--base/i18n/icu_string_conversions_unittest.cc235
-rw-r--r--base/i18n/icu_util.cc333
-rw-r--r--base/i18n/icu_util.h67
-rw-r--r--base/i18n/message_formatter.cc142
-rw-r--r--base/i18n/message_formatter.h128
-rw-r--r--base/i18n/message_formatter_unittest.cc185
-rw-r--r--base/i18n/number_formatting.cc97
-rw-r--r--base/i18n/number_formatting.h38
-rw-r--r--base/i18n/number_formatting_unittest.cc142
-rw-r--r--base/i18n/rtl.cc496
-rw-r--r--base/i18n/rtl_unittest.cc556
-rw-r--r--base/i18n/streaming_utf8_validator.cc59
-rw-r--r--base/i18n/streaming_utf8_validator.h66
-rw-r--r--base/i18n/streaming_utf8_validator_perftest.cc240
-rw-r--r--base/i18n/streaming_utf8_validator_unittest.cc412
-rw-r--r--base/i18n/string_compare.cc29
-rw-r--r--base/i18n/string_compare.h28
-rw-r--r--base/i18n/string_search.cc81
-rw-r--r--base/i18n/string_search.h55
-rw-r--r--base/i18n/string_search_unittest.cc228
-rw-r--r--base/i18n/time_formatting.cc301
-rw-r--r--base/i18n/time_formatting.h142
-rw-r--r--base/i18n/time_formatting_unittest.cc433
-rw-r--r--base/i18n/timezone.cc34
-rw-r--r--base/i18n/timezone.h24
-rw-r--r--base/i18n/timezone_unittest.cc27
-rw-r--r--base/i18n/unicodestring.h32
-rw-r--r--base/i18n/utf8_validator_tables.cc55
-rw-r--r--base/i18n/utf8_validator_tables.h32
-rw-r--r--base/json/json_perftest.cc84
-rw-r--r--base/linux_util.cc226
-rw-r--r--base/linux_util.h44
-rw-r--r--base/logging.cc8
-rw-r--r--base/memory/discardable_memory.cc13
-rw-r--r--base/memory/discardable_memory.h78
-rw-r--r--base/memory/discardable_memory_allocator.cc29
-rw-r--r--base/memory/discardable_memory_allocator.h38
-rw-r--r--base/memory/discardable_shared_memory.cc514
-rw-r--r--base/memory/discardable_shared_memory.h187
-rw-r--r--base/memory/discardable_shared_memory_unittest.cc456
-rw-r--r--base/memory/memory_coordinator_client.cc27
-rw-r--r--base/memory/memory_coordinator_client.h79
-rw-r--r--base/memory/memory_coordinator_client_registry.cc41
-rw-r--r--base/memory/memory_coordinator_client_registry.h56
-rw-r--r--base/memory/memory_coordinator_client_registry_unittest.cc58
-rw-r--r--base/memory/memory_coordinator_proxy.cc37
-rw-r--r--base/memory/memory_coordinator_proxy.h49
-rw-r--r--base/memory/memory_pressure_listener.cc129
-rw-r--r--base/memory/memory_pressure_listener.h102
-rw-r--r--base/memory/memory_pressure_listener_unittest.cc79
-rw-r--r--base/memory/memory_pressure_monitor.cc71
-rw-r--r--base/memory/memory_pressure_monitor.h53
-rw-r--r--base/memory/memory_pressure_monitor_chromeos.cc288
-rw-r--r--base/memory/memory_pressure_monitor_chromeos.h128
-rw-r--r--base/memory/memory_pressure_monitor_chromeos_unittest.cc172
-rw-r--r--base/memory/memory_pressure_monitor_unittest.cc33
-rw-r--r--base/memory/platform_shared_memory_region_android.cc203
-rw-r--r--base/memory/platform_shared_memory_region_mac.cc233
-rw-r--r--base/memory/ptr_util_unittest.cc40
-rw-r--r--base/memory/ref_counted_unittest.nc28
-rw-r--r--base/memory/shared_memory_handle.h4
-rw-r--r--base/memory/shared_memory_posix.cc38
-rw-r--r--base/memory/shared_memory_tracker.cc147
-rw-r--r--base/memory/shared_memory_tracker.h90
-rw-r--r--base/message_loop/message_loop.cc10
-rw-r--r--base/message_loop/message_loop.h7
-rw-r--r--base/message_loop/message_loop_current.cc4
-rw-r--r--base/message_loop/message_loop_current.h4
-rw-r--r--base/message_loop/message_loop_unittest.cc6
-rw-r--r--base/message_loop/message_pump_android.cc313
-rw-r--r--base/message_loop/message_pump_android.h102
-rw-r--r--base/message_loop/message_pump_for_ui.h4
-rw-r--r--base/message_loop/message_pump_libevent_unittest.cc263
-rw-r--r--base/message_loop/message_pump_perftest.cc243
-rw-r--r--base/metrics/field_trial_params_unittest.cc458
-rw-r--r--base/metrics/histogram_functions_unittest.cc127
-rw-r--r--base/metrics/histogram_unittest.nc90
-rw-r--r--base/native_library_unittest.cc166
-rw-r--r--base/nix/mime_util_xdg.cc33
-rw-r--r--base/nix/mime_util_xdg.h36
-rw-r--r--base/nix/xdg_util.cc152
-rw-r--r--base/nix/xdg_util.h77
-rw-r--r--base/nix/xdg_util_unittest.cc181
-rw-r--r--base/numerics/BUILD.gn28
-rw-r--r--base/os_compat_android.cc178
-rw-r--r--base/os_compat_android.h21
-rw-r--r--base/os_compat_android_unittest.cc41
-rw-r--r--base/path_service_unittest.cc278
-rw-r--r--base/posix/safe_strerror.cc13
-rw-r--r--base/power_monitor/power_monitor.cc66
-rw-r--r--base/power_monitor/power_monitor_device_source.cc33
-rw-r--r--base/power_monitor/power_monitor_device_source_android.cc39
-rw-r--r--base/power_monitor/power_monitor_device_source_chromeos.cc40
-rw-r--r--base/power_monitor/power_monitor_device_source_stub.cc14
-rw-r--r--base/power_monitor/power_monitor_source.cc69
-rw-r--r--base/power_monitor/power_monitor_unittest.cc83
-rw-r--r--base/process/memory_unittest.cc533
-rw-r--r--base/process/process_linux.cc201
-rw-r--r--base/process/process_metrics_unittest.cc4
-rw-r--r--base/process/process_unittest.cc330
-rw-r--r--base/process/process_util_unittest.cc1357
-rw-r--r--base/profiler/native_stack_sampler.cc34
-rw-r--r--base/profiler/native_stack_sampler.h97
-rw-r--r--base/profiler/native_stack_sampler_posix.cc19
-rw-r--r--base/profiler/stack_sampling_profiler.cc808
-rw-r--r--base/profiler/stack_sampling_profiler.h354
-rw-r--r--base/profiler/stack_sampling_profiler_unittest.cc1522
-rw-r--r--base/profiler/test_support_library.cc30
-rw-r--r--base/profiler/win32_stack_frame_unwinder.cc186
-rw-r--r--base/profiler/win32_stack_frame_unwinder.h102
-rw-r--r--base/profiler/win32_stack_frame_unwinder_unittest.cc223
-rw-r--r--base/run_loop.h2
-rw-r--r--base/run_loop_unittest.cc636
-rw-r--r--base/safe_numerics_unittest.cc1640
-rw-r--r--base/scoped_native_library_unittest.cc48
-rw-r--r--base/sequenced_task_runner_unittest.cc104
-rw-r--r--base/strings/latin1_string_conversions.cc19
-rw-r--r--base/strings/latin1_string_conversions.h34
-rw-r--r--base/strings/utf_offset_string_conversions.cc268
-rw-r--r--base/strings/utf_offset_string_conversions.h114
-rw-r--r--base/strings/utf_offset_string_conversions_unittest.cc300
-rw-r--r--base/supports_user_data.cc51
-rw-r--r--base/supports_user_data.h87
-rw-r--r--base/supports_user_data_unittest.cc40
-rw-r--r--base/synchronization/waitable_event_watcher_unittest.cc429
-rw-r--r--base/sys_byteorder_unittest.cc142
-rw-r--r--base/sys_info_android.cc241
-rw-r--r--base/syslog_logging.cc119
-rw-r--r--base/syslog_logging.h50
-rw-r--r--base/system_monitor/system_monitor.cc51
-rw-r--r--base/system_monitor/system_monitor.h75
-rw-r--r--base/system_monitor/system_monitor_unittest.cc55
-rw-r--r--base/task_scheduler/delayed_task_manager_unittest.cc209
-rw-r--r--base/task_scheduler/initialization_util.cc22
-rw-r--r--base/task_scheduler/initialization_util.h21
-rw-r--r--base/task_scheduler/priority_queue_unittest.cc170
-rw-r--r--base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc662
-rw-r--r--base/task_scheduler/scheduler_worker_pool_impl_unittest.cc1707
-rw-r--r--base/task_scheduler/scheduler_worker_stack_unittest.cc254
-rw-r--r--base/task_scheduler/scheduler_worker_unittest.cc897
-rw-r--r--base/task_scheduler/task_scheduler_impl_unittest.cc841
-rw-r--r--base/task_scheduler/task_tracker_posix_unittest.cc101
-rw-r--r--base/task_scheduler/task_tracker_unittest.cc1364
-rw-r--r--base/task_scheduler/task_unittest.cc60
-rw-r--r--base/task_scheduler/test_task_factory.cc106
-rw-r--r--base/task_scheduler/test_task_factory.h99
-rw-r--r--base/test/android/java/src/org/chromium/base/ContentUriTestUtils.java46
-rw-r--r--base/test/android/java/src/org/chromium/base/ITestCallback.aidl23
-rw-r--r--base/test/android/java/src/org/chromium/base/ITestController.aidl25
-rw-r--r--base/test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java65
-rw-r--r--base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java40
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java383
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientService.java14
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientService0.java10
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientService1.java10
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientService2.java10
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientService3.java10
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientService4.java10
-rw-r--r--base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java94
-rw-r--r--base/test/android/java/src/org/chromium/base/TestUiThread.java51
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java291
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java162
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java277
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java137
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java83
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/SetUpStatement.java35
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/SetUpTestRule.java35
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java87
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java142
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java168
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java42
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java42
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/MethodParamAnnotationRule.java62
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/MethodParamRule.java35
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java78
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java129
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java94
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java221
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java36
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java69
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java115
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java118
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/CallbackHelper.java252
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java188
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java49
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/DisableIfSkipCheck.java84
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java22
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java24
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/Feature.java29
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java22
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java238
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java32
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java26
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/Manual.java21
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/Matchers.java44
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java43
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java19
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheck.java43
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java37
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/RestrictionSkipCheck.java78
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/RetryOnFailure.java25
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/ScalableTimeout.java29
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/SkipCheck.java49
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java85
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/TestThread.java143
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/TimeoutScale.java22
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java84
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/UserActionTester.java51
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java32
-rw-r--r--base/test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java23
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java49
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java64
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java119
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java72
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java32
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java105
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java77
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java133
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java108
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java201
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java193
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java95
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java129
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java130
-rw-r--r--base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java132
-rw-r--r--base/test/fuzzed_data_provider.cc98
-rw-r--r--base/test/fuzzed_data_provider.h80
-rw-r--r--base/test/gtest_xml_unittest_result_printer.cc162
-rw-r--r--base/test/gtest_xml_unittest_result_printer.h55
-rw-r--r--base/test/gtest_xml_util.cc234
-rw-r--r--base/test/gtest_xml_util.h27
-rw-r--r--base/test/icu_test_util.cc39
-rw-r--r--base/test/icu_test_util.h35
-rw-r--r--base/test/launcher/test_launcher.cc1345
-rw-r--r--base/test/launcher/test_launcher.h268
-rw-r--r--base/test/launcher/test_launcher_tracer.cc53
-rw-r--r--base/test/launcher/test_launcher_tracer.h55
-rw-r--r--base/test/launcher/test_result.cc96
-rw-r--r--base/test/launcher/test_result.h104
-rw-r--r--base/test/launcher/test_results_tracker.cc541
-rw-r--r--base/test/launcher/test_results_tracker.h149
-rw-r--r--base/test/launcher/unit_test_launcher.cc750
-rw-r--r--base/test/launcher/unit_test_launcher.h134
-rw-r--r--base/test/malloc_wrapper.cc11
-rw-r--r--base/test/malloc_wrapper.h21
-rw-r--r--base/test/metrics/histogram_tester_unittest.cc157
-rw-r--r--base/test/metrics/user_action_tester.cc38
-rw-r--r--base/test/metrics/user_action_tester.h50
-rw-r--r--base/test/metrics/user_action_tester_unittest.cc86
-rw-r--r--base/test/mock_callback.h366
-rw-r--r--base/test/mock_callback.h.pump85
-rw-r--r--base/test/mock_callback_unittest.cc59
-rw-r--r--base/test/mock_devices_changed_observer.cc13
-rw-r--r--base/test/mock_devices_changed_observer.h31
-rw-r--r--base/test/mock_log.cc68
-rw-r--r--base/test/mock_log.h100
-rw-r--r--base/test/multiprocess_test.cc4
-rw-r--r--base/test/native_library_test_utils.cc19
-rw-r--r--base/test/native_library_test_utils.h26
-rw-r--r--base/test/null_task_runner.cc29
-rw-r--r--base/test/null_task_runner.h39
-rw-r--r--base/test/perf_log.cc45
-rw-r--r--base/test/perf_log.h24
-rw-r--r--base/test/perf_test_suite.cc50
-rw-r--r--base/test/perf_test_suite.h22
-rw-r--r--base/test/perf_time_logger.cc27
-rw-r--r--base/test/perf_time_logger.h37
-rw-r--r--base/test/power_monitor_test_base.cc68
-rw-r--r--base/test/power_monitor_test_base.h54
-rw-r--r--base/test/run_all_base_unittests.cc15
-rw-r--r--base/test/run_all_perftests.cc9
-rw-r--r--base/test/run_all_unittests.cc15
-rw-r--r--base/test/scoped_command_line.cc22
-rw-r--r--base/test/scoped_command_line.h34
-rw-r--r--base/test/scoped_mock_time_message_loop_task_runner.cc38
-rw-r--r--base/test/scoped_mock_time_message_loop_task_runner.h45
-rw-r--r--base/test/scoped_mock_time_message_loop_task_runner_unittest.cc120
-rw-r--r--base/test/scoped_path_override.cc40
-rw-r--r--base/test/scoped_path_override.h43
-rw-r--r--base/test/sequenced_task_runner_test_template.cc269
-rw-r--r--base/test/sequenced_task_runner_test_template.h350
-rw-r--r--base/test/task_runner_test_template.cc47
-rw-r--r--base/test/task_runner_test_template.h230
-rw-r--r--base/test/test_discardable_memory_allocator.cc61
-rw-r--r--base/test/test_discardable_memory_allocator.h32
-rw-r--r--base/test/test_file_util_android.cc26
-rw-r--r--base/test/test_message_loop.cc18
-rw-r--r--base/test/test_message_loop.h34
-rw-r--r--base/test/test_pending_task_unittest.cc57
-rw-r--r--base/test/test_shared_library.cc30
-rw-r--r--base/test/test_suite.cc486
-rw-r--r--base/test/test_suite.h103
-rw-r--r--base/test/test_support_android.cc225
-rw-r--r--base/test/test_support_android.h25
-rw-r--r--base/test/test_ui_thread_android.cc14
-rw-r--r--base/test/test_ui_thread_android.h20
-rw-r--r--base/test/thread_test_helper.cc41
-rw-r--r--base/test/thread_test_helper.h50
-rw-r--r--base/test/trace_event_analyzer.cc1069
-rw-r--r--base/test/trace_event_analyzer.h842
-rw-r--r--base/test/trace_event_analyzer_unittest.cc961
-rw-r--r--base/test/trace_to_file.cc106
-rw-r--r--base/test/trace_to_file.h35
-rw-r--r--base/test/values_test_util.cc76
-rw-r--r--base/test/values_test_util.h53
-rw-r--r--base/third_party/dynamic_annotations/LICENSE28
-rw-r--r--base/third_party/dynamic_annotations/README.chromium23
-rw-r--r--base/third_party/valgrind/LICENSE39
-rw-r--r--base/third_party/valgrind/README.chromium11
-rw-r--r--base/threading/platform_thread_android.cc96
-rw-r--r--base/threading/post_task_and_reply_impl_unittest.cc198
-rw-r--r--base/threading/sequenced_task_runner_handle_unittest.cc90
-rw-r--r--base/threading/thread_perftest.cc321
-rw-r--r--base/threading/thread_task_runner_handle_unittest.cc122
-rw-r--r--base/threading/watchdog.cc183
-rw-r--r--base/threading/watchdog.h96
-rw-r--r--base/threading/watchdog_unittest.cc141
-rw-r--r--base/time/time.h6
-rw-r--r--base/tools_sanity_unittest.cc423
-rw-r--r--base/trace_event/auto_open_close_event.cc52
-rw-r--r--base/trace_event/auto_open_close_event.h57
-rw-r--r--base/trace_event/blame_context.cc111
-rw-r--r--base/trace_event/blame_context.h138
-rw-r--r--base/trace_event/blame_context_unittest.cc175
-rw-r--r--base/trace_event/category_registry.cc156
-rw-r--r--base/trace_event/category_registry.h93
-rw-r--r--base/trace_event/cfi_backtrace_android.cc314
-rw-r--r--base/trace_event/cfi_backtrace_android.h157
-rw-r--r--base/trace_event/cfi_backtrace_android_unittest.cc197
-rw-r--r--base/trace_event/event_name_filter.cc26
-rw-r--r--base/trace_event/event_name_filter.h46
-rw-r--r--base/trace_event/event_name_filter_unittest.cc42
-rw-r--r--base/trace_event/heap_profiler_allocation_context.cc88
-rw-r--r--base/trace_event/heap_profiler_allocation_context.h132
-rw-r--r--base/trace_event/heap_profiler_allocation_context_tracker.cc274
-rw-r--r--base/trace_event/heap_profiler_allocation_context_tracker.h140
-rw-r--r--base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc350
-rw-r--r--base/trace_event/heap_profiler_event_filter.cc70
-rw-r--r--base/trace_event/heap_profiler_event_filter.h40
-rw-r--r--base/trace_event/java_heap_dump_provider_android.cc47
-rw-r--r--base/trace_event/java_heap_dump_provider_android.h36
-rw-r--r--base/trace_event/java_heap_dump_provider_android_unittest.cc22
-rw-r--r--base/trace_event/malloc_dump_provider.cc189
-rw-r--r--base/trace_event/malloc_dump_provider.h56
-rw-r--r--base/trace_event/memory_allocator_dump.cc148
-rw-r--r--base/trace_event/memory_allocator_dump.h153
-rw-r--r--base/trace_event/memory_allocator_dump_guid.cc40
-rw-r--r--base/trace_event/memory_allocator_dump_guid.h55
-rw-r--r--base/trace_event/memory_allocator_dump_unittest.cc177
-rw-r--r--base/trace_event/memory_dump_manager.cc545
-rw-r--r--base/trace_event/memory_dump_manager.h267
-rw-r--r--base/trace_event/memory_dump_manager_test_utils.h38
-rw-r--r--base/trace_event/memory_dump_manager_unittest.cc840
-rw-r--r--base/trace_event/memory_dump_provider.h52
-rw-r--r--base/trace_event/memory_dump_provider_info.cc43
-rw-r--r--base/trace_event/memory_dump_provider_info.h108
-rw-r--r--base/trace_event/memory_dump_request_args.cc64
-rw-r--r--base/trace_event/memory_dump_request_args.h101
-rw-r--r--base/trace_event/memory_dump_scheduler.cc118
-rw-r--r--base/trace_event/memory_dump_scheduler.h76
-rw-r--r--base/trace_event/memory_dump_scheduler_unittest.cc200
-rw-r--r--base/trace_event/memory_infra_background_whitelist.cc392
-rw-r--r--base/trace_event/memory_infra_background_whitelist.h33
-rw-r--r--base/trace_event/memory_infra_background_whitelist_unittest.cc37
-rw-r--r--base/trace_event/memory_usage_estimator.cc14
-rw-r--r--base/trace_event/memory_usage_estimator.h654
-rw-r--r--base/trace_event/memory_usage_estimator_unittest.cc265
-rw-r--r--base/trace_event/process_memory_dump.cc511
-rw-r--r--base/trace_event/process_memory_dump.h284
-rw-r--r--base/trace_event/process_memory_dump_unittest.cc565
-rw-r--r--base/trace_event/trace_buffer.cc347
-rw-r--r--base/trace_event/trace_buffer.h130
-rw-r--r--base/trace_event/trace_category.h109
-rw-r--r--base/trace_event/trace_category_unittest.cc155
-rw-r--r--base/trace_event/trace_config.cc618
-rw-r--r--base/trace_event/trace_config.h321
-rw-r--r--base/trace_event/trace_config_category_filter.cc235
-rw-r--r--base/trace_event/trace_config_category_filter.h81
-rw-r--r--base/trace_event/trace_config_memory_test_util.h152
-rw-r--r--base/trace_event/trace_config_unittest.cc663
-rw-r--r--base/trace_event/trace_event.h6
-rw-r--r--base/trace_event/trace_event_android.cc216
-rw-r--r--base/trace_event/trace_event_android_unittest.cc22
-rw-r--r--base/trace_event/trace_event_argument.cc576
-rw-r--r--base/trace_event/trace_event_argument.h92
-rw-r--r--base/trace_event/trace_event_argument_unittest.cc165
-rw-r--r--base/trace_event/trace_event_filter.cc17
-rw-r--r--base/trace_event/trace_event_filter.h51
-rw-r--r--base/trace_event/trace_event_filter_test_utils.cc61
-rw-r--r--base/trace_event/trace_event_filter_test_utils.h53
-rw-r--r--base/trace_event/trace_event_impl.cc489
-rw-r--r--base/trace_event/trace_event_impl.h191
-rw-r--r--base/trace_event/trace_event_memory_overhead.cc179
-rw-r--r--base/trace_event/trace_event_memory_overhead.h95
-rw-r--r--base/trace_event/trace_event_system_stats_monitor.cc132
-rw-r--r--base/trace_event/trace_event_system_stats_monitor.h76
-rw-r--r--base/trace_event/trace_event_system_stats_monitor_unittest.cc68
-rw-r--r--base/trace_event/trace_event_unittest.cc3169
-rw-r--r--base/trace_event/trace_log.cc1787
-rw-r--r--base/trace_event/trace_log.h528
-rw-r--r--base/trace_event/trace_log_constants.cc26
-rw-r--r--base/trace_event/tracing_agent.cc24
-rw-r--r--base/trace_event/tracing_agent.h96
-rw-r--r--base/unguessable_token_unittest.cc155
-rw-r--r--base/value_conversions.cc99
-rw-r--r--base/value_conversions.h35
-rwxr-xr-xbuild/android/gyp/util/build_utils_test.py44
-rw-r--r--build/android/gyp/util/jar_info_utils.py52
-rwxr-xr-xbuild/android/gyp/util/md5_check_test.py144
-rw-r--r--build/android/gyp/util/proguard_util.py212
-rw-r--r--build/android/gyp/util/resource_utils.py511
-rwxr-xr-xbuild/android/pylib/constants/host_paths_unittest.py50
-rw-r--r--build/android/pylib/content_settings.py80
-rw-r--r--build/android/pylib/device_settings.py199
-rw-r--r--build/android/pylib/pexpect.py21
-rwxr-xr-xbuild/android/pylib/restart_adbd.sh20
-rw-r--r--build/android/pylib/valgrind_tools.py130
-rwxr-xr-xbuild/apply_locales.py45
-rw-r--r--build/build_config.h13
-rwxr-xr-xbuild/check_gn_headers.py304
-rwxr-xr-xbuild/check_gn_headers_unittest.py101
-rwxr-xr-xbuild/check_return_value.py17
-rwxr-xr-xbuild/clobber.py132
-rwxr-xr-xbuild/cp.py23
-rwxr-xr-xbuild/detect_host_arch.py51
-rwxr-xr-xbuild/dir_exists.py23
-rwxr-xr-xbuild/download_translation_unit_tool.py54
-rwxr-xr-xbuild/env_dump.py56
-rwxr-xr-xbuild/extract_from_cab.py63
-rwxr-xr-xbuild/find_depot_tools.py73
-rwxr-xr-xbuild/find_isolated_tests.py78
-rwxr-xr-xbuild/fix_gn_headers.py218
-rwxr-xr-xbuild/get_landmines.py82
-rwxr-xr-xbuild/get_syzygy_binaries.py529
-rw-r--r--build/gn_helpers_unittest.py117
-rw-r--r--build/gn_run_binary.py31
-rw-r--r--build/gyp_chromium.py68
-rw-r--r--build/gyp_environment.py30
-rw-r--r--build/gyp_helper.py68
-rw-r--r--build/gypi_to_gn.py192
-rw-r--r--build/landmine_utils.py33
-rwxr-xr-xbuild/landmines.py145
-rw-r--r--build/precompile.h53
-rwxr-xr-xbuild/print_python_deps.py113
-rwxr-xr-xbuild/protoc_java.py85
-rw-r--r--build/redirect_stdout.py19
-rwxr-xr-xbuild/rm.py38
-rwxr-xr-xbuild/run_swarming_xcode_install.py81
-rwxr-xr-xbuild/swarming_xcode_install.py64
-rwxr-xr-xbuild/symlink.py60
-rwxr-xr-xbuild/vs_toolchain.py471
-rwxr-xr-xbuild/write_build_date_header.py118
-rwxr-xr-xbuild/write_buildflag_header.py95
-rw-r--r--components/json_schema/README6
-rw-r--r--components/json_schema/json_schema_validator_unittest.cc177
-rw-r--r--components/json_schema/json_schema_validator_unittest_base.cc710
-rw-r--r--components/json_schema/json_schema_validator_unittest_base.h56
-rw-r--r--components/policy/core/common/async_policy_loader.cc137
-rw-r--r--components/policy/core/common/async_policy_loader.h126
-rw-r--r--components/policy/core/common/async_policy_provider.cc131
-rw-r--r--components/policy/core/common/async_policy_provider.h80
-rw-r--r--components/policy/core/common/async_policy_provider_unittest.cc227
-rw-r--r--components/policy/core/common/config_dir_policy_loader.cc240
-rw-r--r--components/policy/core/common/config_dir_policy_loader.h72
-rw-r--r--components/policy/core/common/config_dir_policy_loader_unittest.cc244
-rw-r--r--components/policy/core/common/configuration_policy_provider.cc75
-rw-r--r--components/policy/core/common/configuration_policy_provider.h105
-rw-r--r--components/policy/core/common/configuration_policy_provider_test.cc420
-rw-r--r--components/policy/core/common/configuration_policy_provider_test.h158
-rw-r--r--components/policy/core/common/external_data_fetcher.cc45
-rw-r--r--components/policy/core/common/external_data_fetcher.h53
-rw-r--r--components/policy/core/common/external_data_manager.h36
-rw-r--r--components/policy/core/common/fake_async_policy_loader.cc37
-rw-r--r--components/policy/core/common/fake_async_policy_loader.h54
-rw-r--r--components/policy/core/common/generate_policy_source_unittest.cc227
-rw-r--r--components/policy/core/common/mock_configuration_policy_provider.cc48
-rw-r--r--components/policy/core/common/mock_configuration_policy_provider.h66
-rw-r--r--components/policy/core/common/mock_policy_service.cc21
-rw-r--r--components/policy/core/common/mock_policy_service.h39
-rw-r--r--components/policy/core/common/plist_writer.cc91
-rw-r--r--components/policy/core/common/plist_writer.h25
-rw-r--r--components/policy/core/common/plist_writer_unittest.cc135
-rw-r--r--components/policy/core/common/policy_bundle.cc104
-rw-r--r--components/policy/core/common/policy_bundle.h74
-rw-r--r--components/policy/core/common/policy_bundle_unittest.cc263
-rw-r--r--components/policy/core/common/policy_details.h48
-rw-r--r--components/policy/core/common/policy_map.cc234
-rw-r--r--components/policy/core/common/policy_map.h157
-rw-r--r--components/policy/core/common/policy_map_unittest.cc354
-rw-r--r--components/policy/core/common/policy_namespace.cc43
-rw-r--r--components/policy/core/common/policy_namespace.h66
-rw-r--r--components/policy/core/common/policy_pref_names.cc30
-rw-r--r--components/policy/core/common/policy_pref_names.h21
-rw-r--r--components/policy/core/common/policy_proto_decoders.cc189
-rw-r--r--components/policy/core/common/policy_proto_decoders.h34
-rw-r--r--components/policy/core/common/policy_scheduler.cc73
-rw-r--r--components/policy/core/common/policy_scheduler.h98
-rw-r--r--components/policy/core/common/policy_scheduler_unittest.cc133
-rw-r--r--components/policy/core/common/policy_service.cc44
-rw-r--r--components/policy/core/common/policy_service.h116
-rw-r--r--components/policy/core/common/policy_service_impl.cc278
-rw-r--r--components/policy/core/common/policy_service_impl.h103
-rw-r--r--components/policy/core/common/policy_service_impl_unittest.cc706
-rw-r--r--components/policy/core/common/policy_service_stub.cc34
-rw-r--r--components/policy/core/common/policy_service_stub.h42
-rw-r--r--components/policy/core/common/policy_statistics_collector.cc94
-rw-r--r--components/policy/core/common/policy_statistics_collector.h69
-rw-r--r--components/policy/core/common/policy_statistics_collector_unittest.cc189
-rw-r--r--components/policy/core/common/policy_switches.cc22
-rw-r--r--components/policy/core/common/policy_switches.h22
-rw-r--r--components/policy/core/common/policy_test_utils.cc209
-rw-r--r--components/policy/core/common/policy_test_utils.h69
-rw-r--r--components/policy/core/common/preg_parser.cc410
-rw-r--r--components/policy/core/common/preg_parser.h56
-rw-r--r--components/policy/core/common/preg_parser_fuzzer.cc45
-rw-r--r--components/policy/core/common/preg_parser_unittest.cc194
-rw-r--r--components/policy/core/common/proxy_policy_provider.cc65
-rw-r--r--components/policy/core/common/proxy_policy_provider.h64
-rw-r--r--components/policy/core/common/proxy_policy_provider_unittest.cc102
-rw-r--r--components/policy/core/common/schema_map.cc118
-rw-r--r--components/policy/core/common/schema_map.h68
-rw-r--r--components/policy/core/common/schema_map_unittest.cc308
-rw-r--r--components/policy/core/common/schema_registry.cc278
-rw-r--r--components/policy/core/common/schema_registry.h170
-rw-r--r--components/policy/core/common/schema_registry_tracking_policy_provider.cc99
-rw-r--r--components/policy/core/common/schema_registry_tracking_policy_provider.h92
-rw-r--r--components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc244
-rw-r--r--components/policy/core/common/schema_registry_unittest.cc329
-rw-r--r--components/policy/core/common/schema_unittest.cc1286
-rw-r--r--components/timers/alarm_timer_unittest.cc372
-rw-r--r--dbus/bus_unittest.cc420
-rw-r--r--dbus/dbus_statistics_unittest.cc178
-rw-r--r--dbus/end_to_end_async_unittest.cc645
-rw-r--r--dbus/end_to_end_sync_unittest.cc126
-rw-r--r--dbus/message_unittest.cc727
-rw-r--r--dbus/mock_unittest.cc215
-rw-r--r--dbus/object_manager_unittest.cc419
-rw-r--r--dbus/object_proxy_unittest.cc147
-rw-r--r--dbus/property_unittest.cc545
-rw-r--r--dbus/signal_sender_verification_unittest.cc394
-rw-r--r--dbus/string_util_unittest.cc31
-rw-r--r--dbus/util_unittest.cc16
-rw-r--r--dbus/values_util_unittest.cc687
-rw-r--r--ipc/ipc_channel_nacl.cc396
-rw-r--r--ipc/ipc_channel_nacl.h114
-rw-r--r--ipc/ipc_test.mojom54
-rwxr-xr-xlibchrome_tools/files_not_built16
-rw-r--r--[-rwxr-xr-x]libchrome_tools/mojom_generate_type_mappings.py17
-rw-r--r--libchrome_tools/patches/0001-Fix-pending_broker_clients-handling.patch44
-rw-r--r--libchrome_tools/patches/Add-base-NoDestructor-T.patch129
-rw-r--r--libchrome_tools/patches/Add-header-files-base-check_op-notreached-h.patch48
-rw-r--r--libchrome_tools/patches/Connect-to-NameOwnerChanged-signal-when-setting-call.patch163
-rw-r--r--libchrome_tools/patches/Fix-TimeDelta.patch164
-rw-r--r--libchrome_tools/patches/Fix-Wdefaulted-function-deleted-warning-in-MessageLo.patch38
-rw-r--r--libchrome_tools/patches/Mojo-Check-if-dispatcher-is-null-in-Core-UnwrapPlatf.patch38
-rw-r--r--libchrome_tools/patches/Refactor-AlarmTimer-to-report-error-to-the-caller.patch180
-rw-r--r--libchrome_tools/patches/WaitForServiceToBeAvailable.patch45
-rw-r--r--libchrome_tools/patches/components-timers-fix-fd-leak-in-AlarmTimer.patch102
-rw-r--r--libchrome_tools/patches/dbus-Add-TryRegisterFallback.patch137
-rw-r--r--libchrome_tools/patches/dbus-Make-Bus-is_connected-mockable.patch93
-rw-r--r--libchrome_tools/patches/dbus-Remove-LOG-ERROR-in-ObjectProxy.patch58
-rw-r--r--libchrome_tools/patches/dbus-Support-UnexportMethod-from-an-exported-object.patch194
-rw-r--r--libchrome_tools/patches/enable-location-source.patch26
-rw-r--r--libchrome_tools/patches/fix-fd-watcher-leak.patch188
-rw-r--r--libchrome_tools/patches/libchrome-Add-EmptyResponseCallback-for-backward-com.patch42
-rw-r--r--libchrome_tools/patches/libchrome-Introduce-stub-ConvertableToTraceFormat.patch55
-rw-r--r--libchrome_tools/patches/libchrome-Remove-glib-dependency.patch31
-rw-r--r--libchrome_tools/patches/libchrome-Unpatch-sys.path-update.patch41
-rw-r--r--libchrome_tools/patches/libchrome-Update-crypto.patch182
-rw-r--r--libchrome_tools/patches/libchrome-fix-integer-overflow-if-microseconds-is-IN.patch27
-rw-r--r--libchrome_tools/patches/patches75
-rw-r--r--libchrome_tools/patches/r680000-forward-compatibility-patch-part-1.patch222
-rw-r--r--libchrome_tools/patches/r680000-forward-compatibility-patch-part-2.patch94
-rwxr-xr-xlibchrome_tools/uprev/copy_new_files.py74
-rwxr-xr-xlibchrome_tools/uprev/dirty_uprev.py69
-rw-r--r--libchrome_tools/uprev/filtered_utils.py108
-rw-r--r--libchrome_tools/uprev/filters.py129
-rwxr-xr-xlibchrome_tools/uprev/generate_filtered_tree.py257
-rw-r--r--libchrome_tools/uprev/lazytree.py169
-rwxr-xr-xlibchrome_tools/uprev/reconnect_history.py333
-rw-r--r--libchrome_tools/uprev/utils.py261
-rw-r--r--mojo/BUILD.gn69
-rw-r--r--mojo/PRESUBMIT.py44
-rw-r--r--mojo/core/BUILD.gn325
-rw-r--r--mojo/core/broker_win.cc162
-rw-r--r--mojo/core/channel_fuchsia.cc466
-rw-r--r--mojo/core/channel_win.cc377
-rw-r--r--mojo/core/embedder/BUILD.gn29
-rw-r--r--mojo/core/node_controller.cc7
-rw-r--r--mojo/core/ports/BUILD.gn59
-rw-r--r--mojo/core/test/BUILD.gn88
-rw-r--r--mojo/core/test/test_utils_win.cc49
-rw-r--r--mojo/public/BUILD.gn33
-rw-r--r--mojo/public/c/system/BUILD.gn38
-rw-r--r--mojo/public/c/system/tests/BUILD.gn38
-rw-r--r--mojo/public/c/test_support/BUILD.gn15
-rw-r--r--mojo/public/cpp/base/BUILD.gn85
-rw-r--r--mojo/public/cpp/base/logfont_win.typemap18
-rw-r--r--mojo/public/cpp/base/logfont_win_mojom_traits.cc39
-rw-r--r--mojo/public/cpp/base/logfont_win_mojom_traits.h30
-rw-r--r--mojo/public/cpp/bindings/BUILD.gn228
-rw-r--r--mojo/public/cpp/bindings/tests/BUILD.gn156
-rw-r--r--mojo/public/cpp/platform/BUILD.gn50
-rw-r--r--mojo/public/cpp/platform/named_platform_channel_fuchsia.cc26
-rw-r--r--mojo/public/cpp/platform/named_platform_channel_win.cc110
-rw-r--r--mojo/public/cpp/platform/tests/BUILD.gn19
-rw-r--r--mojo/public/cpp/system/BUILD.gn75
-rw-r--r--mojo/public/cpp/system/tests/BUILD.gn35
-rw-r--r--mojo/public/cpp/test_support/BUILD.gn20
-rw-r--r--mojo/public/interfaces/BUILD.gn9
-rw-r--r--mojo/public/interfaces/bindings/BUILD.gn24
-rw-r--r--mojo/public/interfaces/bindings/tests/BUILD.gn266
-rw-r--r--mojo/public/java/BUILD.gn79
-rw-r--r--mojo/public/java/system/BUILD.gn177
-rw-r--r--mojo/public/js/BUILD.gn72
-rw-r--r--mojo/public/mojom/base/BUILD.gn45
-rw-r--r--mojo/public/mojom/base/logfont_win.mojom (renamed from ipc/constants.mojom)9
-rw-r--r--mojo/public/tools/bindings/BUILD.gn86
-rw-r--r--mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl4
-rw-r--r--mojo/public/tools/fuzzers/BUILD.gn67
-rw-r--r--soong/Android.bp9
-rw-r--r--testing/empty_main.cc8
-rw-r--r--testing/gmock_mutant.h130
-rw-r--r--third_party/ashmem/ashmem.h15
-rw-r--r--ui/gfx/geometry/angle_conversions.h29
-rw-r--r--ui/gfx/geometry/axis_transform2d.cc16
-rw-r--r--ui/gfx/geometry/axis_transform2d.h138
-rw-r--r--ui/gfx/geometry/axis_transform2d_unittest.cc91
-rw-r--r--ui/gfx/geometry/box_f.cc70
-rw-r--r--ui/gfx/geometry/box_f.h160
-rw-r--r--ui/gfx/geometry/box_unittest.cc175
-rw-r--r--ui/gfx/geometry/cubic_bezier.cc213
-rw-r--r--ui/gfx/geometry/cubic_bezier.h96
-rw-r--r--ui/gfx/geometry/cubic_bezier_unittest.cc230
-rw-r--r--ui/gfx/geometry/dip_util.cc88
-rw-r--r--ui/gfx/geometry/dip_util.h41
-rw-r--r--ui/gfx/geometry/insets_unittest.cc139
-rw-r--r--ui/gfx/geometry/matrix3_f.cc291
-rw-r--r--ui/gfx/geometry/matrix3_f.h139
-rw-r--r--ui/gfx/geometry/matrix3_unittest.cc182
-rw-r--r--ui/gfx/geometry/mojo/BUILD.gn51
-rw-r--r--ui/gfx/geometry/point3_f.cc40
-rw-r--r--ui/gfx/geometry/point3_f.h128
-rw-r--r--ui/gfx/geometry/point3_unittest.cc71
-rw-r--r--ui/gfx/geometry/point_unittest.cc236
-rw-r--r--ui/gfx/geometry/quad_f.cc134
-rw-r--r--ui/gfx/geometry/quad_f.h130
-rw-r--r--ui/gfx/geometry/quad_unittest.cc361
-rw-r--r--ui/gfx/geometry/quaternion.cc106
-rw-r--r--ui/gfx/geometry/quaternion.h93
-rw-r--r--ui/gfx/geometry/quaternion_unittest.cc169
-rw-r--r--ui/gfx/geometry/rect_conversions.cc82
-rw-r--r--ui/gfx/geometry/rect_conversions.h36
-rw-r--r--ui/gfx/geometry/rect_unittest.cc1141
-rw-r--r--ui/gfx/geometry/safe_integer_conversions_unittest.cc80
-rw-r--r--ui/gfx/geometry/scroll_offset_unittest.cc124
-rw-r--r--ui/gfx/geometry/size_unittest.cc251
-rw-r--r--ui/gfx/geometry/test/rect_test_util.cc23
-rw-r--r--ui/gfx/geometry/test/rect_test_util.h21
-rw-r--r--ui/gfx/geometry/vector2d_conversions.cc30
-rw-r--r--ui/gfx/geometry/vector2d_conversions.h24
-rw-r--r--ui/gfx/geometry/vector2d_unittest.cc293
-rw-r--r--ui/gfx/geometry/vector3d_f.cc108
-rw-r--r--ui/gfx/geometry/vector3d_f.h151
-rw-r--r--ui/gfx/geometry/vector3d_unittest.cc347
-rw-r--r--ui/gfx/range/BUILD.gn35
-rw-r--r--ui/gfx/range/mojo/BUILD.gn49
900 files changed, 4746 insertions, 139329 deletions
diff --git a/Android.bp b/Android.bp
index 6bd807c029..8104e8829b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -20,485 +20,19 @@
// for details.
// Note: gensrcs does not support exclude_srcs, so filegroup rule is
// introduced.
-package {
- default_applicable_licenses: ["external_libchrome_license"],
-}
-
-// Added automatically by a large-scale-change that took the approach of
-// 'apply every license found to every target'. While this makes sure we respect
-// every license restriction, it may not be entirely correct.
-//
-// e.g. GPL in an MIT project might only apply to the contrib/ directory.
-//
-// Please consider splitting the single license below into multiple licenses,
-// taking care not to lose any license_kind information, and overriding the
-// default license using the 'licenses: [...]' property on targets as needed.
-//
-// For unused files, consider creating a 'fileGroup' with "//visibility:private"
-// to attach the license to, and including a comment whether the files may be
-// used in the current project.
-// See: http://go/android-license-faq
-license {
- name: "external_libchrome_license",
- visibility: [":__subpackages__"],
- license_kinds: [
- "SPDX-license-identifier-Apache-2.0",
- "SPDX-license-identifier-BSD",
- "SPDX-license-identifier-GPL-2.0",
- "SPDX-license-identifier-LGPL-2.1",
- "SPDX-license-identifier-MIT",
- "SPDX-license-identifier-MPL",
- "SPDX-license-identifier-Unicode-DFS",
- "legacy_unencumbered",
- ],
- license_text: [
- "NOTICE",
- ],
-}
-
filegroup {
name: "libchrome-include-sources",
srcs: [
- "base/allocator/allocator_extension.h",
- "base/allocator/allocator_shim.h",
- "base/allocator/allocator_shim_internals.h",
- "base/allocator/allocator_shim_override_cpp_symbols.h",
- "base/allocator/allocator_shim_override_libc_symbols.h",
- "base/allocator/allocator_shim_override_linker_wrapped_symbols.h",
- "base/allocator/buildflags.h",
- "base/android/android_hardware_buffer_compat.h",
- "base/android/build_info.h",
- "base/android/content_uri_utils.h",
- "base/android/java_exception_reporter.h",
- "base/android/jni_android.h",
- "base/android/jni_array.h",
- "base/android/jni_string.h",
- "base/android/path_utils.h",
- "base/android/scoped_hardware_buffer_handle.h",
- "base/android/scoped_java_ref.h",
- "base/android/sys_utils.h",
- "base/at_exit.h",
- "base/atomic_ref_count.h",
- "base/atomic_sequence_num.h",
- "base/atomicops.h",
- "base/atomicops_internals_atomicword_compat.h",
- "base/atomicops_internals_portable.h",
- "base/atomicops_internals_x86_msvc.h",
- "base/auto_reset.h",
- "base/barrier_closure.h",
- "base/base64.h",
- "base/base64url.h",
- "base/base_export.h",
- "base/base_paths.h",
- "base/base_paths_android.h",
- "base/base_paths_posix.h",
- "base/base_switches.h",
- "base/big_endian.h",
- "base/bind.h",
- "base/bind_helpers.h",
- "base/bind_internal.h",
- "base/bit_cast.h",
- "base/bits.h",
- "base/build_time.h",
- "base/callback.h",
- "base/callback_forward.h",
- "base/callback_helpers.h",
- "base/callback_internal.h",
- "base/callback_list.h",
- "base/cancelable_callback.h",
- "base/cfi_buildflags.h",
- "base/command_line.h",
- "base/compiler_specific.h",
- "base/component_export.h",
- "base/containers/adapters.h",
- "base/containers/circular_deque.h",
- "base/containers/flat_map.h",
- "base/containers/flat_set.h",
- "base/containers/flat_tree.h",
- "base/containers/hash_tables.h",
- "base/containers/linked_list.h",
- "base/containers/mru_cache.h",
- "base/containers/queue.h",
- "base/containers/ring_buffer.h",
- "base/containers/small_map.h",
- "base/containers/span.h",
- "base/containers/stack.h",
- "base/containers/stack_container.h",
- "base/containers/vector_buffer.h",
- "base/cpu.h",
- "base/critical_closure.h",
- "base/debug/activity_tracker.h",
- "base/debug/alias.h",
- "base/debug/crash_logging.h",
- "base/debug/debugger.h",
- "base/debug/debugging_buildflags.h",
- "base/debug/dump_without_crashing.h",
- "base/debug/elf_reader_linux.h",
- "base/debug/leak_annotations.h",
- "base/debug/leak_tracker.h",
- "base/debug/proc_maps_linux.h",
- "base/debug/profiler.h",
- "base/debug/stack_trace.h",
- "base/debug/task_annotator.h",
- "base/debug/thread_heap_usage_tracker.h",
- "base/environment.h",
- "base/export_template.h",
- "base/feature_list.h",
- "base/file_descriptor_posix.h",
- "base/file_version_info.h",
- "base/files/dir_reader_fallback.h",
- "base/files/dir_reader_linux.h",
- "base/files/dir_reader_posix.h",
- "base/files/file.h",
- "base/files/file_descriptor_watcher_posix.h",
- "base/files/file_enumerator.h",
- "base/files/file_path.h",
- "base/files/file_path_watcher.h",
- "base/files/file_tracing.h",
- "base/files/file_util.h",
- "base/files/important_file_writer.h",
- "base/files/memory_mapped_file.h",
- "base/files/platform_file.h",
- "base/files/scoped_file.h",
- "base/files/scoped_temp_dir.h",
- "base/format_macros.h",
- "base/gtest_prod_util.h",
- "base/guid.h",
- "base/hash.h",
- "base/i18n/base_i18n_export.h",
- "base/i18n/rtl.h",
- "base/json/json_file_value_serializer.h",
- "base/json/json_parser.h",
- "base/json/json_reader.h",
- "base/json/json_string_value_serializer.h",
- "base/json/json_value_converter.h",
- "base/json/json_writer.h",
- "base/json/string_escape.h",
- "base/lazy_instance.h",
- "base/lazy_instance_helpers.h",
- "base/location.h",
- "base/logging.h",
- "base/macros.h",
- "base/md5.h",
- "base/memory/aligned_memory.h",
- "base/memory/free_deleter.h",
- "base/memory/linked_ptr.h",
- "base/memory/platform_shared_memory_region.h",
- "base/memory/protected_memory.h",
- "base/memory/protected_memory_buildflags.h",
- "base/memory/protected_memory_cfi.h",
- "base/memory/ptr_util.h",
- "base/memory/raw_scoped_refptr_mismatch_checker.h",
- "base/memory/read_only_shared_memory_region.h",
- "base/memory/ref_counted.h",
- "base/memory/ref_counted_delete_on_sequence.h",
- "base/memory/ref_counted_memory.h",
- "base/memory/scoped_policy.h",
- "base/memory/scoped_refptr.h",
- "base/memory/shared_memory.h",
- "base/memory/shared_memory_handle.h",
- "base/memory/shared_memory_helper.h",
- "base/memory/shared_memory_mapping.h",
- "base/memory/singleton.h",
- "base/memory/unsafe_shared_memory_region.h",
- "base/memory/weak_ptr.h",
- "base/memory/writable_shared_memory_region.h",
- "base/message_loop/incoming_task_queue.h",
- "base/message_loop/message_loop.h",
- "base/message_loop/message_loop_current.h",
- "base/message_loop/message_loop_task_runner.h",
- "base/message_loop/message_pump.h",
- "base/message_loop/message_pump_default.h",
- "base/message_loop/message_pump_for_io.h",
- "base/message_loop/message_pump_for_ui.h",
- "base/message_loop/message_pump_glib.h",
- "base/message_loop/message_pump_libevent.h",
- "base/message_loop/timer_slack.h",
- "base/message_loop/watchable_io_message_pump_posix.h",
- "base/metrics/bucket_ranges.h",
- "base/metrics/dummy_histogram.h",
- "base/metrics/field_trial.h",
- "base/metrics/field_trial_param_associator.h",
- "base/metrics/field_trial_params.h",
- "base/metrics/histogram.h",
- "base/metrics/histogram_base.h",
- "base/metrics/histogram_delta_serialization.h",
- "base/metrics/histogram_flattener.h",
- "base/metrics/histogram_functions.h",
- "base/metrics/histogram_macros.h",
- "base/metrics/histogram_macros_internal.h",
- "base/metrics/histogram_macros_local.h",
- "base/metrics/histogram_samples.h",
- "base/metrics/histogram_snapshot_manager.h",
- "base/metrics/metrics_hashes.h",
- "base/metrics/persistent_histogram_allocator.h",
- "base/metrics/persistent_histogram_storage.h",
- "base/metrics/persistent_memory_allocator.h",
- "base/metrics/persistent_sample_map.h",
- "base/metrics/record_histogram_checker.h",
- "base/metrics/sample_map.h",
- "base/metrics/sample_vector.h",
- "base/metrics/single_sample_metrics.h",
- "base/metrics/sparse_histogram.h",
- "base/metrics/statistics_recorder.h",
- "base/metrics/user_metrics.h",
- "base/metrics/user_metrics_action.h",
- "base/native_library.h",
- "base/no_destructor.h",
- "base/numerics/checked_math.h",
- "base/numerics/checked_math_impl.h",
- "base/numerics/clamped_math.h",
- "base/numerics/clamped_math_impl.h",
- "base/numerics/math_constants.h",
- "base/numerics/ranges.h",
- "base/numerics/safe_conversions.h",
- "base/numerics/safe_conversions_arm_impl.h",
- "base/numerics/safe_conversions_impl.h",
- "base/numerics/safe_math.h",
- "base/numerics/safe_math_arm_impl.h",
- "base/numerics/safe_math_clang_gcc_impl.h",
- "base/numerics/safe_math_shared_impl.h",
- "base/observer_list.h",
- "base/observer_list_threadsafe.h",
- "base/optional.h",
- "base/os_compat_android.h",
- "base/path_service.h",
- "base/pending_task.h",
- "base/pickle.h",
- "base/posix/eintr_wrapper.h",
- "base/posix/file_descriptor_shuffle.h",
- "base/posix/global_descriptors.h",
- "base/posix/safe_strerror.h",
- "base/posix/unix_domain_socket.h",
- "base/post_task_and_reply_with_result_internal.h",
- "base/power_monitor/power_monitor.h",
- "base/power_monitor/power_monitor_device_source.h",
- "base/power_monitor/power_monitor_source.h",
- "base/power_monitor/power_observer.h",
- "base/process/internal_aix.h",
- "base/process/internal_linux.h",
- "base/process/kill.h",
- "base/process/launch.h",
- "base/process/memory.h",
- "base/process/process.h",
- "base/process/process_handle.h",
- "base/process/process_info.h",
- "base/process/process_iterator.h",
- "base/process/process_metrics.h",
- "base/process/process_metrics_iocounters.h",
- "base/rand_util.h",
- "base/run_loop.h",
- "base/sampling_heap_profiler/lock_free_address_hash_set.h",
- "base/sampling_heap_profiler/sampling_heap_profiler.h",
- "base/scoped_clear_errno.h",
- "base/scoped_generic.h",
- "base/scoped_native_library.h",
- "base/scoped_observer.h",
- "base/sequence_checker.h",
- "base/sequence_checker_impl.h",
- "base/sequence_token.h",
- "base/sequenced_task_runner.h",
- "base/sequenced_task_runner_helpers.h",
- "base/sha1.h",
- "base/single_thread_task_runner.h",
- "base/stl_util.h",
- "base/strings/char_traits.h",
- "base/strings/nullable_string16.h",
- "base/strings/old_utf_string_conversions.h",
- "base/strings/pattern.h",
- "base/strings/safe_sprintf.h",
- "base/strings/strcat.h",
- "base/strings/string16.h",
- "base/strings/string_number_conversions.h",
- "base/strings/string_piece.h",
- "base/strings/string_piece_forward.h",
- "base/strings/string_split.h",
- "base/strings/string_tokenizer.h",
- "base/strings/string_util.h",
- "base/strings/string_util_posix.h",
- "base/strings/stringize_macros.h",
- "base/strings/stringprintf.h",
- "base/strings/sys_string_conversions.h",
- "base/strings/utf_string_conversion_utils.h",
- "base/strings/utf_string_conversions.h",
- "base/sync_socket.h",
- "base/synchronization/atomic_flag.h",
- "base/synchronization/cancellation_flag.h",
- "base/synchronization/condition_variable.h",
- "base/synchronization/lock.h",
- "base/synchronization/lock_impl.h",
- "base/synchronization/spin_wait.h",
- "base/synchronization/synchronization_buildflags.h",
- "base/synchronization/waitable_event.h",
- "base/synchronization/waitable_event_watcher.h",
- "base/sys_byteorder.h",
- "base/sys_info.h",
- "base/sys_info_internal.h",
- "base/task/cancelable_task_tracker.h",
- "base/task/sequence_manager/enqueue_order.h",
- "base/task/sequence_manager/graceful_queue_shutdown_helper.h",
- "base/task/sequence_manager/intrusive_heap.h",
- "base/task/sequence_manager/lazily_deallocated_deque.h",
- "base/task/sequence_manager/lazy_now.h",
- "base/task/sequence_manager/moveable_auto_lock.h",
- "base/task/sequence_manager/real_time_domain.h",
- "base/task/sequence_manager/sequence_manager.h",
- "base/task/sequence_manager/sequence_manager_impl.h",
- "base/task/sequence_manager/sequenced_task_source.h",
- "base/task/sequence_manager/task_queue.h",
- "base/task/sequence_manager/task_queue_impl.h",
- "base/task/sequence_manager/task_queue_selector.h",
- "base/task/sequence_manager/task_queue_selector_logic.h",
- "base/task/sequence_manager/task_time_observer.h",
- "base/task/sequence_manager/test/fake_task.h",
- "base/task/sequence_manager/test/lazy_thread_controller_for_test.h",
- "base/task/sequence_manager/test/mock_time_domain.h",
- "base/task/sequence_manager/test/sequence_manager_for_test.h",
- "base/task/sequence_manager/test/test_task_queue.h",
- "base/task/sequence_manager/test/test_task_time_observer.h",
- "base/task/sequence_manager/thread_controller.h",
- "base/task/sequence_manager/thread_controller_impl.h",
- "base/task/sequence_manager/thread_controller_with_message_pump_impl.h",
- "base/task/sequence_manager/time_domain.h",
- "base/task/sequence_manager/work_queue.h",
- "base/task/sequence_manager/work_queue_sets.h",
- "base/task_runner.h",
- "base/task_runner_util.h",
- "base/task_scheduler/can_schedule_sequence_observer.h",
- "base/task_scheduler/delayed_task_manager.h",
- "base/task_scheduler/environment_config.h",
- "base/task_scheduler/lazy_task_runner.h",
- "base/task_scheduler/post_task.h",
- "base/task_scheduler/priority_queue.h",
- "base/task_scheduler/scheduler_lock.h",
- "base/task_scheduler/scheduler_lock_impl.h",
- "base/task_scheduler/scheduler_single_thread_task_runner_manager.h",
- "base/task_scheduler/scheduler_worker.h",
- "base/task_scheduler/scheduler_worker_observer.h",
- "base/task_scheduler/scheduler_worker_params.h",
- "base/task_scheduler/scheduler_worker_pool.h",
- "base/task_scheduler/scheduler_worker_pool_impl.h",
- "base/task_scheduler/scheduler_worker_pool_params.h",
- "base/task_scheduler/scheduler_worker_stack.h",
- "base/task_scheduler/scoped_set_task_priority_for_current_thread.h",
- "base/task_scheduler/sequence.h",
- "base/task_scheduler/sequence_sort_key.h",
- "base/task_scheduler/service_thread.h",
- "base/task_scheduler/single_thread_task_runner_thread_mode.h",
- "base/task_scheduler/task.h",
- "base/task_scheduler/task_scheduler.h",
- "base/task_scheduler/task_scheduler_impl.h",
- "base/task_scheduler/task_tracker.h",
- "base/task_scheduler/task_tracker_posix.h",
- "base/task_scheduler/task_traits.h",
- "base/task_scheduler/task_traits_details.h",
- "base/task_scheduler/test_utils.h",
- "base/task_scheduler/tracked_ref.h",
- "base/template_util.h",
- "base/test/bind_test_util.h",
- "base/test/copy_only_int.h",
- "base/test/fontconfig_util_linux.h",
- "base/test/gtest_util.h",
- "base/test/metrics/histogram_enum_reader.h",
- "base/test/metrics/histogram_tester.h",
- "base/test/mock_entropy_provider.h",
- "base/test/move_only_int.h",
- "base/test/multiprocess_test.h",
- "base/test/scoped_environment_variable_override.h",
- "base/test/scoped_feature_list.h",
- "base/test/scoped_locale.h",
- "base/test/scoped_task_environment.h",
- "base/test/simple_test_clock.h",
- "base/test/simple_test_tick_clock.h",
- "base/test/test_file_util.h",
- "base/test/test_io_thread.h",
- "base/test/test_mock_time_task_runner.h",
- "base/test/test_pending_task.h",
- "base/test/test_shared_memory_util.h",
- "base/test/test_simple_task_runner.h",
- "base/test/test_switches.h",
- "base/test/test_timeouts.h",
- "base/third_party/dynamic_annotations/dynamic_annotations.h",
- "base/third_party/icu/icu_utf.h",
- "base/third_party/libevent/event.h",
- "base/third_party/nspr/prtime.h",
- "base/third_party/symbolize/symbolize.h",
- "base/third_party/valgrind/memcheck.h",
- "base/third_party/valgrind/valgrind.h",
- "base/thread_annotations.h",
- "base/threading/platform_thread.h",
- "base/threading/platform_thread_internal_posix.h",
- "base/threading/post_task_and_reply_impl.h",
- "base/threading/scoped_blocking_call.h",
- "base/threading/sequence_local_storage_map.h",
- "base/threading/sequence_local_storage_slot.h",
- "base/threading/sequenced_task_runner_handle.h",
- "base/threading/simple_thread.h",
- "base/threading/thread.h",
- "base/threading/thread_checker.h",
- "base/threading/thread_checker_impl.h",
- "base/threading/thread_collision_warner.h",
- "base/threading/thread_id_name_manager.h",
- "base/threading/thread_local.h",
- "base/threading/thread_local_storage.h",
- "base/threading/thread_restrictions.h",
- "base/threading/thread_task_runner_handle.h",
- "base/time/clock.h",
- "base/time/default_clock.h",
- "base/time/default_tick_clock.h",
- "base/time/tick_clock.h",
- "base/time/time.h",
- "base/time/time_override.h",
- "base/time/time_to_iso8601.h",
- "base/timer/elapsed_timer.h",
- "base/timer/hi_res_timer_manager.h",
- "base/timer/mock_timer.h",
- "base/timer/timer.h",
- "base/trace_event/common/trace_event_common.h",
- "base/trace_event/heap_profiler.h",
- "base/trace_event/trace_event.h",
- "base/tuple.h",
- "base/unguessable_token.h",
- "base/value_iterators.h",
- "base/values.h",
- "base/version.h",
- "base/vlog.h",
- "build/build_config.h",
- "build/buildflag.h",
- "device/bluetooth/bluetooth_advertisement.h",
- "device/bluetooth/bluetooth_common.h",
- "device/bluetooth/bluetooth_export.h",
- "device/bluetooth/bluetooth_uuid.h",
- "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h",
- "testing/gmock/include/gmock/gmock.h",
- "testing/gtest/include/gtest/gtest.h",
- "testing/gtest/include/gtest/gtest_prod.h",
- "testing/multiprocess_func_list.h",
- "testing/platform_test.h",
- "third_party/ashmem/ashmem.h",
- "third_party/modp_b64/modp_b64.h",
- "third_party/protobuf/src/google/protobuf/message_lite.h",
- "third_party/re2/src/re2/re2.h",
- "ui/gfx/geometry/insets.h",
- "ui/gfx/geometry/insets_f.h",
- "ui/gfx/geometry/mojo/geometry_struct_traits.h",
- "ui/gfx/geometry/point.h",
- "ui/gfx/geometry/point_conversions.h",
- "ui/gfx/geometry/point_f.h",
- "ui/gfx/geometry/rect.h",
- "ui/gfx/geometry/rect_f.h",
- "ui/gfx/geometry/safe_integer_conversions.h",
- "ui/gfx/geometry/scroll_offset.h",
- "ui/gfx/geometry/size.h",
- "ui/gfx/geometry/size_conversions.h",
- "ui/gfx/geometry/size_f.h",
- "ui/gfx/geometry/vector2d.h",
- "ui/gfx/geometry/vector2d_f.h",
- "ui/gfx/gfx_export.h",
- "ui/gfx/range/gfx_range_export.h",
- "ui/gfx/range/mojo/range_struct_traits.h",
- "ui/gfx/range/range.h",
- "ui/gfx/range/range_f.h",
+ "base/**/*.h",
+ "build/**/*.h",
+ "components/**/*.h",
+ "device/**/*.h",
+ "testing/**/*.h",
+ "third_party/**/*.h",
+ "ui/**/*.h",
+ ],
+ exclude_srcs: [
+ "base/android/**/*",
],
}
@@ -533,8 +67,6 @@ cc_defaults {
// so the raw header files are used for them.
generated_headers: ["libchrome-include"],
export_generated_headers: ["libchrome-include"],
- header_libs: ["jni_headers"],
- export_header_lib_headers: ["jni_headers"],
target: {
host: {
cflags: [
@@ -614,10 +146,12 @@ libchromeCommonSrc = [
"base/md5.cc",
"base/memory/aligned_memory.cc",
"base/memory/platform_shared_memory_region.cc",
+ "base/memory/platform_shared_memory_region_posix.cc",
"base/memory/read_only_shared_memory_region.cc",
"base/memory/ref_counted.cc",
"base/memory/ref_counted_memory.cc",
"base/memory/shared_memory_handle.cc",
+ "base/memory/shared_memory_handle_posix.cc",
"base/memory/shared_memory_helper.cc",
"base/memory/shared_memory_mapping.cc",
"base/memory/unsafe_shared_memory_region.cc",
@@ -772,42 +306,19 @@ libchromeLinuxSrc = [
"base/sys_info_linux.cc",
"base/threading/platform_thread_internal_posix.cc",
"base/threading/platform_thread_linux.cc",
+ "components/timers/alarm_timer_chromeos.cc",
]
libchromeLinuxGlibcSrc = [
"base/allocator/allocator_shim.cc",
"base/allocator/allocator_shim_default_dispatch_to_glibc.cc",
"base/debug/stack_trace_posix.cc",
- "base/memory/platform_shared_memory_region_posix.cc",
- "base/memory/shared_memory_handle_posix.cc",
-]
-
-libchromeLinuxBionicSrc = [
- "base/debug/stack_trace_android.cc",
- "base/memory/platform_shared_memory_region_posix.cc",
- "base/memory/shared_memory_handle_posix.cc",
]
libchromeAndroidSrc = [
- "base/android/android_hardware_buffer_compat.cc",
- "base/android/build_info.cc",
- "base/android/content_uri_utils.cc",
- "base/android/java_exception_reporter.cc",
- "base/android/jni_android.cc",
- "base/android/jni_array.cc",
- "base/android/jni_string.cc",
- "base/android/path_utils.cc",
- "base/android/scoped_java_ref.cc",
- "base/android/scoped_hardware_buffer_handle.cc",
- "base/android/sys_utils.cc",
- "base/base_paths_android.cc",
"base/debug/stack_trace_android.cc",
- "base/memory/platform_shared_memory_region_android.cc",
"base/memory/shared_memory_android.cc",
- "base/memory/shared_memory_handle_android.cc",
- "base/os_compat_android.cc",
- "base/sys_info_android.cc",
- "base/time/time_android.cc",
+ "base/sys_info_chromeos.cc",
]
// libchrome static+shared for host and device
@@ -821,34 +332,19 @@ cc_library {
srcs: libchromeCommonSrc,
export_shared_lib_headers: ["libbase"],
- export_header_lib_headers: ["libgtest_prod_headers"],
+ export_static_lib_headers: ["libgtest_prod"],
shared_libs: [
"libbase",
"libevent",
],
- header_libs: [
- "libgtest_prod_headers",
- ],
static_libs: [
+ "libgtest_prod",
"libmodpb64",
],
- generated_headers: [
- "libmojo_jni_headers",
- "libmojo_jni_registration_headers",
- ],
- export_generated_headers: [
- "libmojo_jni_registration_headers",
- ],
target: {
linux: {
srcs: libchromeLinuxSrc,
},
- linux_bionic: {
- srcs: libchromeLinuxBionicSrc,
- shared_libs: [
- "liblog",
- ],
- },
linux_glibc: {
srcs: libchromeLinuxGlibcSrc,
},
@@ -1339,10 +835,7 @@ genrule {
srcs: [
"base/android/java/src/org/chromium/base/BuildInfo.java",
- "base/android/java/src/org/chromium/base/ContentUriUtils.java",
"base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "base/android/java/src/org/chromium/base/PathUtils.java",
- "base/android/java/src/org/chromium/base/SysUtils.java",
"base/android/java/src/org/chromium/base/ThreadUtils.java",
"mojo/public/java/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java",
"mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java",
@@ -1352,11 +845,8 @@ genrule {
out: [
"jni/BaseRunLoop_jni.h",
"jni/BuildInfo_jni.h",
- "jni/ContentUriUtils_jni.h",
"jni/CoreImpl_jni.h",
"jni/JavaExceptionReporter_jni.h",
- "jni/PathUtils_jni.h",
- "jni/SysUtils_jni.h",
"jni/WatcherImpl_jni.h",
],
}
@@ -1469,80 +959,10 @@ java_library {
srcs: [
":libmojo_mojom_java_srcs",
- "base/android/java/src/org/chromium/base/BuildConfig.java",
- "base/android/java/src/org/chromium/base/BuildInfo.java",
- "base/android/java/src/org/chromium/base/ContextUtils.java",
- "base/android/java/src/org/chromium/base/DiscardableReferencePool.java",
- "base/android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "base/android/java/src/org/chromium/base/Log.java",
- "base/android/java/src/org/chromium/base/PackageUtils.java",
- "base/android/java/src/org/chromium/base/StrictModeContext.java",
- "base/android/java/src/org/chromium/base/Supplier.java",
- "base/android/java/src/org/chromium/base/ThreadUtils.java",
- "base/android/java/src/org/chromium/base/TimezoneUtils.java",
- "base/android/java/src/org/chromium/base/VisibleForTesting.java",
- "base/android/java/src/org/chromium/base/annotations/AccessedByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNative.java",
- "base/android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
- "base/android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
- "base/android/java/src/org/chromium/base/annotations/JNINamespace.java",
- "base/android/java/src/org/chromium/base/annotations/MainDex.java",
- "base/android/java/src/org/chromium/base/annotations/NativeCall.java",
- "base/android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
- "base/android/java/src/org/chromium/base/annotations/RemovableInRelease.java",
- "base/android/java/src/org/chromium/base/annotations/UsedByReflection.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/AssociatedInterfaceNotSupported.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/AssociatedInterfaceRequestNotSupported.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/AutoCloseableRouter.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/BindingsHelper.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Callbacks.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/ConnectionErrorHandler.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Connector.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/DataHeader.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Decoder.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/DelegatingConnectionErrorHandler.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/DeserializationException.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/ExceptionHandler.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/ExecutorFactory.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/HandleOwner.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceControlMessagesHelper.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/InterfaceRequest.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Message.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageHeader.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageReceiver.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/MessageReceiverWithResponder.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Router.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/RouterImpl.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/SerializationException.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/ServiceMessage.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/SideEffectFreeCloseable.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Struct.java",
- "mojo/public/java/bindings/src/org/chromium/mojo/bindings/Union.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/Core.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/DataPipe.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/Flags.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/Handle.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/InvalidHandle.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/MessagePipeHandle.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/MojoException.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/MojoResult.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/Pair.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/ResultAnd.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/RunLoop.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/SharedBufferHandle.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/UntypedHandle.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/Watcher.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/BaseRunLoop.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/CoreImpl.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/HandleBase.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/UntypedHandleImpl.java",
- "mojo/public/java/system/src/org/chromium/mojo/system/impl/WatcherImpl.java",
+ "base/android/java/src/**/*.java",
+ "mojo/android/system/src/**/*.java",
+ "mojo/public/java/bindings/src/**/*.java",
+ "mojo/public/java/system/src/**/*.java",
],
static_libs: [
diff --git a/BUILD.IGNORE b/BUILD.IGNORE
deleted file mode 100644
index d84edf6d59..0000000000
--- a/BUILD.IGNORE
+++ /dev/null
@@ -1,10 +0,0 @@
-android
-components/policy
-fuzzer
-perftest
-power_monitor
-test_runner
-tests
-trace_event
-ui/gfx
-unittest
diff --git a/BUILD.gn b/BUILD.gn
index 6cb4e68bde..b956970b24 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1,12 +1,8 @@
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-#
-# BUILD.gn doesn't compile all files in the directory to reduce build size.
-# Missing files can be added if needed.
import("//common-mk/mojom_bindings_generator.gni")
-import("//common-mk/mojom_type_mappings_generator.gni")
import("//common-mk/pkg_config.gni")
group("all") {
@@ -36,11 +32,9 @@ config("libchrome_config") {
cflags = [
"-Wno-deprecated-register",
"-Wno-narrowing",
- "-Wno-unreachable-code-return",
"-Wno-unused-local-typedefs",
"-Xclang-only=-Wno-char-subscripts",
]
-
# Address sanitizer + coverage builds do not support -z,defs.
if (!(use.asan || use.coverage)) {
ldflags = [ "-Wl,-z,defs" ]
@@ -51,7 +45,6 @@ config("base_core_config") {
cflags = [
# Suppressing warning in base/strings/stringprintf.cc.
"-Wno-format-nonliteral",
-
# This is for _exit(1) in base/debug/debugger_posix.cc.
"-Wno-unreachable-code",
]
@@ -61,15 +54,8 @@ libbase_sublibs = [
{
name = "base-core"
output_name = name + "-${libbase_ver}"
- libs = [
- "pthread",
- "rt",
- "modp_b64",
- ]
- pkg_deps = [
- "glib-2.0",
- "libevent",
- ]
+ libs = [ "pthread", "rt", "modp_b64" ]
+ pkg_deps = [ "glib-2.0", "libevent" ]
configs = [ ":base_core_config" ]
sources = [
"base/allocator/allocator_extension.cc",
@@ -139,8 +125,8 @@ libbase_sublibs = [
"base/memory/shared_memory_handle.cc",
"base/memory/shared_memory_handle_posix.cc",
"base/memory/shared_memory_helper.cc",
- "base/memory/shared_memory_mapping.cc",
"base/memory/shared_memory_posix.cc",
+ "base/memory/shared_memory_mapping.cc",
"base/memory/unsafe_shared_memory_region.cc",
"base/memory/weak_ptr.cc",
"base/memory/writable_shared_memory_region.cc",
@@ -171,8 +157,8 @@ libbase_sublibs = [
"base/metrics/sample_vector.cc",
"base/metrics/sparse_histogram.cc",
"base/metrics/statistics_recorder.cc",
- "base/observer_list_threadsafe.cc",
"base/path_service.cc",
+ "base/observer_list_threadsafe.cc",
"base/pending_task.cc",
"base/pickle.cc",
"base/posix/file_descriptor_shuffle.cc",
@@ -200,8 +186,8 @@ libbase_sublibs = [
"base/rand_util_posix.cc",
"base/run_loop.cc",
"base/sequence_checker_impl.cc",
- "base/sequence_token.cc",
"base/sequenced_task_runner.cc",
+ "base/sequence_token.cc",
"base/sha1.cc",
"base/strings/nullable_string16.cc",
"base/strings/pattern.cc",
@@ -228,11 +214,10 @@ libbase_sublibs = [
"base/sys_info_chromeos.cc",
"base/sys_info_linux.cc",
"base/sys_info_posix.cc",
- "base/task/cancelable_task_tracker.cc",
"base/task_runner.cc",
+ "base/task/cancelable_task_tracker.cc",
"base/task_scheduler/delayed_task_manager.cc",
"base/task_scheduler/environment_config.cc",
- "base/task_scheduler/lazy_task_runner.cc",
"base/task_scheduler/post_task.cc",
"base/task_scheduler/priority_queue.cc",
"base/task_scheduler/scheduler_lock_impl.cc",
@@ -249,9 +234,9 @@ libbase_sublibs = [
"base/task_scheduler/task.cc",
"base/task_scheduler/task_scheduler.cc",
"base/task_scheduler/task_scheduler_impl.cc",
+ "base/task_scheduler/task_traits.cc",
"base/task_scheduler/task_tracker.cc",
"base/task_scheduler/task_tracker_posix.cc",
- "base/task_scheduler/task_traits.cc",
"base/third_party/dynamic_annotations/dynamic_annotations.c",
"base/third_party/icu/icu_utf.cc",
"base/third_party/nspr/prtime.cc",
@@ -272,6 +257,8 @@ libbase_sublibs = [
"base/threading/thread_local_storage_posix.cc",
"base/threading/thread_restrictions.cc",
"base/threading/thread_task_runner_handle.cc",
+ "base/timer/elapsed_timer.cc",
+ "base/timer/timer.cc",
"base/time/clock.cc",
"base/time/default_clock.cc",
"base/time/default_tick_clock.cc",
@@ -281,8 +268,6 @@ libbase_sublibs = [
"base/time/time_exploded_posix.cc",
"base/time/time_now_posix.cc",
"base/time/time_override.cc",
- "base/timer/elapsed_timer.cc",
- "base/timer/timer.cc",
"base/unguessable_token.cc",
"base/value_iterators.cc",
"base/values.cc",
@@ -297,8 +282,8 @@ libbase_sublibs = [
deps = [ ":base-core" ]
libs = [ "dl" ]
sources = [
- "base/native_library.cc",
"base/native_library_posix.cc",
+ "base/native_library.cc",
"base/scoped_native_library.cc",
]
},
@@ -322,7 +307,6 @@ libbase_sublibs = [
output_name = name + "-${libbase_ver}"
testonly = true
sources = [
- "base/test/scoped_task_environment.cc",
"base/test/simple_test_clock.cc",
"base/test/simple_test_tick_clock.cc",
"base/test/test_file_util.cc",
@@ -333,7 +317,7 @@ libbase_sublibs = [
"base/test/test_switches.cc",
"base/test/test_timeouts.cc",
]
- },
+ }
]
if (use.crypto) {
@@ -341,14 +325,8 @@ if (use.crypto) {
{
name = "base-crypto"
output_name = name + "-${libbase_ver}"
- deps = [
- ":base-core",
- ":base-dl",
- ]
- pkg_deps = [
- "nss",
- "openssl",
- ]
+ deps = [ ":base-core", ":base-dl" ]
+ pkg_deps = [ "nss", "openssl" ]
sources = [
"crypto/hmac.cc",
"crypto/hmac_nss.cc",
@@ -369,11 +347,10 @@ if (use.crypto) {
"crypto/symmetric_key_nss.cc",
"crypto/third_party/nss/rsawrapr.c",
"crypto/third_party/nss/sha512.cc",
-
# Added to libchrome only (not upstream) to support OpenSSL 1.1 API
"crypto/libcrypto-compat.c",
]
- },
+ }
]
}
@@ -385,9 +362,9 @@ if (use.dbus) {
deps = [ ":base-core" ]
pkg_deps = [ "dbus-1" ]
if (use.fuzzer) {
- pkg_deps += [ "protobuf" ]
+ pkg_deps += [ "protobuf" ]
} else {
- pkg_deps += [ "protobuf-lite" ]
+ pkg_deps += [ "protobuf-lite" ]
}
sources = [
"dbus/bus.cc",
@@ -411,9 +388,9 @@ if (use.dbus) {
testonly = true
pkg_deps = [ "dbus-1" ]
if (use.fuzzer) {
- pkg_deps += [ "protobuf" ]
+ pkg_deps += [ "protobuf" ]
} else {
- pkg_deps += [ "protobuf-lite" ]
+ pkg_deps += [ "protobuf-lite" ]
}
sources = [
"dbus/mock_bus.cc",
@@ -473,7 +450,7 @@ foreach(attr, libbase_sublibs) {
}
configs += [
":libchrome_config",
- "//common-mk:visibility_default",
+ "//common-mk:visibility_default"
]
if (buildtype == "static_library") {
configs -= [ "//common-mk:use_thin_archive" ]
@@ -496,26 +473,20 @@ action("base") {
script = "//common-mk/write_args.py"
outputs = [ "${root_out_dir}/lib/lib${target_name}-${libbase_ver}.so" ]
args = [ "--output" ] + outputs + [ "--" ] + [
- "GROUP",
- "(",
- "AS_NEEDED",
- "(",
- ]
+ "GROUP", "(", "AS_NEEDED", "(",
+ ]
foreach(attr, libbase_sublibs) {
if (!defined(attr.testonly) || !attr.testonly) {
args += [ "-l" + attr.output_name ]
}
}
- args += [
- ")",
- ")",
- ]
+ args += [ ")", ")" ]
}
libchrome_exported_cflags = [
- "-I/usr/include/base-${libbase_ver}",
- "-Wno-unused-local-typedefs",
- "-DBASE_VER=${libbase_ver}",
+ "-I/usr/include/base-${libbase_ver}",
+ "-Wno-unused-local-typedefs",
+ "-DBASE_VER=${libbase_ver}",
]
if (use.asan) {
@@ -529,7 +500,8 @@ generate_pkg_config("libchrome") {
version = "${libbase_ver}"
requires_private = []
foreach(attr, libbase_sublibs) {
- if ((!defined(attr.testonly) || !attr.testonly) && defined(attr.pkg_deps)) {
+ if ((!defined(attr.testonly) || !attr.testonly)
+ && defined(attr.pkg_deps)) {
requires_private += attr.pkg_deps
}
}
@@ -559,20 +531,14 @@ action("base-test") {
script = "//common-mk/write_args.py"
outputs = [ "${root_out_dir}/lib${target_name}-${libbase_ver}.a" ]
args = [ "--output" ] + outputs + [ "--" ] + [
- "GROUP",
- "(",
- "AS_NEEDED",
- "(",
- ]
+ "GROUP", "(", "AS_NEEDED", "(",
+ ]
foreach(attr, libbase_sublibs) {
if (defined(attr.testonly) && attr.testonly) {
args += [ "-l" + attr.output_name ]
}
}
- args += [
- ")",
- ")",
- ]
+ args += [ ")", ")" ]
}
generate_pkg_config("libchrome-test") {
@@ -600,33 +566,8 @@ generate_pkg_config("libchrome-test") {
}
if (use.mojo) {
- generate_mojom_type_mappings("mojom_type_mappings") {
- mojom_type_mappings_generator =
- "libchrome_tools/mojom_generate_type_mappings.py"
- sources = [
- "mojo/public/cpp/base/big_buffer.typemap",
- "mojo/public/cpp/base/big_string.typemap",
- "mojo/public/cpp/base/file.typemap",
- "mojo/public/cpp/base/file_error.typemap",
- "mojo/public/cpp/base/file_info.typemap",
- "mojo/public/cpp/base/file_path.typemap",
- "mojo/public/cpp/base/memory_allocator_dump_cross_process_uid.typemap",
- "mojo/public/cpp/base/process_id.typemap",
- "mojo/public/cpp/base/read_only_buffer.typemap",
- "mojo/public/cpp/base/ref_counted_memory.typemap",
- "mojo/public/cpp/base/shared_memory.typemap",
- "mojo/public/cpp/base/string16.typemap",
- "mojo/public/cpp/base/text_direction.typemap",
- "mojo/public/cpp/base/thread_priority.typemap",
- "mojo/public/cpp/base/time.typemap",
- "mojo/public/cpp/base/unguessable_token.typemap",
- "mojo/public/cpp/base/values.typemap",
- ]
- }
generate_mojom_bindings_gen("mojom_bindings_gen") {
- mojom_bindings_generator =
- "mojo/public/tools/bindings/mojom_bindings_generator.py"
- typemaps = get_target_outputs(":mojom_type_mappings")
+ mojom_bindings_generator = "mojo/public/tools/bindings/mojom_bindings_generator.py"
sources = [
"ipc/ipc.mojom",
"mojo/public/mojom/base/big_buffer.mojom",
@@ -635,7 +576,6 @@ if (use.mojo) {
"mojo/public/mojom/base/file_error.mojom",
"mojo/public/mojom/base/file_info.mojom",
"mojo/public/mojom/base/file_path.mojom",
- "mojo/public/mojom/base/memory_allocator_dump_cross_process_uid.mojom",
"mojo/public/mojom/base/process_id.mojom",
"mojo/public/mojom/base/read_only_buffer.mojom",
"mojo/public/mojom/base/ref_counted_memory.mojom",
@@ -652,8 +592,7 @@ if (use.mojo) {
}
generate_mojom_bindings_gen("mojom_bindings_native_gen") {
- mojom_bindings_generator =
- "mojo/public/tools/bindings/mojom_bindings_generator.py"
+ mojom_bindings_generator = "mojo/public/tools/bindings/mojom_bindings_generator.py"
sources = [
"mojo/public/interfaces/bindings/interface_control_messages.mojom",
"mojo/public/interfaces/bindings/native_struct.mojom",
@@ -667,14 +606,7 @@ if (use.mojo) {
# crbug.com/924035.
static_library("mojo") {
output_name = "mojo-${libbase_ver}"
- deps = [
- ":base-core",
- ":base-crypto",
- ":mojom_bindings_gen",
- ":mojom_bindings_native_gen",
- ":mojom_type_mappings",
- ]
-
+ deps = [ ":base-core", ":base-crypto", ":mojom_bindings_gen", ":mojom_bindings_native_gen" ]
# TODO(hidehiko): Consolidate with build_config.h.
configs -= [
"//common-mk:use_thin_archive",
@@ -686,131 +618,129 @@ if (use.mojo) {
"//common-mk:nouse_thin_archive",
"//common-mk:pic",
]
- sources =
- [
- "ipc/ipc_message.cc",
- "ipc/ipc_message_attachment.cc",
- "ipc/ipc_message_attachment_set.cc",
- "ipc/ipc_message_utils.cc",
- "ipc/ipc_mojo_handle_attachment.cc",
- "ipc/ipc_mojo_message_helper.cc",
- "ipc/ipc_mojo_param_traits.cc",
- "ipc/ipc_platform_file_attachment_posix.cc",
- "mojo/core/invitation_dispatcher.cc",
- "mojo/core/connection_params.cc",
- "mojo/core/channel_posix.cc",
- "mojo/core/platform_handle_dispatcher.cc",
- "mojo/core/mojo_core.cc",
- "mojo/core/channel.cc",
- "mojo/core/entrypoints.cc",
- "mojo/core/broker_posix.cc",
- "mojo/core/data_pipe_producer_dispatcher.cc",
- "mojo/core/broker_host.cc",
- "mojo/core/watcher_dispatcher.cc",
- "mojo/core/request_context.cc",
- "mojo/core/configuration.cc",
- "mojo/core/node_channel.cc",
- "mojo/core/shared_buffer_dispatcher.cc",
- "mojo/core/watch.cc",
- "mojo/core/embedder/scoped_ipc_support.cc",
- "mojo/core/embedder/embedder.cc",
- "mojo/core/message_pipe_dispatcher.cc",
- "mojo/core/handle_table.cc",
- "mojo/core/core.cc",
- "mojo/core/ports/event.cc",
- "mojo/core/ports/name.cc",
- "mojo/core/ports/port.cc",
- "mojo/core/ports/message_queue.cc",
- "mojo/core/ports/port_locker.cc",
- "mojo/core/ports/node.cc",
- "mojo/core/ports/user_message.cc",
- "mojo/core/ports/port_ref.cc",
- "mojo/core/data_pipe_consumer_dispatcher.cc",
- "mojo/core/scoped_process_handle.cc",
- "mojo/core/node_controller.cc",
- "mojo/core/watcher_set.cc",
- "mojo/core/dispatcher.cc",
- "mojo/core/platform_handle_in_transit.cc",
- "mojo/core/platform_handle_utils.cc",
- "mojo/core/platform_shared_memory_mapping.cc",
- "mojo/core/user_message_impl.cc",
- "mojo/core/data_pipe_control_message.cc",
- "mojo/public/c/system/thunks.cc",
- "mojo/public/cpp/base/big_string_mojom_traits.cc",
- "mojo/public/cpp/base/shared_memory_mojom_traits.cc",
- "mojo/public/cpp/base/unguessable_token_mojom_traits.cc",
- "mojo/public/cpp/base/ref_counted_memory_mojom_traits.cc",
- "mojo/public/cpp/base/big_buffer.cc",
- "mojo/public/cpp/base/read_only_buffer_mojom_traits.cc",
- "mojo/public/cpp/base/string16_mojom_traits.cc",
- "mojo/public/cpp/base/big_buffer_mojom_traits.cc",
- "mojo/public/cpp/base/file_info_mojom_traits.cc",
- "mojo/public/cpp/base/time_mojom_traits.cc",
- "mojo/public/cpp/base/thread_priority_mojom_traits.cc",
- "mojo/public/cpp/base/text_direction_mojom_traits.cc",
- "mojo/public/cpp/base/values_mojom_traits.cc",
- "mojo/public/cpp/base/file_path_mojom_traits.cc",
- "mojo/public/cpp/base/process_id_mojom_traits.cc",
- "mojo/public/cpp/base/file_mojom_traits.cc",
- "mojo/public/cpp/bindings/lib/serialization_context.cc",
- "mojo/public/cpp/bindings/lib/associated_interface_ptr_state.cc",
- "mojo/public/cpp/bindings/lib/array_internal.cc",
- "mojo/public/cpp/bindings/lib/interface_ptr_state.cc",
- "mojo/public/cpp/bindings/lib/buffer.cc",
- "mojo/public/cpp/bindings/lib/sync_call_restrictions.cc",
- "mojo/public/cpp/bindings/lib/multiplex_router.cc",
- "mojo/public/cpp/bindings/lib/sync_handle_watcher.cc",
- "mojo/public/cpp/bindings/lib/validation_errors.cc",
- "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc",
- "mojo/public/cpp/bindings/lib/message_dumper.cc",
- "mojo/public/cpp/bindings/lib/sync_event_watcher.cc",
- "mojo/public/cpp/bindings/lib/task_runner_helper.cc",
- "mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc",
- "mojo/public/cpp/bindings/lib/validation_context.cc",
- "mojo/public/cpp/bindings/lib/associated_group.cc",
- "mojo/public/cpp/bindings/lib/native_struct_serialization.cc",
- "mojo/public/cpp/bindings/lib/validation_util.cc",
- "mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc",
- "mojo/public/cpp/bindings/lib/filter_chain.cc",
- "mojo/public/cpp/bindings/lib/message.cc",
- "mojo/public/cpp/bindings/lib/unserialized_message_context.cc",
- "mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc",
- "mojo/public/cpp/bindings/lib/control_message_proxy.cc",
- "mojo/public/cpp/bindings/lib/control_message_handler.cc",
- "mojo/public/cpp/bindings/lib/connector.cc",
- "mojo/public/cpp/bindings/lib/interface_endpoint_client.cc",
- "mojo/public/cpp/bindings/lib/sync_handle_registry.cc",
- "mojo/public/cpp/bindings/lib/associated_binding.cc",
- "mojo/public/cpp/bindings/lib/message_header_validator.cc",
- "mojo/public/cpp/bindings/lib/associated_group_controller.cc",
- "mojo/public/cpp/bindings/lib/associated_interface_ptr.cc",
- "mojo/public/cpp/bindings/lib/fixed_buffer.cc",
- "mojo/public/cpp/bindings/lib/message_internal.cc",
- "mojo/public/cpp/bindings/lib/binding_state.cc",
- "mojo/public/cpp/platform/platform_channel_endpoint.cc",
- "mojo/public/cpp/platform/platform_handle.cc",
- "mojo/public/cpp/platform/named_platform_channel.cc",
- "mojo/public/cpp/platform/platform_channel.cc",
- "mojo/public/cpp/platform/platform_channel_server_endpoint.cc",
- "mojo/public/cpp/platform/socket_utils_posix.cc",
- "mojo/public/cpp/platform/named_platform_channel_posix.cc",
- "mojo/public/cpp/system/buffer.cc",
- "mojo/public/cpp/system/platform_handle.cc",
- "mojo/public/cpp/system/wait.cc",
- "mojo/public/cpp/system/wait_set.cc",
- "mojo/public/cpp/system/data_pipe_utils.cc",
- "mojo/public/cpp/system/scope_to_message_pipe.cc",
- "mojo/public/cpp/system/handle_signal_tracker.cc",
- "mojo/public/cpp/system/trap.cc",
- "mojo/public/cpp/system/isolated_connection.cc",
- "mojo/public/cpp/system/string_data_pipe_producer.cc",
- "mojo/public/cpp/system/data_pipe_drainer.cc",
- "mojo/public/cpp/system/invitation.cc",
- "mojo/public/cpp/system/simple_watcher.cc",
- "mojo/public/cpp/system/file_data_pipe_producer.cc",
- "mojo/public/cpp/system/message_pipe.cc",
- ] + get_target_outputs(":mojom_bindings_gen") +
- get_target_outputs(":mojom_bindings_native_gen")
+ sources = [
+ "ipc/ipc_message.cc",
+ "ipc/ipc_message_attachment.cc",
+ "ipc/ipc_message_attachment_set.cc",
+ "ipc/ipc_message_utils.cc",
+ "ipc/ipc_mojo_handle_attachment.cc",
+ "ipc/ipc_mojo_message_helper.cc",
+ "ipc/ipc_mojo_param_traits.cc",
+ "ipc/ipc_platform_file_attachment_posix.cc",
+ "mojo/core/invitation_dispatcher.cc",
+ "mojo/core/connection_params.cc",
+ "mojo/core/channel_posix.cc",
+ "mojo/core/platform_handle_dispatcher.cc",
+ "mojo/core/mojo_core.cc",
+ "mojo/core/channel.cc",
+ "mojo/core/entrypoints.cc",
+ "mojo/core/broker_posix.cc",
+ "mojo/core/data_pipe_producer_dispatcher.cc",
+ "mojo/core/broker_host.cc",
+ "mojo/core/watcher_dispatcher.cc",
+ "mojo/core/request_context.cc",
+ "mojo/core/configuration.cc",
+ "mojo/core/node_channel.cc",
+ "mojo/core/shared_buffer_dispatcher.cc",
+ "mojo/core/watch.cc",
+ "mojo/core/embedder/scoped_ipc_support.cc",
+ "mojo/core/embedder/embedder.cc",
+ "mojo/core/message_pipe_dispatcher.cc",
+ "mojo/core/handle_table.cc",
+ "mojo/core/core.cc",
+ "mojo/core/ports/event.cc",
+ "mojo/core/ports/name.cc",
+ "mojo/core/ports/port.cc",
+ "mojo/core/ports/message_queue.cc",
+ "mojo/core/ports/port_locker.cc",
+ "mojo/core/ports/node.cc",
+ "mojo/core/ports/user_message.cc",
+ "mojo/core/ports/port_ref.cc",
+ "mojo/core/data_pipe_consumer_dispatcher.cc",
+ "mojo/core/scoped_process_handle.cc",
+ "mojo/core/node_controller.cc",
+ "mojo/core/watcher_set.cc",
+ "mojo/core/dispatcher.cc",
+ "mojo/core/platform_handle_in_transit.cc",
+ "mojo/core/platform_handle_utils.cc",
+ "mojo/core/platform_shared_memory_mapping.cc",
+ "mojo/core/user_message_impl.cc",
+ "mojo/core/data_pipe_control_message.cc",
+ "mojo/public/c/system/thunks.cc",
+ "mojo/public/cpp/base/big_string_mojom_traits.cc",
+ "mojo/public/cpp/base/shared_memory_mojom_traits.cc",
+ "mojo/public/cpp/base/unguessable_token_mojom_traits.cc",
+ "mojo/public/cpp/base/ref_counted_memory_mojom_traits.cc",
+ "mojo/public/cpp/base/big_buffer.cc",
+ "mojo/public/cpp/base/read_only_buffer_mojom_traits.cc",
+ "mojo/public/cpp/base/string16_mojom_traits.cc",
+ "mojo/public/cpp/base/big_buffer_mojom_traits.cc",
+ "mojo/public/cpp/base/file_info_mojom_traits.cc",
+ "mojo/public/cpp/base/time_mojom_traits.cc",
+ "mojo/public/cpp/base/thread_priority_mojom_traits.cc",
+ "mojo/public/cpp/base/text_direction_mojom_traits.cc",
+ "mojo/public/cpp/base/values_mojom_traits.cc",
+ "mojo/public/cpp/base/file_path_mojom_traits.cc",
+ "mojo/public/cpp/base/process_id_mojom_traits.cc",
+ "mojo/public/cpp/base/file_mojom_traits.cc",
+ "mojo/public/cpp/bindings/lib/serialization_context.cc",
+ "mojo/public/cpp/bindings/lib/associated_interface_ptr_state.cc",
+ "mojo/public/cpp/bindings/lib/array_internal.cc",
+ "mojo/public/cpp/bindings/lib/interface_ptr_state.cc",
+ "mojo/public/cpp/bindings/lib/buffer.cc",
+ "mojo/public/cpp/bindings/lib/sync_call_restrictions.cc",
+ "mojo/public/cpp/bindings/lib/multiplex_router.cc",
+ "mojo/public/cpp/bindings/lib/sync_handle_watcher.cc",
+ "mojo/public/cpp/bindings/lib/validation_errors.cc",
+ "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc",
+ "mojo/public/cpp/bindings/lib/message_dumper.cc",
+ "mojo/public/cpp/bindings/lib/sync_event_watcher.cc",
+ "mojo/public/cpp/bindings/lib/task_runner_helper.cc",
+ "mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc",
+ "mojo/public/cpp/bindings/lib/validation_context.cc",
+ "mojo/public/cpp/bindings/lib/associated_group.cc",
+ "mojo/public/cpp/bindings/lib/native_struct_serialization.cc",
+ "mojo/public/cpp/bindings/lib/validation_util.cc",
+ "mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc",
+ "mojo/public/cpp/bindings/lib/filter_chain.cc",
+ "mojo/public/cpp/bindings/lib/message.cc",
+ "mojo/public/cpp/bindings/lib/unserialized_message_context.cc",
+ "mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc",
+ "mojo/public/cpp/bindings/lib/control_message_proxy.cc",
+ "mojo/public/cpp/bindings/lib/control_message_handler.cc",
+ "mojo/public/cpp/bindings/lib/connector.cc",
+ "mojo/public/cpp/bindings/lib/interface_endpoint_client.cc",
+ "mojo/public/cpp/bindings/lib/sync_handle_registry.cc",
+ "mojo/public/cpp/bindings/lib/associated_binding.cc",
+ "mojo/public/cpp/bindings/lib/message_header_validator.cc",
+ "mojo/public/cpp/bindings/lib/associated_group_controller.cc",
+ "mojo/public/cpp/bindings/lib/associated_interface_ptr.cc",
+ "mojo/public/cpp/bindings/lib/fixed_buffer.cc",
+ "mojo/public/cpp/bindings/lib/message_internal.cc",
+ "mojo/public/cpp/bindings/lib/binding_state.cc",
+ "mojo/public/cpp/platform/platform_channel_endpoint.cc",
+ "mojo/public/cpp/platform/platform_handle.cc",
+ "mojo/public/cpp/platform/named_platform_channel.cc",
+ "mojo/public/cpp/platform/platform_channel.cc",
+ "mojo/public/cpp/platform/platform_channel_server_endpoint.cc",
+ "mojo/public/cpp/platform/socket_utils_posix.cc",
+ "mojo/public/cpp/platform/named_platform_channel_posix.cc",
+ "mojo/public/cpp/system/buffer.cc",
+ "mojo/public/cpp/system/platform_handle.cc",
+ "mojo/public/cpp/system/wait.cc",
+ "mojo/public/cpp/system/wait_set.cc",
+ "mojo/public/cpp/system/data_pipe_utils.cc",
+ "mojo/public/cpp/system/scope_to_message_pipe.cc",
+ "mojo/public/cpp/system/handle_signal_tracker.cc",
+ "mojo/public/cpp/system/trap.cc",
+ "mojo/public/cpp/system/isolated_connection.cc",
+ "mojo/public/cpp/system/string_data_pipe_producer.cc",
+ "mojo/public/cpp/system/data_pipe_drainer.cc",
+ "mojo/public/cpp/system/invitation.cc",
+ "mojo/public/cpp/system/simple_watcher.cc",
+ "mojo/public/cpp/system/file_data_pipe_producer.cc",
+ "mojo/public/cpp/system/message_pipe.cc",
+ ] + get_target_outputs(":mojom_bindings_gen") + get_target_outputs(":mojom_bindings_native_gen")
}
generate_pkg_config("libmojo") {
diff --git a/METADATA b/METADATA
deleted file mode 100644
index 6d8601bb68..0000000000
--- a/METADATA
+++ /dev/null
@@ -1,3 +0,0 @@
-third_party {
- license_type: RESTRICTED
-}
diff --git a/base/android/android_hardware_buffer_abi.h b/base/android/android_hardware_buffer_abi.h
deleted file mode 100644
index 7012532d18..0000000000
--- a/base/android/android_hardware_buffer_abi.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_ANDROID_ANDROID_HARDWARE_BUFFER_ABI_H_
-#define BASE_ANDROID_ANDROID_HARDWARE_BUFFER_ABI_H_
-
-// Minimal binary interface definitions for AHardwareBuffer based on
-// include/android/hardware_buffer.h from the Android NDK for platform level
-// 26+. This is only intended for use from the AndroidHardwareBufferCompat
-// wrapper for building without NDK platform level support, it is not a
-// general-use header and is not complete.
-//
-// TODO(crbug.com/771171): Delete this file when third_party/android_ndk/
-// is updated to a version that contains the android/hardware_buffer.h file.
-//
-// Please refer to the API documentation for details:
-// https://developer.android.com/ndk/reference/hardware__buffer_8h.html
-
-#include <stdint.h>
-
-// Use "C" linkage to match the original header file. This isn't strictly
-// required since the file is not declaring global functions, but the types
-// should remain in the global namespace for compatibility, and it's a reminder
-// that forward declarations elsewhere should use "extern "C" to avoid
-// namespace issues.
-extern "C" {
-
-typedef struct AHardwareBuffer AHardwareBuffer;
-typedef struct ARect ARect;
-
-enum {
- AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
- AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2,
- AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3,
- AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4,
- AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16,
- AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b,
- AHARDWAREBUFFER_FORMAT_BLOB = 0x21,
-};
-
-enum {
- AHARDWAREBUFFER_USAGE_CPU_READ_NEVER = 0UL,
- AHARDWAREBUFFER_USAGE_CPU_READ_RARELY = 2UL,
- AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN = 3UL,
- AHARDWAREBUFFER_USAGE_CPU_READ_MASK = 0xFUL,
- AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER = 0UL << 4,
- AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY = 2UL << 4,
- AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN = 3UL << 4,
- AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK = 0xFUL << 4,
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE = 1UL << 8,
- AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = 1UL << 9,
- AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14,
- AHARDWAREBUFFER_USAGE_VIDEO_ENCODE = 1UL << 16,
- AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA = 1UL << 23,
- AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24,
-};
-
-typedef struct AHardwareBuffer_Desc {
- uint32_t width;
- uint32_t height;
- uint32_t layers;
- uint32_t format;
- uint64_t usage;
- uint32_t stride;
- uint32_t rfu0;
- uint64_t rfu1;
-} AHardwareBuffer_Desc;
-
-using PFAHardwareBuffer_allocate = void (*)(const AHardwareBuffer_Desc* desc,
- AHardwareBuffer** outBuffer);
-using PFAHardwareBuffer_acquire = void (*)(AHardwareBuffer* buffer);
-using PFAHardwareBuffer_describe = void (*)(const AHardwareBuffer* buffer,
- AHardwareBuffer_Desc* outDesc);
-using PFAHardwareBuffer_lock = int (*)(AHardwareBuffer* buffer,
- uint64_t usage,
- int32_t fence,
- const ARect* rect,
- void** outVirtualAddress);
-using PFAHardwareBuffer_recvHandleFromUnixSocket =
- int (*)(int socketFd, AHardwareBuffer** outBuffer);
-using PFAHardwareBuffer_release = void (*)(AHardwareBuffer* buffer);
-using PFAHardwareBuffer_sendHandleToUnixSocket =
- int (*)(const AHardwareBuffer* buffer, int socketFd);
-using PFAHardwareBuffer_unlock = int (*)(AHardwareBuffer* buffer,
- int32_t* fence);
-
-} // extern "C"
-
-#endif // BASE_ANDROID_ANDROID_HARDWARE_BUFFER_ABI_H_
diff --git a/base/android/android_hardware_buffer_compat.cc b/base/android/android_hardware_buffer_compat.cc
deleted file mode 100644
index 70f058947b..0000000000
--- a/base/android/android_hardware_buffer_compat.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2017 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/android/android_hardware_buffer_compat.h"
-
-#include "base/android/build_info.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-
-#include <dlfcn.h>
-
-namespace base {
-
-namespace {
-
-static base::LazyInstance<AndroidHardwareBufferCompat>::Leaky g_compat =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-AndroidHardwareBufferCompat::AndroidHardwareBufferCompat() {
- DCHECK(IsSupportAvailable());
-
- // TODO(klausw): If the Chromium build requires __ANDROID_API__ >= 26 at some
- // point in the future, we could directly use the global functions instead of
- // dynamic loading. However, since this would be incompatible with pre-Oreo
- // devices, this is unlikely to happen in the foreseeable future, so just
- // unconditionally use dynamic loading.
-
- // cf. base/android/linker/modern_linker_jni.cc
- void* main_dl_handle = dlopen(nullptr, RTLD_NOW);
-
- *reinterpret_cast<void**>(&allocate_) =
- dlsym(main_dl_handle, "AHardwareBuffer_allocate");
- DCHECK(allocate_);
-
- *reinterpret_cast<void**>(&acquire_) =
- dlsym(main_dl_handle, "AHardwareBuffer_acquire");
- DCHECK(acquire_);
-
- *reinterpret_cast<void**>(&describe_) =
- dlsym(main_dl_handle, "AHardwareBuffer_describe");
- DCHECK(describe_);
-
- *reinterpret_cast<void**>(&lock_) =
- dlsym(main_dl_handle, "AHardwareBuffer_lock");
- DCHECK(lock_);
-
- *reinterpret_cast<void**>(&recv_handle_) =
- dlsym(main_dl_handle, "AHardwareBuffer_recvHandleFromUnixSocket");
- DCHECK(recv_handle_);
-
- *reinterpret_cast<void**>(&release_) =
- dlsym(main_dl_handle, "AHardwareBuffer_release");
- DCHECK(release_);
-
- *reinterpret_cast<void**>(&send_handle_) =
- dlsym(main_dl_handle, "AHardwareBuffer_sendHandleToUnixSocket");
- DCHECK(send_handle_);
-
- *reinterpret_cast<void**>(&unlock_) =
- dlsym(main_dl_handle, "AHardwareBuffer_unlock");
- DCHECK(unlock_);
-}
-
-// static
-bool AndroidHardwareBufferCompat::IsSupportAvailable() {
- return base::android::BuildInfo::GetInstance()->sdk_int() >=
- base::android::SDK_VERSION_OREO;
-}
-
-// static
-AndroidHardwareBufferCompat AndroidHardwareBufferCompat::GetInstance() {
- return g_compat.Get();
-}
-
-void AndroidHardwareBufferCompat::Allocate(const AHardwareBuffer_Desc* desc,
- AHardwareBuffer** out_buffer) {
- DCHECK(IsSupportAvailable());
- allocate_(desc, out_buffer);
-}
-
-void AndroidHardwareBufferCompat::Acquire(AHardwareBuffer* buffer) {
- DCHECK(IsSupportAvailable());
- acquire_(buffer);
-}
-
-void AndroidHardwareBufferCompat::Describe(const AHardwareBuffer* buffer,
- AHardwareBuffer_Desc* out_desc) {
- DCHECK(IsSupportAvailable());
- describe_(buffer, out_desc);
-}
-
-int AndroidHardwareBufferCompat::Lock(AHardwareBuffer* buffer,
- uint64_t usage,
- int32_t fence,
- const ARect* rect,
- void** out_virtual_address) {
- DCHECK(IsSupportAvailable());
- return lock_(buffer, usage, fence, rect, out_virtual_address);
-}
-
-int AndroidHardwareBufferCompat::RecvHandleFromUnixSocket(
- int socket_fd,
- AHardwareBuffer** out_buffer) {
- DCHECK(IsSupportAvailable());
- return recv_handle_(socket_fd, out_buffer);
-}
-
-void AndroidHardwareBufferCompat::Release(AHardwareBuffer* buffer) {
- DCHECK(IsSupportAvailable());
- release_(buffer);
-}
-
-int AndroidHardwareBufferCompat::SendHandleToUnixSocket(
- const AHardwareBuffer* buffer,
- int socket_fd) {
- DCHECK(IsSupportAvailable());
- return send_handle_(buffer, socket_fd);
-}
-
-int AndroidHardwareBufferCompat::Unlock(AHardwareBuffer* buffer,
- int32_t* fence) {
- DCHECK(IsSupportAvailable());
- return unlock_(buffer, fence);
-}
-
-} // namespace base
diff --git a/base/android/android_hardware_buffer_compat.h b/base/android/android_hardware_buffer_compat.h
deleted file mode 100644
index 14be3d5b9c..0000000000
--- a/base/android/android_hardware_buffer_compat.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_ANDROID_ANDROID_HARDWARE_BUFFER_COMPAT_H_
-#define BASE_ANDROID_ANDROID_HARDWARE_BUFFER_COMPAT_H_
-
-#include "base/android/android_hardware_buffer_abi.h"
-#include "base/base_export.h"
-#include "base/lazy_instance.h"
-
-namespace base {
-
-// This class provides runtime support for working with AHardwareBuffer objects
-// on Android O systems without requiring building for the Android O NDK level.
-// Don't call GetInstance() unless IsSupportAvailable() returns true.
-class BASE_EXPORT AndroidHardwareBufferCompat {
- public:
- static bool IsSupportAvailable();
- static AndroidHardwareBufferCompat GetInstance();
-
- void Allocate(const AHardwareBuffer_Desc* desc, AHardwareBuffer** outBuffer);
- void Acquire(AHardwareBuffer* buffer);
- void Describe(const AHardwareBuffer* buffer, AHardwareBuffer_Desc* outDesc);
- int Lock(AHardwareBuffer* buffer,
- uint64_t usage,
- int32_t fence,
- const ARect* rect,
- void** out_virtual_address);
- int RecvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer);
- void Release(AHardwareBuffer* buffer);
- int SendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd);
- int Unlock(AHardwareBuffer* buffer, int32_t* fence);
-
- private:
- friend struct base::LazyInstanceTraitsBase<AndroidHardwareBufferCompat>;
- AndroidHardwareBufferCompat();
-
- PFAHardwareBuffer_allocate allocate_;
- PFAHardwareBuffer_acquire acquire_;
- PFAHardwareBuffer_describe describe_;
- PFAHardwareBuffer_lock lock_;
- PFAHardwareBuffer_recvHandleFromUnixSocket recv_handle_;
- PFAHardwareBuffer_release release_;
- PFAHardwareBuffer_sendHandleToUnixSocket send_handle_;
- PFAHardwareBuffer_unlock unlock_;
-};
-
-} // namespace base
-
-#endif // BASE_ANDROID_ANDROID_HARDWARE_BUFFER_COMPAT_H_
diff --git a/base/android/android_image_reader_abi.h b/base/android/android_image_reader_abi.h
deleted file mode 100644
index c81087fe59..0000000000
--- a/base/android/android_image_reader_abi.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2018 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.
-
-#ifndef BASE_ANDROID_ANDROID_IMAGE_READER_ABI_H_
-#define BASE_ANDROID_ANDROID_IMAGE_READER_ABI_H_
-
-// Minimal binary interface definitions for AImage,AImageReader
-// and ANativeWindow based on include/media/NdkImage.h,
-// include/media/NdkImageReader.h and include/android/native_window_jni.h
-// from the Android NDK for platform level 26+. This is only
-// intended for use from the AndroidImageReader wrapper for building
-// without NDK platform level support, it is not a general-use header
-// and is not complete. Only the functions/data types which
-// are currently needed by media/gpu/android/image_reader_gl_owner.h are
-// included in this ABI
-//
-// Please refer to the API documentation for details:
-// https://developer.android.com/ndk/reference/group/media (AIMage and
-// AImageReader)
-// https://developer.android.com/ndk/reference/group/native-activity
-// (ANativeWindow)
-
-#include <android/native_window.h>
-#include <media/NdkMediaError.h>
-
-#include <jni.h>
-#include <stdint.h>
-
-// Use "C" linkage to match the original header file. This isn't strictly
-// required since the file is not declaring global functions, but the types
-// should remain in the global namespace for compatibility, and it's a reminder
-// that forward declarations elsewhere should use "extern "C" to avoid
-// namespace issues.
-extern "C" {
-
-// For AImage
-typedef struct AHardwareBuffer AHardwareBuffer;
-
-typedef struct AImage AImage;
-
-enum AIMAGE_FORMATS {
- AIMAGE_FORMAT_YUV_420_888 = 0x23,
- IMAGE_FORMAT_PRIVATE = 0x22
-};
-
-using pAImage_delete = void (*)(AImage* image);
-
-using pAImage_deleteAsync = void (*)(AImage* image, int releaseFenceFd);
-
-using pAImage_getHardwareBuffer = media_status_t (*)(const AImage* image,
- AHardwareBuffer** buffer);
-
-using pAImage_getWidth = media_status_t (*)(const AImage* image,
- int32_t* width);
-
-using pAImage_getHeight = media_status_t (*)(const AImage* image,
- int32_t* height);
-
-// For AImageReader
-
-typedef struct AImageReader AImageReader;
-
-typedef void (*AImageReader_ImageCallback)(void* context, AImageReader* reader);
-
-typedef struct AImageReader_ImageListener {
- void* context;
- AImageReader_ImageCallback onImageAvailable;
-} AImageReader_ImageListener;
-
-using pAImageReader_new = media_status_t (*)(int32_t width,
- int32_t height,
- int32_t format,
- int32_t maxImages,
- AImageReader** reader);
-
-using pAImageReader_setImageListener =
- media_status_t (*)(AImageReader* reader,
- AImageReader_ImageListener* listener);
-
-using pAImageReader_delete = void (*)(AImageReader* reader);
-
-using pAImageReader_getWindow = media_status_t (*)(AImageReader* reader,
- ANativeWindow** window);
-
-using pAImageReader_acquireLatestImageAsync =
- media_status_t (*)(AImageReader* reader,
- AImage** image,
- int* acquireFenceFd);
-
-// For ANativeWindow
-using pANativeWindow_toSurface = jobject (*)(JNIEnv* env,
- ANativeWindow* window);
-
-} // extern "C"
-
-#endif // BASE_ANDROID_ANDROID_IMAGE_READER_ABI_H_
diff --git a/base/android/android_image_reader_compat.cc b/base/android/android_image_reader_compat.cc
deleted file mode 100644
index 0b08c179d8..0000000000
--- a/base/android/android_image_reader_compat.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2018 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/android/android_image_reader_compat.h"
-
-#include <dlfcn.h>
-
-#include "base/android/build_info.h"
-#include "base/feature_list.h"
-#include "base/logging.h"
-
-#define LOAD_FUNCTION(lib, func) \
- do { \
- func##_ = reinterpret_cast<p##func>(dlsym(lib, #func)); \
- if (!func##_) { \
- DLOG(ERROR) << "Unable to load function " << #func; \
- return false; \
- } \
- } while (0)
-
-namespace base {
-namespace android {
-
-AndroidImageReader& AndroidImageReader::GetInstance() {
- // C++11 static local variable initialization is
- // thread-safe.
- static base::NoDestructor<AndroidImageReader> instance;
- return *instance;
-}
-
-bool AndroidImageReader::IsSupported() {
- return is_supported_;
-}
-
-AndroidImageReader::AndroidImageReader() {
- is_supported_ = LoadFunctions();
-}
-
-bool AndroidImageReader::LoadFunctions() {
- // If the Chromium build requires __ANDROID_API__ >= 26 at some
- // point in the future, we could directly use the global functions instead of
- // dynamic loading. However, since this would be incompatible with pre-Oreo
- // devices, this is unlikely to happen in the foreseeable future, so we use
- // dynamic loading.
-
- // Functions are not present for android version older than OREO
- if (base::android::BuildInfo::GetInstance()->sdk_int() <
- base::android::SDK_VERSION_OREO) {
- return false;
- }
-
- void* libmediandk = dlopen("libmediandk.so", RTLD_NOW);
- if (libmediandk == nullptr) {
- LOG(ERROR) << "Couldnt open libmediandk.so";
- return false;
- }
-
- LOAD_FUNCTION(libmediandk, AImage_delete);
- LOAD_FUNCTION(libmediandk, AImage_deleteAsync);
- LOAD_FUNCTION(libmediandk, AImage_getHardwareBuffer);
- LOAD_FUNCTION(libmediandk, AImage_getWidth);
- LOAD_FUNCTION(libmediandk, AImage_getHeight);
- LOAD_FUNCTION(libmediandk, AImageReader_new);
- LOAD_FUNCTION(libmediandk, AImageReader_setImageListener);
- LOAD_FUNCTION(libmediandk, AImageReader_delete);
- LOAD_FUNCTION(libmediandk, AImageReader_getWindow);
- LOAD_FUNCTION(libmediandk, AImageReader_acquireLatestImageAsync);
-
- void* libandroid = dlopen("libandroid.so", RTLD_NOW);
- if (libandroid == nullptr) {
- LOG(ERROR) << "Couldnt open libandroid.so";
- return false;
- }
-
- LOAD_FUNCTION(libandroid, ANativeWindow_toSurface);
-
- return true;
-}
-
-void AndroidImageReader::AImage_delete(AImage* image) {
- AImage_delete_(image);
-}
-
-void AndroidImageReader::AImage_deleteAsync(AImage* image, int releaseFenceFd) {
- AImage_deleteAsync_(image, releaseFenceFd);
-}
-
-media_status_t AndroidImageReader::AImage_getHardwareBuffer(
- const AImage* image,
- AHardwareBuffer** buffer) {
- return AImage_getHardwareBuffer_(image, buffer);
-}
-
-media_status_t AndroidImageReader::AImage_getWidth(const AImage* image,
- int32_t* width) {
- return AImage_getWidth_(image, width);
-}
-
-media_status_t AndroidImageReader::AImage_getHeight(const AImage* image,
- int32_t* height) {
- return AImage_getHeight_(image, height);
-}
-
-media_status_t AndroidImageReader::AImageReader_new(int32_t width,
- int32_t height,
- int32_t format,
- int32_t maxImages,
- AImageReader** reader) {
- return AImageReader_new_(width, height, format, maxImages, reader);
-}
-
-media_status_t AndroidImageReader::AImageReader_setImageListener(
- AImageReader* reader,
- AImageReader_ImageListener* listener) {
- return AImageReader_setImageListener_(reader, listener);
-}
-
-void AndroidImageReader::AImageReader_delete(AImageReader* reader) {
- AImageReader_delete_(reader);
-}
-
-media_status_t AndroidImageReader::AImageReader_getWindow(
- AImageReader* reader,
- ANativeWindow** window) {
- return AImageReader_getWindow_(reader, window);
-}
-
-media_status_t AndroidImageReader::AImageReader_acquireLatestImageAsync(
- AImageReader* reader,
- AImage** image,
- int* acquireFenceFd) {
- return AImageReader_acquireLatestImageAsync_(reader, image, acquireFenceFd);
-}
-
-jobject AndroidImageReader::ANativeWindow_toSurface(JNIEnv* env,
- ANativeWindow* window) {
- return ANativeWindow_toSurface_(env, window);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/android_image_reader_compat.h b/base/android/android_image_reader_compat.h
deleted file mode 100644
index 5d5d881f47..0000000000
--- a/base/android/android_image_reader_compat.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2018 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.
-
-#ifndef BASE_ANDROID_ANDROID_IMAGE_READER_COMPAT_H_
-#define BASE_ANDROID_ANDROID_IMAGE_READER_COMPAT_H_
-
-#include "base/android/android_image_reader_abi.h"
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/no_destructor.h"
-
-namespace base {
-namespace android {
-
-// This class provides runtime support for working with AImage, AImageReader and
-// ANativeWindow objects on Android O systems without requiring building for the
-// Android O NDK level. Don't call GetInstance() unless IsSupported() returns
-// true.
-class BASE_EXPORT AndroidImageReader {
- public:
- // Thread safe GetInstance.
- static AndroidImageReader& GetInstance();
-
- // Check if the image reader usage is supported. This function returns TRUE
- // if android version is >=OREO, the media flag is enabled and all the
- // required functions are loaded.
- bool IsSupported();
-
- // Naming convention of all the below functions are chosen to exactly match
- // the function names in the NDK.
- void AImage_delete(AImage* image);
- void AImage_deleteAsync(AImage* image, int releaseFenceFd);
- media_status_t AImage_getHardwareBuffer(const AImage* image,
- AHardwareBuffer** buffer);
- media_status_t AImage_getWidth(const AImage* image, int32_t* width);
- media_status_t AImage_getHeight(const AImage* image, int32_t* height);
- media_status_t AImageReader_new(int32_t width,
- int32_t height,
- int32_t format,
- int32_t maxImages,
- AImageReader** reader);
- media_status_t AImageReader_setImageListener(
- AImageReader* reader,
- AImageReader_ImageListener* listener);
- void AImageReader_delete(AImageReader* reader);
- media_status_t AImageReader_getWindow(AImageReader* reader,
- ANativeWindow** window);
- media_status_t AImageReader_acquireLatestImageAsync(AImageReader* reader,
- AImage** image,
- int* acquireFenceFd);
- jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window);
-
- private:
- friend class base::NoDestructor<AndroidImageReader>;
-
- AndroidImageReader();
- bool LoadFunctions();
-
- bool is_supported_;
- pAImage_delete AImage_delete_;
- pAImage_deleteAsync AImage_deleteAsync_;
- pAImage_getHardwareBuffer AImage_getHardwareBuffer_;
- pAImage_getWidth AImage_getWidth_;
- pAImage_getHeight AImage_getHeight_;
- pAImageReader_new AImageReader_new_;
- pAImageReader_setImageListener AImageReader_setImageListener_;
- pAImageReader_delete AImageReader_delete_;
- pAImageReader_getWindow AImageReader_getWindow_;
- pAImageReader_acquireLatestImageAsync AImageReader_acquireLatestImageAsync_;
- pANativeWindow_toSurface ANativeWindow_toSurface_;
-
- DISALLOW_COPY_AND_ASSIGN(AndroidImageReader);
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_ANDROID_IMAGE_READER_COMPAT_H_
diff --git a/base/android/android_image_reader_compat_unittest.cc b/base/android/android_image_reader_compat_unittest.cc
deleted file mode 100644
index 756ec9f140..0000000000
--- a/base/android/android_image_reader_compat_unittest.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 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/android/android_image_reader_compat.h"
-
-#include <stdint.h>
-#include <memory>
-
-#include "base/android/build_info.h"
-#include "base/test/scoped_feature_list.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace android {
-
-class AndroidImageReaderTest : public testing::Test {
- public:
- AndroidImageReaderTest() = default;
- ~AndroidImageReaderTest() override = default;
-};
-
-// Getting instance of AndroidImageReader will invoke AndroidImageReader
-// constructor which will dlopen the mediandk and androidndk .so files and do
-// all the required symbol lookups.
-TEST_F(AndroidImageReaderTest, GetImageReaderInstance) {
- // It is expected that image reader support will be available from android
- // version OREO.
- EXPECT_EQ(AndroidImageReader::GetInstance().IsSupported(),
- base::android::BuildInfo::GetInstance()->sdk_int() >=
- base::android::SDK_VERSION_OREO);
-}
-
-// There should be only 1 instance of AndroidImageReader im memory. Hence 2
-// instances should have same memory address.
-TEST_F(AndroidImageReaderTest, CompareImageReaderInstance) {
- AndroidImageReader& a1 = AndroidImageReader::GetInstance();
- AndroidImageReader& a2 = AndroidImageReader::GetInstance();
- ASSERT_EQ(&a1, &a2);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/animation_frame_time_histogram.cc b/base/android/animation_frame_time_histogram.cc
deleted file mode 100644
index 23dffd84a0..0000000000
--- a/base/android/animation_frame_time_histogram.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2015 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/android/jni_string.h"
-#include "base/metrics/histogram_macros.h"
-#include "jni/AnimationFrameTimeHistogram_jni.h"
-
-using base::android::JavaParamRef;
-
-// static
-void JNI_AnimationFrameTimeHistogram_SaveHistogram(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- const JavaParamRef<jstring>& j_histogram_name,
- const JavaParamRef<jlongArray>& j_frame_times_ms,
- jint j_count) {
- jlong *frame_times_ms = env->GetLongArrayElements(j_frame_times_ms, NULL);
- std::string histogram_name = base::android::ConvertJavaStringToUTF8(
- env, j_histogram_name);
-
- for (int i = 0; i < j_count; ++i) {
- UMA_HISTOGRAM_TIMES(histogram_name.c_str(),
- base::TimeDelta::FromMilliseconds(frame_times_ms[i]));
- }
-}
diff --git a/base/android/apk_assets.cc b/base/android/apk_assets.cc
deleted file mode 100644
index de468b497f..0000000000
--- a/base/android/apk_assets.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 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 <jni.h>
-
-#include "base/android/apk_assets.h"
-
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/file_descriptor_store.h"
-#include "jni/ApkAssets_jni.h"
-
-namespace base {
-namespace android {
-
-int OpenApkAsset(const std::string& file_path,
- base::MemoryMappedFile::Region* region) {
- // The AssetManager API of the NDK does not expose a method for accessing raw
- // resources :(
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jlongArray> jarr = Java_ApkAssets_open(
- env, base::android::ConvertUTF8ToJavaString(env, file_path));
- std::vector<jlong> results;
- base::android::JavaLongArrayToLongVector(env, jarr.obj(), &results);
- CHECK_EQ(3U, results.size());
- int fd = static_cast<int>(results[0]);
- region->offset = results[1];
- region->size = results[2];
- return fd;
-}
-
-bool RegisterApkAssetWithFileDescriptorStore(const std::string& key,
- const base::FilePath& file_path) {
- base::MemoryMappedFile::Region region =
- base::MemoryMappedFile::Region::kWholeFile;
- int asset_fd = OpenApkAsset(file_path.value(), &region);
- if (asset_fd == -1)
- return false;
- base::FileDescriptorStore::GetInstance().Set(key, base::ScopedFD(asset_fd),
- region);
- return true;
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/apk_assets.h b/base/android/apk_assets.h
deleted file mode 100644
index cdac0000af..0000000000
--- a/base/android/apk_assets.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_ANDROID_APK_ASSETS_H_
-#define BASE_ANDROID_APK_ASSETS_H_
-
-#include <string>
-
-#include "base/android/jni_android.h"
-#include "base/files/file_path.h"
-#include "base/files/memory_mapped_file.h"
-
-namespace base {
-namespace android {
-
-// Opens an asset (e.g. a .pak file) from the apk.
-// Can be used from renderer process.
-// Fails if the asset is not stored uncompressed within the .apk.
-// Returns: The File Descriptor of the asset, or -1 upon failure.
-// Input arguments:
-// - |file_path|: Path to file within .apk. e.g.: assets/foo.pak
-// Output arguments:
-// - |region|: size & offset (in bytes) within the .apk of the asset.
-BASE_EXPORT int OpenApkAsset(
- const std::string& file_path,
- base::MemoryMappedFile::Region* region);
-
-// Registers an uncompressed asset from within the apk in the
-// FileDescriptorStore.
-// Returns: true in case of success, false otherwise.
-BASE_EXPORT bool RegisterApkAssetWithFileDescriptorStore(
- const std::string& key,
- const base::FilePath& file_path);
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_APK_ASSETS_H_
diff --git a/base/android/application_status_listener.cc b/base/android/application_status_listener.cc
deleted file mode 100644
index c8c2cc68e9..0000000000
--- a/base/android/application_status_listener.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// 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/android/application_status_listener.h"
-
-#include <jni.h>
-
-#include "base/lazy_instance.h"
-#include "base/observer_list_threadsafe.h"
-#include "jni/ApplicationStatus_jni.h"
-
-namespace base {
-namespace android {
-
-namespace {
-
-struct LeakyLazyObserverListTraits :
- base::internal::LeakyLazyInstanceTraits<
- ObserverListThreadSafe<ApplicationStatusListener> > {
- static ObserverListThreadSafe<ApplicationStatusListener>*
- New(void* instance) {
- ObserverListThreadSafe<ApplicationStatusListener>* ret =
- base::internal::LeakyLazyInstanceTraits<ObserverListThreadSafe<
- ApplicationStatusListener>>::New(instance);
- // Leaky.
- ret->AddRef();
- return ret;
- }
-};
-
-LazyInstance<ObserverListThreadSafe<ApplicationStatusListener>,
- LeakyLazyObserverListTraits> g_observers =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-ApplicationStatusListener::ApplicationStatusListener(
- const ApplicationStatusListener::ApplicationStateChangeCallback& callback)
- : callback_(callback) {
- DCHECK(!callback_.is_null());
- g_observers.Get().AddObserver(this);
-
- Java_ApplicationStatus_registerThreadSafeNativeApplicationStateListener(
- AttachCurrentThread());
-}
-
-ApplicationStatusListener::~ApplicationStatusListener() {
- g_observers.Get().RemoveObserver(this);
-}
-
-void ApplicationStatusListener::Notify(ApplicationState state) {
- callback_.Run(state);
-}
-
-// static
-void ApplicationStatusListener::NotifyApplicationStateChange(
- ApplicationState state) {
- g_observers.Get().Notify(FROM_HERE, &ApplicationStatusListener::Notify,
- state);
-}
-
-// static
-ApplicationState ApplicationStatusListener::GetState() {
- return static_cast<ApplicationState>(
- Java_ApplicationStatus_getStateForApplication(AttachCurrentThread()));
-}
-
-static void JNI_ApplicationStatus_OnApplicationStateChange(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- jint new_state) {
- ApplicationState application_state = static_cast<ApplicationState>(new_state);
- ApplicationStatusListener::NotifyApplicationStateChange(application_state);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/application_status_listener.h b/base/android/application_status_listener.h
deleted file mode 100644
index fcc26a2946..0000000000
--- a/base/android/application_status_listener.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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.
-
-#ifndef BASE_ANDROID_APPLICATION_STATUS_LISTENER_H_
-#define BASE_ANDROID_APPLICATION_STATUS_LISTENER_H_
-
-#include <jni.h>
-
-#include "base/android/jni_android.h"
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/singleton.h"
-#include "base/observer_list_threadsafe.h"
-
-namespace base {
-namespace android {
-
-// Define application state values like APPLICATION_STATE_VISIBLE in a
-// way that ensures they're always the same than their Java counterpart.
-//
-// Note that these states represent the most visible Activity state.
-// If there are activities with states paused and stopped, only
-// HAS_PAUSED_ACTIVITIES should be returned.
-//
-// A Java counterpart will be generated for this enum.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base
-enum ApplicationState {
- APPLICATION_STATE_UNKNOWN = 0,
- APPLICATION_STATE_HAS_RUNNING_ACTIVITIES = 1,
- APPLICATION_STATE_HAS_PAUSED_ACTIVITIES = 2,
- APPLICATION_STATE_HAS_STOPPED_ACTIVITIES = 3,
- APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES = 4
-};
-
-// A native helper class to listen to state changes of the Android
-// Application. This mirrors org.chromium.base.ApplicationStatus.
-// any thread.
-//
-// To start listening, create a new instance, passing a callback to a
-// function that takes an ApplicationState parameter. To stop listening,
-// simply delete the listener object. The implementation guarantees
-// that the callback will always be called on the thread that created
-// the listener.
-//
-// Example:
-//
-// void OnApplicationStateChange(ApplicationState state) {
-// ...
-// }
-//
-// // Start listening.
-// ApplicationStatusListener* my_listener =
-// new ApplicationStatusListener(
-// base::Bind(&OnApplicationStateChange));
-//
-// ...
-//
-// // Stop listening.
-// delete my_listener
-//
-class BASE_EXPORT ApplicationStatusListener {
- public:
- typedef base::Callback<void(ApplicationState)> ApplicationStateChangeCallback;
-
- explicit ApplicationStatusListener(
- const ApplicationStateChangeCallback& callback);
- ~ApplicationStatusListener();
-
- // Internal use only: must be public to be called from JNI and unit tests.
- static void NotifyApplicationStateChange(ApplicationState state);
-
- // Expose jni call for ApplicationStatus.getStateForApplication.
- static ApplicationState GetState();
-
- private:
- void Notify(ApplicationState state);
-
- ApplicationStateChangeCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(ApplicationStatusListener);
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_APPLICATION_STATUS_LISTENER_H_
diff --git a/base/android/application_status_listener_unittest.cc b/base/android/application_status_listener_unittest.cc
deleted file mode 100644
index 803dedb128..0000000000
--- a/base/android/application_status_listener_unittest.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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/android/application_status_listener.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/callback_forward.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace android {
-
-namespace {
-
-using base::android::ScopedJavaLocalRef;
-
-// An invalid ApplicationState value.
-const ApplicationState kInvalidApplicationState =
- static_cast<ApplicationState>(100);
-
-// Used to generate a callback that stores the new state at a given location.
-void StoreStateTo(ApplicationState* target, ApplicationState state) {
- *target = state;
-}
-
-void RunTasksUntilIdle() {
- RunLoop run_loop;
- run_loop.RunUntilIdle();
-}
-
-// Shared state for the multi-threaded test.
-// This uses a thread to register for events and listen to them, while state
-// changes are forced on the main thread.
-class MultiThreadedTest {
- public:
- MultiThreadedTest()
- : state_(kInvalidApplicationState),
- event_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED),
- thread_("ApplicationStatusTest thread"),
- main_() {}
-
- void Run() {
- // Start the thread and tell it to register for events.
- thread_.Start();
- thread_.task_runner()->PostTask(
- FROM_HERE, base::Bind(&MultiThreadedTest::RegisterThreadForEvents,
- base::Unretained(this)));
-
- // Wait for its completion.
- event_.Wait();
-
- // Change state, then wait for the thread to modify state.
- ApplicationStatusListener::NotifyApplicationStateChange(
- APPLICATION_STATE_HAS_RUNNING_ACTIVITIES);
- event_.Wait();
- EXPECT_EQ(APPLICATION_STATE_HAS_RUNNING_ACTIVITIES, state_);
-
- // Again
- ApplicationStatusListener::NotifyApplicationStateChange(
- APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES);
- event_.Wait();
- EXPECT_EQ(APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES, state_);
- }
-
- private:
- void ExpectOnThread() {
- EXPECT_EQ(thread_.message_loop(), base::MessageLoop::current());
- }
-
- void RegisterThreadForEvents() {
- ExpectOnThread();
- listener_.reset(new ApplicationStatusListener(base::Bind(
- &MultiThreadedTest::StoreStateAndSignal, base::Unretained(this))));
- EXPECT_TRUE(listener_.get());
- event_.Signal();
- }
-
- void StoreStateAndSignal(ApplicationState state) {
- ExpectOnThread();
- state_ = state;
- event_.Signal();
- }
-
- ApplicationState state_;
- base::WaitableEvent event_;
- base::Thread thread_;
- base::MessageLoop main_;
- std::unique_ptr<ApplicationStatusListener> listener_;
-};
-
-} // namespace
-
-TEST(ApplicationStatusListenerTest, SingleThread) {
- MessageLoop message_loop;
-
- ApplicationState result = kInvalidApplicationState;
-
- // Create a new listener that stores the new state into |result| on every
- // state change.
- ApplicationStatusListener listener(
- base::Bind(&StoreStateTo, base::Unretained(&result)));
-
- EXPECT_EQ(kInvalidApplicationState, result);
-
- ApplicationStatusListener::NotifyApplicationStateChange(
- APPLICATION_STATE_HAS_RUNNING_ACTIVITIES);
- RunTasksUntilIdle();
- EXPECT_EQ(APPLICATION_STATE_HAS_RUNNING_ACTIVITIES, result);
-
- ApplicationStatusListener::NotifyApplicationStateChange(
- APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES);
- RunTasksUntilIdle();
- EXPECT_EQ(APPLICATION_STATE_HAS_DESTROYED_ACTIVITIES, result);
-}
-
-TEST(ApplicationStatusListenerTest, TwoThreads) {
- MultiThreadedTest test;
- test.Run();
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/base_jni_onload.cc b/base/android/base_jni_onload.cc
deleted file mode 100644
index 170dd8402f..0000000000
--- a/base/android/base_jni_onload.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 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/android/base_jni_onload.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_utils.h"
-#include "base/android/library_loader/library_loader_hooks.h"
-#include "base/bind.h"
-
-namespace base {
-namespace android {
-
-bool OnJNIOnLoadInit() {
- InitAtExitManager();
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::InitReplacementClassLoader(env,
- base::android::GetClassLoader(env));
- return true;
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/callback_android.cc b/base/android/callback_android.cc
deleted file mode 100644
index 7143664155..0000000000
--- a/base/android/callback_android.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 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/android/callback_android.h"
-
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "jni/Callback_jni.h"
-
-namespace base {
-namespace android {
-
-void RunObjectCallbackAndroid(const JavaRef<jobject>& callback,
- const JavaRef<jobject>& arg) {
- Java_Helper_onObjectResultFromNative(AttachCurrentThread(), callback, arg);
-}
-
-void RunBooleanCallbackAndroid(const JavaRef<jobject>& callback, bool arg) {
- Java_Helper_onBooleanResultFromNative(AttachCurrentThread(), callback,
- static_cast<jboolean>(arg));
-}
-
-void RunIntCallbackAndroid(const JavaRef<jobject>& callback, int arg) {
- Java_Helper_onIntResultFromNative(AttachCurrentThread(), callback, arg);
-}
-
-void RunStringCallbackAndroid(const JavaRef<jobject>& callback,
- const std::string& arg) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> java_string = ConvertUTF8ToJavaString(env, arg);
- Java_Helper_onObjectResultFromNative(env, callback, java_string);
-}
-
-void RunByteArrayCallbackAndroid(const JavaRef<jobject>& callback,
- const std::vector<uint8_t>& arg) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jbyteArray> j_bytes = ToJavaByteArray(env, arg);
- Java_Helper_onObjectResultFromNative(env, callback, j_bytes);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/callback_android.h b/base/android/callback_android.h
deleted file mode 100644
index 8a14c1fa39..0000000000
--- a/base/android/callback_android.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_ANDROID_CALLBACK_ANDROID_H_
-#define BASE_ANDROID_CALLBACK_ANDROID_H_
-
-#include <jni.h>
-#include <string>
-#include <vector>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/base_export.h"
-
-// Provides helper utility methods that run the given callback with the
-// specified argument.
-namespace base {
-namespace android {
-
-void BASE_EXPORT RunObjectCallbackAndroid(const JavaRef<jobject>& callback,
- const JavaRef<jobject>& arg);
-
-void BASE_EXPORT RunBooleanCallbackAndroid(const JavaRef<jobject>& callback,
- bool arg);
-
-void BASE_EXPORT RunIntCallbackAndroid(const JavaRef<jobject>& callback,
- int arg);
-
-void BASE_EXPORT RunStringCallbackAndroid(const JavaRef<jobject>& callback,
- const std::string& arg);
-
-void BASE_EXPORT RunByteArrayCallbackAndroid(const JavaRef<jobject>& callback,
- const std::vector<uint8_t>& arg);
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_CALLBACK_ANDROID_H_
diff --git a/base/android/child_process_binding_types.h b/base/android/child_process_binding_types.h
deleted file mode 100644
index a3900d5e81..0000000000
--- a/base/android/child_process_binding_types.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 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.
-
-#ifndef BASE_ANDROID_CHILD_PROCESS_BINDING_TYPES_H_
-#define BASE_ANDROID_CHILD_PROCESS_BINDING_TYPES_H_
-
-namespace base {
-namespace android {
-
-// Defines the state of bindgings with child process. See ChildProcessConnection
-// to see what the bindings are. Note these values are used as array indices.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base
-enum class ChildBindingState {
- UNBOUND,
- WAIVED,
- MODERATE,
- STRONG,
- MAX_VALUE = STRONG
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_CHILD_PROCESS_BINDING_TYPES_H_
diff --git a/base/android/child_process_service.cc b/base/android/child_process_service.cc
deleted file mode 100644
index 013a70b564..0000000000
--- a/base/android/child_process_service.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2017 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/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/android/library_loader/library_loader_hooks.h"
-#include "base/file_descriptor_store.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "base/posix/global_descriptors.h"
-#include "jni/ChildProcessService_jni.h"
-
-using base::android::JavaIntArrayToIntVector;
-using base::android::JavaParamRef;
-
-namespace base {
-namespace android {
-
-void JNI_ChildProcessService_RegisterFileDescriptors(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jobjectArray>& j_keys,
- const JavaParamRef<jintArray>& j_ids,
- const JavaParamRef<jintArray>& j_fds,
- const JavaParamRef<jlongArray>& j_offsets,
- const JavaParamRef<jlongArray>& j_sizes) {
- std::vector<base::Optional<std::string>> keys;
- jsize keys_size = env->GetArrayLength(j_keys);
- keys.reserve(keys_size);
- for (jsize i = 0; i < keys_size; i++) {
- base::android::ScopedJavaLocalRef<jstring> str(
- env, static_cast<jstring>(env->GetObjectArrayElement(j_keys, i)));
- base::Optional<std::string> key;
- if (!str.is_null()) {
- key = base::android::ConvertJavaStringToUTF8(env, str);
- }
- keys.push_back(std::move(key));
- }
-
- std::vector<int> ids;
- base::android::JavaIntArrayToIntVector(env, j_ids, &ids);
- std::vector<int> fds;
- base::android::JavaIntArrayToIntVector(env, j_fds, &fds);
- std::vector<int64_t> offsets;
- base::android::JavaLongArrayToInt64Vector(env, j_offsets, &offsets);
- std::vector<int64_t> sizes;
- base::android::JavaLongArrayToInt64Vector(env, j_sizes, &sizes);
-
- DCHECK_EQ(keys.size(), ids.size());
- DCHECK_EQ(ids.size(), fds.size());
- DCHECK_EQ(fds.size(), offsets.size());
- DCHECK_EQ(offsets.size(), sizes.size());
-
- for (size_t i = 0; i < ids.size(); i++) {
- base::MemoryMappedFile::Region region = {offsets.at(i), sizes.at(i)};
- const base::Optional<std::string>& key = keys.at(i);
- int id = ids.at(i);
- int fd = fds.at(i);
- if (key) {
- base::FileDescriptorStore::GetInstance().Set(*key, base::ScopedFD(fd),
- region);
- } else {
- base::GlobalDescriptors::GetInstance()->Set(id, fd, region);
- }
- }
-}
-
-void JNI_ChildProcessService_ExitChildProcess(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- VLOG(0) << "ChildProcessService: Exiting child process.";
- base::android::LibraryLoaderExitHook();
- _exit(0);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/command_line_android.cc b/base/android/command_line_android.cc
deleted file mode 100644
index c9b545f526..0000000000
--- a/base/android/command_line_android.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2013 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/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "jni/CommandLine_jni.h"
-
-using base::android::ConvertUTF8ToJavaString;
-using base::android::ConvertJavaStringToUTF8;
-using base::android::JavaParamRef;
-using base::android::ScopedJavaLocalRef;
-using base::CommandLine;
-
-namespace {
-
-void JNI_CommandLine_AppendJavaStringArrayToCommandLine(
- JNIEnv* env,
- const JavaParamRef<jobjectArray>& array,
- bool includes_program) {
- std::vector<std::string> vec;
- if (array)
- base::android::AppendJavaStringArrayToStringVector(env, array, &vec);
- if (!includes_program)
- vec.insert(vec.begin(), std::string());
- CommandLine extra_command_line(vec);
- CommandLine::ForCurrentProcess()->AppendArguments(extra_command_line,
- includes_program);
-}
-
-} // namespace
-
-static jboolean JNI_CommandLine_HasSwitch(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jswitch) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- return CommandLine::ForCurrentProcess()->HasSwitch(switch_string);
-}
-
-static ScopedJavaLocalRef<jstring> JNI_CommandLine_GetSwitchValue(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jswitch) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- std::string value(CommandLine::ForCurrentProcess()->GetSwitchValueNative(
- switch_string));
- if (value.empty())
- return ScopedJavaLocalRef<jstring>();
- return ConvertUTF8ToJavaString(env, value);
-}
-
-static void JNI_CommandLine_AppendSwitch(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jswitch) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- CommandLine::ForCurrentProcess()->AppendSwitch(switch_string);
-}
-
-static void JNI_CommandLine_AppendSwitchWithValue(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jswitch,
- const JavaParamRef<jstring>& jvalue) {
- std::string switch_string(ConvertJavaStringToUTF8(env, jswitch));
- std::string value_string (ConvertJavaStringToUTF8(env, jvalue));
- CommandLine::ForCurrentProcess()->AppendSwitchASCII(switch_string,
- value_string);
-}
-
-static void JNI_CommandLine_AppendSwitchesAndArguments(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jobjectArray>& array) {
- JNI_CommandLine_AppendJavaStringArrayToCommandLine(env, array, false);
-}
-
-static void JNI_CommandLine_Init(
- JNIEnv* env,
- const JavaParamRef<jclass>& jclazz,
- const JavaParamRef<jobjectArray>& init_command_line) {
- // TODO(port): Make an overload of Init() that takes StringVector rather than
- // have to round-trip via AppendArguments.
- CommandLine::Init(0, nullptr);
- JNI_CommandLine_AppendJavaStringArrayToCommandLine(env, init_command_line,
- true);
-}
diff --git a/base/android/content_uri_utils.cc b/base/android/content_uri_utils.cc
deleted file mode 100644
index a7955dca6b..0000000000
--- a/base/android/content_uri_utils.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 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/android/content_uri_utils.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "jni/ContentUriUtils_jni.h"
-
-using base::android::ConvertUTF8ToJavaString;
-using base::android::ScopedJavaLocalRef;
-
-namespace base {
-
-bool ContentUriExists(const FilePath& content_uri) {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> j_uri =
- ConvertUTF8ToJavaString(env, content_uri.value());
- return Java_ContentUriUtils_contentUriExists(env, j_uri);
-}
-
-File OpenContentUriForRead(const FilePath& content_uri) {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> j_uri =
- ConvertUTF8ToJavaString(env, content_uri.value());
- jint fd = Java_ContentUriUtils_openContentUriForRead(env, j_uri);
- if (fd < 0)
- return File();
- return File(fd);
-}
-
-std::string GetContentUriMimeType(const FilePath& content_uri) {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> j_uri =
- ConvertUTF8ToJavaString(env, content_uri.value());
- ScopedJavaLocalRef<jstring> j_mime =
- Java_ContentUriUtils_getMimeType(env, j_uri);
- if (j_mime.is_null())
- return std::string();
-
- return base::android::ConvertJavaStringToUTF8(env, j_mime.obj());
-}
-
-} // namespace base
diff --git a/base/android/content_uri_utils.h b/base/android/content_uri_utils.h
deleted file mode 100644
index 6d817c051e..0000000000
--- a/base/android/content_uri_utils.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_ANDROID_CONTENT_URI_UTILS_H_
-#define BASE_ANDROID_CONTENT_URI_UTILS_H_
-
-#include <jni.h>
-
-#include "base/base_export.h"
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-
-namespace base {
-
-// Opens a content URI for read and returns the file descriptor to the caller.
-// Returns -1 if the URI is invalid.
-BASE_EXPORT File OpenContentUriForRead(const FilePath& content_uri);
-
-// Check whether a content URI exists.
-BASE_EXPORT bool ContentUriExists(const FilePath& content_uri);
-
-// Gets MIME type from a content URI. Returns an empty string if the URI is
-// invalid.
-BASE_EXPORT std::string GetContentUriMimeType(const FilePath& content_uri);
-
-} // namespace base
-
-#endif // BASE_ANDROID_CONTENT_URI_UTILS_H_
diff --git a/base/android/content_uri_utils_unittest.cc b/base/android/content_uri_utils_unittest.cc
deleted file mode 100644
index 0e5cf0cbbb..0000000000
--- a/base/android/content_uri_utils_unittest.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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/android/content_uri_utils.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/test/test_file_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace android {
-
-// Disable on Android ASAN bot due to consistent failures: crbug.com/807080.
-#if !defined(ADDRESS_SANITIZER)
-TEST(ContentUriUtilsTest, ContentUriMimeTest) {
- // Get the test image path.
- FilePath data_dir;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
- data_dir = data_dir.AppendASCII("file_util");
- ASSERT_TRUE(PathExists(data_dir));
- FilePath image_file = data_dir.Append(FILE_PATH_LITERAL("red.png"));
-
- // Insert the image into MediaStore. MediaStore will do some conversions, and
- // return the content URI.
- FilePath path = base::InsertImageIntoMediaStore(image_file);
- EXPECT_TRUE(path.IsContentUri());
- EXPECT_TRUE(PathExists(path));
-
- std::string mime = GetContentUriMimeType(path);
- EXPECT_EQ(mime, std::string("image/png"));
-
- FilePath invalid_path("content://foo.bar");
- mime = GetContentUriMimeType(invalid_path);
- EXPECT_TRUE(mime.empty());
-}
-#endif
-
-} // namespace android
-} // namespace base
diff --git a/base/android/cpu_features.cc b/base/android/cpu_features.cc
deleted file mode 100644
index 7c1dbe314c..0000000000
--- a/base/android/cpu_features.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 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.
-
-#include <cpu-features.h>
-
-#include "base/android/jni_android.h"
-#include "jni/CpuFeatures_jni.h"
-
-namespace base {
-namespace android {
-
-jint JNI_CpuFeatures_GetCoreCount(JNIEnv*, const JavaParamRef<jclass>&) {
- return android_getCpuCount();
-}
-
-jlong JNI_CpuFeatures_GetCpuFeatures(JNIEnv*, const JavaParamRef<jclass>&) {
- return android_getCpuFeatures();
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/early_trace_event_binding.cc b/base/android/early_trace_event_binding.cc
deleted file mode 100644
index bf6b910675..0000000000
--- a/base/android/early_trace_event_binding.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2016 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 <stdint.h>
-
-#include "base/android/jni_string.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "jni/EarlyTraceEvent_jni.h"
-
-namespace base {
-namespace android {
-
-const char kEarlyJavaCategory[] = "EarlyJava";
-
-static void JNI_EarlyTraceEvent_RecordEarlyEvent(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- jlong begin_time_ns,
- jlong end_time_ns,
- jint thread_id,
- jlong thread_duration_ms) {
- std::string name = ConvertJavaStringToUTF8(env, jname);
- int64_t begin_us = begin_time_ns / 1000;
- int64_t end_us = end_time_ns / 1000;
- int64_t thread_duration_us = thread_duration_ms * 1000;
-
- INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMPS(
- kEarlyJavaCategory, name.c_str(), trace_event_internal::kNoId, thread_id,
- TimeTicks::FromInternalValue(begin_us),
- TimeTicks::FromInternalValue(end_us),
- ThreadTicks::Now() + TimeDelta::FromMicroseconds(thread_duration_us),
- TRACE_EVENT_FLAG_COPY);
-}
-
-static void JNI_EarlyTraceEvent_RecordEarlyStartAsyncEvent(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- jlong id,
- jlong timestamp_ns) {
- std::string name = ConvertJavaStringToUTF8(env, jname);
- int64_t timestamp_us = timestamp_ns / 1000;
-
- TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0(
- kEarlyJavaCategory, name.c_str(), id,
- base::TimeTicks() + base::TimeDelta::FromMicroseconds(timestamp_us));
-}
-
-static void JNI_EarlyTraceEvent_RecordEarlyFinishAsyncEvent(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- jlong id,
- jlong timestamp_ns) {
- std::string name = ConvertJavaStringToUTF8(env, jname);
- int64_t timestamp_us = timestamp_ns / 1000;
-
- TRACE_EVENT_COPY_ASYNC_END_WITH_TIMESTAMP0(
- kEarlyJavaCategory, name.c_str(), id,
- base::TimeTicks() + base::TimeDelta::FromMicroseconds(timestamp_us));
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/event_log.cc b/base/android/event_log.cc
deleted file mode 100644
index 3eb5926b1f..0000000000
--- a/base/android/event_log.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2013 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/android/event_log.h"
-#include "jni/EventLog_jni.h"
-
-namespace base {
-namespace android {
-
-void EventLogWriteInt(int tag, int value) {
- Java_EventLog_writeEvent(AttachCurrentThread(), tag, value);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/event_log.h b/base/android/event_log.h
deleted file mode 100644
index ebd5919a5b..0000000000
--- a/base/android/event_log.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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.
-
-#ifndef BASE_ANDROID_EVENT_LOG_H_
-#define BASE_ANDROID_EVENT_LOG_H_
-
-#include <jni.h>
-
-#include "base/base_export.h"
-
-namespace base {
-namespace android {
-
-void BASE_EXPORT EventLogWriteInt(int tag, int value);
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_EVENT_LOG_H_
diff --git a/base/android/field_trial_list.cc b/base/android/field_trial_list.cc
deleted file mode 100644
index 1dec5b537a..0000000000
--- a/base/android/field_trial_list.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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 <jni.h>
-
-#include <map>
-#include <string>
-
-#include "base/android/jni_string.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_params.h"
-#include "jni/FieldTrialList_jni.h"
-
-using base::android::ConvertJavaStringToUTF8;
-using base::android::ConvertUTF8ToJavaString;
-using base::android::JavaParamRef;
-using base::android::ScopedJavaLocalRef;
-
-static ScopedJavaLocalRef<jstring> JNI_FieldTrialList_FindFullName(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jtrial_name) {
- std::string trial_name(ConvertJavaStringToUTF8(env, jtrial_name));
- return ConvertUTF8ToJavaString(
- env, base::FieldTrialList::FindFullName(trial_name));
-}
-
-static jboolean JNI_FieldTrialList_TrialExists(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jtrial_name) {
- std::string trial_name(ConvertJavaStringToUTF8(env, jtrial_name));
- return base::FieldTrialList::TrialExists(trial_name);
-}
-
-static ScopedJavaLocalRef<jstring> JNI_FieldTrialList_GetVariationParameter(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jtrial_name,
- const JavaParamRef<jstring>& jparameter_key) {
- std::map<std::string, std::string> parameters;
- base::GetFieldTrialParams(ConvertJavaStringToUTF8(env, jtrial_name),
- &parameters);
- return ConvertUTF8ToJavaString(
- env, parameters[ConvertJavaStringToUTF8(env, jparameter_key)]);
-}
diff --git a/base/android/important_file_writer_android.cc b/base/android/important_file_writer_android.cc
deleted file mode 100644
index fcaa3b1ea0..0000000000
--- a/base/android/important_file_writer_android.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 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 <string>
-
-#include "base/android/jni_string.h"
-#include "base/files/important_file_writer.h"
-#include "base/threading/thread_restrictions.h"
-#include "jni/ImportantFileWriterAndroid_jni.h"
-
-namespace base {
-namespace android {
-
-static jboolean JNI_ImportantFileWriterAndroid_WriteFileAtomically(
- JNIEnv* env,
- const JavaParamRef<jclass>& /* clazz */,
- const JavaParamRef<jstring>& file_name,
- const JavaParamRef<jbyteArray>& data) {
- // This is called on the UI thread during shutdown to save tab data, so
- // needs to enable IO.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- std::string native_file_name;
- base::android::ConvertJavaStringToUTF8(env, file_name, &native_file_name);
- base::FilePath path(native_file_name);
- int data_length = env->GetArrayLength(data);
- jbyte* native_data = env->GetByteArrayElements(data, NULL);
- std::string native_data_string(reinterpret_cast<char *>(native_data),
- data_length);
- bool result = base::ImportantFileWriter::WriteFileAtomically(
- path, native_data_string);
- env->ReleaseByteArrayElements(data, native_data, JNI_ABORT);
- return result;
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/java/src/org/chromium/base/ActivityState.java b/base/android/java/src/org/chromium/base/ActivityState.java
deleted file mode 100644
index b14814c1c0..0000000000
--- a/base/android/java/src/org/chromium/base/ActivityState.java
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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;
-
-import android.support.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * A set of states that represent the last state change of an Activity.
- */
-@Retention(RetentionPolicy.SOURCE)
-@IntDef({ActivityState.CREATED, ActivityState.STARTED, ActivityState.RESUMED, ActivityState.PAUSED,
- ActivityState.STOPPED, ActivityState.DESTROYED})
-public @interface ActivityState {
- /**
- * Represents Activity#onCreate().
- */
- int CREATED = 1;
-
- /**
- * Represents Activity#onStart().
- */
- int STARTED = 2;
-
- /**
- * Represents Activity#onResume().
- */
- int RESUMED = 3;
-
- /**
- * Represents Activity#onPause().
- */
- int PAUSED = 4;
-
- /**
- * Represents Activity#onStop().
- */
- int STOPPED = 5;
-
- /**
- * Represents Activity#onDestroy(). This is also used when the state of an Activity is unknown.
- */
- int DESTROYED = 6;
-}
diff --git a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
deleted file mode 100644
index ad5cdd815b..0000000000
--- a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2015 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;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TimeAnimator;
-import android.animation.TimeAnimator.TimeListener;
-import android.util.Log;
-
-/**
- * Record Android animation frame rate and save it to UMA histogram. This is mainly for monitoring
- * any jankiness of short Chrome Android animations. It is limited to few seconds of recording.
- */
-public class AnimationFrameTimeHistogram {
- private static final String TAG = "AnimationFrameTimeHistogram";
- private static final int MAX_FRAME_TIME_NUM = 600; // 10 sec on 60 fps.
-
- private final Recorder mRecorder = new Recorder();
- private final String mHistogramName;
-
- /**
- * @param histogramName The histogram name that the recorded frame times will be saved.
- * This must be also defined in histograms.xml
- * @return An AnimatorListener instance that records frame time histogram on start and end
- * automatically.
- */
- public static AnimatorListener getAnimatorRecorder(final String histogramName) {
- return new AnimatorListenerAdapter() {
- private final AnimationFrameTimeHistogram mAnimationFrameTimeHistogram =
- new AnimationFrameTimeHistogram(histogramName);
-
- @Override
- public void onAnimationStart(Animator animation) {
- mAnimationFrameTimeHistogram.startRecording();
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mAnimationFrameTimeHistogram.endRecording();
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mAnimationFrameTimeHistogram.endRecording();
- }
- };
- }
-
- /**
- * @param histogramName The histogram name that the recorded frame times will be saved.
- * This must be also defined in histograms.xml
- */
- public AnimationFrameTimeHistogram(String histogramName) {
- mHistogramName = histogramName;
- }
-
- /**
- * Start recording frame times. The recording can fail if it exceeds a few seconds.
- */
- public void startRecording() {
- mRecorder.startRecording();
- }
-
- /**
- * End recording and save it to histogram. It won't save histogram if the recording wasn't
- * successful.
- */
- public void endRecording() {
- if (mRecorder.endRecording()) {
- nativeSaveHistogram(mHistogramName,
- mRecorder.getFrameTimesMs(), mRecorder.getFrameTimesCount());
- }
- mRecorder.cleanUp();
- }
-
- /**
- * Record Android animation frame rate and return the result.
- */
- private static class Recorder implements TimeListener {
- // TODO(kkimlabs): If we can use in the future, migrate to Choreographer for minimal
- // workload.
- private final TimeAnimator mAnimator = new TimeAnimator();
- private long[] mFrameTimesMs;
- private int mFrameTimesCount;
-
- private Recorder() {
- mAnimator.setTimeListener(this);
- }
-
- private void startRecording() {
- assert !mAnimator.isRunning();
- mFrameTimesCount = 0;
- mFrameTimesMs = new long[MAX_FRAME_TIME_NUM];
- mAnimator.start();
- }
-
- /**
- * @return Whether the recording was successful. If successful, the result is available via
- * getFrameTimesNs and getFrameTimesCount.
- */
- private boolean endRecording() {
- boolean succeeded = mAnimator.isStarted();
- mAnimator.end();
- return succeeded;
- }
-
- private long[] getFrameTimesMs() {
- return mFrameTimesMs;
- }
-
- private int getFrameTimesCount() {
- return mFrameTimesCount;
- }
-
- /**
- * Deallocates the temporary buffer to record frame times. Must be called after ending
- * the recording and getting the result.
- */
- private void cleanUp() {
- mFrameTimesMs = null;
- }
-
- @Override
- public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
- if (mFrameTimesCount == mFrameTimesMs.length) {
- mAnimator.end();
- cleanUp();
- Log.w(TAG, "Animation frame time recording reached the maximum number. It's either"
- + "the animation took too long or recording end is not called.");
- return;
- }
-
- // deltaTime is 0 for the first frame.
- if (deltaTime > 0) {
- mFrameTimesMs[mFrameTimesCount++] = deltaTime;
- }
- }
- }
-
- private native void nativeSaveHistogram(String histogramName, long[] frameTimesMs, int count);
-}
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
deleted file mode 100644
index d1c4693c4a..0000000000
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ /dev/null
@@ -1,705 +0,0 @@
-// Copyright 2013 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;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.app.PendingIntent;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.VectorDrawable;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.PowerManager;
-import android.os.Process;
-import android.os.StatFs;
-import android.os.StrictMode;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.text.Html;
-import android.text.Spanned;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.inputmethod.InputMethodSubtype;
-import android.view.textclassifier.TextClassifier;
-import android.widget.TextView;
-
-import java.io.File;
-import java.io.UnsupportedEncodingException;
-
-/**
- * Utility class to use new APIs that were added after ICS (API level 14).
- */
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
-public class ApiCompatibilityUtils {
- private ApiCompatibilityUtils() {
- }
-
- /**
- * Compares two long values numerically. The value returned is identical to what would be
- * returned by {@link Long#compare(long, long)} which is available since API level 19.
- */
- public static int compareLong(long lhs, long rhs) {
- return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
- }
-
- /**
- * Compares two boolean values. The value returned is identical to what would be returned by
- * {@link Boolean#compare(boolean, boolean)} which is available since API level 19.
- */
- public static int compareBoolean(boolean lhs, boolean rhs) {
- return lhs == rhs ? 0 : lhs ? 1 : -1;
- }
-
- /**
- * Checks that the object reference is not null and throws NullPointerException if it is.
- * See {@link Objects#requireNonNull} which is available since API level 19.
- * @param obj The object to check
- */
- @NonNull
- public static <T> T requireNonNull(T obj) {
- if (obj == null) throw new NullPointerException();
- return obj;
- }
-
- /**
- * Checks that the object reference is not null and throws NullPointerException if it is.
- * See {@link Objects#requireNonNull} which is available since API level 19.
- * @param obj The object to check
- * @param message The message to put into NullPointerException
- */
- @NonNull
- public static <T> T requireNonNull(T obj, String message) {
- if (obj == null) throw new NullPointerException(message);
- return obj;
- }
-
- /**
- * {@link String#getBytes()} but specifying UTF-8 as the encoding and capturing the resulting
- * UnsupportedEncodingException.
- */
- public static byte[] getBytesUtf8(String str) {
- try {
- return str.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("UTF-8 encoding not available.", e);
- }
- }
-
- /**
- * Returns true if view's layout direction is right-to-left.
- *
- * @param view the View whose layout is being considered
- */
- public static boolean isLayoutRtl(View view) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- } else {
- // All layouts are LTR before JB MR1.
- return false;
- }
- }
-
- /**
- * @see Configuration#getLayoutDirection()
- */
- public static int getLayoutDirection(Configuration configuration) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return configuration.getLayoutDirection();
- } else {
- // All layouts are LTR before JB MR1.
- return View.LAYOUT_DIRECTION_LTR;
- }
- }
-
- /**
- * @return True if the running version of the Android supports printing.
- */
- public static boolean isPrintingSupported() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
- }
-
- /**
- * @return True if the running version of the Android supports elevation. Elevation of a view
- * determines the visual appearance of its shadow.
- */
- public static boolean isElevationSupported() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
- }
-
- /**
- * @see android.view.View#setLayoutDirection(int)
- */
- public static void setLayoutDirection(View view, int layoutDirection) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- view.setLayoutDirection(layoutDirection);
- } else {
- // Do nothing. RTL layouts aren't supported before JB MR1.
- }
- }
-
- /**
- * @see android.view.View#setTextAlignment(int)
- */
- public static void setTextAlignment(View view, int textAlignment) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- view.setTextAlignment(textAlignment);
- } else {
- // Do nothing. RTL text isn't supported before JB MR1.
- }
- }
-
- /**
- * @see android.view.View#setTextDirection(int)
- */
- public static void setTextDirection(View view, int textDirection) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- view.setTextDirection(textDirection);
- } else {
- // Do nothing. RTL text isn't supported before JB MR1.
- }
- }
-
- /**
- * See {@link android.view.View#setLabelFor(int)}.
- */
- public static void setLabelFor(View labelView, int id) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- labelView.setLabelFor(id);
- } else {
- // Do nothing. #setLabelFor() isn't supported before JB MR1.
- }
- }
-
- /**
- * @see android.widget.TextView#getCompoundDrawablesRelative()
- */
- public static Drawable[] getCompoundDrawablesRelative(TextView textView) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return textView.getCompoundDrawablesRelative();
- } else {
- return textView.getCompoundDrawables();
- }
- }
-
- /**
- * @see android.widget.TextView#setCompoundDrawablesRelative(Drawable, Drawable, Drawable,
- * Drawable)
- */
- public static void setCompoundDrawablesRelative(TextView textView, Drawable start, Drawable top,
- Drawable end, Drawable bottom) {
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
- // On JB MR1, due to a platform bug, setCompoundDrawablesRelative() is a no-op if the
- // view has ever been measured. As a workaround, use setCompoundDrawables() directly.
- // See: http://crbug.com/368196 and http://crbug.com/361709
- boolean isRtl = isLayoutRtl(textView);
- textView.setCompoundDrawables(isRtl ? end : start, top, isRtl ? start : end, bottom);
- } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
- textView.setCompoundDrawablesRelative(start, top, end, bottom);
- } else {
- textView.setCompoundDrawables(start, top, end, bottom);
- }
- }
-
- /**
- * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,
- * Drawable, Drawable, Drawable)
- */
- public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
- Drawable start, Drawable top, Drawable end, Drawable bottom) {
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
- // Work around the platform bug described in setCompoundDrawablesRelative() above.
- boolean isRtl = isLayoutRtl(textView);
- textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
- isRtl ? start : end, bottom);
- } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
- textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
- } else {
- textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
- }
- }
-
- /**
- * @see android.widget.TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int,
- * int)
- */
- public static void setCompoundDrawablesRelativeWithIntrinsicBounds(TextView textView,
- int start, int top, int end, int bottom) {
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1) {
- // Work around the platform bug described in setCompoundDrawablesRelative() above.
- boolean isRtl = isLayoutRtl(textView);
- textView.setCompoundDrawablesWithIntrinsicBounds(isRtl ? end : start, top,
- isRtl ? start : end, bottom);
- } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
- textView.setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom);
- } else {
- textView.setCompoundDrawablesWithIntrinsicBounds(start, top, end, bottom);
- }
- }
-
- /**
- * @see android.text.Html#toHtml(Spanned, int)
- * @param option is ignored on below N
- */
- @SuppressWarnings("deprecation")
- public static String toHtml(Spanned spanned, int option) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- return Html.toHtml(spanned, option);
- } else {
- return Html.toHtml(spanned);
- }
- }
-
- // These methods have a new name, and the old name is deprecated.
-
- /**
- * @see android.app.PendingIntent#getCreatorPackage()
- */
- @SuppressWarnings("deprecation")
- public static String getCreatorPackage(PendingIntent intent) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return intent.getCreatorPackage();
- } else {
- return intent.getTargetPackage();
- }
- }
-
- /**
- * @see android.provider.Settings.Global#DEVICE_PROVISIONED
- */
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- public static boolean isDeviceProvisioned(Context context) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) return true;
- if (context == null) return true;
- if (context.getContentResolver() == null) return true;
- return Settings.Global.getInt(
- context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- }
-
- /**
- * @see android.app.Activity#finishAndRemoveTask()
- */
- public static void finishAndRemoveTask(Activity activity) {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
- activity.finishAndRemoveTask();
- } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
- // crbug.com/395772 : Fallback for Activity.finishAndRemoveTask() failing.
- new FinishAndRemoveTaskWithRetry(activity).run();
- } else {
- activity.finish();
- }
- }
-
- /**
- * Set elevation if supported.
- */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public static boolean setElevation(View view, float elevationValue) {
- if (!isElevationSupported()) return false;
-
- view.setElevation(elevationValue);
- return true;
- }
-
- /**
- * Gets an intent to start the Android system notification settings activity for an app.
- *
- * @param context Context of the app whose settings intent should be returned.
- */
- public static Intent getNotificationSettingsIntent(Context context) {
- Intent intent = new Intent();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
- intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
- } else {
- intent.setAction("android.settings.ACTION_APP_NOTIFICATION_SETTINGS");
- intent.putExtra("app_package", context.getPackageName());
- intent.putExtra("app_uid", context.getApplicationInfo().uid);
- }
- return intent;
- }
-
- private static class FinishAndRemoveTaskWithRetry implements Runnable {
- private static final long RETRY_DELAY_MS = 500;
- private static final long MAX_TRY_COUNT = 3;
- private final Activity mActivity;
- private int mTryCount;
-
- FinishAndRemoveTaskWithRetry(Activity activity) {
- mActivity = activity;
- }
-
- @Override
- public void run() {
- mActivity.finishAndRemoveTask();
- mTryCount++;
- if (!mActivity.isFinishing()) {
- if (mTryCount < MAX_TRY_COUNT) {
- ThreadUtils.postOnUiThreadDelayed(this, RETRY_DELAY_MS);
- } else {
- mActivity.finish();
- }
- }
- }
- }
-
- /**
- * @return Whether the screen of the device is interactive.
- */
- @SuppressWarnings("deprecation")
- public static boolean isInteractive(Context context) {
- PowerManager manager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
- return manager.isInteractive();
- } else {
- return manager.isScreenOn();
- }
- }
-
- @SuppressWarnings("deprecation")
- public static int getActivityNewDocumentFlag() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
- } else {
- return Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;
- }
- }
-
- /**
- * @see android.provider.Settings.Secure#SKIP_FIRST_USE_HINTS
- */
- public static boolean shouldSkipFirstUseHints(ContentResolver contentResolver) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return Settings.Secure.getInt(
- contentResolver, Settings.Secure.SKIP_FIRST_USE_HINTS, 0) != 0;
- } else {
- return false;
- }
- }
-
- /**
- * @param activity Activity that should get the task description update.
- * @param title Title of the activity.
- * @param icon Icon of the activity.
- * @param color Color of the activity. It must be a fully opaque color.
- */
- public static void setTaskDescription(Activity activity, String title, Bitmap icon, int color) {
- // TaskDescription requires an opaque color.
- assert Color.alpha(color) == 255;
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- ActivityManager.TaskDescription description =
- new ActivityManager.TaskDescription(title, icon, color);
- activity.setTaskDescription(description);
- }
- }
-
- /**
- * @see android.view.Window#setStatusBarColor(int color).
- */
- public static void setStatusBarColor(Window window, int statusBarColor) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
-
- // If both system bars are black, we can remove these from our layout,
- // removing or shrinking the SurfaceFlinger overlay required for our views.
- // This benefits battery usage on L and M. However, this no longer provides a battery
- // benefit as of N and starts to cause flicker bugs on O, so don't bother on O and up.
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && statusBarColor == Color.BLACK
- && window.getNavigationBarColor() == Color.BLACK) {
- window.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- } else {
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- }
- window.setStatusBarColor(statusBarColor);
- }
-
- /**
- * Sets the status bar icons to dark or light. Note that this is only valid for
- * Android M+.
- *
- * @param rootView The root view used to request updates to the system UI theming.
- * @param useDarkIcons Whether the status bar icons should be dark.
- */
- public static void setStatusBarIconColor(View rootView, boolean useDarkIcons) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
-
- int systemUiVisibility = rootView.getSystemUiVisibility();
- if (useDarkIcons) {
- systemUiVisibility |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- } else {
- systemUiVisibility &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- }
- rootView.setSystemUiVisibility(systemUiVisibility);
- }
-
- /**
- * @see android.content.res.Resources#getDrawable(int id).
- * TODO(ltian): use {@link AppCompatResources} to parse drawable to prevent fail on
- * {@link VectorDrawable}. (http://crbug.com/792129)
- */
- @SuppressWarnings("deprecation")
- public static Drawable getDrawable(Resources res, int id) throws NotFoundException {
- StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- try {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return res.getDrawable(id, null);
- } else {
- return res.getDrawable(id);
- }
- } finally {
- StrictMode.setThreadPolicy(oldPolicy);
- }
- }
-
- /**
- * @see android.content.res.Resources#getDrawableForDensity(int id, int density).
- */
- @SuppressWarnings("deprecation")
- public static Drawable getDrawableForDensity(Resources res, int id, int density) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return res.getDrawableForDensity(id, density, null);
- } else {
- return res.getDrawableForDensity(id, density);
- }
- }
-
- /**
- * @see android.app.Activity#finishAfterTransition().
- */
- public static void finishAfterTransition(Activity activity) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- activity.finishAfterTransition();
- } else {
- activity.finish();
- }
- }
-
- /**
- * @see android.content.pm.PackageManager#getUserBadgedIcon(Drawable, android.os.UserHandle).
- */
- public static Drawable getUserBadgedIcon(Context context, int id) {
- Drawable drawable = getDrawable(context.getResources(), id);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- PackageManager packageManager = context.getPackageManager();
- drawable = packageManager.getUserBadgedIcon(drawable, Process.myUserHandle());
- }
- return drawable;
- }
-
- /**
- * @see android.content.pm.PackageManager#getUserBadgedDrawableForDensity(Drawable drawable,
- * UserHandle user, Rect badgeLocation, int badgeDensity).
- */
- public static Drawable getUserBadgedDrawableForDensity(
- Context context, Drawable drawable, Rect badgeLocation, int density) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- PackageManager packageManager = context.getPackageManager();
- return packageManager.getUserBadgedDrawableForDensity(
- drawable, Process.myUserHandle(), badgeLocation, density);
- }
- return drawable;
- }
-
- /**
- * @see android.content.res.Resources#getColor(int id).
- */
- @SuppressWarnings("deprecation")
- public static int getColor(Resources res, int id) throws NotFoundException {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- return res.getColor(id, null);
- } else {
- return res.getColor(id);
- }
- }
-
- /**
- * @see android.graphics.drawable.Drawable#getColorFilter().
- */
- @SuppressWarnings("NewApi")
- public static ColorFilter getColorFilter(Drawable drawable) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return drawable.getColorFilter();
- } else {
- return null;
- }
- }
-
- /**
- * @see android.widget.TextView#setTextAppearance(int id).
- */
- @SuppressWarnings("deprecation")
- public static void setTextAppearance(TextView view, int id) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- view.setTextAppearance(id);
- } else {
- view.setTextAppearance(view.getContext(), id);
- }
- }
-
- /**
- * See {@link android.os.StatFs#getAvailableBlocksLong}.
- */
- @SuppressWarnings("deprecation")
- public static long getAvailableBlocks(StatFs statFs) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- return statFs.getAvailableBlocksLong();
- } else {
- return statFs.getAvailableBlocks();
- }
- }
-
- /**
- * See {@link android.os.StatFs#getBlockCount}.
- */
- @SuppressWarnings("deprecation")
- public static long getBlockCount(StatFs statFs) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- return statFs.getBlockCountLong();
- } else {
- return statFs.getBlockCount();
- }
- }
-
- /**
- * See {@link android.os.StatFs#getBlockSize}.
- */
- @SuppressWarnings("deprecation")
- public static long getBlockSize(StatFs statFs) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- return statFs.getBlockSizeLong();
- } else {
- return statFs.getBlockSize();
- }
- }
-
- /**
- * @param context The Android context, used to retrieve the UserManager system service.
- * @return Whether the device is running in demo mode.
- */
- @SuppressWarnings("NewApi")
- public static boolean isDemoUser(Context context) {
- // UserManager#isDemoUser() is only available in Android NMR1+.
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N_MR1) return false;
-
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- return userManager.isDemoUser();
- }
-
- /**
- * @see Context#checkPermission(String, int, int)
- */
- public static int checkPermission(Context context, String permission, int pid, int uid) {
- try {
- return context.checkPermission(permission, pid, uid);
- } catch (RuntimeException e) {
- // Some older versions of Android throw odd errors when checking for permissions, so
- // just swallow the exception and treat it as the permission is denied.
- // crbug.com/639099
- return PackageManager.PERMISSION_DENIED;
- }
- }
-
- /**
- * @see android.view.inputmethod.InputMethodSubType#getLocate()
- */
- @SuppressWarnings("deprecation")
- public static String getLocale(InputMethodSubtype inputMethodSubType) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- return inputMethodSubType.getLanguageTag();
- } else {
- return inputMethodSubType.getLocale();
- }
- }
-
- /**
- * Get a URI for |file| which has the image capture. This function assumes that path of |file|
- * is based on the result of UiUtils.getDirectoryForImageCapture().
- *
- * @param file image capture file.
- * @return URI for |file|.
- */
- public static Uri getUriForImageCaptureFile(File file) {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2
- ? ContentUriUtils.getContentUriFromFile(file)
- : Uri.fromFile(file);
- }
-
- /**
- * Get the URI for a downloaded file.
- *
- * @param file A downloaded file.
- * @return URI for |file|.
- */
- public static Uri getUriForDownloadedFile(File file) {
- return Build.VERSION.SDK_INT > Build.VERSION_CODES.M
- ? FileUtils.getUriForFile(file)
- : Uri.fromFile(file);
- }
-
- /**
- * @see android.view.Window#FEATURE_INDETERMINATE_PROGRESS
- */
- public static void setWindowIndeterminateProgress(Window window) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
- @SuppressWarnings("deprecation")
- int featureNumber = Window.FEATURE_INDETERMINATE_PROGRESS;
-
- @SuppressWarnings("deprecation")
- int featureValue = Window.PROGRESS_VISIBILITY_OFF;
-
- window.setFeatureInt(featureNumber, featureValue);
- }
- }
-
- /**
- * @param activity The {@link Activity} to check.
- * @return Whether or not {@code activity} is currently in Android N+ multi-window mode.
- */
- public static boolean isInMultiWindowMode(Activity activity) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
- return false;
- }
- return activity.isInMultiWindowMode();
- }
-
- /**
- * Disables the Smart Select {@link TextClassifier} for the given {@link TextView} instance.
- * @param textView The {@link TextView} that should have its classifier disabled.
- */
- @TargetApi(Build.VERSION_CODES.O)
- public static void disableSmartSelectionTextClassifier(TextView textView) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
-
- textView.setTextClassifier(TextClassifier.NO_OP);
- }
-
- /**
- * Creates an ActivityOptions Bundle with basic options and the LaunchDisplayId set.
- * @param displayId The id of the display to launch into.
- * @return The created bundle, or null if unsupported.
- */
- public static Bundle createLaunchDisplayIdActivityOptions(int displayId) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return null;
-
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(displayId);
- return options.toBundle();
- }
-}
diff --git a/base/android/java/src/org/chromium/base/ApkAssets.java b/base/android/java/src/org/chromium/base/ApkAssets.java
deleted file mode 100644
index 19108e5957..0000000000
--- a/base/android/java/src/org/chromium/base/ApkAssets.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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;
-
-import android.content.res.AssetFileDescriptor;
-import android.content.res.AssetManager;
-import android.util.Log;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-import java.io.IOException;
-
-/**
- * A utility class to retrieve references to uncompressed assets insides the apk. A reference is
- * defined as tuple (file descriptor, offset, size) enabling direct mapping without deflation.
- * This can be used even within the renderer process, since it just dup's the apk's fd.
- */
-@JNINamespace("base::android")
-public class ApkAssets {
- private static final String LOGTAG = "ApkAssets";
-
- @CalledByNative
- public static long[] open(String fileName) {
- AssetFileDescriptor afd = null;
- try {
- AssetManager manager = ContextUtils.getApplicationContext().getAssets();
- afd = manager.openNonAssetFd(fileName);
- return new long[] {afd.getParcelFileDescriptor().detachFd(), afd.getStartOffset(),
- afd.getLength()};
- } catch (IOException e) {
- // As a general rule there's no point logging here because the caller should handle
- // receiving an fd of -1 sensibly, and the log message is either mirrored later, or
- // unwanted (in the case where a missing file is expected), or wanted but will be
- // ignored, as most non-fatal logs are.
- // It makes sense to log here when the file exists, but is unable to be opened as an fd
- // because (for example) it is unexpectedly compressed in an apk. In that case, the log
- // message might save someone some time working out what has gone wrong.
- // For that reason, we only suppress the message when the exception message doesn't look
- // informative (Android framework passes the filename as the message on actual file not
- // found, and the empty string also wouldn't give any useful information for debugging).
- if (!e.getMessage().equals("") && !e.getMessage().equals(fileName)) {
- Log.e(LOGTAG, "Error while loading asset " + fileName + ": " + e);
- }
- return new long[] {-1, -1, -1};
- } finally {
- try {
- if (afd != null) {
- afd.close();
- }
- } catch (IOException e2) {
- Log.e(LOGTAG, "Unable to close AssetFileDescriptor", e2);
- }
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java
deleted file mode 100644
index 9496da8c1e..0000000000
--- a/base/android/java/src/org/chromium/base/ApplicationStatus.java
+++ /dev/null
@@ -1,620 +0,0 @@
-// 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;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.Application;
-import android.app.Application.ActivityLifecycleCallbacks;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.view.Window;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-import java.lang.ref.WeakReference;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Provides information about the current activity's status, and a way
- * to register / unregister listeners for state changes.
- */
-@JNINamespace("base::android")
-public class ApplicationStatus {
- private static final String TOOLBAR_CALLBACK_INTERNAL_WRAPPER_CLASS =
- "android.support.v7.internal.app.ToolbarActionBar$ToolbarCallbackWrapper";
- // In builds using the --use_unpublished_apis flag, the ToolbarActionBar class name does not
- // include the "internal" package.
- private static final String TOOLBAR_CALLBACK_WRAPPER_CLASS =
- "android.support.v7.app.ToolbarActionBar$ToolbarCallbackWrapper";
- private static final String WINDOW_PROFILER_CALLBACK =
- "com.android.tools.profiler.support.event.WindowProfilerCallback";
-
- private static class ActivityInfo {
- private int mStatus = ActivityState.DESTROYED;
- private ObserverList<ActivityStateListener> mListeners = new ObserverList<>();
-
- /**
- * @return The current {@link ActivityState} of the activity.
- */
- @ActivityState
- public int getStatus() {
- return mStatus;
- }
-
- /**
- * @param status The new {@link ActivityState} of the activity.
- */
- public void setStatus(@ActivityState int status) {
- mStatus = status;
- }
-
- /**
- * @return A list of {@link ActivityStateListener}s listening to this activity.
- */
- public ObserverList<ActivityStateListener> getListeners() {
- return mListeners;
- }
- }
-
- static {
- // Chrome initializes this only for the main process. This assert aims to try and catch
- // usages from GPU / renderers, while still allowing tests.
- assert ContextUtils.isMainProcess()
- || ContextUtils.getProcessName().contains(":test")
- : "Cannot use ApplicationState from process: "
- + ContextUtils.getProcessName();
- }
-
- private static final Object sCurrentApplicationStateLock = new Object();
-
- @SuppressLint("SupportAnnotationUsage")
- @ApplicationState
- // The getStateForApplication() historically returned ApplicationState.HAS_DESTROYED_ACTIVITIES
- // when no activity has been observed.
- private static Integer sCurrentApplicationState = ApplicationState.HAS_DESTROYED_ACTIVITIES;
-
- /** Last activity that was shown (or null if none or it was destroyed). */
- @SuppressLint("StaticFieldLeak")
- private static Activity sActivity;
-
- /** A lazily initialized listener that forwards application state changes to native. */
- private static ApplicationStateListener sNativeApplicationStateListener;
-
- private static boolean sIsInitialized;
-
- /**
- * A map of which observers listen to state changes from which {@link Activity}.
- */
- private static final Map<Activity, ActivityInfo> sActivityInfo = new ConcurrentHashMap<>();
-
- /**
- * A list of observers to be notified when any {@link Activity} has a state change.
- */
- private static final ObserverList<ActivityStateListener> sGeneralActivityStateListeners =
- new ObserverList<>();
-
- /**
- * A list of observers to be notified when the visibility state of this {@link Application}
- * changes. See {@link #getStateForApplication()}.
- */
- private static final ObserverList<ApplicationStateListener> sApplicationStateListeners =
- new ObserverList<>();
-
- /**
- * A list of observers to be notified when the window focus changes.
- * See {@link #registerWindowFocusChangedListener}.
- */
- private static final ObserverList<WindowFocusChangedListener> sWindowFocusListeners =
- new ObserverList<>();
-
- /**
- * Interface to be implemented by listeners.
- */
- public interface ApplicationStateListener {
- /**
- * Called when the application's state changes.
- * @param newState The application state.
- */
- void onApplicationStateChange(@ApplicationState int newState);
- }
-
- /**
- * Interface to be implemented by listeners.
- */
- public interface ActivityStateListener {
- /**
- * Called when the activity's state changes.
- * @param activity The activity that had a state change.
- * @param newState New activity state.
- */
- void onActivityStateChange(Activity activity, @ActivityState int newState);
- }
-
- /**
- * Interface to be implemented by listeners for window focus events.
- */
- public interface WindowFocusChangedListener {
- /**
- * Called when the window focus changes for {@code activity}.
- * @param activity The {@link Activity} that has a window focus changed event.
- * @param hasFocus Whether or not {@code activity} gained or lost focus.
- */
- public void onWindowFocusChanged(Activity activity, boolean hasFocus);
- }
-
- private ApplicationStatus() {}
-
- /**
- * Registers a listener to receive window focus updates on activities in this application.
- * @param listener Listener to receive window focus events.
- */
- public static void registerWindowFocusChangedListener(WindowFocusChangedListener listener) {
- sWindowFocusListeners.addObserver(listener);
- }
-
- /**
- * Unregisters a listener from receiving window focus updates on activities in this application.
- * @param listener Listener that doesn't want to receive window focus events.
- */
- public static void unregisterWindowFocusChangedListener(WindowFocusChangedListener listener) {
- sWindowFocusListeners.removeObserver(listener);
- }
-
- /**
- * Intercepts calls to an existing Window.Callback. Most invocations are passed on directly
- * to the composed Window.Callback but enables intercepting/manipulating others.
- *
- * This is used to relay window focus changes throughout the app and remedy a bug in the
- * appcompat library.
- */
- private static class WindowCallbackProxy implements InvocationHandler {
- private final Window.Callback mCallback;
- private final Activity mActivity;
-
- public WindowCallbackProxy(Activity activity, Window.Callback callback) {
- mCallback = callback;
- mActivity = activity;
- }
-
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if (method.getName().equals("onWindowFocusChanged") && args.length == 1
- && args[0] instanceof Boolean) {
- onWindowFocusChanged((boolean) args[0]);
- return null;
- } else {
- try {
- return method.invoke(mCallback, args);
- } catch (InvocationTargetException e) {
- // Special-case for when a method is not defined on the underlying
- // Window.Callback object. Because we're using a Proxy to forward all method
- // calls, this breaks the Android framework's handling for apps built against
- // an older SDK. The framework expects an AbstractMethodError but due to
- // reflection it becomes wrapped inside an InvocationTargetException. Undo the
- // wrapping to signal the framework accordingly.
- if (e.getCause() instanceof AbstractMethodError) {
- throw e.getCause();
- }
- throw e;
- }
- }
- }
-
- public void onWindowFocusChanged(boolean hasFocus) {
- mCallback.onWindowFocusChanged(hasFocus);
-
- for (WindowFocusChangedListener listener : sWindowFocusListeners) {
- listener.onWindowFocusChanged(mActivity, hasFocus);
- }
- }
- }
-
- /**
- * Initializes the activity status for a specified application.
- *
- * @param application The application whose status you wish to monitor.
- */
- public static void initialize(Application application) {
- if (sIsInitialized) return;
- sIsInitialized = true;
-
- registerWindowFocusChangedListener(new WindowFocusChangedListener() {
- @Override
- public void onWindowFocusChanged(Activity activity, boolean hasFocus) {
- if (!hasFocus || activity == sActivity) return;
-
- int state = getStateForActivity(activity);
-
- if (state != ActivityState.DESTROYED && state != ActivityState.STOPPED) {
- sActivity = activity;
- }
-
- // TODO(dtrainor): Notify of active activity change?
- }
- });
-
- application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
- @Override
- public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
- onStateChange(activity, ActivityState.CREATED);
- Window.Callback callback = activity.getWindow().getCallback();
- activity.getWindow().setCallback((Window.Callback) Proxy.newProxyInstance(
- Window.Callback.class.getClassLoader(), new Class[] {Window.Callback.class},
- new ApplicationStatus.WindowCallbackProxy(activity, callback)));
- }
-
- @Override
- public void onActivityDestroyed(Activity activity) {
- onStateChange(activity, ActivityState.DESTROYED);
- checkCallback(activity);
- }
-
- @Override
- public void onActivityPaused(Activity activity) {
- onStateChange(activity, ActivityState.PAUSED);
- checkCallback(activity);
- }
-
- @Override
- public void onActivityResumed(Activity activity) {
- onStateChange(activity, ActivityState.RESUMED);
- checkCallback(activity);
- }
-
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
- checkCallback(activity);
- }
-
- @Override
- public void onActivityStarted(Activity activity) {
- onStateChange(activity, ActivityState.STARTED);
- checkCallback(activity);
- }
-
- @Override
- public void onActivityStopped(Activity activity) {
- onStateChange(activity, ActivityState.STOPPED);
- checkCallback(activity);
- }
-
- private void checkCallback(Activity activity) {
- if (BuildConfig.DCHECK_IS_ON) {
- Class<? extends Window.Callback> callback =
- activity.getWindow().getCallback().getClass();
- assert(Proxy.isProxyClass(callback)
- || callback.getName().equals(TOOLBAR_CALLBACK_WRAPPER_CLASS)
- || callback.getName().equals(TOOLBAR_CALLBACK_INTERNAL_WRAPPER_CLASS)
- || callback.getName().equals(WINDOW_PROFILER_CALLBACK));
- }
- }
- });
- }
-
- /**
- * Asserts that initialize method has been called.
- */
- private static void assertInitialized() {
- if (!sIsInitialized) {
- throw new IllegalStateException("ApplicationStatus has not been initialized yet.");
- }
- }
-
- /**
- * Must be called by the main activity when it changes state.
- *
- * @param activity Current activity.
- * @param newState New state value.
- */
- private static void onStateChange(Activity activity, @ActivityState int newState) {
- if (activity == null) throw new IllegalArgumentException("null activity is not supported");
-
- if (sActivity == null
- || newState == ActivityState.CREATED
- || newState == ActivityState.RESUMED
- || newState == ActivityState.STARTED) {
- sActivity = activity;
- }
-
- int oldApplicationState = getStateForApplication();
- ActivityInfo info;
-
- synchronized (sCurrentApplicationStateLock) {
- if (newState == ActivityState.CREATED) {
- assert !sActivityInfo.containsKey(activity);
- sActivityInfo.put(activity, new ActivityInfo());
- }
-
- info = sActivityInfo.get(activity);
- info.setStatus(newState);
-
- // Remove before calling listeners so that isEveryActivityDestroyed() returns false when
- // this was the last activity.
- if (newState == ActivityState.DESTROYED) {
- sActivityInfo.remove(activity);
- if (activity == sActivity) sActivity = null;
- }
-
- sCurrentApplicationState = determineApplicationState();
- }
-
- // Notify all state observers that are specifically listening to this activity.
- for (ActivityStateListener listener : info.getListeners()) {
- listener.onActivityStateChange(activity, newState);
- }
-
- // Notify all state observers that are listening globally for all activity state
- // changes.
- for (ActivityStateListener listener : sGeneralActivityStateListeners) {
- listener.onActivityStateChange(activity, newState);
- }
-
- int applicationState = getStateForApplication();
- if (applicationState != oldApplicationState) {
- for (ApplicationStateListener listener : sApplicationStateListeners) {
- listener.onApplicationStateChange(applicationState);
- }
- }
- }
-
- /**
- * Testing method to update the state of the specified activity.
- */
- @VisibleForTesting
- public static void onStateChangeForTesting(Activity activity, int newState) {
- onStateChange(activity, newState);
- }
-
- /**
- * @return The most recent focused {@link Activity} tracked by this class. Being focused means
- * out of all the activities tracked here, it has most recently gained window focus.
- */
- public static Activity getLastTrackedFocusedActivity() {
- return sActivity;
- }
-
- /**
- * @return A {@link List} of all non-destroyed {@link Activity}s.
- */
- public static List<WeakReference<Activity>> getRunningActivities() {
- assertInitialized();
- List<WeakReference<Activity>> activities = new ArrayList<>();
- for (Activity activity : sActivityInfo.keySet()) {
- activities.add(new WeakReference<>(activity));
- }
- return activities;
- }
-
- /**
- * Query the state for a given activity. If the activity is not being tracked, this will
- * return {@link ActivityState#DESTROYED}.
- *
- * <p>
- * Please note that Chrome can have multiple activities running simultaneously. Please also
- * look at {@link #getStateForApplication()} for more details.
- *
- * <p>
- * When relying on this method, be familiar with the expected life cycle state
- * transitions:
- * <a href="http://developer.android.com/guide/components/activities.html#Lifecycle">
- * Activity Lifecycle
- * </a>
- *
- * <p>
- * During activity transitions (activity B launching in front of activity A), A will completely
- * paused before the creation of activity B begins.
- *
- * <p>
- * A basic flow for activity A starting, followed by activity B being opened and then closed:
- * <ul>
- * <li> -- Starting Activity A --
- * <li> Activity A - ActivityState.CREATED
- * <li> Activity A - ActivityState.STARTED
- * <li> Activity A - ActivityState.RESUMED
- * <li> -- Starting Activity B --
- * <li> Activity A - ActivityState.PAUSED
- * <li> Activity B - ActivityState.CREATED
- * <li> Activity B - ActivityState.STARTED
- * <li> Activity B - ActivityState.RESUMED
- * <li> Activity A - ActivityState.STOPPED
- * <li> -- Closing Activity B, Activity A regaining focus --
- * <li> Activity B - ActivityState.PAUSED
- * <li> Activity A - ActivityState.STARTED
- * <li> Activity A - ActivityState.RESUMED
- * <li> Activity B - ActivityState.STOPPED
- * <li> Activity B - ActivityState.DESTROYED
- * </ul>
- *
- * @param activity The activity whose state is to be returned.
- * @return The state of the specified activity (see {@link ActivityState}).
- */
- @ActivityState
- public static int getStateForActivity(@Nullable Activity activity) {
- ApplicationStatus.assertInitialized();
- if (activity == null) return ActivityState.DESTROYED;
- ActivityInfo info = sActivityInfo.get(activity);
- return info != null ? info.getStatus() : ActivityState.DESTROYED;
- }
-
- /**
- * @return The state of the application (see {@link ApplicationState}).
- */
- @ApplicationState
- @CalledByNative
- public static int getStateForApplication() {
- synchronized (sCurrentApplicationStateLock) {
- return sCurrentApplicationState;
- }
- }
-
- /**
- * Checks whether or not any Activity in this Application is visible to the user. Note that
- * this includes the PAUSED state, which can happen when the Activity is temporarily covered
- * by another Activity's Fragment (e.g.).
- * @return Whether any Activity under this Application is visible.
- */
- public static boolean hasVisibleActivities() {
- int state = getStateForApplication();
- return state == ApplicationState.HAS_RUNNING_ACTIVITIES
- || state == ApplicationState.HAS_PAUSED_ACTIVITIES;
- }
-
- /**
- * Checks to see if there are any active Activity instances being watched by ApplicationStatus.
- * @return True if all Activities have been destroyed.
- */
- public static boolean isEveryActivityDestroyed() {
- return sActivityInfo.isEmpty();
- }
-
- /**
- * Registers the given listener to receive state changes for all activities.
- * @param listener Listener to receive state changes.
- */
- public static void registerStateListenerForAllActivities(ActivityStateListener listener) {
- sGeneralActivityStateListeners.addObserver(listener);
- }
-
- /**
- * Registers the given listener to receive state changes for {@code activity}. After a call to
- * {@link ActivityStateListener#onActivityStateChange(Activity, int)} with
- * {@link ActivityState#DESTROYED} all listeners associated with that particular
- * {@link Activity} are removed.
- * @param listener Listener to receive state changes.
- * @param activity Activity to track or {@code null} to track all activities.
- */
- @SuppressLint("NewApi")
- public static void registerStateListenerForActivity(ActivityStateListener listener,
- Activity activity) {
- if (activity == null) {
- throw new IllegalStateException("Attempting to register listener on a null activity.");
- }
- ApplicationStatus.assertInitialized();
-
- ActivityInfo info = sActivityInfo.get(activity);
- if (info == null) {
- throw new IllegalStateException(
- "Attempting to register listener on an untracked activity.");
- }
- assert info.getStatus() != ActivityState.DESTROYED;
- info.getListeners().addObserver(listener);
- }
-
- /**
- * Unregisters the given listener from receiving activity state changes.
- * @param listener Listener that doesn't want to receive state changes.
- */
- public static void unregisterActivityStateListener(ActivityStateListener listener) {
- sGeneralActivityStateListeners.removeObserver(listener);
-
- // Loop through all observer lists for all activities and remove the listener.
- for (ActivityInfo info : sActivityInfo.values()) {
- info.getListeners().removeObserver(listener);
- }
- }
-
- /**
- * Registers the given listener to receive state changes for the application.
- * @param listener Listener to receive state state changes.
- */
- public static void registerApplicationStateListener(ApplicationStateListener listener) {
- sApplicationStateListeners.addObserver(listener);
- }
-
- /**
- * Unregisters the given listener from receiving state changes.
- * @param listener Listener that doesn't want to receive state changes.
- */
- public static void unregisterApplicationStateListener(ApplicationStateListener listener) {
- sApplicationStateListeners.removeObserver(listener);
- }
-
- /**
- * Robolectric JUnit tests create a new application between each test, while all the context
- * in static classes isn't reset. This function allows to reset the application status to avoid
- * being in a dirty state.
- */
- public static void destroyForJUnitTests() {
- sApplicationStateListeners.clear();
- sGeneralActivityStateListeners.clear();
- sActivityInfo.clear();
- sWindowFocusListeners.clear();
- sIsInitialized = false;
- synchronized (sCurrentApplicationStateLock) {
- sCurrentApplicationState = determineApplicationState();
- }
- sActivity = null;
- sNativeApplicationStateListener = null;
- }
-
- /**
- * Registers the single thread-safe native activity status listener.
- * This handles the case where the caller is not on the main thread.
- * Note that this is used by a leaky singleton object from the native
- * side, hence lifecycle management is greatly simplified.
- */
- @CalledByNative
- private static void registerThreadSafeNativeApplicationStateListener() {
- ThreadUtils.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (sNativeApplicationStateListener != null) return;
-
- sNativeApplicationStateListener = new ApplicationStateListener() {
- @Override
- public void onApplicationStateChange(int newState) {
- nativeOnApplicationStateChange(newState);
- }
- };
- registerApplicationStateListener(sNativeApplicationStateListener);
- }
- });
- }
-
- /**
- * Determines the current application state as defined by {@link ApplicationState}. This will
- * loop over all the activities and check their state to determine what the general application
- * state should be.
- * @return HAS_RUNNING_ACTIVITIES if any activity is not paused, stopped, or destroyed.
- * HAS_PAUSED_ACTIVITIES if none are running and one is paused.
- * HAS_STOPPED_ACTIVITIES if none are running/paused and one is stopped.
- * HAS_DESTROYED_ACTIVITIES if none are running/paused/stopped.
- */
- @ApplicationState
- private static int determineApplicationState() {
- boolean hasPausedActivity = false;
- boolean hasStoppedActivity = false;
-
- for (ActivityInfo info : sActivityInfo.values()) {
- int state = info.getStatus();
- if (state != ActivityState.PAUSED
- && state != ActivityState.STOPPED
- && state != ActivityState.DESTROYED) {
- return ApplicationState.HAS_RUNNING_ACTIVITIES;
- } else if (state == ActivityState.PAUSED) {
- hasPausedActivity = true;
- } else if (state == ActivityState.STOPPED) {
- hasStoppedActivity = true;
- }
- }
-
- if (hasPausedActivity) return ApplicationState.HAS_PAUSED_ACTIVITIES;
- if (hasStoppedActivity) return ApplicationState.HAS_STOPPED_ACTIVITIES;
- return ApplicationState.HAS_DESTROYED_ACTIVITIES;
- }
-
- // Called to notify the native side of state changes.
- // IMPORTANT: This is always called on the main thread!
- private static native void nativeOnApplicationStateChange(@ApplicationState int newState);
-}
diff --git a/base/android/java/src/org/chromium/base/BaseSwitches.java b/base/android/java/src/org/chromium/base/BaseSwitches.java
deleted file mode 100644
index fe47cdda1d..0000000000
--- a/base/android/java/src/org/chromium/base/BaseSwitches.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2013 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;
-
-/**
- * Contains all of the command line switches that are specific to the base/
- * portion of Chromium on Android.
- */
-public abstract class BaseSwitches {
- // Block ChildProcessMain thread of render process service until a Java debugger is attached.
- // To pause even earlier: am set-debug-app org.chromium.chrome:sandbox_process0
- // However, this flag is convenient when you don't know the process number, or want
- // all renderers to pause (set-debug-app applies to only one process at a time).
- public static final String RENDERER_WAIT_FOR_JAVA_DEBUGGER = "renderer-wait-for-java-debugger";
-
- // Force low-end device mode when set.
- public static final String ENABLE_LOW_END_DEVICE_MODE = "enable-low-end-device-mode";
-
- // Force disabling of low-end device mode when set.
- public static final String DISABLE_LOW_END_DEVICE_MODE = "disable-low-end-device-mode";
-
- // Adds additional thread idle time information into the trace event output.
- public static final String ENABLE_IDLE_TRACING = "enable-idle-tracing";
-
- // Default country code to be used for search engine localization.
- public static final String DEFAULT_COUNTRY_CODE_AT_INSTALL = "default-country-code";
-
- // Prevent instantiation.
- private BaseSwitches() {}
-}
diff --git a/base/android/java/src/org/chromium/base/Callback.java b/base/android/java/src/org/chromium/base/Callback.java
deleted file mode 100644
index f5f20b9c75..0000000000
--- a/base/android/java/src/org/chromium/base/Callback.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2015 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;
-
-import org.chromium.base.annotations.CalledByNative;
-
-/**
- * A simple single-argument callback to handle the result of a computation.
- *
- * @param <T> The type of the computation's result.
- */
-public interface Callback<T> {
- /**
- * Invoked with the result of a computation.
- */
- void onResult(T result);
-
- /**
- * JNI Generator does not know how to target static methods on interfaces
- * (which is new in Java 8, and requires desugaring).
- */
- abstract class Helper {
- @SuppressWarnings("unchecked")
- @CalledByNative("Helper")
- static void onObjectResultFromNative(Callback callback, Object result) {
- callback.onResult(result);
- }
-
- @SuppressWarnings("unchecked")
- @CalledByNative("Helper")
- static void onBooleanResultFromNative(Callback callback, boolean result) {
- callback.onResult(Boolean.valueOf(result));
- }
-
- @SuppressWarnings("unchecked")
- @CalledByNative("Helper")
- static void onIntResultFromNative(Callback callback, int result) {
- callback.onResult(Integer.valueOf(result));
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/CollectionUtil.java b/base/android/java/src/org/chromium/base/CollectionUtil.java
deleted file mode 100644
index 60933807b8..0000000000
--- a/base/android/java/src/org/chromium/base/CollectionUtil.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2013 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;
-
-import android.support.annotation.NonNull;
-import android.util.Pair;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Functions used for easier initialization of Java collections. Inspired by
- * functionality in com.google.common.collect in Guava but cherry-picked to
- * bare-minimum functionality to avoid bloat. (http://crbug.com/272790 provides
- * further details)
- */
-public final class CollectionUtil {
- private CollectionUtil() {}
-
- @SafeVarargs
- public static <E> HashSet<E> newHashSet(E... elements) {
- HashSet<E> set = new HashSet<E>(elements.length);
- Collections.addAll(set, elements);
- return set;
- }
-
- @SafeVarargs
- public static <E> ArrayList<E> newArrayList(E... elements) {
- ArrayList<E> list = new ArrayList<E>(elements.length);
- Collections.addAll(list, elements);
- return list;
- }
-
- @VisibleForTesting
- public static <E> ArrayList<E> newArrayList(Iterable<E> iterable) {
- ArrayList<E> list = new ArrayList<E>();
- for (E element : iterable) {
- list.add(element);
- }
- return list;
- }
-
- @SafeVarargs
- public static <K, V> HashMap<K, V> newHashMap(Pair<? extends K, ? extends V>... entries) {
- HashMap<K, V> map = new HashMap<>();
- for (Pair<? extends K, ? extends V> entry : entries) {
- map.put(entry.first, entry.second);
- }
- return map;
- }
-
- public static boolean[] booleanListToBooleanArray(@NonNull List<Boolean> list) {
- boolean[] array = new boolean[list.size()];
- for (int i = 0; i < list.size(); i++) {
- array[i] = list.get(i);
- }
- return array;
- }
-
- public static int[] integerListToIntArray(@NonNull List<Integer> list) {
- int[] array = new int[list.size()];
- for (int i = 0; i < list.size(); i++) {
- array[i] = list.get(i);
- }
- return array;
- }
-
- public static long[] longListToLongArray(@NonNull List<Long> list) {
- long[] array = new long[list.size()];
- for (int i = 0; i < list.size(); i++) {
- array[i] = list.get(i);
- }
- return array;
- }
-
- // This is a utility helper method that adds functionality available in API 24 (see
- // Collection.forEach).
- public static <T> void forEach(Collection<? extends T> collection, Callback<T> worker) {
- for (T entry : collection) worker.onResult(entry);
- }
-
- // This is a utility helper method that adds functionality available in API 24 (see
- // Collection.forEach).
- @SuppressWarnings("unchecked")
- public static <K, V> void forEach(
- Map<? extends K, ? extends V> map, Callback<Entry<K, V>> worker) {
- for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
- worker.onResult((Map.Entry<K, V>) entry);
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/CommandLine.java b/base/android/java/src/org/chromium/base/CommandLine.java
deleted file mode 100644
index 963b1464af..0000000000
--- a/base/android/java/src/org/chromium/base/CommandLine.java
+++ /dev/null
@@ -1,389 +0,0 @@
-// Copyright 2013 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;
-
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import org.chromium.base.annotations.MainDex;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Java mirror of base/command_line.h.
- * Android applications don't have command line arguments. Instead, they're "simulated" by reading a
- * file at a specific location early during startup. Applications each define their own files, e.g.,
- * ContentShellApplication.COMMAND_LINE_FILE.
-**/
-@MainDex
-public abstract class CommandLine {
- // Public abstract interface, implemented in derived classes.
- // All these methods reflect their native-side counterparts.
- /**
- * Returns true if this command line contains the given switch.
- * (Switch names ARE case-sensitive).
- */
- @VisibleForTesting
- public abstract boolean hasSwitch(String switchString);
-
- /**
- * Return the value associated with the given switch, or null.
- * @param switchString The switch key to lookup. It should NOT start with '--' !
- * @return switch value, or null if the switch is not set or set to empty.
- */
- public abstract String getSwitchValue(String switchString);
-
- /**
- * Return the value associated with the given switch, or {@code defaultValue} if the switch
- * was not specified.
- * @param switchString The switch key to lookup. It should NOT start with '--' !
- * @param defaultValue The default value to return if the switch isn't set.
- * @return Switch value, or {@code defaultValue} if the switch is not set or set to empty.
- */
- public String getSwitchValue(String switchString, String defaultValue) {
- String value = getSwitchValue(switchString);
- return TextUtils.isEmpty(value) ? defaultValue : value;
- }
-
- /**
- * Append a switch to the command line. There is no guarantee
- * this action happens before the switch is needed.
- * @param switchString the switch to add. It should NOT start with '--' !
- */
- @VisibleForTesting
- public abstract void appendSwitch(String switchString);
-
- /**
- * Append a switch and value to the command line. There is no
- * guarantee this action happens before the switch is needed.
- * @param switchString the switch to add. It should NOT start with '--' !
- * @param value the value for this switch.
- * For example, --foo=bar becomes 'foo', 'bar'.
- */
- public abstract void appendSwitchWithValue(String switchString, String value);
-
- /**
- * Append switch/value items in "command line" format (excluding argv[0] program name).
- * E.g. { '--gofast', '--username=fred' }
- * @param array an array of switch or switch/value items in command line format.
- * Unlike the other append routines, these switches SHOULD start with '--' .
- * Unlike init(), this does not include the program name in array[0].
- */
- public abstract void appendSwitchesAndArguments(String[] array);
-
- /**
- * Determine if the command line is bound to the native (JNI) implementation.
- * @return true if the underlying implementation is delegating to the native command line.
- */
- public boolean isNativeImplementation() {
- return false;
- }
-
- /**
- * Returns the switches and arguments passed into the program, with switches and their
- * values coming before all of the arguments.
- */
- protected abstract String[] getCommandLineArguments();
-
- /**
- * Destroy the command line. Called when a different instance is set.
- * @see #setInstance
- */
- protected void destroy() {}
-
- private static final AtomicReference<CommandLine> sCommandLine =
- new AtomicReference<CommandLine>();
-
- /**
- * @return true if the command line has already been initialized.
- */
- public static boolean isInitialized() {
- return sCommandLine.get() != null;
- }
-
- // Equivalent to CommandLine::ForCurrentProcess in C++.
- @VisibleForTesting
- public static CommandLine getInstance() {
- CommandLine commandLine = sCommandLine.get();
- assert commandLine != null;
- return commandLine;
- }
-
- /**
- * Initialize the singleton instance, must be called exactly once (either directly or
- * via one of the convenience wrappers below) before using the static singleton instance.
- * @param args command line flags in 'argv' format: args[0] is the program name.
- */
- public static void init(@Nullable String[] args) {
- setInstance(new JavaCommandLine(args));
- }
-
- /**
- * Initialize the command line from the command-line file.
- *
- * @param file The fully qualified command line file.
- */
- public static void initFromFile(String file) {
- char[] buffer = readFileAsUtf8(file);
- init(buffer == null ? null : tokenizeQuotedArguments(buffer));
- }
-
- /**
- * Resets both the java proxy and the native command lines. This allows the entire
- * command line initialization to be re-run including the call to onJniLoaded.
- */
- @VisibleForTesting
- public static void reset() {
- setInstance(null);
- }
-
- /**
- * Parse command line flags from a flat buffer, supporting double-quote enclosed strings
- * containing whitespace. argv elements are derived by splitting the buffer on whitepace;
- * double quote characters may enclose tokens containing whitespace; a double-quote literal
- * may be escaped with back-slash. (Otherwise backslash is taken as a literal).
- * @param buffer A command line in command line file format as described above.
- * @return the tokenized arguments, suitable for passing to init().
- */
- @VisibleForTesting
- static String[] tokenizeQuotedArguments(char[] buffer) {
- // Just field trials can take up to 10K of command line.
- if (buffer.length > 64 * 1024) {
- // Check that our test runners are setting a reasonable number of flags.
- throw new RuntimeException("Flags file too big: " + buffer.length);
- }
-
- ArrayList<String> args = new ArrayList<String>();
- StringBuilder arg = null;
- final char noQuote = '\0';
- final char singleQuote = '\'';
- final char doubleQuote = '"';
- char currentQuote = noQuote;
- for (char c : buffer) {
- // Detect start or end of quote block.
- if ((currentQuote == noQuote && (c == singleQuote || c == doubleQuote))
- || c == currentQuote) {
- if (arg != null && arg.length() > 0 && arg.charAt(arg.length() - 1) == '\\') {
- // Last char was a backslash; pop it, and treat c as a literal.
- arg.setCharAt(arg.length() - 1, c);
- } else {
- currentQuote = currentQuote == noQuote ? c : noQuote;
- }
- } else if (currentQuote == noQuote && Character.isWhitespace(c)) {
- if (arg != null) {
- args.add(arg.toString());
- arg = null;
- }
- } else {
- if (arg == null) arg = new StringBuilder();
- arg.append(c);
- }
- }
- if (arg != null) {
- if (currentQuote != noQuote) {
- Log.w(TAG, "Unterminated quoted string: " + arg);
- }
- args.add(arg.toString());
- }
- return args.toArray(new String[args.size()]);
- }
-
- private static final String TAG = "CommandLine";
- private static final String SWITCH_PREFIX = "--";
- private static final String SWITCH_TERMINATOR = SWITCH_PREFIX;
- private static final String SWITCH_VALUE_SEPARATOR = "=";
-
- public static void enableNativeProxy() {
- // Make a best-effort to ensure we make a clean (atomic) switch over from the old to
- // the new command line implementation. If another thread is modifying the command line
- // when this happens, all bets are off. (As per the native CommandLine).
- sCommandLine.set(new NativeCommandLine(getJavaSwitchesOrNull()));
- }
-
- @Nullable
- public static String[] getJavaSwitchesOrNull() {
- CommandLine commandLine = sCommandLine.get();
- if (commandLine != null) {
- return commandLine.getCommandLineArguments();
- }
- return null;
- }
-
- private static void setInstance(CommandLine commandLine) {
- CommandLine oldCommandLine = sCommandLine.getAndSet(commandLine);
- if (oldCommandLine != null) {
- oldCommandLine.destroy();
- }
- }
-
- /**
- * @param fileName the file to read in.
- * @return Array of chars read from the file, or null if the file cannot be read.
- */
- private static char[] readFileAsUtf8(String fileName) {
- File f = new File(fileName);
- try (FileReader reader = new FileReader(f)) {
- char[] buffer = new char[(int) f.length()];
- int charsRead = reader.read(buffer);
- // charsRead < f.length() in the case of multibyte characters.
- return Arrays.copyOfRange(buffer, 0, charsRead);
- } catch (IOException e) {
- return null; // Most likely file not found.
- }
- }
-
- private CommandLine() {}
-
- private static class JavaCommandLine extends CommandLine {
- private HashMap<String, String> mSwitches = new HashMap<String, String>();
- private ArrayList<String> mArgs = new ArrayList<String>();
-
- // The arguments begin at index 1, since index 0 contains the executable name.
- private int mArgsBegin = 1;
-
- JavaCommandLine(@Nullable String[] args) {
- if (args == null || args.length == 0 || args[0] == null) {
- mArgs.add("");
- } else {
- mArgs.add(args[0]);
- appendSwitchesInternal(args, 1);
- }
- // Invariant: we always have the argv[0] program name element.
- assert mArgs.size() > 0;
- }
-
- @Override
- protected String[] getCommandLineArguments() {
- return mArgs.toArray(new String[mArgs.size()]);
- }
-
- @Override
- public boolean hasSwitch(String switchString) {
- return mSwitches.containsKey(switchString);
- }
-
- @Override
- public String getSwitchValue(String switchString) {
- // This is slightly round about, but needed for consistency with the NativeCommandLine
- // version which does not distinguish empty values from key not present.
- String value = mSwitches.get(switchString);
- return value == null || value.isEmpty() ? null : value;
- }
-
- @Override
- public void appendSwitch(String switchString) {
- appendSwitchWithValue(switchString, null);
- }
-
- /**
- * Appends a switch to the current list.
- * @param switchString the switch to add. It should NOT start with '--' !
- * @param value the value for this switch.
- */
- @Override
- public void appendSwitchWithValue(String switchString, String value) {
- mSwitches.put(switchString, value == null ? "" : value);
-
- // Append the switch and update the switches/arguments divider mArgsBegin.
- String combinedSwitchString = SWITCH_PREFIX + switchString;
- if (value != null && !value.isEmpty()) {
- combinedSwitchString += SWITCH_VALUE_SEPARATOR + value;
- }
-
- mArgs.add(mArgsBegin++, combinedSwitchString);
- }
-
- @Override
- public void appendSwitchesAndArguments(String[] array) {
- appendSwitchesInternal(array, 0);
- }
-
- // Add the specified arguments, but skipping the first |skipCount| elements.
- private void appendSwitchesInternal(String[] array, int skipCount) {
- boolean parseSwitches = true;
- for (String arg : array) {
- if (skipCount > 0) {
- --skipCount;
- continue;
- }
-
- if (arg.equals(SWITCH_TERMINATOR)) {
- parseSwitches = false;
- }
-
- if (parseSwitches && arg.startsWith(SWITCH_PREFIX)) {
- String[] parts = arg.split(SWITCH_VALUE_SEPARATOR, 2);
- String value = parts.length > 1 ? parts[1] : null;
- appendSwitchWithValue(parts[0].substring(SWITCH_PREFIX.length()), value);
- } else {
- mArgs.add(arg);
- }
- }
- }
- }
-
- private static class NativeCommandLine extends CommandLine {
- public NativeCommandLine(@Nullable String[] args) {
- nativeInit(args);
- }
-
- @Override
- public boolean hasSwitch(String switchString) {
- return nativeHasSwitch(switchString);
- }
-
- @Override
- public String getSwitchValue(String switchString) {
- return nativeGetSwitchValue(switchString);
- }
-
- @Override
- public void appendSwitch(String switchString) {
- nativeAppendSwitch(switchString);
- }
-
- @Override
- public void appendSwitchWithValue(String switchString, String value) {
- nativeAppendSwitchWithValue(switchString, value);
- }
-
- @Override
- public void appendSwitchesAndArguments(String[] array) {
- nativeAppendSwitchesAndArguments(array);
- }
-
- @Override
- public boolean isNativeImplementation() {
- return true;
- }
-
- @Override
- protected String[] getCommandLineArguments() {
- assert false;
- return null;
- }
-
- @Override
- protected void destroy() {
- // TODO(https://crbug.com/771205): Downgrade this to an assert once we have eliminated
- // tests that do this.
- throw new IllegalStateException("Can't destroy native command line after startup");
- }
- }
-
- private static native void nativeInit(String[] args);
- private static native boolean nativeHasSwitch(String switchString);
- private static native String nativeGetSwitchValue(String switchString);
- private static native void nativeAppendSwitch(String switchString);
- private static native void nativeAppendSwitchWithValue(String switchString, String value);
- private static native void nativeAppendSwitchesAndArguments(String[] array);
-}
diff --git a/base/android/java/src/org/chromium/base/CommandLineInitUtil.java b/base/android/java/src/org/chromium/base/CommandLineInitUtil.java
deleted file mode 100644
index e51b95d6b5..0000000000
--- a/base/android/java/src/org/chromium/base/CommandLineInitUtil.java
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2015 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;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.os.Build;
-import android.provider.Settings;
-import android.support.annotation.Nullable;
-
-import java.io.File;
-
-/**
- * Provides implementation of command line initialization for Android.
- */
-public final class CommandLineInitUtil {
- /**
- * The location of the command line file needs to be in a protected
- * directory so requires root access to be tweaked, i.e., no other app in a
- * regular (non-rooted) device can change this file's contents.
- * See below for debugging on a regular (non-rooted) device.
- */
- private static final String COMMAND_LINE_FILE_PATH = "/data/local";
-
- /**
- * This path (writable by the shell in regular non-rooted "user" builds) is used when:
- * 1) The "debug app" is set to the application calling this.
- * and
- * 2) ADB is enabled.
- * 3) Force enabled by the embedder.
- */
- private static final String COMMAND_LINE_FILE_PATH_DEBUG_APP = "/data/local/tmp";
-
- private CommandLineInitUtil() {
- }
-
- /**
- * Initializes the CommandLine class, pulling command line arguments from {@code fileName}.
- * @param fileName The name of the command line file to pull arguments from.
- */
- public static void initCommandLine(String fileName) {
- initCommandLine(fileName, null);
- }
-
- /**
- * Initializes the CommandLine class, pulling command line arguments from {@code fileName}.
- * @param fileName The name of the command line file to pull arguments from.
- * @param shouldUseDebugFlags If non-null, returns whether debug flags are allowed to be used.
- */
- public static void initCommandLine(
- String fileName, @Nullable Supplier<Boolean> shouldUseDebugFlags) {
- assert !CommandLine.isInitialized();
- File commandLineFile = new File(COMMAND_LINE_FILE_PATH_DEBUG_APP, fileName);
- // shouldUseDebugCommandLine() uses IPC, so don't bother calling it if no flags file exists.
- boolean debugFlagsExist = commandLineFile.exists();
- if (!debugFlagsExist || !shouldUseDebugCommandLine(shouldUseDebugFlags)) {
- commandLineFile = new File(COMMAND_LINE_FILE_PATH, fileName);
- }
- CommandLine.initFromFile(commandLineFile.getPath());
- }
-
- /**
- * Use an alternative path if:
- * - The current build is "eng" or "userdebug", OR
- * - adb is enabled and this is the debug app, OR
- * - Force enabled by the embedder.
- * @param shouldUseDebugFlags If non-null, returns whether debug flags are allowed to be used.
- */
- private static boolean shouldUseDebugCommandLine(
- @Nullable Supplier<Boolean> shouldUseDebugFlags) {
- if (shouldUseDebugFlags != null && shouldUseDebugFlags.get()) return true;
- Context context = ContextUtils.getApplicationContext();
- String debugApp = Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1
- ? getDebugAppPreJBMR1(context)
- : getDebugAppJBMR1(context);
- // Check isDebugAndroid() last to get full code coverage when using userdebug devices.
- return context.getPackageName().equals(debugApp) || BuildInfo.isDebugAndroid();
- }
-
- @SuppressLint("NewApi")
- private static String getDebugAppJBMR1(Context context) {
- boolean adbEnabled = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.ADB_ENABLED, 0) == 1;
- if (adbEnabled) {
- return Settings.Global.getString(context.getContentResolver(),
- Settings.Global.DEBUG_APP);
- }
- return null;
- }
-
- @SuppressWarnings("deprecation")
- private static String getDebugAppPreJBMR1(Context context) {
- boolean adbEnabled = Settings.System.getInt(context.getContentResolver(),
- Settings.System.ADB_ENABLED, 0) == 1;
- if (adbEnabled) {
- return Settings.System.getString(context.getContentResolver(),
- Settings.System.DEBUG_APP);
- }
- return null;
- }
-}
diff --git a/base/android/java/src/org/chromium/base/ContentUriUtils.java b/base/android/java/src/org/chromium/base/ContentUriUtils.java
deleted file mode 100644
index ba92a56c4f..0000000000
--- a/base/android/java/src/org/chromium/base/ContentUriUtils.java
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2013 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;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.provider.DocumentsContract;
-import android.util.Log;
-import android.webkit.MimeTypeMap;
-
-import org.chromium.base.annotations.CalledByNative;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-/**
- * This class provides methods to access content URI schemes.
- */
-public abstract class ContentUriUtils {
- private static final String TAG = "ContentUriUtils";
- private static FileProviderUtil sFileProviderUtil;
-
- // Guards access to sFileProviderUtil.
- private static final Object sLock = new Object();
-
- /**
- * Provides functionality to translate a file into a content URI for use
- * with a content provider.
- */
- public interface FileProviderUtil {
- /**
- * Generate a content URI from the given file.
- *
- * @param file The file to be translated.
- */
- Uri getContentUriFromFile(File file);
- }
-
- // Prevent instantiation.
- private ContentUriUtils() {}
-
- public static void setFileProviderUtil(FileProviderUtil util) {
- synchronized (sLock) {
- sFileProviderUtil = util;
- }
- }
-
- public static Uri getContentUriFromFile(File file) {
- synchronized (sLock) {
- if (sFileProviderUtil != null) {
- return sFileProviderUtil.getContentUriFromFile(file);
- }
- }
- return null;
- }
-
- /**
- * Opens the content URI for reading, and returns the file descriptor to
- * the caller. The caller is responsible for closing the file descriptor.
- *
- * @param uriString the content URI to open
- * @return file descriptor upon success, or -1 otherwise.
- */
- @CalledByNative
- public static int openContentUriForRead(String uriString) {
- AssetFileDescriptor afd = getAssetFileDescriptor(uriString);
- if (afd != null) {
- return afd.getParcelFileDescriptor().detachFd();
- }
- return -1;
- }
-
- /**
- * Check whether a content URI exists.
- *
- * @param uriString the content URI to query.
- * @return true if the URI exists, or false otherwise.
- */
- @CalledByNative
- public static boolean contentUriExists(String uriString) {
- AssetFileDescriptor asf = null;
- try {
- asf = getAssetFileDescriptor(uriString);
- return asf != null;
- } finally {
- // Do not use StreamUtil.closeQuietly here, as AssetFileDescriptor
- // does not implement Closeable until KitKat.
- if (asf != null) {
- try {
- asf.close();
- } catch (IOException e) {
- // Closing quietly.
- }
- }
- }
- }
-
- /**
- * Retrieve the MIME type for the content URI.
- *
- * @param uriString the content URI to look up.
- * @return MIME type or null if the input params are empty or invalid.
- */
- @CalledByNative
- public static String getMimeType(String uriString) {
- ContentResolver resolver = ContextUtils.getApplicationContext().getContentResolver();
- Uri uri = Uri.parse(uriString);
- if (isVirtualDocument(uri)) {
- String[] streamTypes = resolver.getStreamTypes(uri, "*/*");
- return (streamTypes != null && streamTypes.length > 0) ? streamTypes[0] : null;
- }
- return resolver.getType(uri);
- }
-
- /**
- * Helper method to open a content URI and returns the ParcelFileDescriptor.
- *
- * @param uriString the content URI to open.
- * @return AssetFileDescriptor of the content URI, or NULL if the file does not exist.
- */
- private static AssetFileDescriptor getAssetFileDescriptor(String uriString) {
- ContentResolver resolver = ContextUtils.getApplicationContext().getContentResolver();
- Uri uri = Uri.parse(uriString);
-
- try {
- if (isVirtualDocument(uri)) {
- String[] streamTypes = resolver.getStreamTypes(uri, "*/*");
- if (streamTypes != null && streamTypes.length > 0) {
- AssetFileDescriptor afd =
- resolver.openTypedAssetFileDescriptor(uri, streamTypes[0], null);
- if (afd != null && afd.getStartOffset() != 0) {
- // Do not use StreamUtil.closeQuietly here, as AssetFileDescriptor
- // does not implement Closeable until KitKat.
- try {
- afd.close();
- } catch (IOException e) {
- // Closing quietly.
- }
- throw new SecurityException("Cannot open files with non-zero offset type.");
- }
- return afd;
- }
- } else {
- ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r");
- if (pfd != null) {
- return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
- }
- }
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Cannot find content uri: " + uriString, e);
- } catch (SecurityException e) {
- Log.w(TAG, "Cannot open content uri: " + uriString, e);
- } catch (Exception e) {
- Log.w(TAG, "Unknown content uri: " + uriString, e);
- }
- return null;
- }
-
- /**
- * Method to resolve the display name of a content URI.
- *
- * @param uri the content URI to be resolved.
- * @param context {@link Context} in interest.
- * @param columnField the column field to query.
- * @return the display name of the @code uri if present in the database
- * or an empty string otherwise.
- */
- public static String getDisplayName(Uri uri, Context context, String columnField) {
- if (uri == null) return "";
- ContentResolver contentResolver = context.getContentResolver();
- try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) {
- if (cursor != null && cursor.getCount() >= 1) {
- cursor.moveToFirst();
- int displayNameIndex = cursor.getColumnIndex(columnField);
- if (displayNameIndex == -1) {
- return "";
- }
- String displayName = cursor.getString(displayNameIndex);
- // For Virtual documents, try to modify the file extension so it's compatible
- // with the alternative MIME type.
- if (hasVirtualFlag(cursor)) {
- String[] mimeTypes = contentResolver.getStreamTypes(uri, "*/*");
- if (mimeTypes != null && mimeTypes.length > 0) {
- String ext =
- MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeTypes[0]);
- if (ext != null) {
- // Just append, it's simpler and more secure than altering an
- // existing extension.
- displayName += "." + ext;
- }
- }
- }
- return displayName;
- }
- } catch (NullPointerException e) {
- // Some android models don't handle the provider call correctly.
- // see crbug.com/345393
- return "";
- }
- return "";
- }
-
- /**
- * Checks whether the passed Uri represents a virtual document.
- *
- * @param uri the content URI to be resolved.
- * @return True for virtual file, false for any other file.
- */
- private static boolean isVirtualDocument(Uri uri) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return false;
- if (uri == null) return false;
- if (!DocumentsContract.isDocumentUri(ContextUtils.getApplicationContext(), uri)) {
- return false;
- }
- ContentResolver contentResolver = ContextUtils.getApplicationContext().getContentResolver();
- try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) {
- if (cursor != null && cursor.getCount() >= 1) {
- cursor.moveToFirst();
- return hasVirtualFlag(cursor);
- }
- } catch (NullPointerException e) {
- // Some android models don't handle the provider call correctly.
- // see crbug.com/345393
- return false;
- }
- return false;
- }
-
- /**
- * Checks whether the passed cursor for a document has a virtual document flag.
- *
- * The called must close the passed cursor.
- *
- * @param cursor Cursor with COLUMN_FLAGS.
- * @return True for virtual file, false for any other file.
- */
- private static boolean hasVirtualFlag(Cursor cursor) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return false;
- int index = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_FLAGS);
- return index > -1
- && (cursor.getLong(index) & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0;
- }
-}
diff --git a/base/android/java/src/org/chromium/base/CpuFeatures.java b/base/android/java/src/org/chromium/base/CpuFeatures.java
deleted file mode 100644
index ae4969c99e..0000000000
--- a/base/android/java/src/org/chromium/base/CpuFeatures.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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;
-
-import org.chromium.base.annotations.JNINamespace;
-
-// The only purpose of this class is to allow sending CPU properties
-// from the browser process to sandboxed renderer processes. This is
-// needed because sandboxed processes cannot, on ARM, query the kernel
-// about the CPU's properties by parsing /proc, so this operation must
-// be performed in the browser process, and the result passed to
-// renderer ones.
-//
-// For more context, see http://crbug.com/164154
-//
-// Technically, this is a wrapper around the native NDK cpufeatures
-// library. The exact CPU features bits are never used in Java so
-// there is no point in duplicating their definitions here.
-//
-@JNINamespace("base::android")
-public abstract class CpuFeatures {
- /**
- * Return the number of CPU Cores on the device.
- */
- public static int getCount() {
- return nativeGetCoreCount();
- }
-
- /**
- * Return the CPU feature mask.
- * This is a 64-bit integer that corresponds to the CPU's features.
- * The value comes directly from android_getCpuFeatures().
- */
- public static long getMask() {
- return nativeGetCpuFeatures();
- }
-
- private static native int nativeGetCoreCount();
- private static native long nativeGetCpuFeatures();
-}
diff --git a/base/android/java/src/org/chromium/base/EarlyTraceEvent.java b/base/android/java/src/org/chromium/base/EarlyTraceEvent.java
deleted file mode 100644
index 0f64fc2329..0000000000
--- a/base/android/java/src/org/chromium/base/EarlyTraceEvent.java
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2016 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;
-
-import android.annotation.SuppressLint;
-import android.os.Build;
-import android.os.Process;
-import android.os.StrictMode;
-import android.os.SystemClock;
-
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.MainDex;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** Support for early tracing, before the native library is loaded.
- *
- * This is limited, as:
- * - Arguments are not supported
- * - Thread time is not reported
- * - Two events with the same name cannot be in progress at the same time.
- *
- * Events recorded here are buffered in Java until the native library is available. Then it waits
- * for the completion of pending events, and sends the events to the native side.
- *
- * Locking: This class is threadsafe. It is enabled when general tracing is, and then disabled when
- * tracing is enabled from the native side. Event completions are still processed as long
- * as some are pending, then early tracing is permanently disabled after dumping the
- * events. This means that if any early event is still pending when tracing is disabled,
- * all early events are dropped.
- */
-@JNINamespace("base::android")
-@MainDex
-public class EarlyTraceEvent {
- // Must be kept in sync with the native kAndroidTraceConfigFile.
- private static final String TRACE_CONFIG_FILENAME = "/data/local/chrome-trace-config.json";
-
- /** Single trace event. */
- @VisibleForTesting
- static final class Event {
- final String mName;
- final int mThreadId;
- final long mBeginTimeNanos;
- final long mBeginThreadTimeMillis;
- long mEndTimeNanos;
- long mEndThreadTimeMillis;
-
- Event(String name) {
- mName = name;
- mThreadId = Process.myTid();
- mBeginTimeNanos = elapsedRealtimeNanos();
- mBeginThreadTimeMillis = SystemClock.currentThreadTimeMillis();
- }
-
- void end() {
- assert mEndTimeNanos == 0;
- assert mEndThreadTimeMillis == 0;
- mEndTimeNanos = elapsedRealtimeNanos();
- mEndThreadTimeMillis = SystemClock.currentThreadTimeMillis();
- }
-
- @VisibleForTesting
- @SuppressLint("NewApi")
- static long elapsedRealtimeNanos() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return SystemClock.elapsedRealtimeNanos();
- } else {
- return SystemClock.elapsedRealtime() * 1000000;
- }
- }
- }
-
- @VisibleForTesting
- static final class AsyncEvent {
- final boolean mIsStart;
- final String mName;
- final long mId;
- final long mTimestampNanos;
-
- AsyncEvent(String name, long id, boolean isStart) {
- mName = name;
- mId = id;
- mIsStart = isStart;
- mTimestampNanos = Event.elapsedRealtimeNanos();
- }
- }
-
- // State transitions are:
- // - enable(): DISABLED -> ENABLED
- // - disable(): ENABLED -> FINISHING
- // - Once there are no pending events: FINISHING -> FINISHED.
- @VisibleForTesting static final int STATE_DISABLED = 0;
- @VisibleForTesting static final int STATE_ENABLED = 1;
- @VisibleForTesting static final int STATE_FINISHING = 2;
- @VisibleForTesting static final int STATE_FINISHED = 3;
-
- // Locks the fields below.
- private static final Object sLock = new Object();
-
- @VisibleForTesting static volatile int sState = STATE_DISABLED;
- // Not final as these object are not likely to be used at all.
- @VisibleForTesting static List<Event> sCompletedEvents;
- @VisibleForTesting
- static Map<String, Event> sPendingEventByKey;
- @VisibleForTesting static List<AsyncEvent> sAsyncEvents;
- @VisibleForTesting static List<String> sPendingAsyncEvents;
-
- /** @see TraceEvent#MaybeEnableEarlyTracing().
- */
- static void maybeEnable() {
- ThreadUtils.assertOnUiThread();
- boolean shouldEnable = false;
- // Checking for the trace config filename touches the disk.
- StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- try {
- if (CommandLine.getInstance().hasSwitch("trace-startup")) {
- shouldEnable = true;
- } else {
- try {
- shouldEnable = (new File(TRACE_CONFIG_FILENAME)).exists();
- } catch (SecurityException e) {
- // Access denied, not enabled.
- }
- }
- } finally {
- StrictMode.setThreadPolicy(oldPolicy);
- }
- if (shouldEnable) enable();
- }
-
- @VisibleForTesting
- static void enable() {
- synchronized (sLock) {
- if (sState != STATE_DISABLED) return;
- sCompletedEvents = new ArrayList<Event>();
- sPendingEventByKey = new HashMap<String, Event>();
- sAsyncEvents = new ArrayList<AsyncEvent>();
- sPendingAsyncEvents = new ArrayList<String>();
- sState = STATE_ENABLED;
- }
- }
-
- /**
- * Disables Early tracing.
- *
- * Once this is called, no new event will be registered. However, end() calls are still recorded
- * as long as there are pending events. Once there are none left, pass the events to the native
- * side.
- */
- static void disable() {
- synchronized (sLock) {
- if (!enabled()) return;
- sState = STATE_FINISHING;
- maybeFinishLocked();
- }
- }
-
- /**
- * Returns whether early tracing is currently active.
- *
- * Active means that Early Tracing is either enabled or waiting to complete pending events.
- */
- static boolean isActive() {
- int state = sState;
- return (state == STATE_ENABLED || state == STATE_FINISHING);
- }
-
- static boolean enabled() {
- return sState == STATE_ENABLED;
- }
-
- /** @see {@link TraceEvent#begin()}. */
- public static void begin(String name) {
- // begin() and end() are going to be called once per TraceEvent, this avoids entering a
- // synchronized block at each and every call.
- if (!enabled()) return;
- Event event = new Event(name);
- Event conflictingEvent;
- synchronized (sLock) {
- if (!enabled()) return;
- conflictingEvent = sPendingEventByKey.put(makeEventKeyForCurrentThread(name), event);
- }
- if (conflictingEvent != null) {
- throw new IllegalArgumentException(
- "Multiple pending trace events can't have the same name");
- }
- }
-
- /** @see {@link TraceEvent#end()}. */
- public static void end(String name) {
- if (!isActive()) return;
- synchronized (sLock) {
- if (!isActive()) return;
- Event event = sPendingEventByKey.remove(makeEventKeyForCurrentThread(name));
- if (event == null) return;
- event.end();
- sCompletedEvents.add(event);
- if (sState == STATE_FINISHING) maybeFinishLocked();
- }
- }
-
- /** @see {@link TraceEvent#startAsync()}. */
- public static void startAsync(String name, long id) {
- if (!enabled()) return;
- AsyncEvent event = new AsyncEvent(name, id, true /*isStart*/);
- synchronized (sLock) {
- if (!enabled()) return;
- sAsyncEvents.add(event);
- sPendingAsyncEvents.add(name);
- }
- }
-
- /** @see {@link TraceEvent#finishAsync()}. */
- public static void finishAsync(String name, long id) {
- if (!isActive()) return;
- AsyncEvent event = new AsyncEvent(name, id, false /*isStart*/);
- synchronized (sLock) {
- if (!isActive()) return;
- if (!sPendingAsyncEvents.remove(name)) return;
- sAsyncEvents.add(event);
- if (sState == STATE_FINISHING) maybeFinishLocked();
- }
- }
-
- @VisibleForTesting
- static void resetForTesting() {
- sState = EarlyTraceEvent.STATE_DISABLED;
- sCompletedEvents = null;
- sPendingEventByKey = null;
- sAsyncEvents = null;
- sPendingAsyncEvents = null;
- }
-
- private static void maybeFinishLocked() {
- if (!sCompletedEvents.isEmpty()) {
- dumpEvents(sCompletedEvents);
- sCompletedEvents.clear();
- }
- if (!sAsyncEvents.isEmpty()) {
- dumpAsyncEvents(sAsyncEvents);
- sAsyncEvents.clear();
- }
- if (sPendingEventByKey.isEmpty() && sPendingAsyncEvents.isEmpty()) {
- sState = STATE_FINISHED;
- sPendingEventByKey = null;
- sCompletedEvents = null;
- sPendingAsyncEvents = null;
- sAsyncEvents = null;
- }
- }
-
- private static void dumpEvents(List<Event> events) {
- long offsetNanos = getOffsetNanos();
- for (Event e : events) {
- nativeRecordEarlyEvent(e.mName, e.mBeginTimeNanos + offsetNanos,
- e.mEndTimeNanos + offsetNanos, e.mThreadId,
- e.mEndThreadTimeMillis - e.mBeginThreadTimeMillis);
- }
- }
- private static void dumpAsyncEvents(List<AsyncEvent> events) {
- long offsetNanos = getOffsetNanos();
- for (AsyncEvent e : events) {
- if (e.mIsStart) {
- nativeRecordEarlyStartAsyncEvent(e.mName, e.mId, e.mTimestampNanos + offsetNanos);
- } else {
- nativeRecordEarlyFinishAsyncEvent(e.mName, e.mId, e.mTimestampNanos + offsetNanos);
- }
- }
- }
-
- private static long getOffsetNanos() {
- long nativeNowNanos = TimeUtils.nativeGetTimeTicksNowUs() * 1000;
- long javaNowNanos = Event.elapsedRealtimeNanos();
- return nativeNowNanos - javaNowNanos;
- }
-
- /**
- * Returns a key which consists of |name| and the ID of the current thread.
- * The key is used with pending events making them thread-specific, thus avoiding
- * an exception when similarly named events are started from multiple threads.
- */
- @VisibleForTesting
- static String makeEventKeyForCurrentThread(String name) {
- return name + "@" + Process.myTid();
- }
-
- private static native void nativeRecordEarlyEvent(String name, long beginTimNanos,
- long endTimeNanos, int threadId, long threadDurationMillis);
- private static native void nativeRecordEarlyStartAsyncEvent(
- String name, long id, long timestamp);
- private static native void nativeRecordEarlyFinishAsyncEvent(
- String name, long id, long timestamp);
-}
diff --git a/base/android/java/src/org/chromium/base/EventLog.java b/base/android/java/src/org/chromium/base/EventLog.java
deleted file mode 100644
index f889175b7a..0000000000
--- a/base/android/java/src/org/chromium/base/EventLog.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * A simple interface to Android's EventLog to be used by native code.
- */
-@JNINamespace("base::android")
-public class EventLog {
-
- @CalledByNative
- public static void writeEvent(int tag, int value) {
- android.util.EventLog.writeEvent(tag, value);
- }
-}
diff --git a/base/android/java/src/org/chromium/base/FieldTrialList.java b/base/android/java/src/org/chromium/base/FieldTrialList.java
deleted file mode 100644
index c3468a4af0..0000000000
--- a/base/android/java/src/org/chromium/base/FieldTrialList.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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;
-
-import org.chromium.base.annotations.MainDex;
-
-/**
- * Helper to get field trial information.
- */
-@MainDex
-public class FieldTrialList {
-
- private FieldTrialList() {}
-
- /**
- * @param trialName The name of the trial to get the group for.
- * @return The group name chosen for the named trial, or the empty string if the trial does
- * not exist.
- */
- public static String findFullName(String trialName) {
- return nativeFindFullName(trialName);
- }
-
- /**
- * @param trialName The name of the trial to get the group for.
- * @return Whether the trial exists or not.
- */
- public static boolean trialExists(String trialName) {
- return nativeTrialExists(trialName);
- }
-
- /**
- * @param trialName The name of the trial with the parameter.
- * @param parameterKey The key of the parameter.
- * @return The value of the parameter or an empty string if not found.
- */
- public static String getVariationParameter(String trialName, String parameterKey) {
- return nativeGetVariationParameter(trialName, parameterKey);
- }
-
- private static native String nativeFindFullName(String trialName);
- private static native boolean nativeTrialExists(String trialName);
- private static native String nativeGetVariationParameter(String trialName, String parameterKey);
-}
diff --git a/base/android/java/src/org/chromium/base/FileUtils.java b/base/android/java/src/org/chromium/base/FileUtils.java
deleted file mode 100644
index e44cd928ae..0000000000
--- a/base/android/java/src/org/chromium/base/FileUtils.java
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2015 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;
-
-import android.content.Context;
-import android.net.Uri;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Helper methods for dealing with Files.
- */
-public class FileUtils {
- private static final String TAG = "FileUtils";
-
- /**
- * Delete the given File and (if it's a directory) everything within it.
- */
- public static void recursivelyDeleteFile(File currentFile) {
- ThreadUtils.assertOnBackgroundThread();
- if (currentFile.isDirectory()) {
- File[] files = currentFile.listFiles();
- if (files != null) {
- for (File file : files) {
- recursivelyDeleteFile(file);
- }
- }
- }
-
- if (!currentFile.delete()) Log.e(TAG, "Failed to delete: " + currentFile);
- }
-
- /**
- * Delete the given files or directories by calling {@link #recursivelyDeleteFile(File)}.
- * @param files The files to delete.
- */
- public static void batchDeleteFiles(List<File> files) {
- ThreadUtils.assertOnBackgroundThread();
-
- for (File file : files) {
- if (file.exists()) recursivelyDeleteFile(file);
- }
- }
-
- /**
- * Extracts an asset from the app's APK to a file.
- * @param context
- * @param assetName Name of the asset to extract.
- * @param dest File to extract the asset to.
- * @return true on success.
- */
- public static boolean extractAsset(Context context, String assetName, File dest) {
- InputStream inputStream = null;
- OutputStream outputStream = null;
- try {
- inputStream = context.getAssets().open(assetName);
- outputStream = new BufferedOutputStream(new FileOutputStream(dest));
- byte[] buffer = new byte[8192];
- int c;
- while ((c = inputStream.read(buffer)) != -1) {
- outputStream.write(buffer, 0, c);
- }
- inputStream.close();
- outputStream.close();
- return true;
- } catch (IOException e) {
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException ex) {
- }
- }
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException ex) {
- }
- }
- }
- return false;
- }
-
- /**
- * Atomically copies the data from an input stream into an output file.
- * @param is Input file stream to read data from.
- * @param outFile Output file path.
- * @param buffer Caller-provided buffer. Provided to avoid allocating the same
- * buffer on each call when copying several files in sequence.
- * @throws IOException in case of I/O error.
- */
- public static void copyFileStreamAtomicWithBuffer(InputStream is, File outFile, byte[] buffer)
- throws IOException {
- File tmpOutputFile = new File(outFile.getPath() + ".tmp");
- try (OutputStream os = new FileOutputStream(tmpOutputFile)) {
- Log.i(TAG, "Writing to %s", outFile);
-
- int count = 0;
- while ((count = is.read(buffer, 0, buffer.length)) != -1) {
- os.write(buffer, 0, count);
- }
- }
- if (!tmpOutputFile.renameTo(outFile)) {
- throw new IOException();
- }
- }
-
- /**
- * Returns a URI that points at the file.
- * @param file File to get a URI for.
- * @return URI that points at that file, either as a content:// URI or a file:// URI.
- */
- public static Uri getUriForFile(File file) {
- // TODO(crbug/709584): Uncomment this when http://crbug.com/709584 has been fixed.
- // assert !ThreadUtils.runningOnUiThread();
- Uri uri = null;
-
- try {
- // Try to obtain a content:// URI, which is preferred to a file:// URI so that
- // receiving apps don't attempt to determine the file's mime type (which often fails).
- uri = ContentUriUtils.getContentUriFromFile(file);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Could not create content uri: " + e);
- }
-
- if (uri == null) uri = Uri.fromFile(file);
-
- return uri;
- }
-
- /**
- * Returns the file extension, or an empty string if none.
- * @param file Name of the file, with or without the full path.
- * @return empty string if no extension, extension otherwise.
- */
- public static String getExtension(String file) {
- int index = file.lastIndexOf('.');
- if (index == -1) return "";
- return file.substring(index + 1).toLowerCase(Locale.US);
- }
-}
diff --git a/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java b/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java
deleted file mode 100644
index cbaf7f76a1..0000000000
--- a/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 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;
-
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * This class provides an interface to the native class for writing
- * important data files without risking data loss.
- */
-@JNINamespace("base::android")
-public class ImportantFileWriterAndroid {
-
- /**
- * Write a binary file atomically.
- *
- * This either writes all the data or leaves the file unchanged.
- *
- * @param fileName The complete path of the file to be written
- * @param data The data to be written to the file
- * @return true if the data was written to the file, false if not.
- */
- public static boolean writeFileAtomically(String fileName, byte[] data) {
- return nativeWriteFileAtomically(fileName, data);
- }
-
- private static native boolean nativeWriteFileAtomically(
- String fileName, byte[] data);
-}
diff --git a/base/android/java/src/org/chromium/base/JNIUtils.java b/base/android/java/src/org/chromium/base/JNIUtils.java
deleted file mode 100644
index 3fcec91316..0000000000
--- a/base/android/java/src/org/chromium/base/JNIUtils.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.MainDex;
-
-/**
- * This class provides JNI-related methods to the native library.
- */
-@MainDex
-public class JNIUtils {
- private static Boolean sSelectiveJniRegistrationEnabled;
-
- /**
- * This returns a ClassLoader that is capable of loading Chromium Java code. Such a ClassLoader
- * is needed for the few cases where the JNI mechanism is unable to automatically determine the
- * appropriate ClassLoader instance.
- */
- @CalledByNative
- public static Object getClassLoader() {
- return JNIUtils.class.getClassLoader();
- }
-
- /**
- * @return whether or not the current process supports selective JNI registration.
- */
- @CalledByNative
- public static boolean isSelectiveJniRegistrationEnabled() {
- if (sSelectiveJniRegistrationEnabled == null) {
- sSelectiveJniRegistrationEnabled = false;
- }
- return sSelectiveJniRegistrationEnabled;
- }
-
- /**
- * Allow this process to selectively perform JNI registration. This must be called before
- * loading native libraries or it will have no effect.
- */
- public static void enableSelectiveJniRegistration() {
- assert sSelectiveJniRegistrationEnabled == null;
- sSelectiveJniRegistrationEnabled = true;
- }
-}
diff --git a/base/android/java/src/org/chromium/base/JavaHandlerThread.java b/base/android/java/src/org/chromium/base/JavaHandlerThread.java
deleted file mode 100644
index 9a1c924398..0000000000
--- a/base/android/java/src/org/chromium/base/JavaHandlerThread.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2013 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;
-
-import android.os.Build;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.MainDex;
-
-import java.lang.Thread.UncaughtExceptionHandler;
-
-/**
- * Thread in Java with an Android Handler. This class is not thread safe.
- */
-@JNINamespace("base::android")
-@MainDex
-public class JavaHandlerThread {
- private final HandlerThread mThread;
-
- private Throwable mUnhandledException;
-
- /**
- * Construct a java-only instance. Can be connected with native side later.
- * Useful for cases where a java thread is needed before native library is loaded.
- */
- public JavaHandlerThread(String name, int priority) {
- mThread = new HandlerThread(name, priority);
- }
-
- @CalledByNative
- private static JavaHandlerThread create(String name, int priority) {
- return new JavaHandlerThread(name, priority);
- }
-
- public Looper getLooper() {
- assert hasStarted();
- return mThread.getLooper();
- }
-
- public void maybeStart() {
- if (hasStarted()) return;
- mThread.start();
- }
-
- @CalledByNative
- private void startAndInitialize(final long nativeThread, final long nativeEvent) {
- maybeStart();
- new Handler(mThread.getLooper()).post(new Runnable() {
- @Override
- public void run() {
- nativeInitializeThread(nativeThread, nativeEvent);
- }
- });
- }
-
- @CalledByNative
- private void quitThreadSafely(final long nativeThread) {
- // Allow pending java tasks to run, but don't run any delayed or newly queued up tasks.
- new Handler(mThread.getLooper()).post(new Runnable() {
- @Override
- public void run() {
- mThread.quit();
- nativeOnLooperStopped(nativeThread);
- }
- });
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
- // When we can, signal that new tasks queued up won't be run.
- mThread.getLooper().quitSafely();
- }
- }
-
- @CalledByNative
- private void joinThread() {
- boolean joined = false;
- while (!joined) {
- try {
- mThread.join();
- joined = true;
- } catch (InterruptedException e) {
- }
- }
- }
-
- private boolean hasStarted() {
- return mThread.getState() != Thread.State.NEW;
- }
-
- @CalledByNative
- private boolean isAlive() {
- return mThread.isAlive();
- }
-
- // This should *only* be used for tests. In production we always need to call the original
- // uncaught exception handler (the framework's) after any uncaught exception handling we do, as
- // it generates crash dumps and kills the process.
- @CalledByNative
- private void listenForUncaughtExceptionsForTesting() {
- mThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- mUnhandledException = e;
- }
- });
- }
-
- @CalledByNative
- private Throwable getUncaughtExceptionIfAny() {
- return mUnhandledException;
- }
-
- private native void nativeInitializeThread(long nativeJavaHandlerThread, long nativeEvent);
- private native void nativeOnLooperStopped(long nativeJavaHandlerThread);
-}
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java
deleted file mode 100644
index 05d39029a5..0000000000
--- a/base/android/java/src/org/chromium/base/LocaleUtils.java
+++ /dev/null
@@ -1,207 +0,0 @@
-// 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;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.os.LocaleList;
-import android.text.TextUtils;
-
-import org.chromium.base.annotations.CalledByNative;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-/**
- * This class provides the locale related methods.
- */
-public class LocaleUtils {
- /**
- * Guards this class from being instantiated.
- */
- private LocaleUtils() {
- }
-
- /**
- * Java keeps deprecated language codes for Hebrew, Yiddish and Indonesian but Chromium uses
- * updated ones. Similarly, Android uses "tl" while Chromium uses "fil" for Tagalog/Filipino.
- * So apply a mapping here.
- * See http://developer.android.com/reference/java/util/Locale.html
- * @return a updated language code for Chromium with given language string.
- */
- public static String getUpdatedLanguageForChromium(String language) {
- // IMPORTANT: Keep in sync with the mapping found in:
- // build/android/gyp/util/resource_utils.py
- switch (language) {
- case "iw":
- return "he"; // Hebrew
- case "ji":
- return "yi"; // Yiddish
- case "in":
- return "id"; // Indonesian
- case "tl":
- return "fil"; // Filipino
- default:
- return language;
- }
- }
-
- /**
- * @return a locale with updated language codes for Chromium, with translated modern language
- * codes used by Chromium.
- */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @VisibleForTesting
- public static Locale getUpdatedLocaleForChromium(Locale locale) {
- String language = locale.getLanguage();
- String languageForChrome = getUpdatedLanguageForChromium(language);
- if (languageForChrome.equals(language)) {
- return locale;
- }
- return new Locale.Builder().setLocale(locale).setLanguage(languageForChrome).build();
- }
-
- /**
- * Android uses "tl" while Chromium uses "fil" for Tagalog/Filipino.
- * So apply a mapping here.
- * See http://developer.android.com/reference/java/util/Locale.html
- * @return a updated language code for Android with given language string.
- */
- public static String getUpdatedLanguageForAndroid(String language) {
- // IMPORTANT: Keep in sync with the mapping found in:
- // build/android/gyp/util/resource_utils.py
- switch (language) {
- case "und":
- return ""; // Undefined
- case "fil":
- return "tl"; // Filipino
- default:
- return language;
- }
- }
-
- /**
- * @return a locale with updated language codes for Android, from translated modern language
- * codes used by Chromium.
- */
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @VisibleForTesting
- public static Locale getUpdatedLocaleForAndroid(Locale locale) {
- String language = locale.getLanguage();
- String languageForAndroid = getUpdatedLanguageForAndroid(language);
- if (languageForAndroid.equals(language)) {
- return locale;
- }
- return new Locale.Builder().setLocale(locale).setLanguage(languageForAndroid).build();
- }
-
- /**
- * This function creates a Locale object from xx-XX style string where xx is language code
- * and XX is a country code. This works for API level lower than 21.
- * @return the locale that best represents the language tag.
- */
- public static Locale forLanguageTagCompat(String languageTag) {
- String[] tag = languageTag.split("-");
- if (tag.length == 0) {
- return new Locale("");
- }
- String language = getUpdatedLanguageForAndroid(tag[0]);
- if ((language.length() != 2 && language.length() != 3)) {
- return new Locale("");
- }
- if (tag.length == 1) {
- return new Locale(language);
- }
- String country = tag[1];
- if (country.length() != 2 && country.length() != 3) {
- return new Locale(language);
- }
- return new Locale(language, country);
- }
-
- /**
- * This function creates a Locale object from xx-XX style string where xx is language code
- * and XX is a country code.
- * @return the locale that best represents the language tag.
- */
- public static Locale forLanguageTag(String languageTag) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- Locale locale = Locale.forLanguageTag(languageTag);
- return getUpdatedLocaleForAndroid(locale);
- }
- return forLanguageTagCompat(languageTag);
- }
-
- /**
- * Converts Locale object to the BCP 47 compliant string format.
- * This works for API level lower than 24.
- *
- * Note that for Android M or before, we cannot use Locale.getLanguage() and
- * Locale.toLanguageTag() for this purpose. Since Locale.getLanguage() returns deprecated
- * language code even if the Locale object is constructed with updated language code. As for
- * Locale.toLanguageTag(), it does a special conversion from deprecated language code to updated
- * one, but it is only usable for Android N or after.
- * @return a well-formed IETF BCP 47 language tag with language and country code that
- * represents this locale.
- */
- public static String toLanguageTag(Locale locale) {
- String language = getUpdatedLanguageForChromium(locale.getLanguage());
- String country = locale.getCountry();
- if (language.equals("no") && country.equals("NO") && locale.getVariant().equals("NY")) {
- return "nn-NO";
- }
- return country.isEmpty() ? language : language + "-" + country;
- }
-
- /**
- * Converts LocaleList object to the comma separated BCP 47 compliant string format.
- *
- * @return a well-formed IETF BCP 47 language tag with language and country code that
- * represents this locale list.
- */
- @TargetApi(Build.VERSION_CODES.N)
- public static String toLanguageTags(LocaleList localeList) {
- ArrayList<String> newLocaleList = new ArrayList<>();
- for (int i = 0; i < localeList.size(); i++) {
- Locale locale = getUpdatedLocaleForChromium(localeList.get(i));
- newLocaleList.add(toLanguageTag(locale));
- }
- return TextUtils.join(",", newLocaleList);
- }
-
- /**
- * @return a comma separated language tags string that represents a default locale.
- * Each language tag is well-formed IETF BCP 47 language tag with language and country
- * code.
- */
- @CalledByNative
- public static String getDefaultLocaleString() {
- return toLanguageTag(Locale.getDefault());
- }
-
- /**
- * @return a comma separated language tags string that represents a default locale or locales.
- * Each language tag is well-formed IETF BCP 47 language tag with language and country
- * code.
- */
- public static String getDefaultLocaleListString() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- return toLanguageTags(LocaleList.getDefault());
- }
- return getDefaultLocaleString();
- }
-
- /**
- * @return The default country code set during install.
- */
- @CalledByNative
- private static String getDefaultCountryCode() {
- CommandLine commandLine = CommandLine.getInstance();
- return commandLine.hasSwitch(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL)
- ? commandLine.getSwitchValue(BaseSwitches.DEFAULT_COUNTRY_CODE_AT_INSTALL)
- : Locale.getDefault().getCountry();
- }
-
-}
diff --git a/base/android/java/src/org/chromium/base/MemoryPressureListener.java b/base/android/java/src/org/chromium/base/MemoryPressureListener.java
deleted file mode 100644
index 6c80970f48..0000000000
--- a/base/android/java/src/org/chromium/base/MemoryPressureListener.java
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2013 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;
-
-import android.app.Activity;
-import android.content.ComponentCallbacks2;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.memory.MemoryPressureCallback;
-
-/**
- * This class is Java equivalent of base::MemoryPressureListener: it distributes pressure
- * signals to callbacks.
- *
- * The class also serves as an entry point to the native side - once native code is ready,
- * it adds native callback.
- *
- * notifyMemoryPressure() is called exclusively by MemoryPressureMonitor, which
- * monitors and throttles pressure signals.
- *
- * NOTE: this class should only be used on UiThread as defined by ThreadUtils (which is
- * Android main thread for Chrome, but can be some other thread for WebView).
- */
-@MainDex
-public class MemoryPressureListener {
- /**
- * Sending an intent with this action to Chrome will cause it to issue a call to onLowMemory
- * thus simulating a low memory situations.
- */
- private static final String ACTION_LOW_MEMORY = "org.chromium.base.ACTION_LOW_MEMORY";
-
- /**
- * Sending an intent with this action to Chrome will cause it to issue a call to onTrimMemory
- * thus simulating a low memory situations.
- */
- private static final String ACTION_TRIM_MEMORY = "org.chromium.base.ACTION_TRIM_MEMORY";
-
- /**
- * Sending an intent with this action to Chrome will cause it to issue a call to onTrimMemory
- * with notification level TRIM_MEMORY_RUNNING_CRITICAL thus simulating a low memory situation
- */
- private static final String ACTION_TRIM_MEMORY_RUNNING_CRITICAL =
- "org.chromium.base.ACTION_TRIM_MEMORY_RUNNING_CRITICAL";
-
- /**
- * Sending an intent with this action to Chrome will cause it to issue a call to onTrimMemory
- * with notification level TRIM_MEMORY_MODERATE thus simulating a low memory situation
- */
- private static final String ACTION_TRIM_MEMORY_MODERATE =
- "org.chromium.base.ACTION_TRIM_MEMORY_MODERATE";
-
- private static final ObserverList<MemoryPressureCallback> sCallbacks = new ObserverList<>();
-
- /**
- * Called by the native side to add native callback.
- */
- @CalledByNative
- private static void addNativeCallback() {
- addCallback(MemoryPressureListener::nativeOnMemoryPressure);
- }
-
- /**
- * Adds a memory pressure callback.
- * Callback is only added once, regardless of the number of addCallback() calls.
- * This method should be called only on ThreadUtils.UiThread.
- */
- public static void addCallback(MemoryPressureCallback callback) {
- sCallbacks.addObserver(callback);
- }
-
- /**
- * Removes previously added memory pressure callback.
- * This method should be called only on ThreadUtils.UiThread.
- */
- public static void removeCallback(MemoryPressureCallback callback) {
- sCallbacks.removeObserver(callback);
- }
-
- /**
- * Distributes |pressure| to all callbacks.
- * This method should be called only on ThreadUtils.UiThread.
- */
- public static void notifyMemoryPressure(@MemoryPressureLevel int pressure) {
- for (MemoryPressureCallback callback : sCallbacks) {
- callback.onPressure(pressure);
- }
- }
-
- /**
- * Used by applications to simulate a memory pressure signal. By throwing certain intent
- * actions.
- */
- public static boolean handleDebugIntent(Activity activity, String action) {
- if (ACTION_LOW_MEMORY.equals(action)) {
- simulateLowMemoryPressureSignal(activity);
- } else if (ACTION_TRIM_MEMORY.equals(action)) {
- simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
- } else if (ACTION_TRIM_MEMORY_RUNNING_CRITICAL.equals(action)) {
- simulateTrimMemoryPressureSignal(activity,
- ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL);
- } else if (ACTION_TRIM_MEMORY_MODERATE.equals(action)) {
- simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_MODERATE);
- } else {
- return false;
- }
-
- return true;
- }
-
- private static void simulateLowMemoryPressureSignal(Activity activity) {
- // The Application and the Activity each have a list of callbacks they notify when this
- // method is called. Notifying these will simulate the event at the App/Activity level
- // as well as trigger the listener bound from native in this process.
- activity.getApplication().onLowMemory();
- activity.onLowMemory();
- }
-
- private static void simulateTrimMemoryPressureSignal(Activity activity, int level) {
- // The Application and the Activity each have a list of callbacks they notify when this
- // method is called. Notifying these will simulate the event at the App/Activity level
- // as well as trigger the listener bound from native in this process.
- activity.getApplication().onTrimMemory(level);
- activity.onTrimMemory(level);
- }
-
- private static native void nativeOnMemoryPressure(@MemoryPressureLevel int pressure);
-}
diff --git a/base/android/java/src/org/chromium/base/NonThreadSafe.java b/base/android/java/src/org/chromium/base/NonThreadSafe.java
deleted file mode 100644
index 53f38d2c81..0000000000
--- a/base/android/java/src/org/chromium/base/NonThreadSafe.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2015 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;
-
-/**
- * NonThreadSafe is a helper class used to help verify that methods of a
- * class are called from the same thread.
- */
-public class NonThreadSafe {
- private Long mThreadId;
-
- public NonThreadSafe() {
- ensureThreadIdAssigned();
- }
-
- /**
- * Changes the thread that is checked for in CalledOnValidThread. This may
- * be useful when an object may be created on one thread and then used
- * exclusively on another thread.
- */
- @VisibleForTesting
- public synchronized void detachFromThread() {
- mThreadId = null;
- }
-
- /**
- * Checks if the method is called on the valid thread.
- * Assigns the current thread if no thread was assigned.
- */
- @SuppressWarnings("NoSynchronizedMethodCheck")
- public synchronized boolean calledOnValidThread() {
- ensureThreadIdAssigned();
- return mThreadId.equals(Thread.currentThread().getId());
- }
-
- private void ensureThreadIdAssigned() {
- if (mThreadId == null) mThreadId = Thread.currentThread().getId();
- }
-}
diff --git a/base/android/java/src/org/chromium/base/ObserverList.java b/base/android/java/src/org/chromium/base/ObserverList.java
deleted file mode 100644
index 59276c6ea8..0000000000
--- a/base/android/java/src/org/chromium/base/ObserverList.java
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2013 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;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import javax.annotation.concurrent.NotThreadSafe;
-
-/**
- * A container for a list of observers.
- * <p/>
- * This container can be modified during iteration without invalidating the iterator.
- * So, it safely handles the case of an observer removing itself or other observers from the list
- * while observers are being notified.
- * <p/>
- * The implementation (and the interface) is heavily influenced by the C++ ObserverList.
- * Notable differences:
- * - The iterator implements NOTIFY_EXISTING_ONLY.
- * - The range-based for loop is left to the clients to implement in terms of iterator().
- * <p/>
- * This class is not threadsafe. Observers MUST be added, removed and will be notified on the same
- * thread this is created.
- *
- * @param <E> The type of observers that this list should hold.
- */
-@NotThreadSafe
-public class ObserverList<E> implements Iterable<E> {
- /**
- * Extended iterator interface that provides rewind functionality.
- */
- public interface RewindableIterator<E> extends Iterator<E> {
- /**
- * Rewind the iterator back to the beginning.
- *
- * If we need to iterate multiple times, we can avoid iterator object reallocation by using
- * this method.
- */
- public void rewind();
- }
-
- public final List<E> mObservers = new ArrayList<E>();
- private int mIterationDepth;
- private int mCount;
- private boolean mNeedsCompact;
-
- public ObserverList() {}
-
- /**
- * Add an observer to the list.
- * <p/>
- * An observer should not be added to the same list more than once. If an iteration is already
- * in progress, this observer will be not be visible during that iteration.
- *
- * @return true if the observer list changed as a result of the call.
- */
- public boolean addObserver(E obs) {
- // Avoid adding null elements to the list as they may be removed on a compaction.
- if (obs == null || mObservers.contains(obs)) {
- return false;
- }
-
- // Structurally modifying the underlying list here. This means we
- // cannot use the underlying list's iterator to iterate over the list.
- boolean result = mObservers.add(obs);
- assert result;
-
- ++mCount;
- return true;
- }
-
- /**
- * Remove an observer from the list if it is in the list.
- *
- * @return true if an element was removed as a result of this call.
- */
- public boolean removeObserver(E obs) {
- if (obs == null) {
- return false;
- }
-
- int index = mObservers.indexOf(obs);
- if (index == -1) {
- return false;
- }
-
- if (mIterationDepth == 0) {
- // No one is iterating over the list.
- mObservers.remove(index);
- } else {
- mNeedsCompact = true;
- mObservers.set(index, null);
- }
- --mCount;
- assert mCount >= 0;
-
- return true;
- }
-
- public boolean hasObserver(E obs) {
- return mObservers.contains(obs);
- }
-
- public void clear() {
- mCount = 0;
-
- if (mIterationDepth == 0) {
- mObservers.clear();
- return;
- }
-
- int size = mObservers.size();
- mNeedsCompact |= size != 0;
- for (int i = 0; i < size; i++) {
- mObservers.set(i, null);
- }
- }
-
- @Override
- public Iterator<E> iterator() {
- return new ObserverListIterator();
- }
-
- /**
- * It's the same as {@link ObserverList#iterator()} but the return type is
- * {@link RewindableIterator}. Use this iterator type if you need to use
- * {@link RewindableIterator#rewind()}.
- */
- public RewindableIterator<E> rewindableIterator() {
- return new ObserverListIterator();
- }
-
- /**
- * Returns the number of observers currently registered in the ObserverList.
- * This is equivalent to the number of non-empty spaces in |mObservers|.
- */
- public int size() {
- return mCount;
- }
-
- /**
- * Returns true if the ObserverList contains no observers.
- */
- public boolean isEmpty() {
- return mCount == 0;
- }
-
- /**
- * Compact the underlying list be removing null elements.
- * <p/>
- * Should only be called when mIterationDepth is zero.
- */
- private void compact() {
- assert mIterationDepth == 0;
- for (int i = mObservers.size() - 1; i >= 0; i--) {
- if (mObservers.get(i) == null) {
- mObservers.remove(i);
- }
- }
- }
-
- private void incrementIterationDepth() {
- mIterationDepth++;
- }
-
- private void decrementIterationDepthAndCompactIfNeeded() {
- mIterationDepth--;
- assert mIterationDepth >= 0;
- if (mIterationDepth > 0) return;
- if (!mNeedsCompact) return;
- mNeedsCompact = false;
- compact();
- }
-
- /**
- * Returns the size of the underlying storage of the ObserverList.
- * It will take into account the empty spaces inside |mObservers|.
- */
- private int capacity() {
- return mObservers.size();
- }
-
- private E getObserverAt(int index) {
- return mObservers.get(index);
- }
-
- private class ObserverListIterator implements RewindableIterator<E> {
- private int mListEndMarker;
- private int mIndex;
- private boolean mIsExhausted;
-
- private ObserverListIterator() {
- ObserverList.this.incrementIterationDepth();
- mListEndMarker = ObserverList.this.capacity();
- }
-
- @Override
- public void rewind() {
- compactListIfNeeded();
- ObserverList.this.incrementIterationDepth();
- mListEndMarker = ObserverList.this.capacity();
- mIsExhausted = false;
- mIndex = 0;
- }
-
- @Override
- public boolean hasNext() {
- int lookupIndex = mIndex;
- while (lookupIndex < mListEndMarker
- && ObserverList.this.getObserverAt(lookupIndex) == null) {
- lookupIndex++;
- }
- if (lookupIndex < mListEndMarker) return true;
-
- // We have reached the end of the list, allow for compaction.
- compactListIfNeeded();
- return false;
- }
-
- @Override
- public E next() {
- // Advance if the current element is null.
- while (mIndex < mListEndMarker && ObserverList.this.getObserverAt(mIndex) == null) {
- mIndex++;
- }
- if (mIndex < mListEndMarker) return ObserverList.this.getObserverAt(mIndex++);
-
- // We have reached the end of the list, allow for compaction.
- compactListIfNeeded();
- throw new NoSuchElementException();
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- private void compactListIfNeeded() {
- if (!mIsExhausted) {
- mIsExhausted = true;
- ObserverList.this.decrementIterationDepthAndCompactIfNeeded();
- }
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/PathService.java b/base/android/java/src/org/chromium/base/PathService.java
deleted file mode 100644
index 9807c2e82a..0000000000
--- a/base/android/java/src/org/chromium/base/PathService.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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;
-
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * This class provides java side access to the native PathService.
- */
-@JNINamespace("base::android")
-public abstract class PathService {
-
- // Must match the value of DIR_MODULE in base/base_paths.h!
- public static final int DIR_MODULE = 3;
-
- // Prevent instantiation.
- private PathService() {}
-
- public static void override(int what, String path) {
- nativeOverride(what, path);
- }
-
- private static native void nativeOverride(int what, String path);
-}
diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java
deleted file mode 100644
index e6fc8029b8..0000000000
--- a/base/android/java/src/org/chromium/base/PathUtils.java
+++ /dev/null
@@ -1,263 +0,0 @@
-// 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;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.os.Build;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.system.Os;
-import android.text.TextUtils;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.metrics.RecordHistogram;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * This class provides the path related methods for the native library.
- */
-@MainDex
-public abstract class PathUtils {
- private static final String TAG = "PathUtils";
- private static final String THUMBNAIL_DIRECTORY_NAME = "textures";
-
- private static final int DATA_DIRECTORY = 0;
- private static final int THUMBNAIL_DIRECTORY = 1;
- private static final int CACHE_DIRECTORY = 2;
- private static final int NUM_DIRECTORIES = 3;
- private static final AtomicBoolean sInitializationStarted = new AtomicBoolean();
- private static AsyncTask<Void, Void, String[]> sDirPathFetchTask;
-
- // If the AsyncTask started in setPrivateDataDirectorySuffix() fails to complete by the time we
- // need the values, we will need the suffix so that we can restart the task synchronously on
- // the UI thread.
- private static String sDataDirectorySuffix;
- private static String sCacheSubDirectory;
-
- // Prevent instantiation.
- private PathUtils() {}
-
- /**
- * Initialization-on-demand holder. This exists for thread-safe lazy initialization. It will
- * cause getOrComputeDirectoryPaths() to be called (safely) the first time DIRECTORY_PATHS is
- * accessed.
- *
- * <p>See https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom.
- */
- private static class Holder {
- private static final String[] DIRECTORY_PATHS = getOrComputeDirectoryPaths();
- }
-
- /**
- * Get the directory paths from sDirPathFetchTask if available, or compute it synchronously
- * on the UI thread otherwise. This should only be called as part of Holder's initialization
- * above to guarantee thread-safety as part of the initialization-on-demand holder idiom.
- */
- private static String[] getOrComputeDirectoryPaths() {
- try {
- // We need to call sDirPathFetchTask.cancel() here to prevent races. If it returns
- // true, that means that the task got canceled successfully (and thus, it did not
- // finish running its task). Otherwise, it failed to cancel, meaning that it was
- // already finished.
- if (sDirPathFetchTask.cancel(false)) {
- // Allow disk access here because we have no other choice.
- try (StrictModeContext unused = StrictModeContext.allowDiskWrites()) {
- // sDirPathFetchTask did not complete. We have to run the code it was supposed
- // to be responsible for synchronously on the UI thread.
- return PathUtils.setPrivateDataDirectorySuffixInternal();
- }
- } else {
- // sDirPathFetchTask succeeded, and the values we need should be ready to access
- // synchronously in its internal future.
- return sDirPathFetchTask.get();
- }
- } catch (InterruptedException e) {
- } catch (ExecutionException e) {
- }
-
- return null;
- }
-
- @SuppressLint("NewApi")
- private static void chmod(String path, int mode) {
- // Both Os.chmod and ErrnoException require SDK >= 21. But while Dalvik on < 21 tolerates
- // Os.chmod, it throws VerifyError for ErrnoException, so catch Exception instead.
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
- try {
- Os.chmod(path, mode);
- } catch (Exception e) {
- Log.e(TAG, "Failed to set permissions for path \"" + path + "\"");
- }
- }
-
- /**
- * Fetch the path of the directory where private data is to be stored by the application. This
- * is meant to be called in an AsyncTask in setPrivateDataDirectorySuffix(), but if we need the
- * result before the AsyncTask has had a chance to finish, then it's best to cancel the task
- * and run it on the UI thread instead, inside getOrComputeDirectoryPaths().
- *
- * @see Context#getDir(String, int)
- */
- private static String[] setPrivateDataDirectorySuffixInternal() {
- String[] paths = new String[NUM_DIRECTORIES];
- Context appContext = ContextUtils.getApplicationContext();
- paths[DATA_DIRECTORY] = appContext.getDir(
- sDataDirectorySuffix, Context.MODE_PRIVATE).getPath();
- // MODE_PRIVATE results in rwxrwx--x, but we want rwx------, as a defence-in-depth measure.
- chmod(paths[DATA_DIRECTORY], 0700);
- paths[THUMBNAIL_DIRECTORY] = appContext.getDir(
- THUMBNAIL_DIRECTORY_NAME, Context.MODE_PRIVATE).getPath();
- if (appContext.getCacheDir() != null) {
- if (sCacheSubDirectory == null) {
- paths[CACHE_DIRECTORY] = appContext.getCacheDir().getPath();
- } else {
- paths[CACHE_DIRECTORY] =
- new File(appContext.getCacheDir(), sCacheSubDirectory).getPath();
- }
- }
- return paths;
- }
-
- /**
- * Starts an asynchronous task to fetch the path of the directory where private data is to be
- * stored by the application.
- *
- * <p>This task can run long (or more likely be delayed in a large task queue), in which case we
- * want to cancel it and run on the UI thread instead. Unfortunately, this means keeping a bit
- * of extra static state - we need to store the suffix and the application context in case we
- * need to try to re-execute later.
- *
- * @param suffix The private data directory suffix.
- * @param cacheSubDir The subdirectory in the cache directory to use, if non-null.
- * @see Context#getDir(String, int)
- */
- public static void setPrivateDataDirectorySuffix(String suffix, String cacheSubDir) {
- // This method should only be called once, but many tests end up calling it multiple times,
- // so adding a guard here.
- if (!sInitializationStarted.getAndSet(true)) {
- assert ContextUtils.getApplicationContext() != null;
- sDataDirectorySuffix = suffix;
- sCacheSubDirectory = cacheSubDir;
- sDirPathFetchTask = new AsyncTask<Void, Void, String[]>() {
- @Override
- protected String[] doInBackground(Void... unused) {
- return PathUtils.setPrivateDataDirectorySuffixInternal();
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
- }
-
- public static void setPrivateDataDirectorySuffix(String suffix) {
- setPrivateDataDirectorySuffix(suffix, null);
- }
-
- /**
- * @param index The index of the cached directory path.
- * @return The directory path requested.
- */
- private static String getDirectoryPath(int index) {
- return Holder.DIRECTORY_PATHS[index];
- }
-
- /**
- * @return the private directory that is used to store application data.
- */
- @CalledByNative
- public static String getDataDirectory() {
- assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
- return getDirectoryPath(DATA_DIRECTORY);
- }
-
- /**
- * @return the cache directory.
- */
- @CalledByNative
- public static String getCacheDirectory() {
- assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
- return getDirectoryPath(CACHE_DIRECTORY);
- }
-
- @CalledByNative
- public static String getThumbnailCacheDirectory() {
- assert sDirPathFetchTask != null : "setDataDirectorySuffix must be called first.";
- return getDirectoryPath(THUMBNAIL_DIRECTORY);
- }
-
- /**
- * @return the public downloads directory.
- */
- @SuppressWarnings("unused")
- @CalledByNative
- private static String getDownloadsDirectory() {
- // Temporarily allowing disk access while fixing. TODO: http://crbug.com/508615
- try (StrictModeContext unused = StrictModeContext.allowDiskReads()) {
- long time = SystemClock.elapsedRealtime();
- String downloadsPath =
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
- .getPath();
- RecordHistogram.recordTimesHistogram("Android.StrictMode.DownloadsDir",
- SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS);
- return downloadsPath;
- }
- }
-
- /**
- * @return Download directories including the default storage directory on SD card, and a
- * private directory on external SD card.
- */
- @SuppressWarnings("unused")
- @CalledByNative
- public static String[] getAllPrivateDownloadsDirectories() {
- File[] files;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- try (StrictModeContext unused = StrictModeContext.allowDiskWrites()) {
- files = ContextUtils.getApplicationContext().getExternalFilesDirs(
- Environment.DIRECTORY_DOWNLOADS);
- }
- } else {
- files = new File[] {Environment.getExternalStorageDirectory()};
- }
-
- ArrayList<String> absolutePaths = new ArrayList<String>();
- for (int i = 0; i < files.length; ++i) {
- if (files[i] == null || TextUtils.isEmpty(files[i].getAbsolutePath())) continue;
- absolutePaths.add(files[i].getAbsolutePath());
- }
-
- return absolutePaths.toArray(new String[absolutePaths.size()]);
- }
-
- /**
- * @return the path to native libraries.
- */
- @SuppressWarnings("unused")
- @CalledByNative
- private static String getNativeLibraryDirectory() {
- ApplicationInfo ai = ContextUtils.getApplicationContext().getApplicationInfo();
- if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0
- || (ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- return ai.nativeLibraryDir;
- }
-
- return "/system/lib/";
- }
-
- /**
- * @return the external storage directory.
- */
- @SuppressWarnings("unused")
- @CalledByNative
- public static String getExternalStorageDirectory() {
- return Environment.getExternalStorageDirectory().getAbsolutePath();
- }
-}
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java
deleted file mode 100644
index ae36a75d00..0000000000
--- a/base/android/java/src/org/chromium/base/PowerMonitor.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// 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;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * Integrates native PowerMonitor with the java side.
- */
-@JNINamespace("base::android")
-public class PowerMonitor {
- private static PowerMonitor sInstance;
-
- private boolean mIsBatteryPower;
-
- public static void createForTests() {
- // Applications will create this once the JNI side has been fully wired up both sides. For
- // tests, we just need native -> java, that is, we don't need to notify java -> native on
- // creation.
- sInstance = new PowerMonitor();
- }
-
- /**
- * Create a PowerMonitor instance if none exists.
- */
- public static void create() {
- ThreadUtils.assertOnUiThread();
-
- if (sInstance != null) return;
-
- Context context = ContextUtils.getApplicationContext();
- sInstance = new PowerMonitor();
- IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
- Intent batteryStatusIntent = context.registerReceiver(null, ifilter);
- if (batteryStatusIntent != null) onBatteryChargingChanged(batteryStatusIntent);
-
- IntentFilter powerConnectedFilter = new IntentFilter();
- powerConnectedFilter.addAction(Intent.ACTION_POWER_CONNECTED);
- powerConnectedFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
- context.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- PowerMonitor.onBatteryChargingChanged(intent);
- }
- }, powerConnectedFilter);
- }
-
- private PowerMonitor() {
- }
-
- private static void onBatteryChargingChanged(Intent intent) {
- assert sInstance != null;
- int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
- // If we're not plugged, assume we're running on battery power.
- sInstance.mIsBatteryPower = chargePlug != BatteryManager.BATTERY_PLUGGED_USB
- && chargePlug != BatteryManager.BATTERY_PLUGGED_AC;
- nativeOnBatteryChargingChanged();
- }
-
- @CalledByNative
- private static boolean isBatteryPower() {
- // Creation of the PowerMonitor can be deferred based on the browser startup path. If the
- // battery power is requested prior to the browser triggering the creation, force it to be
- // created now.
- if (sInstance == null) create();
-
- return sInstance.mIsBatteryPower;
- }
-
- private static native void nativeOnBatteryChargingChanged();
-}
diff --git a/base/android/java/src/org/chromium/base/Promise.java b/base/android/java/src/org/chromium/base/Promise.java
deleted file mode 100644
index 4319148d9c..0000000000
--- a/base/android/java/src/org/chromium/base/Promise.java
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright 2016 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;
-
-import android.os.Handler;
-import android.support.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A Promise class to be used as a placeholder for a result that will be provided asynchronously.
- * It must only be accessed from a single thread.
- * @param <T> The type the Promise will be fulfilled with.
- */
-public class Promise<T> {
- // TODO(peconn): Implement rejection handlers that can recover from rejection.
-
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({UNFULFILLED, FULFILLED, REJECTED})
- private @interface PromiseState {}
-
- private static final int UNFULFILLED = 0;
- private static final int FULFILLED = 1;
- private static final int REJECTED = 2;
-
- @PromiseState
- private int mState = UNFULFILLED;
-
- private T mResult;
- private final List<Callback<T>> mFulfillCallbacks = new LinkedList<>();
-
- private Exception mRejectReason;
- private final List<Callback<Exception>> mRejectCallbacks = new LinkedList<>();
-
- private final Thread mThread = Thread.currentThread();
- private final Handler mHandler = new Handler();
-
- private boolean mThrowingRejectionHandler;
-
- /**
- * A function class for use when chaining Promises with {@link Promise#then(Function)}.
- * @param <A> The type of the function input.
- * @param <R> The type of the function output.
- */
- public interface Function<A, R> {
- R apply(A argument);
- }
-
- /**
- * A function class for use when chaining Promises with {@link Promise#then(AsyncFunction)}.
- * @param <A> The type of the function input.
- * @param <R> The type of the function output.
- */
- public interface AsyncFunction<A, R> {
- Promise<R> apply(A argument);
- }
-
- /**
- * An exception class for when a rejected Promise is not handled and cannot pass the rejection
- * to a subsequent Promise.
- */
- public static class UnhandledRejectionException extends RuntimeException {
- public UnhandledRejectionException(String message, Throwable cause) {
- super(message, cause);
- }
- }
-
- /**
- * Convenience method that calls {@link #then(Callback, Callback)} providing a rejection
- * {@link Callback} that throws a {@link UnhandledRejectionException}. Only use this on
- * Promises that do not have rejection handlers or dependant Promises.
- */
- public void then(Callback<T> onFulfill) {
- checkThread();
-
- // Allow multiple single argument then(Callback)'s, but don't bother adding duplicate
- // throwing rejection handlers.
- if (mThrowingRejectionHandler) {
- thenInner(onFulfill);
- return;
- }
-
- assert mRejectCallbacks.size() == 0 : "Do not call the single argument "
- + "Promise.then(Callback) on a Promise that already has a rejection handler.";
-
- Callback<Exception> onReject = reason -> {
- throw new UnhandledRejectionException(
- "Promise was rejected without a rejection handler.", reason);
- };
-
- then(onFulfill, onReject);
- mThrowingRejectionHandler = true;
- }
-
- /**
- * Queues {@link Callback}s to be run when the Promise is either fulfilled or rejected. If the
- * Promise is already fulfilled or rejected, the appropriate callback will be run on the next
- * iteration of the message loop.
- *
- * @param onFulfill The Callback to be called on fulfillment.
- * @param onReject The Callback to be called on rejection. The argument to onReject will
- * may be null if the Promise was rejected manually.
- */
- public void then(Callback<T> onFulfill, Callback<Exception> onReject) {
- checkThread();
- thenInner(onFulfill);
- exceptInner(onReject);
- }
-
- /**
- * Adds a rejection handler to the Promise. This handler will be called if this Promise or any
- * Promises this Promise depends on is rejected or fails. The {@link Callback} will be given
- * the exception that caused the rejection, or null if the rejection was manual (caused by a
- * call to {@link #reject()}.
- */
- public void except(Callback<Exception> onReject) {
- checkThread();
- exceptInner(onReject);
- }
-
- private void thenInner(Callback<T> onFulfill) {
- if (mState == FULFILLED) {
- postCallbackToLooper(onFulfill, mResult);
- } else if (mState == UNFULFILLED) {
- mFulfillCallbacks.add(onFulfill);
- }
- }
-
- private void exceptInner(Callback<Exception> onReject) {
- assert !mThrowingRejectionHandler : "Do not add an exception handler to a Promise you have "
- + "called the single argument Promise.then(Callback) on.";
-
- if (mState == REJECTED) {
- postCallbackToLooper(onReject, mRejectReason);
- } else if (mState == UNFULFILLED) {
- mRejectCallbacks.add(onReject);
- }
- }
-
- /**
- * Queues a {@link Promise.Function} to be run when the Promise is fulfilled. When this Promise
- * is fulfilled, the function will be run and its result will be place in the returned Promise.
- */
- public <R> Promise<R> then(final Function<T, R> function) {
- checkThread();
-
- // Create a new Promise to store the result of the function.
- final Promise<R> promise = new Promise<>();
-
- // Once this Promise is fulfilled:
- // - Apply the given function to the result.
- // - Fulfill the new Promise.
- thenInner(result -> {
- try {
- promise.fulfill(function.apply(result));
- } catch (Exception e) {
- // If function application fails, reject the next Promise.
- promise.reject(e);
- }
- });
-
- // If this Promise is rejected, reject the next Promise.
- exceptInner(promise::reject);
-
- return promise;
- }
-
- /**
- * Queues a {@link Promise.AsyncFunction} to be run when the Promise is fulfilled. When this
- * Promise is fulfilled, the AsyncFunction will be run. When the result of the AsyncFunction is
- * available, it will be placed in the returned Promise.
- */
- public <R> Promise<R> then(final AsyncFunction<T, R> function) {
- checkThread();
-
- // Create a new Promise to be returned.
- final Promise<R> promise = new Promise<>();
-
- // Once this Promise is fulfilled:
- // - Apply the given function to the result (giving us an inner Promise).
- // - On fulfillment of this inner Promise, fulfill our return Promise.
- thenInner(result -> {
- try {
- // When the inner Promise is fulfilled, fulfill the return Promise.
- // Alternatively, if the inner Promise is rejected, reject the return Promise.
- function.apply(result).then(promise::fulfill, promise::reject);
- } catch (Exception e) {
- // If creating the inner Promise failed, reject the next Promise.
- promise.reject(e);
- }
- });
-
- // If this Promise is rejected, reject the next Promise.
- exceptInner(promise::reject);
-
- return promise;
- }
-
- /**
- * Fulfills the Promise with the result and passes it to any {@link Callback}s previously queued
- * on the next iteration of the message loop.
- */
- public void fulfill(final T result) {
- checkThread();
- assert mState == UNFULFILLED;
-
- mState = FULFILLED;
- mResult = result;
-
- for (final Callback<T> callback : mFulfillCallbacks) {
- postCallbackToLooper(callback, result);
- }
-
- mFulfillCallbacks.clear();
- }
-
- /**
- * Rejects the Promise, rejecting all those Promises that rely on it.
- *
- * This may throw an exception if a dependent Promise fails to handle the rejection, so it is
- * important to make it explicit when a Promise may be rejected, so that users of that Promise
- * know to provide rejection handling.
- */
- public void reject(final Exception reason) {
- checkThread();
- assert mState == UNFULFILLED;
-
- mState = REJECTED;
- mRejectReason = reason;
-
- for (final Callback<Exception> callback : mRejectCallbacks) {
- postCallbackToLooper(callback, reason);
- }
- mRejectCallbacks.clear();
- }
-
- /**
- * Rejects a Promise, see {@link #reject(Exception)}.
- */
- public void reject() {
- reject(null);
- }
-
- /**
- * Returns whether the promise is fulfilled.
- */
- public boolean isFulfilled() {
- checkThread();
- return mState == FULFILLED;
- }
-
- /**
- * Returns whether the promise is rejected.
- */
- public boolean isRejected() {
- checkThread();
- return mState == REJECTED;
- }
-
- /**
- * Must be called after the promise has been fulfilled.
- *
- * @return The promised result.
- */
- public T getResult() {
- assert isFulfilled();
- return mResult;
- }
-
- /**
- * Convenience method to return a Promise fulfilled with the given result.
- */
- public static <T> Promise<T> fulfilled(T result) {
- Promise<T> promise = new Promise<>();
- promise.fulfill(result);
- return promise;
- }
-
- private void checkThread() {
- assert mThread == Thread.currentThread() : "Promise must only be used on a single Thread.";
- }
-
- // We use a different template parameter here so this can be used for both T and Throwables.
- private <S> void postCallbackToLooper(final Callback<S> callback, final S result) {
- // Post the callbacks to the Thread looper so we don't get a long chain of callbacks
- // holding up the thread.
- mHandler.post(() -> callback.onResult(result));
- }
-}
diff --git a/base/android/java/src/org/chromium/base/SecureRandomInitializer.java b/base/android/java/src/org/chromium/base/SecureRandomInitializer.java
deleted file mode 100644
index bfd7b4943a..0000000000
--- a/base/android/java/src/org/chromium/base/SecureRandomInitializer.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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;
-
-import android.annotation.SuppressLint;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.SecureRandom;
-
-/**
- * This class contains code to initialize a SecureRandom generator securely on Android platforms
- * <= 4.3. See
- * {@link http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html}.
- */
-// TODO(crbug.com/635567): Fix this properly.
-@SuppressLint("SecureRandom")
-public class SecureRandomInitializer {
- private static final int NUM_RANDOM_BYTES = 16;
-
- /**
- * Safely initializes the random number generator, by seeding it with data from /dev/urandom.
- */
- public static void initialize(SecureRandom generator) throws IOException {
- try (FileInputStream fis = new FileInputStream("/dev/urandom")) {
- byte[] seedBytes = new byte[NUM_RANDOM_BYTES];
- if (fis.read(seedBytes) != seedBytes.length) {
- throw new IOException("Failed to get enough random data.");
- }
- generator.setSeed(seedBytes);
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/StreamUtil.java b/base/android/java/src/org/chromium/base/StreamUtil.java
deleted file mode 100644
index f8cbfeeb9e..0000000000
--- a/base/android/java/src/org/chromium/base/StreamUtil.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 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;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- * Helper methods to deal with stream related tasks.
- */
-public class StreamUtil {
- /**
- * Handle closing a {@link java.io.Closeable} via {@link java.io.Closeable#close()} and catch
- * the potentially thrown {@link java.io.IOException}.
- * @param closeable The Closeable to be closed.
- */
- public static void closeQuietly(Closeable closeable) {
- if (closeable == null) return;
-
- try {
- closeable.close();
- } catch (IOException ex) {
- // Ignore the exception on close.
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/SysUtils.java b/base/android/java/src/org/chromium/base/SysUtils.java
deleted file mode 100644
index d4eb30de5b..0000000000
--- a/base/android/java/src/org/chromium/base/SysUtils.java
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2013 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;
-
-import android.annotation.TargetApi;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.StrictMode;
-import android.util.Log;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.metrics.CachedMetrics;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Exposes system related information about the current device.
- */
-@JNINamespace("base::android")
-public class SysUtils {
- // A device reporting strictly more total memory in megabytes cannot be considered 'low-end'.
- private static final int ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB = 512;
- private static final int ANDROID_O_LOW_MEMORY_DEVICE_THRESHOLD_MB = 1024;
-
- private static final String TAG = "SysUtils";
-
- private static Boolean sLowEndDevice;
- private static Integer sAmountOfPhysicalMemoryKB;
-
- private static CachedMetrics.BooleanHistogramSample sLowEndMatches =
- new CachedMetrics.BooleanHistogramSample("Android.SysUtilsLowEndMatches");
-
- private SysUtils() { }
-
- /**
- * Return the amount of physical memory on this device in kilobytes.
- * @return Amount of physical memory in kilobytes, or 0 if there was
- * an error trying to access the information.
- */
- private static int detectAmountOfPhysicalMemoryKB() {
- // Extract total memory RAM size by parsing /proc/meminfo, note that
- // this is exactly what the implementation of sysconf(_SC_PHYS_PAGES)
- // does. However, it can't be called because this method must be
- // usable before any native code is loaded.
-
- // An alternative is to use ActivityManager.getMemoryInfo(), but this
- // requires a valid ActivityManager handle, which can only come from
- // a valid Context object, which itself cannot be retrieved
- // during early startup, where this method is called. And making it
- // an explicit parameter here makes all call paths _much_ more
- // complicated.
-
- Pattern pattern = Pattern.compile("^MemTotal:\\s+([0-9]+) kB$");
- // Synchronously reading files in /proc in the UI thread is safe.
- StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- try {
- FileReader fileReader = new FileReader("/proc/meminfo");
- try {
- BufferedReader reader = new BufferedReader(fileReader);
- try {
- String line;
- for (;;) {
- line = reader.readLine();
- if (line == null) {
- Log.w(TAG, "/proc/meminfo lacks a MemTotal entry?");
- break;
- }
- Matcher m = pattern.matcher(line);
- if (!m.find()) continue;
-
- int totalMemoryKB = Integer.parseInt(m.group(1));
- // Sanity check.
- if (totalMemoryKB <= 1024) {
- Log.w(TAG, "Invalid /proc/meminfo total size in kB: " + m.group(1));
- break;
- }
-
- return totalMemoryKB;
- }
-
- } finally {
- reader.close();
- }
- } finally {
- fileReader.close();
- }
- } catch (Exception e) {
- Log.w(TAG, "Cannot get total physical size from /proc/meminfo", e);
- } finally {
- StrictMode.setThreadPolicy(oldPolicy);
- }
-
- return 0;
- }
-
- /**
- * @return Whether or not this device should be considered a low end device.
- */
- @CalledByNative
- public static boolean isLowEndDevice() {
- if (sLowEndDevice == null) {
- sLowEndDevice = detectLowEndDevice();
- }
- return sLowEndDevice.booleanValue();
- }
-
- /**
- * @return Whether or not this device should be considered a low end device.
- */
- public static int amountOfPhysicalMemoryKB() {
- if (sAmountOfPhysicalMemoryKB == null) {
- sAmountOfPhysicalMemoryKB = detectAmountOfPhysicalMemoryKB();
- }
- return sAmountOfPhysicalMemoryKB.intValue();
- }
-
- /**
- * @return Whether or not the system has low available memory.
- */
- @CalledByNative
- public static boolean isCurrentlyLowMemory() {
- ActivityManager am =
- (ActivityManager) ContextUtils.getApplicationContext().getSystemService(
- Context.ACTIVITY_SERVICE);
- ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
- am.getMemoryInfo(info);
- return info.lowMemory;
- }
-
- /**
- * Resets the cached value, if any.
- */
- @VisibleForTesting
- public static void resetForTesting() {
- sLowEndDevice = null;
- sAmountOfPhysicalMemoryKB = null;
- }
-
- public static boolean hasCamera(final Context context) {
- final PackageManager pm = context.getPackageManager();
- // JellyBean support.
- boolean hasCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- hasCamera |= pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
- }
- return hasCamera;
- }
-
- @TargetApi(Build.VERSION_CODES.KITKAT)
- private static boolean detectLowEndDevice() {
- assert CommandLine.isInitialized();
- if (CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_LOW_END_DEVICE_MODE)) {
- return true;
- }
- if (CommandLine.getInstance().hasSwitch(BaseSwitches.DISABLE_LOW_END_DEVICE_MODE)) {
- return false;
- }
-
- sAmountOfPhysicalMemoryKB = detectAmountOfPhysicalMemoryKB();
- boolean isLowEnd = true;
- if (sAmountOfPhysicalMemoryKB <= 0) {
- isLowEnd = false;
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- isLowEnd = sAmountOfPhysicalMemoryKB / 1024 <= ANDROID_O_LOW_MEMORY_DEVICE_THRESHOLD_MB;
- } else {
- isLowEnd = sAmountOfPhysicalMemoryKB / 1024 <= ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB;
- }
-
- // For evaluation purposes check whether our computation agrees with Android API value.
- Context appContext = ContextUtils.getApplicationContext();
- boolean isLowRam = false;
- if (appContext != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- isLowRam = ((ActivityManager) ContextUtils.getApplicationContext().getSystemService(
- Context.ACTIVITY_SERVICE))
- .isLowRamDevice();
- }
- sLowEndMatches.record(isLowEnd == isLowRam);
-
- return isLowEnd;
- }
-
- /**
- * Creates a new trace event to log the number of minor / major page faults, if tracing is
- * enabled.
- */
- public static void logPageFaultCountToTracing() {
- nativeLogPageFaultCountToTracing();
- }
-
- private static native void nativeLogPageFaultCountToTracing();
-}
diff --git a/base/android/java/src/org/chromium/base/ThrowUncaughtException.java b/base/android/java/src/org/chromium/base/ThrowUncaughtException.java
deleted file mode 100644
index d5f18a278d..0000000000
--- a/base/android/java/src/org/chromium/base/ThrowUncaughtException.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 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;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.MainDex;
-
-@MainDex
-abstract class ThrowUncaughtException {
- @CalledByNative
- private static void post() {
- ThreadUtils.postOnUiThread(new Runnable() {
- @Override
- public void run() {
- throw new RuntimeException("Intentional exception not caught by JNI");
- }
- });
- }
-}
diff --git a/base/android/java/src/org/chromium/base/TimeUtils.java b/base/android/java/src/org/chromium/base/TimeUtils.java
deleted file mode 100644
index dcacabf205..0000000000
--- a/base/android/java/src/org/chromium/base/TimeUtils.java
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 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;
-
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.MainDex;
-
-/** Time-related utilities. */
-@JNINamespace("base::android")
-@MainDex
-public class TimeUtils {
- private TimeUtils() {}
-
- /** Returns TimeTicks::Now() in microseconds. */
- public static native long nativeGetTimeTicksNowUs();
-}
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java
deleted file mode 100644
index 96590900e0..0000000000
--- a/base/android/java/src/org/chromium/base/TraceEvent.java
+++ /dev/null
@@ -1,387 +0,0 @@
-// 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;
-
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.os.SystemClock;
-import android.util.Log;
-import android.util.Printer;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.MainDex;
-/**
- * Java mirror of Chrome trace event API. See base/trace_event/trace_event.h.
- *
- * To get scoped trace events, use the "try with resource" construct, for instance:
- * <pre>{@code
- * try (TraceEvent e = TraceEvent.scoped("MyTraceEvent")) {
- * // code.
- * }
- * }</pre>
- *
- * It is OK to use tracing before the native library has loaded, in a slightly restricted fashion.
- * @see EarlyTraceEvent for details.
- */
-@JNINamespace("base::android")
-@MainDex
-public class TraceEvent implements AutoCloseable {
- private static volatile boolean sEnabled;
- private static volatile boolean sATraceEnabled; // True when taking an Android systrace.
-
- private static class BasicLooperMonitor implements Printer {
- private static final String EARLY_TOPLEVEL_TASK_NAME = "Looper.dispatchMessage: ";
-
- @Override
- public void println(final String line) {
- if (line.startsWith(">")) {
- beginHandling(line);
- } else {
- assert line.startsWith("<");
- endHandling(line);
- }
- }
-
- void beginHandling(final String line) {
- // May return an out-of-date value. this is not an issue as EarlyTraceEvent#begin()
- // will filter the event in this case.
- boolean earlyTracingActive = EarlyTraceEvent.isActive();
- if (sEnabled || earlyTracingActive) {
- String target = getTarget(line);
- if (sEnabled) {
- nativeBeginToplevel(target);
- } else if (earlyTracingActive) {
- // Synthesize a task name instead of using a parameter, as early tracing doesn't
- // support parameters.
- EarlyTraceEvent.begin(EARLY_TOPLEVEL_TASK_NAME + target);
- }
- }
- }
-
- void endHandling(final String line) {
- if (EarlyTraceEvent.isActive()) {
- EarlyTraceEvent.end(EARLY_TOPLEVEL_TASK_NAME + getTarget(line));
- }
- if (sEnabled) nativeEndToplevel();
- }
-
- /**
- * Android Looper formats |line| as ">>>>> Dispatching to (TARGET) [...]" since at least
- * 2009 (Donut). Extracts the TARGET part of the message.
- */
- private static String getTarget(String logLine) {
- int start = logLine.indexOf('(', 21); // strlen(">>>>> Dispatching to ")
- int end = start == -1 ? -1 : logLine.indexOf(')', start);
- return end != -1 ? logLine.substring(start + 1, end) : "";
- }
- }
-
- /**
- * A class that records, traces and logs statistics about the UI thead's Looper.
- * The output of this class can be used in a number of interesting ways:
- * <p>
- * <ol><li>
- * When using chrometrace, there will be a near-continuous line of
- * measurements showing both event dispatches as well as idles;
- * </li><li>
- * Logging messages are output for events that run too long on the
- * event dispatcher, making it easy to identify problematic areas;
- * </li><li>
- * Statistics are output whenever there is an idle after a non-trivial
- * amount of activity, allowing information to be gathered about task
- * density and execution cadence on the Looper;
- * </li></ol>
- * <p>
- * The class attaches itself as an idle handler to the main Looper, and
- * monitors the execution of events and idle notifications. Task counters
- * accumulate between idle notifications and get reset when a new idle
- * notification is received.
- */
- private static final class IdleTracingLooperMonitor extends BasicLooperMonitor
- implements MessageQueue.IdleHandler {
- // Tags for dumping to logcat or TraceEvent
- private static final String TAG = "TraceEvent.LooperMonitor";
- private static final String IDLE_EVENT_NAME = "Looper.queueIdle";
-
- // Calculation constants
- private static final long FRAME_DURATION_MILLIS = 1000L / 60L; // 60 FPS
- // A reasonable threshold for defining a Looper event as "long running"
- private static final long MIN_INTERESTING_DURATION_MILLIS =
- FRAME_DURATION_MILLIS;
- // A reasonable threshold for a "burst" of tasks on the Looper
- private static final long MIN_INTERESTING_BURST_DURATION_MILLIS =
- MIN_INTERESTING_DURATION_MILLIS * 3;
-
- // Stats tracking
- private long mLastIdleStartedAt;
- private long mLastWorkStartedAt;
- private int mNumTasksSeen;
- private int mNumIdlesSeen;
- private int mNumTasksSinceLastIdle;
-
- // State
- private boolean mIdleMonitorAttached;
-
- // Called from within the begin/end methods only.
- // This method can only execute on the looper thread, because that is
- // the only thread that is permitted to call Looper.myqueue().
- private final void syncIdleMonitoring() {
- if (sEnabled && !mIdleMonitorAttached) {
- // approximate start time for computational purposes
- mLastIdleStartedAt = SystemClock.elapsedRealtime();
- Looper.myQueue().addIdleHandler(this);
- mIdleMonitorAttached = true;
- Log.v(TAG, "attached idle handler");
- } else if (mIdleMonitorAttached && !sEnabled) {
- Looper.myQueue().removeIdleHandler(this);
- mIdleMonitorAttached = false;
- Log.v(TAG, "detached idle handler");
- }
- }
-
- @Override
- final void beginHandling(final String line) {
- // Close-out any prior 'idle' period before starting new task.
- if (mNumTasksSinceLastIdle == 0) {
- TraceEvent.end(IDLE_EVENT_NAME);
- }
- mLastWorkStartedAt = SystemClock.elapsedRealtime();
- syncIdleMonitoring();
- super.beginHandling(line);
- }
-
- @Override
- final void endHandling(final String line) {
- final long elapsed = SystemClock.elapsedRealtime()
- - mLastWorkStartedAt;
- if (elapsed > MIN_INTERESTING_DURATION_MILLIS) {
- traceAndLog(Log.WARN, "observed a task that took "
- + elapsed + "ms: " + line);
- }
- super.endHandling(line);
- syncIdleMonitoring();
- mNumTasksSeen++;
- mNumTasksSinceLastIdle++;
- }
-
- private static void traceAndLog(int level, String message) {
- TraceEvent.instant("TraceEvent.LooperMonitor:IdleStats", message);
- Log.println(level, TAG, message);
- }
-
- @Override
- public final boolean queueIdle() {
- final long now = SystemClock.elapsedRealtime();
- if (mLastIdleStartedAt == 0) mLastIdleStartedAt = now;
- final long elapsed = now - mLastIdleStartedAt;
- mNumIdlesSeen++;
- TraceEvent.begin(IDLE_EVENT_NAME, mNumTasksSinceLastIdle + " tasks since last idle.");
- if (elapsed > MIN_INTERESTING_BURST_DURATION_MILLIS) {
- // Dump stats
- String statsString = mNumTasksSeen + " tasks and "
- + mNumIdlesSeen + " idles processed so far, "
- + mNumTasksSinceLastIdle + " tasks bursted and "
- + elapsed + "ms elapsed since last idle";
- traceAndLog(Log.DEBUG, statsString);
- }
- mLastIdleStartedAt = now;
- mNumTasksSinceLastIdle = 0;
- return true; // stay installed
- }
- }
-
- // Holder for monitor avoids unnecessary construction on non-debug runs
- private static final class LooperMonitorHolder {
- private static final BasicLooperMonitor sInstance =
- CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_IDLE_TRACING)
- ? new IdleTracingLooperMonitor() : new BasicLooperMonitor();
- }
-
- private final String mName;
-
- /**
- * Constructor used to support the "try with resource" construct.
- */
- private TraceEvent(String name, String arg) {
- mName = name;
- begin(name, arg);
- }
-
- @Override
- public void close() {
- end(mName);
- }
-
- /**
- * Factory used to support the "try with resource" construct.
- *
- * Note that if tracing is not enabled, this will not result in allocating an object.
- *
- * @param name Trace event name.
- * @param name The arguments of the event.
- * @return a TraceEvent, or null if tracing is not enabled.
- */
- public static TraceEvent scoped(String name, String arg) {
- if (!(EarlyTraceEvent.enabled() || enabled())) return null;
- return new TraceEvent(name, arg);
- }
-
- /**
- * Similar to {@link #scoped(String, String arg)}, but uses null for |arg|.
- */
- public static TraceEvent scoped(String name) {
- return scoped(name, null);
- }
-
- /**
- * Register an enabled observer, such that java traces are always enabled with native.
- */
- public static void registerNativeEnabledObserver() {
- nativeRegisterEnabledObserver();
- }
-
- /**
- * Notification from native that tracing is enabled/disabled.
- */
- @CalledByNative
- public static void setEnabled(boolean enabled) {
- if (enabled) EarlyTraceEvent.disable();
- // Only disable logging if Chromium enabled it originally, so as to not disrupt logging done
- // by other applications
- if (sEnabled != enabled) {
- sEnabled = enabled;
- // Android M+ systrace logs this on its own. Only log it if not writing to Android
- // systrace.
- if (sATraceEnabled) return;
- ThreadUtils.getUiThreadLooper().setMessageLogging(
- enabled ? LooperMonitorHolder.sInstance : null);
- }
- }
-
- /**
- * May enable early tracing depending on the environment.
- *
- * Must be called after the command-line has been read.
- */
- public static void maybeEnableEarlyTracing() {
- EarlyTraceEvent.maybeEnable();
- if (EarlyTraceEvent.isActive()) {
- ThreadUtils.getUiThreadLooper().setMessageLogging(LooperMonitorHolder.sInstance);
- }
- }
-
- /**
- * Enables or disabled Android systrace path of Chrome tracing. If enabled, all Chrome
- * traces will be also output to Android systrace. Because of the overhead of Android
- * systrace, this is for WebView only.
- */
- public static void setATraceEnabled(boolean enabled) {
- if (sATraceEnabled == enabled) return;
- sATraceEnabled = enabled;
- if (enabled) {
- // Calls TraceEvent.setEnabled(true) via
- // TraceLog::EnabledStateObserver::OnTraceLogEnabled
- nativeStartATrace();
- } else {
- // Calls TraceEvent.setEnabled(false) via
- // TraceLog::EnabledStateObserver::OnTraceLogDisabled
- nativeStopATrace();
- }
- }
-
- /**
- * @return True if tracing is enabled, false otherwise.
- * It is safe to call trace methods without checking if TraceEvent
- * is enabled.
- */
- public static boolean enabled() {
- return sEnabled;
- }
-
- /**
- * Triggers the 'instant' native trace event with no arguments.
- * @param name The name of the event.
- */
- public static void instant(String name) {
- if (sEnabled) nativeInstant(name, null);
- }
-
- /**
- * Triggers the 'instant' native trace event.
- * @param name The name of the event.
- * @param arg The arguments of the event.
- */
- public static void instant(String name, String arg) {
- if (sEnabled) nativeInstant(name, arg);
- }
-
- /**
- * Triggers the 'start' native trace event with no arguments.
- * @param name The name of the event.
- * @param id The id of the asynchronous event.
- */
- public static void startAsync(String name, long id) {
- EarlyTraceEvent.startAsync(name, id);
- if (sEnabled) nativeStartAsync(name, id);
- }
-
- /**
- * Triggers the 'finish' native trace event with no arguments.
- * @param name The name of the event.
- * @param id The id of the asynchronous event.
- */
- public static void finishAsync(String name, long id) {
- EarlyTraceEvent.finishAsync(name, id);
- if (sEnabled) nativeFinishAsync(name, id);
- }
-
- /**
- * Triggers the 'begin' native trace event with no arguments.
- * @param name The name of the event.
- */
- public static void begin(String name) {
- begin(name, null);
- }
-
- /**
- * Triggers the 'begin' native trace event.
- * @param name The name of the event.
- * @param arg The arguments of the event.
- */
- public static void begin(String name, String arg) {
- EarlyTraceEvent.begin(name);
- if (sEnabled) nativeBegin(name, arg);
- }
-
- /**
- * Triggers the 'end' native trace event with no arguments.
- * @param name The name of the event.
- */
- public static void end(String name) {
- end(name, null);
- }
-
- /**
- * Triggers the 'end' native trace event.
- * @param name The name of the event.
- * @param arg The arguments of the event.
- */
- public static void end(String name, String arg) {
- EarlyTraceEvent.end(name);
- if (sEnabled) nativeEnd(name, arg);
- }
-
- private static native void nativeRegisterEnabledObserver();
- private static native void nativeStartATrace();
- private static native void nativeStopATrace();
- private static native void nativeInstant(String name, String arg);
- private static native void nativeBegin(String name, String arg);
- private static native void nativeEnd(String name, String arg);
- private static native void nativeBeginToplevel(String target);
- private static native void nativeEndToplevel();
- private static native void nativeStartAsync(String name, long id);
- private static native void nativeFinishAsync(String name, long id);
-}
diff --git a/base/android/java/src/org/chromium/base/UnguessableToken.java b/base/android/java/src/org/chromium/base/UnguessableToken.java
deleted file mode 100644
index 4b1619dae8..0000000000
--- a/base/android/java/src/org/chromium/base/UnguessableToken.java
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2016 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;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import org.chromium.base.annotations.CalledByNative;
-
-/**
- * This class mirrors unguessable_token.h . Since tokens are passed by value,
- * we don't bother to maintain a native token. This implements Parcelable so
- * that it may be sent via binder.
- *
- * To get one of these from native, one must start with a
- * base::UnguessableToken, then create a Java object from it. See
- * jni_unguessable_token.h for information.
- */
-public class UnguessableToken implements Parcelable {
- private final long mHigh;
- private final long mLow;
-
- private UnguessableToken(long high, long low) {
- mHigh = high;
- mLow = low;
- }
-
- @CalledByNative
- private static UnguessableToken create(long high, long low) {
- return new UnguessableToken(high, low);
- }
-
- @CalledByNative
- public long getHighForSerialization() {
- return mHigh;
- }
-
- @CalledByNative
- public long getLowForSerialization() {
- return mLow;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mHigh);
- dest.writeLong(mLow);
- }
-
- public static final Parcelable.Creator<UnguessableToken> CREATOR =
- new Parcelable.Creator<UnguessableToken>() {
- @Override
- public UnguessableToken createFromParcel(Parcel source) {
- long high = source.readLong();
- long low = source.readLong();
- if (high == 0 || low == 0) {
- // Refuse to create an empty UnguessableToken.
- return null;
- }
- return new UnguessableToken(high, low);
- }
-
- @Override
- public UnguessableToken[] newArray(int size) {
- return new UnguessableToken[size];
- }
- };
-
- // To avoid unwieldy calls in JNI for tests, parcel and unparcel.
- // TODO(liberato): It would be nice if we could include this only with a
- // java driver that's linked only with unit tests, but i don't see a way
- // to do that.
- @CalledByNative
- private UnguessableToken parcelAndUnparcelForTesting() {
- Parcel parcel = Parcel.obtain();
- writeToParcel(parcel, 0);
-
- // Rewind the parcel and un-parcel.
- parcel.setDataPosition(0);
- UnguessableToken token = CREATOR.createFromParcel(parcel);
- parcel.recycle();
-
- return token;
- }
-};
diff --git a/base/android/java/src/org/chromium/base/annotations/DoNotInline.java b/base/android/java/src/org/chromium/base/annotations/DoNotInline.java
deleted file mode 100644
index 9252f3a79b..0000000000
--- a/base/android/java/src/org/chromium/base/annotations/DoNotInline.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2018 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.annotations;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The annotated method or class should never be inlined.
- *
- * The annotated method (or methods on the annotated class) are guaranteed not to be inlined by
- * Proguard. Other optimizations may still apply.
- */
-@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.CLASS)
-public @interface DoNotInline {}
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
deleted file mode 100644
index 5bc62042d4..0000000000
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ /dev/null
@@ -1,829 +0,0 @@
-// 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.library_loader;
-
-import static org.chromium.base.metrics.CachedMetrics.EnumeratedHistogramSample;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.os.Process;
-import android.os.StrictMode;
-import android.os.SystemClock;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
-import android.system.Os;
-
-import org.chromium.base.AsyncTask;
-import org.chromium.base.BuildConfig;
-import org.chromium.base.BuildInfo;
-import org.chromium.base.CommandLine;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.FileUtils;
-import org.chromium.base.Log;
-import org.chromium.base.SysUtils;
-import org.chromium.base.TraceEvent;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.metrics.RecordHistogram;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.zip.ZipFile;
-
-import javax.annotation.Nullable;
-
-/**
- * This class provides functionality to load and register the native libraries.
- * Callers are allowed to separate loading the libraries from initializing them.
- * This may be an advantage for Android Webview, where the libraries can be loaded
- * by the zygote process, but then needs per process initialization after the
- * application processes are forked from the zygote process.
- *
- * The libraries may be loaded and initialized from any thread. Synchronization
- * primitives are used to ensure that overlapping requests from different
- * threads are handled sequentially.
- *
- * See also base/android/library_loader/library_loader_hooks.cc, which contains
- * the native counterpart to this class.
- */
-@MainDex
-@JNINamespace("base::android")
-public class LibraryLoader {
- private static final String TAG = "LibraryLoader";
-
- // Set to true to enable debug logs.
- private static final boolean DEBUG = false;
-
- // Experience shows that on some devices, the PackageManager fails to properly extract
- // native shared libraries to the /data partition at installation or upgrade time,
- // which creates all kind of chaos (https://crbug.com/806998).
- //
- // We implement a fallback when we detect the issue by manually extracting the library
- // into Chromium's own data directory, then retrying to load the new library from here.
- //
- // This will work for any device running K-. Starting with Android L, render processes
- // cannot access the file system anymore, and extraction will always fail for them.
- // However, the issue doesn't seem to appear in the field for Android L.
- //
- // Also, starting with M, the issue doesn't exist if shared libraries are stored
- // uncompressed in the APK (as Chromium does), because the system linker can access them
- // directly, and the PackageManager will thus never extract them in the first place.
- static public final boolean PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION =
- Build.VERSION.SDK_INT <= VERSION_CODES.KITKAT;
-
- // Location of extracted native libraries.
- private static final String LIBRARY_DIR = "native_libraries";
-
- // SharedPreferences key for "don't prefetch libraries" flag
- private static final String DONT_PREFETCH_LIBRARIES_KEY = "dont_prefetch_libraries";
-
- private static final EnumeratedHistogramSample sRelinkerCountHistogram =
- new EnumeratedHistogramSample("ChromiumAndroidLinker.RelinkerFallbackCount", 2);
-
- // The singleton instance of LibraryLoader. Never null (not final for tests).
- private static LibraryLoader sInstance = new LibraryLoader();
-
- // One-way switch becomes true when the libraries are initialized (
- // by calling nativeLibraryLoaded, which forwards to LibraryLoaded(...) in
- // library_loader_hooks.cc).
- // Note that this member should remain a one-way switch, since it accessed from multiple
- // threads without a lock.
- private volatile boolean mInitialized;
-
- // One-way switch that becomes true once
- // {@link asyncPrefetchLibrariesToMemory} has been called.
- private final AtomicBoolean mPrefetchLibraryHasBeenCalled = new AtomicBoolean();
-
- // Guards all fields below.
- private final Object mLock = new Object();
-
- private NativeLibraryPreloader mLibraryPreloader;
- private boolean mLibraryPreloaderCalled;
-
- // One-way switch becomes true when the libraries are loaded.
- private boolean mLoaded;
-
- // One-way switch becomes true when the Java command line is switched to
- // native.
- private boolean mCommandLineSwitched;
-
- // One-way switches recording attempts to use Relro sharing in the browser.
- // The flags are used to report UMA stats later.
- private boolean mIsUsingBrowserSharedRelros;
- private boolean mLoadAtFixedAddressFailed;
-
- // One-way switch becomes true if the Chromium library was loaded from the
- // APK file directly.
- private boolean mLibraryWasLoadedFromApk;
-
- // The type of process the shared library is loaded in.
- private @LibraryProcessType int mLibraryProcessType;
-
- // The number of milliseconds it took to load all the native libraries, which
- // will be reported via UMA. Set once when the libraries are done loading.
- private long mLibraryLoadTimeMs;
-
- // The return value of NativeLibraryPreloader.loadLibrary(), which will be reported
- // via UMA, it is initialized to the invalid value which shouldn't showup in UMA
- // report.
- private int mLibraryPreloaderStatus = -1;
-
- /**
- * Call this method to determine if this chromium project must
- * use this linker. If not, System.loadLibrary() should be used to load
- * libraries instead.
- */
- public static boolean useCrazyLinker() {
- // TODO(digit): Remove this early return GVR is loadable.
- // A non-monochrome APK (such as ChromePublic.apk or ChromeModernPublic.apk) on N+ cannot
- // use the Linker because the latter is incompatible with the GVR library. Fall back
- // to using System.loadLibrary() or System.load() at the cost of no RELRO sharing.
- //
- // A non-monochrome APK (such as ChromePublic.apk) can be installed on N+ in these
- // circumstances:
- // * installing APK manually
- // * after OTA from M to N
- // * side-installing Chrome (possibly from another release channel)
- // * Play Store bugs leading to incorrect APK flavor being installed
- //
- if (Build.VERSION.SDK_INT >= VERSION_CODES.N) return false;
-
- // The auto-generated NativeLibraries.sUseLinker variable will be true if the
- // build has not explicitly disabled Linker features.
- return NativeLibraries.sUseLinker;
- }
-
- /**
- * Call this method to determine if the chromium project must load the library
- * directly from a zip file.
- */
- private static boolean isInZipFile() {
- // The auto-generated NativeLibraries.sUseLibraryInZipFile variable will be true
- // iff the library remains embedded in the APK zip file on the target.
- return NativeLibraries.sUseLibraryInZipFile;
- }
-
- /**
- * Set native library preloader, if set, the NativeLibraryPreloader.loadLibrary will be invoked
- * before calling System.loadLibrary, this only applies when not using the chromium linker.
- *
- * @param loader the NativeLibraryPreloader, it shall only be set once and before the
- * native library loaded.
- */
- public void setNativeLibraryPreloader(NativeLibraryPreloader loader) {
- synchronized (mLock) {
- assert mLibraryPreloader == null && !mLoaded;
- mLibraryPreloader = loader;
- }
- }
-
- public static LibraryLoader getInstance() {
- return sInstance;
- }
-
- private LibraryLoader() {}
-
- /**
- * This method blocks until the library is fully loaded and initialized.
- *
- * @param processType the process the shared library is loaded in.
- */
- public void ensureInitialized(@LibraryProcessType int processType) throws ProcessInitException {
- synchronized (mLock) {
- if (mInitialized) {
- // Already initialized, nothing to do.
- return;
- }
- loadAlreadyLocked(ContextUtils.getApplicationContext());
- initializeAlreadyLocked(processType);
- }
- }
-
- /**
- * Calls native library preloader (see {@link #setNativeLibraryPreloader}) with the app
- * context. If there is no preloader set, this function does nothing.
- * Preloader is called only once, so calling it explicitly via this method means
- * that it won't be (implicitly) called during library loading.
- */
- public void preloadNow() {
- preloadNowOverrideApplicationContext(ContextUtils.getApplicationContext());
- }
-
- /**
- * Similar to {@link #preloadNow}, but allows specifying app context to use.
- */
- public void preloadNowOverrideApplicationContext(Context appContext) {
- synchronized (mLock) {
- if (!useCrazyLinker()) {
- preloadAlreadyLocked(appContext);
- }
- }
- }
-
- private void preloadAlreadyLocked(Context appContext) {
- try (TraceEvent te = TraceEvent.scoped("LibraryLoader.preloadAlreadyLocked")) {
- // Preloader uses system linker, we shouldn't preload if Chromium linker is used.
- assert !useCrazyLinker();
- if (mLibraryPreloader != null && !mLibraryPreloaderCalled) {
- mLibraryPreloaderStatus = mLibraryPreloader.loadLibrary(appContext);
- mLibraryPreloaderCalled = true;
- }
- }
- }
-
- /**
- * Checks if library is fully loaded and initialized.
- */
- public boolean isInitialized() {
- return mInitialized;
- }
-
- /**
- * Loads the library and blocks until the load completes. The caller is responsible
- * for subsequently calling ensureInitialized().
- * May be called on any thread, but should only be called once. Note the thread
- * this is called on will be the thread that runs the native code's static initializers.
- * See the comment in doInBackground() for more considerations on this.
- *
- * @throws ProcessInitException if the native library failed to load.
- */
- public void loadNow() throws ProcessInitException {
- loadNowOverrideApplicationContext(ContextUtils.getApplicationContext());
- }
-
- /**
- * Override kept for callers that need to load from a different app context. Do not use unless
- * specifically required to load from another context that is not the current process's app
- * context.
- *
- * @param appContext The overriding app context to be used to load libraries.
- * @throws ProcessInitException if the native library failed to load with this context.
- */
- public void loadNowOverrideApplicationContext(Context appContext) throws ProcessInitException {
- synchronized (mLock) {
- if (mLoaded && appContext != ContextUtils.getApplicationContext()) {
- throw new IllegalStateException("Attempt to load again from alternate context.");
- }
- loadAlreadyLocked(appContext);
- }
- }
-
- /**
- * Initializes the library here and now: must be called on the thread that the
- * native will call its "main" thread. The library must have previously been
- * loaded with loadNow.
- *
- * @param processType the process the shared library is loaded in.
- */
- public void initialize(@LibraryProcessType int processType) throws ProcessInitException {
- synchronized (mLock) {
- initializeAlreadyLocked(processType);
- }
- }
-
- /**
- * Disables prefetching for subsequent runs. The value comes from "DontPrefetchLibraries"
- * finch experiment, and is pushed on every run. I.e. the effect of the finch experiment
- * lags by one run, which is the best we can do considering that prefetching happens way
- * before finch is initialized. Note that since LibraryLoader is in //base, it can't depend
- * on ChromeFeatureList, and has to rely on external code pushing the value.
- *
- * @param dontPrefetch whether not to prefetch libraries
- */
- public static void setDontPrefetchLibrariesOnNextRuns(boolean dontPrefetch) {
- ContextUtils.getAppSharedPreferences()
- .edit()
- .putBoolean(DONT_PREFETCH_LIBRARIES_KEY, dontPrefetch)
- .apply();
- }
-
- /**
- * @return whether not to prefetch libraries (see setDontPrefetchLibrariesOnNextRun()).
- */
- private static boolean isNotPrefetchingLibraries() {
- // This might be the first time getAppSharedPreferences() is used, so relax strict mode
- // to allow disk reads.
- StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- try {
- return ContextUtils.getAppSharedPreferences().getBoolean(
- DONT_PREFETCH_LIBRARIES_KEY, false);
- } finally {
- StrictMode.setThreadPolicy(oldPolicy);
- }
- }
-
- /** Prefetches the native libraries in a background thread.
- *
- * Launches an AsyncTask that, through a short-lived forked process, reads a
- * part of each page of the native library. This is done to warm up the
- * page cache, turning hard page faults into soft ones.
- *
- * This is done this way, as testing shows that fadvise(FADV_WILLNEED) is
- * detrimental to the startup time.
- */
- public void asyncPrefetchLibrariesToMemory() {
- SysUtils.logPageFaultCountToTracing();
- if (isNotPrefetchingLibraries()) return;
-
- final boolean coldStart = mPrefetchLibraryHasBeenCalled.compareAndSet(false, true);
-
- // Collection should start close to the native library load, but doesn't have
- // to be simultaneous with it. Also, don't prefetch in this case, as this would
- // skew the results.
- if (coldStart && CommandLine.getInstance().hasSwitch("log-native-library-residency")) {
- // nativePeriodicallyCollectResidency() sleeps, run it on another thread,
- // and not on the AsyncTask thread pool.
- new Thread(LibraryLoader::nativePeriodicallyCollectResidency).start();
- return;
- }
-
- new LibraryPrefetchTask(coldStart).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
-
- private static class LibraryPrefetchTask extends AsyncTask<Void, Void, Void> {
- private final boolean mColdStart;
-
- public LibraryPrefetchTask(boolean coldStart) {
- mColdStart = coldStart;
- }
-
- @Override
- protected Void doInBackground(Void... params) {
- try (TraceEvent e = TraceEvent.scoped("LibraryLoader.asyncPrefetchLibrariesToMemory")) {
- int percentage = nativePercentageOfResidentNativeLibraryCode();
- // Arbitrary percentage threshold. If most of the native library is already
- // resident (likely with monochrome), don't bother creating a prefetch process.
- boolean prefetch = mColdStart && percentage < 90;
- if (prefetch) {
- nativeForkAndPrefetchNativeLibrary();
- }
- if (percentage != -1) {
- String histogram = "LibraryLoader.PercentageOfResidentCodeBeforePrefetch"
- + (mColdStart ? ".ColdStartup" : ".WarmStartup");
- RecordHistogram.recordPercentageHistogram(histogram, percentage);
- }
- }
- return null;
- }
- }
-
- // Helper for loadAlreadyLocked(). Load a native shared library with the Chromium linker.
- // Sets UMA flags depending on the results of loading.
- private void loadLibraryWithCustomLinkerAlreadyLocked(
- Linker linker, @Nullable String zipFilePath, String libFilePath) {
- assert Thread.holdsLock(mLock);
- if (linker.isUsingBrowserSharedRelros()) {
- // If the browser is set to attempt shared RELROs then we try first with shared
- // RELROs enabled, and if that fails then retry without.
- mIsUsingBrowserSharedRelros = true;
- try {
- linker.loadLibrary(libFilePath);
- } catch (UnsatisfiedLinkError e) {
- Log.w(TAG, "Failed to load native library with shared RELRO, retrying without");
- mLoadAtFixedAddressFailed = true;
- linker.loadLibraryNoFixedAddress(libFilePath);
- }
- } else {
- // No attempt to use shared RELROs in the browser, so load as normal.
- linker.loadLibrary(libFilePath);
- }
-
- // Loaded successfully, so record if we loaded directly from an APK.
- if (zipFilePath != null) {
- mLibraryWasLoadedFromApk = true;
- }
- }
-
- static void incrementRelinkerCountHitHistogram() {
- sRelinkerCountHistogram.record(1);
- }
-
- static void incrementRelinkerCountNotHitHistogram() {
- sRelinkerCountHistogram.record(0);
- }
-
- // Experience shows that on some devices, the system sometimes fails to extract native libraries
- // at installation or update time from the APK. This function will extract the library and
- // return the extracted file path.
- static String getExtractedLibraryPath(Context appContext, String libName) {
- assert PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION;
- Log.w(TAG, "Failed to load libName %s, attempting fallback extraction then trying again",
- libName);
- String libraryEntry = LibraryLoader.makeLibraryPathInZipFile(libName, false, false);
- return extractFileIfStale(appContext, libraryEntry, makeLibraryDirAndSetPermission());
- }
-
- // Invoke either Linker.loadLibrary(...), System.loadLibrary(...) or System.load(...),
- // triggering JNI_OnLoad in native code.
- // TODO(crbug.com/635567): Fix this properly.
- @SuppressLint({"DefaultLocale", "NewApi", "UnsafeDynamicallyLoadedCode"})
- private void loadAlreadyLocked(Context appContext) throws ProcessInitException {
- try (TraceEvent te = TraceEvent.scoped("LibraryLoader.loadAlreadyLocked")) {
- if (!mLoaded) {
- assert !mInitialized;
-
- long startTime = SystemClock.uptimeMillis();
-
- if (useCrazyLinker()) {
- // Load libraries using the Chromium linker.
- Linker linker = Linker.getInstance();
-
- String apkFilePath =
- isInZipFile() ? appContext.getApplicationInfo().sourceDir : null;
- linker.prepareLibraryLoad(apkFilePath);
-
- 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;
- }
-
- // Determine where the library should be loaded from.
- String libFilePath = System.mapLibraryName(library);
- if (apkFilePath != null) {
- Log.i(TAG, " Loading " + library + " from within " + apkFilePath);
- } else {
- Log.i(TAG, "Loading " + library);
- }
-
- try {
- // Load the library using this Linker. May throw UnsatisfiedLinkError.
- loadLibraryWithCustomLinkerAlreadyLocked(
- linker, apkFilePath, libFilePath);
- incrementRelinkerCountNotHitHistogram();
- } catch (UnsatisfiedLinkError e) {
- if (!isInZipFile()
- && PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION) {
- loadLibraryWithCustomLinkerAlreadyLocked(
- linker, null, getExtractedLibraryPath(appContext, library));
- incrementRelinkerCountHitHistogram();
- } else {
- Log.e(TAG, "Unable to load library: " + library);
- throw(e);
- }
- }
- }
-
- linker.finishLibraryLoad();
- } else {
- setEnvForNative();
- preloadAlreadyLocked(appContext);
-
- // If the libraries are located in the zip file, assert that the device API
- // level is M or higher. On devices lower than M, the libraries should
- // always be loaded by Linker.
- assert !isInZipFile() || Build.VERSION.SDK_INT >= VERSION_CODES.M;
-
- // Load libraries using the system linker.
- for (String library : NativeLibraries.LIBRARIES) {
- try {
- if (!isInZipFile()) {
- // The extract and retry logic isn't needed because this path is
- // used only for local development.
- System.loadLibrary(library);
- } else {
- // Load directly from the APK.
- boolean is64Bit = Process.is64Bit();
- String zipFilePath = appContext.getApplicationInfo().sourceDir;
- // In API level 23 and above, it’s possible to open a .so file
- // directly from the APK of the path form
- // "my_zip_file.zip!/libs/libstuff.so". See:
- // https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#opening-shared-libraries-directly-from-an-apk
- String libraryName = zipFilePath + "!/"
- + makeLibraryPathInZipFile(library, true, is64Bit);
- Log.i(TAG, "libraryName: " + libraryName);
- System.load(libraryName);
- }
- } catch (UnsatisfiedLinkError e) {
- Log.e(TAG, "Unable to load library: " + library);
- throw(e);
- }
- }
- }
-
- long stopTime = SystemClock.uptimeMillis();
- mLibraryLoadTimeMs = stopTime - startTime;
- Log.i(TAG, String.format("Time to load native libraries: %d ms (timestamps %d-%d)",
- mLibraryLoadTimeMs,
- startTime % 10000,
- stopTime % 10000));
-
- mLoaded = true;
- }
- } catch (UnsatisfiedLinkError e) {
- throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED, e);
- }
- }
-
- /**
- * @param library The library name that is looking for.
- * @param crazyPrefix true iff adding crazy linker prefix to the file name.
- * @param is64Bit true if the caller think it's run on a 64 bit device.
- * @return the library path name in the zip file.
- */
- @NonNull
- public static String makeLibraryPathInZipFile(
- String library, boolean crazyPrefix, boolean is64Bit) {
- // Determine the ABI string that Android uses to find native libraries. Values are described
- // in: https://developer.android.com/ndk/guides/abis.html
- // The 'armeabi' is omitted here because it is not supported in Chrome/WebView, while Cronet
- // and Cast load the native library via other paths.
- String cpuAbi;
- switch (NativeLibraries.sCpuFamily) {
- case NativeLibraries.CPU_FAMILY_ARM:
- cpuAbi = is64Bit ? "arm64-v8a" : "armeabi-v7a";
- break;
- case NativeLibraries.CPU_FAMILY_X86:
- cpuAbi = is64Bit ? "x86_64" : "x86";
- break;
- case NativeLibraries.CPU_FAMILY_MIPS:
- cpuAbi = is64Bit ? "mips64" : "mips";
- break;
- default:
- throw new RuntimeException("Unknown CPU ABI for native libraries");
- }
-
- // When both the Chromium linker and zip-uncompressed native libraries are used,
- // the build system renames the native shared libraries with a 'crazy.' prefix
- // (e.g. "/lib/armeabi-v7a/libfoo.so" -> "/lib/armeabi-v7a/crazy.libfoo.so").
- //
- // This prevents the package manager from extracting them at installation/update time
- // to the /data directory. The libraries can still be accessed directly by the Chromium
- // linker from the APK.
- String crazyPart = crazyPrefix ? "crazy." : "";
- return String.format("lib/%s/%s%s", cpuAbi, crazyPart, System.mapLibraryName(library));
- }
-
- // The WebView requires the Command Line to be switched over before
- // initialization is done. This is okay in the WebView's case since the
- // JNI is already loaded by this point.
- public void switchCommandLineForWebView() {
- synchronized (mLock) {
- ensureCommandLineSwitchedAlreadyLocked();
- }
- }
-
- // Switch the CommandLine over from Java to native if it hasn't already been done.
- // This must happen after the code is loaded and after JNI is ready (since after the
- // switch the Java CommandLine will delegate all calls the native CommandLine).
- private void ensureCommandLineSwitchedAlreadyLocked() {
- assert mLoaded;
- if (mCommandLineSwitched) {
- return;
- }
- CommandLine.enableNativeProxy();
- mCommandLineSwitched = true;
- }
-
- // Invoke base::android::LibraryLoaded in library_loader_hooks.cc
- private void initializeAlreadyLocked(@LibraryProcessType int processType)
- throws ProcessInitException {
- if (mInitialized) {
- if (mLibraryProcessType != processType) {
- throw new ProcessInitException(
- LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED);
- }
- return;
- }
- mLibraryProcessType = processType;
-
- ensureCommandLineSwitchedAlreadyLocked();
-
- if (!nativeLibraryLoaded(mLibraryProcessType)) {
- Log.e(TAG, "error calling nativeLibraryLoaded");
- throw new ProcessInitException(LoaderErrors.LOADER_ERROR_FAILED_TO_REGISTER_JNI);
- }
-
- // 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\"",
- NativeLibraries.sVersionNumber, nativeGetVersionNumber()));
- if (!NativeLibraries.sVersionNumber.equals(nativeGetVersionNumber())) {
- throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_WRONG_VERSION);
- }
-
- // From now on, keep tracing in sync with native.
- TraceEvent.registerNativeEnabledObserver();
-
- if (processType == LibraryProcessType.PROCESS_BROWSER
- && PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION) {
- // Perform the detection and deletion of obsolete native libraries on a background
- // background thread.
- AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
- @Override
- public void run() {
- final String suffix = BuildInfo.getInstance().extractedFileSuffix;
- final File[] files = getLibraryDir().listFiles();
- if (files == null) return;
-
- for (File file : files) {
- // NOTE: Do not simply look for <suffix> at the end of the file.
- //
- // Extracted library files have names like 'libfoo.so<suffix>', but
- // extractFileIfStale() will use FileUtils.copyFileStreamAtomicWithBuffer()
- // to create them, and this method actually uses a transient temporary file
- // named like 'libfoo.so<suffix>.tmp' to do that. These temporary files, if
- // detected here, should be preserved; hence the reason why contains() is
- // used below.
- if (!file.getName().contains(suffix)) {
- String fileName = file.getName();
- if (!file.delete()) {
- Log.w(TAG, "Unable to remove %s", fileName);
- } else {
- Log.i(TAG, "Removed obsolete file %s", fileName);
- }
- }
- }
- }
- });
- }
-
- // From this point on, native code is ready to use and checkIsReady()
- // shouldn't complain from now on (and in fact, it's used by the
- // following calls).
- // Note that this flag can be accessed asynchronously, so any initialization
- // must be performed before.
- mInitialized = true;
- }
-
- // Called after all native initializations are complete.
- public void onNativeInitializationComplete() {
- synchronized (mLock) {
- recordBrowserProcessHistogramAlreadyLocked();
- }
- }
-
- // Record Chromium linker histogram state for the main browser process. Called from
- // onNativeInitializationComplete().
- private void recordBrowserProcessHistogramAlreadyLocked() {
- assert Thread.holdsLock(mLock);
- if (useCrazyLinker()) {
- nativeRecordChromiumAndroidLinkerBrowserHistogram(mIsUsingBrowserSharedRelros,
- mLoadAtFixedAddressFailed,
- mLibraryWasLoadedFromApk ? LibraryLoadFromApkStatusCodes.SUCCESSFUL
- : LibraryLoadFromApkStatusCodes.UNKNOWN,
- mLibraryLoadTimeMs);
- }
- if (mLibraryPreloader != null) {
- nativeRecordLibraryPreloaderBrowserHistogram(mLibraryPreloaderStatus);
- }
- }
-
- // Register pending Chromium linker histogram state for renderer processes. This cannot be
- // recorded as a histogram immediately because histograms and IPC are not ready at the
- // time it are captured. This function stores a pending value, so that a later call to
- // RecordChromiumAndroidLinkerRendererHistogram() will record it correctly.
- public void registerRendererProcessHistogram(boolean requestedSharedRelro,
- boolean loadAtFixedAddressFailed) {
- synchronized (mLock) {
- if (useCrazyLinker()) {
- nativeRegisterChromiumAndroidLinkerRendererHistogram(
- requestedSharedRelro, loadAtFixedAddressFailed, mLibraryLoadTimeMs);
- }
- if (mLibraryPreloader != null) {
- nativeRegisterLibraryPreloaderRendererHistogram(mLibraryPreloaderStatus);
- }
- }
- }
-
- /**
- * Override the library loader (normally with a mock) for testing.
- * @param loader the mock library loader.
- */
- @VisibleForTesting
- public static void setLibraryLoaderForTesting(LibraryLoader loader) {
- sInstance = loader;
- }
-
- /**
- * Configure ubsan using $UBSAN_OPTIONS. This function needs to be called before any native
- * libraries are loaded because ubsan reads its configuration from $UBSAN_OPTIONS when the
- * native library is loaded.
- */
- public static void setEnvForNative() {
- // The setenv API was added in L. On older versions of Android, we should still see ubsan
- // reports, but they will not have stack traces.
- if (BuildConfig.IS_UBSAN && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- try {
- // This value is duplicated in build/android/pylib/constants/__init__.py.
- Os.setenv("UBSAN_OPTIONS",
- "print_stacktrace=1 stack_trace_format='#%n pc %o %m' "
- + "handle_segv=0 handle_sigbus=0 handle_sigfpe=0",
- true);
- } catch (Exception e) {
- Log.w(TAG, "failed to set UBSAN_OPTIONS", e);
- }
- }
- }
-
- // Android system sometimes fails to extract libraries from APK (https://crbug.com/806998).
- // This function manually extract libraries as a fallback.
- @SuppressLint({"SetWorldReadable"})
- private static String extractFileIfStale(
- Context appContext, String pathWithinApk, File destDir) {
- assert PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION;
-
- String apkPath = appContext.getApplicationInfo().sourceDir;
- String fileName =
- (new File(pathWithinApk)).getName() + BuildInfo.getInstance().extractedFileSuffix;
- File libraryFile = new File(destDir, fileName);
-
- if (!libraryFile.exists()) {
- try (ZipFile zipFile = new ZipFile(apkPath);
- InputStream inputStream =
- zipFile.getInputStream(zipFile.getEntry(pathWithinApk))) {
- if (zipFile.getEntry(pathWithinApk) == null)
- throw new RuntimeException("Cannot find ZipEntry" + pathWithinApk);
-
- FileUtils.copyFileStreamAtomicWithBuffer(
- inputStream, libraryFile, new byte[16 * 1024]);
- libraryFile.setReadable(true, false);
- libraryFile.setExecutable(true, false);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- return libraryFile.getAbsolutePath();
- }
-
- // Ensure the extracted native libraries is created with the right permissions.
- private static File makeLibraryDirAndSetPermission() {
- if (!ContextUtils.isIsolatedProcess()) {
- File cacheDir = ContextCompat.getCodeCacheDir(ContextUtils.getApplicationContext());
- File libDir = new File(cacheDir, LIBRARY_DIR);
- cacheDir.mkdir();
- cacheDir.setExecutable(true, false);
- libDir.mkdir();
- libDir.setExecutable(true, false);
- }
- return getLibraryDir();
- }
-
- // Return File object for the directory containing extracted native libraries.
- private static File getLibraryDir() {
- return new File(
- ContextCompat.getCodeCacheDir(ContextUtils.getApplicationContext()), LIBRARY_DIR);
- }
-
- // Only methods needed before or during normal JNI registration are during System.OnLoad.
- // nativeLibraryLoaded is then called to register everything else. This process is called
- // "initialization". This method will be mapped (by generated code) to the LibraryLoaded
- // definition in base/android/library_loader/library_loader_hooks.cc.
- //
- // Return true on success and false on failure.
- private native boolean nativeLibraryLoaded(@LibraryProcessType int processType);
-
- // Method called to record statistics about the Chromium linker operation for the main
- // browser process. Indicates whether the linker attempted relro sharing for the browser,
- // and if it did, whether the library failed to load at a fixed address. Also records
- // support for loading a library directly from the APK file, and the number of milliseconds
- // it took to load the libraries.
- private native void nativeRecordChromiumAndroidLinkerBrowserHistogram(
- boolean isUsingBrowserSharedRelros,
- boolean loadAtFixedAddressFailed,
- int libraryLoadFromApkStatus,
- long libraryLoadTime);
-
- // Method called to record the return value of NativeLibraryPreloader.loadLibrary for the main
- // browser process.
- private native void nativeRecordLibraryPreloaderBrowserHistogram(int status);
-
- // Method called to register (for later recording) statistics about the Chromium linker
- // operation for a renderer process. Indicates whether the linker attempted relro sharing,
- // and if it did, whether the library failed to load at a fixed address. Also records the
- // number of milliseconds it took to load the libraries.
- private native void nativeRegisterChromiumAndroidLinkerRendererHistogram(
- boolean requestedSharedRelro,
- boolean loadAtFixedAddressFailed,
- long libraryLoadTime);
-
- // Method called to register (for later recording) the return value of
- // NativeLibraryPreloader.loadLibrary for a renderer process.
- private native void nativeRegisterLibraryPreloaderRendererHistogram(int status);
-
- // Get the version of the native library. This is needed so that we can check we
- // have the right version before initializing the (rest of the) JNI.
- private native String nativeGetVersionNumber();
-
- // Finds the ranges corresponding to the native library pages, forks a new
- // process to prefetch these pages and waits for it. The new process then
- // terminates. This is blocking.
- private static native void nativeForkAndPrefetchNativeLibrary();
-
- // Returns the percentage of the native library code page that are currently reseident in
- // memory.
- private static native int nativePercentageOfResidentNativeLibraryCode();
-
- // Periodically logs native library residency from this thread.
- private static native void nativePeriodicallyCollectResidency();
-}
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java
deleted file mode 100644
index 5e30cfa496..0000000000
--- a/base/android/java/src/org/chromium/base/library_loader/Linker.java
+++ /dev/null
@@ -1,1160 +0,0 @@
-// Copyright 2015 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.library_loader;
-
-import android.annotation.SuppressLint;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.StreamUtil;
-import org.chromium.base.SysUtils;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.annotations.AccessedByNative;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.MainDex;
-
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-
-/*
- * Technical note:
- *
- * The point of this class is to provide an alternative to System.loadLibrary()
- * to load native shared libraries. One specific feature that it supports is the
- * ability to save RAM by sharing the ELF RELRO sections between renderer
- * processes.
- *
- * When two processes load the same native library at the _same_ memory address,
- * the content of their RELRO section (which includes C++ vtables or any
- * constants that contain pointers) will be largely identical [1].
- *
- * By default, the RELRO section is backed by private RAM in each process,
- * which is still significant on mobile (e.g. 1.28 MB / process on Chrome 30 for
- * Android).
- *
- * However, it is possible to save RAM by creating a shared memory region,
- * copy the RELRO content into it, then have each process swap its private,
- * regular RELRO, with a shared, read-only, mapping of the shared one.
- *
- * This trick saves 98% of the RELRO section size per extra process, after the
- * first one. On the other hand, this requires careful communication between
- * the process where the shared RELRO is created and the one(s) where it is used.
- *
- * Note that swapping the regular RELRO with the shared one is not an atomic
- * operation. Care must be taken that no other thread tries to run native code
- * that accesses it during it. In practice, this means the swap must happen
- * before library native code is executed.
- *
- * [1] The exceptions are pointers to external, randomized, symbols, like
- * those from some system libraries, but these are very few in practice.
- */
-
-/*
- * Security considerations:
- *
- * - Whether the browser process loads its native libraries at the same
- * addresses as the service ones (to save RAM by sharing the RELRO too)
- * depends on the configuration variable BROWSER_SHARED_RELRO_CONFIG.
- *
- * Not using fixed library addresses in the browser process is preferred
- * for regular devices since it maintains the efficacy of ASLR as an
- * exploit mitigation across the render <-> browser privilege boundary.
- *
- * - The shared RELRO memory region is always forced read-only after creation,
- * which means it is impossible for a compromised service process to map
- * it read-write (e.g. by calling mmap() or mprotect()) and modify its
- * content, altering values seen in other service processes.
- *
- * - Once the RELRO ashmem region or file is mapped into a service process's
- * address space, the corresponding file descriptor is immediately closed. The
- * file descriptor is kept opened in the browser process, because a copy needs
- * to be sent to each new potential service process.
- *
- * - The common library load addresses are randomized for each instance of
- * the program on the device. See getRandomBaseLoadAddress() for more
- * details on how this is obtained.
- *
- * - When loading several libraries in service processes, a simple incremental
- * approach from the original random base load address is used. This is
- * sufficient to deal correctly with component builds (which can use dozens
- * of shared libraries), while regular builds always embed a single shared
- * library per APK.
- */
-
-/**
- * Here's an explanation of how this class is supposed to be used:
- *
- * - Native shared libraries should be loaded with Linker.loadLibrary(),
- * instead of System.loadLibrary(). The two functions should behave the same
- * (at a high level).
- *
- * - Before loading any library, prepareLibraryLoad() should be called.
- *
- * - After loading all libraries, finishLibraryLoad() should be called, before
- * running any native code from any of the libraries (except their static
- * constructors, which can't be avoided).
- *
- * - A service process shall call either initServiceProcess() or
- * disableSharedRelros() early (i.e. before any loadLibrary() call).
- * Otherwise, the linker considers that it is running inside the browser
- * process. This is because various Chromium projects have vastly
- * different initialization paths.
- *
- * disableSharedRelros() completely disables shared RELROs, and loadLibrary()
- * will behave exactly like System.loadLibrary().
- *
- * initServiceProcess(baseLoadAddress) indicates that shared RELROs are to be
- * used in this process.
- *
- * - The browser is in charge of deciding where in memory each library should
- * be loaded. This address must be passed to each service process (see
- * ChromiumLinkerParams.java in content for a helper class to do so).
- *
- * - The browser will also generate shared RELROs for each library it loads.
- * More specifically, by default when in the browser process, the linker
- * will:
- *
- * - Load libraries randomly (just like System.loadLibrary()).
- * - Compute the fixed address to be used to load the same library
- * in service processes.
- * - Create a shared memory region populated with the RELRO region
- * content pre-relocated for the specific fixed address above.
- *
- * Note that these shared RELRO regions cannot be used inside the browser
- * process. They are also never mapped into it.
- *
- * This behaviour is altered by the BROWSER_SHARED_RELRO_CONFIG configuration
- * variable below, which may force the browser to load the libraries at
- * fixed addresses too.
- *
- * - Once all libraries are loaded in the browser process, one can call
- * getSharedRelros() which returns a Bundle instance containing a map that
- * links each loaded library to its shared RELRO region.
- *
- * This Bundle must be passed to each service process, for example through
- * a Binder call (note that the Bundle includes file descriptors and cannot
- * be added as an Intent extra).
- *
- * - In a service process, finishLibraryLoad() and/or loadLibrary() may
- * block until the RELRO section Bundle is received. This is typically
- * done by calling useSharedRelros() from another thread.
- *
- * This method also ensures the process uses the shared RELROs.
- */
-public class Linker {
- // Log tag for this class.
- private static final String TAG = "LibraryLoader";
-
- // Name of the library that contains our JNI code.
- private static final String LINKER_JNI_LIBRARY = "chromium_android_linker";
-
- // Constants used to control the behaviour of the browser process with
- // regards to the shared RELRO section.
- // NEVER -> The browser never uses it itself.
- // LOW_RAM_ONLY -> It is only used on devices with low RAM.
- // ALWAYS -> It is always used.
- // NOTE: These names are known and expected by the Linker test scripts.
- public static final int BROWSER_SHARED_RELRO_CONFIG_NEVER = 0;
- public static final int BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY = 1;
- public static final int BROWSER_SHARED_RELRO_CONFIG_ALWAYS = 2;
-
- // Configuration variable used to control how the browser process uses the
- // shared RELRO. Only change this while debugging linker-related issues.
- // NOTE: This variable's name is known and expected by the Linker test scripts.
- public static final int BROWSER_SHARED_RELRO_CONFIG =
- BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY;
-
- // Constants used to control the memory device config. Can be set explicitly
- // by setMemoryDeviceConfigForTesting().
- // INIT -> Value is undetermined (will check at runtime).
- // LOW -> This is a low-memory device.
- // NORMAL -> This is not a low-memory device.
- public static final int MEMORY_DEVICE_CONFIG_INIT = 0;
- public static final int MEMORY_DEVICE_CONFIG_LOW = 1;
- public static final int MEMORY_DEVICE_CONFIG_NORMAL = 2;
-
- // Indicates if this is a low-memory device or not. The default is to
- // determine this by probing the system at runtime, but this can be forced
- // for testing by calling setMemoryDeviceConfigForTesting().
- private int mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_INIT;
-
- // Set to true to enable debug logs.
- protected static final boolean DEBUG = false;
-
- // Used to pass the shared RELRO Bundle through Binder.
- public static final String EXTRA_LINKER_SHARED_RELROS =
- "org.chromium.base.android.linker.shared_relros";
-
- // Guards all access to the linker.
- protected final Object mLock = new Object();
-
- // The name of a class that implements TestRunner.
- private String mTestRunnerClassName;
-
- // Size of reserved Breakpad guard region. Should match the value of
- // kBreakpadGuardRegionBytes on the JNI side. Used when computing the load
- // addresses of multiple loaded libraries. Set to 0 to disable the guard.
- private static final int BREAKPAD_GUARD_REGION_BYTES = 16 * 1024 * 1024;
-
- // Size of the area requested when using ASLR to obtain a random load address.
- // Should match the value of kAddressSpaceReservationSize on the JNI side.
- // Used when computing the load addresses of multiple loaded libraries to
- // ensure that we don't try to load outside the area originally requested.
- private static final int ADDRESS_SPACE_RESERVATION = 192 * 1024 * 1024;
-
- // Becomes true after linker initialization.
- private boolean mInitialized;
-
- // Set to true if this runs in the browser process. Disabled by initServiceProcess().
- private boolean mInBrowserProcess = true;
-
- // Becomes true to indicate this process needs to wait for a shared RELRO in
- // finishLibraryLoad().
- private boolean mWaitForSharedRelros;
-
- // Becomes true when initialization determines that the browser process can use the
- // shared RELRO.
- private boolean mBrowserUsesSharedRelro;
-
- // The map of all RELRO sections either created or used in this process.
- private Bundle mSharedRelros;
-
- // Current common random base load address. A value of -1 indicates not yet initialized.
- private long mBaseLoadAddress = -1;
-
- // Current fixed-location load address for the next library called by loadLibrary().
- // A value of -1 indicates not yet initialized.
- private long mCurrentLoadAddress = -1;
-
- // Becomes true once prepareLibraryLoad() has been called.
- private boolean mPrepareLibraryLoadCalled;
-
- // The map of libraries that are currently loaded in this process.
- private HashMap<String, LibInfo> mLoadedLibraries;
-
- // Singleton.
- private static final Linker sSingleton = new Linker();
-
- // Private singleton constructor.
- private Linker() {
- // Ensure this class is not referenced unless it's used.
- assert LibraryLoader.useCrazyLinker();
- }
-
- /**
- * Get singleton instance. Returns a Linker.
- *
- * On N+ Monochrome is selected by Play Store. With Monochrome this code is not used, instead
- * Chrome asks the WebView to provide the library (and the shared RELRO). If the WebView fails
- * to provide the library, the system linker is used as a fallback.
- *
- * Linker runs on all Android releases, but is incompatible with GVR library on N+.
- * Linker is preferred on M- because it does not write the shared RELRO to disk at
- * almost every cold startup.
- *
- * @return the Linker implementation instance.
- */
- public static Linker getInstance() {
- return sSingleton;
- }
-
- /**
- * Check that native library linker tests are enabled.
- * If not enabled, calls to testing functions will fail with an assertion
- * error.
- *
- * @return true if native library linker tests are enabled.
- */
- public static boolean areTestsEnabled() {
- return NativeLibraries.sEnableLinkerTests;
- }
-
- /**
- * Assert NativeLibraries.sEnableLinkerTests is true.
- * Hard assertion that we are in a testing context. Cannot be disabled. The
- * test methods in this module permit injection of runnable code by class
- * name. To protect against both malicious and accidental use of these
- * methods, we ensure that NativeLibraries.sEnableLinkerTests is true when
- * any is called.
- */
- private static void assertLinkerTestsAreEnabled() {
- assert NativeLibraries.sEnableLinkerTests : "Testing method called in non-testing context";
- }
-
- /**
- * A public interface used to run runtime linker tests after loading
- * libraries. Should only be used to implement the linker unit tests,
- * which is controlled by the value of NativeLibraries.sEnableLinkerTests
- * configured at build time.
- */
- public interface TestRunner {
- /**
- * Run runtime checks and return true if they all pass.
- *
- * @param memoryDeviceConfig The current memory device configuration.
- * @param inBrowserProcess true iff this is the browser process.
- * @return true if all checks pass.
- */
- public boolean runChecks(int memoryDeviceConfig, boolean inBrowserProcess);
- }
-
- /**
- * Call this to retrieve the name of the current TestRunner class name
- * if any. This can be useful to pass it from the browser process to
- * child ones.
- *
- * @return null or a String holding the name of the class implementing
- * the TestRunner set by calling setTestRunnerClassNameForTesting() previously.
- */
- public final String getTestRunnerClassNameForTesting() {
- // Sanity check. This method may only be called during tests.
- assertLinkerTestsAreEnabled();
-
- synchronized (mLock) {
- return mTestRunnerClassName;
- }
- }
-
- /**
- * Sets the test class name.
- *
- * On the first call, instantiates a Linker and sets its test runner class name. On subsequent
- * calls, checks that the singleton produced by the first call matches the test runner class
- * name.
- */
- public static final void setupForTesting(String testRunnerClassName) {
- if (DEBUG) {
- Log.i(TAG, "setupForTesting(" + testRunnerClassName + ") called");
- }
- // Sanity check. This method may only be called during tests.
- assertLinkerTestsAreEnabled();
-
- synchronized (sSingleton) {
- sSingleton.mTestRunnerClassName = testRunnerClassName;
- }
- }
-
- /**
- * Instantiate and run the current TestRunner, if any. The TestRunner implementation
- * must be instantiated _after_ all libraries are loaded to ensure that its
- * native methods are properly registered.
- *
- * @param memoryDeviceConfig Linker memory config, or 0 if unused
- * @param inBrowserProcess true if in the browser process
- */
- private final void runTestRunnerClassForTesting(
- int memoryDeviceConfig, boolean inBrowserProcess) {
- if (DEBUG) {
- Log.i(TAG, "runTestRunnerClassForTesting called");
- }
- // Sanity check. This method may only be called during tests.
- assertLinkerTestsAreEnabled();
-
- synchronized (mLock) {
- if (mTestRunnerClassName == null) {
- Log.wtf(TAG, "Linker runtime tests not set up for this process");
- assert false;
- }
- if (DEBUG) {
- Log.i(TAG, "Instantiating " + mTestRunnerClassName);
- }
- TestRunner testRunner = null;
- try {
- testRunner = (TestRunner) Class.forName(mTestRunnerClassName)
- .getDeclaredConstructor()
- .newInstance();
- } catch (Exception e) {
- Log.wtf(TAG, "Could not instantiate test runner class by name", e);
- assert false;
- }
-
- if (!testRunner.runChecks(memoryDeviceConfig, inBrowserProcess)) {
- Log.wtf(TAG, "Linker runtime tests failed in this process");
- assert false;
- }
-
- Log.i(TAG, "All linker tests passed");
- }
- }
-
- /**
- * Call this method before any other Linker method to force a specific
- * memory device configuration. Should only be used for testing.
- *
- * @param memoryDeviceConfig MEMORY_DEVICE_CONFIG_LOW or MEMORY_DEVICE_CONFIG_NORMAL.
- */
- public final void setMemoryDeviceConfigForTesting(int memoryDeviceConfig) {
- if (DEBUG) {
- Log.i(TAG, "setMemoryDeviceConfigForTesting(" + memoryDeviceConfig + ") called");
- }
- // Sanity check. This method may only be called during tests.
- assertLinkerTestsAreEnabled();
- assert memoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW
- || memoryDeviceConfig == MEMORY_DEVICE_CONFIG_NORMAL;
-
- synchronized (mLock) {
- assert mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT;
-
- mMemoryDeviceConfig = memoryDeviceConfig;
- if (DEBUG) {
- if (mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW) {
- Log.i(TAG, "Simulating a low-memory device");
- } else {
- Log.i(TAG, "Simulating a regular-memory device");
- }
- }
- }
- }
-
- /**
- * Determine whether a library is the linker library.
- *
- * @param library the name of the library.
- * @return true is the library is the Linker's own JNI library.
- */
- boolean isChromiumLinkerLibrary(String library) {
- return library.equals(LINKER_JNI_LIBRARY);
- }
-
- /**
- * Load the Linker JNI library. Throws UnsatisfiedLinkError on error.
- */
- @SuppressLint({"UnsafeDynamicallyLoadedCode"})
- private static void loadLinkerJniLibrary() {
- LibraryLoader.setEnvForNative();
- if (DEBUG) {
- String libName = "lib" + LINKER_JNI_LIBRARY + ".so";
- Log.i(TAG, "Loading " + libName);
- }
- try {
- System.loadLibrary(LINKER_JNI_LIBRARY);
- LibraryLoader.incrementRelinkerCountNotHitHistogram();
- } catch (UnsatisfiedLinkError e) {
- if (LibraryLoader.PLATFORM_REQUIRES_NATIVE_FALLBACK_EXTRACTION) {
- System.load(LibraryLoader.getExtractedLibraryPath(
- ContextUtils.getApplicationContext(), LINKER_JNI_LIBRARY));
- LibraryLoader.incrementRelinkerCountHitHistogram();
- }
- }
- }
-
- /**
- * Obtain a random base load address at which to place loaded libraries.
- *
- * @return new base load address
- */
- private long getRandomBaseLoadAddress() {
- // nativeGetRandomBaseLoadAddress() returns an address at which it has previously
- // successfully mapped an area larger than the largest library we expect to load,
- // on the basis that we will be able, with high probability, to map our library
- // into it.
- //
- // One issue with this is that we do not yet know the size of the library that
- // we will load is. If it is smaller than the size we used to obtain a random
- // address the library mapping may still succeed. The other issue is that
- // although highly unlikely, there is no guarantee that something else does not
- // map into the area we are going to use between here and when we try to map into it.
- //
- // The above notes mean that all of this is probablistic. It is however okay to do
- // because if, worst case and unlikely, we get unlucky in our choice of address,
- // the back-out and retry without the shared RELRO in the ChildProcessService will
- // keep things running.
- final long address = nativeGetRandomBaseLoadAddress();
- if (DEBUG) {
- Log.i(TAG, String.format(Locale.US, "Random native base load address: 0x%x", address));
- }
- return address;
- }
-
- /**
- * Load a native shared library with the Chromium linker. Note the crazy linker treats
- * libraries and files as equivalent, so you can only open one library in a given zip
- * file. The library must not be the Chromium linker library.
- *
- * @param libFilePath The path of the library (possibly in the zip file).
- */
- void loadLibrary(String libFilePath) {
- if (DEBUG) {
- Log.i(TAG, "loadLibrary: " + libFilePath);
- }
- final boolean isFixedAddressPermitted = true;
- loadLibraryImpl(libFilePath, isFixedAddressPermitted);
- }
-
- /**
- * Load a native shared library with the Chromium linker, ignoring any
- * requested fixed address for RELRO sharing. Note the crazy linker treats libraries and
- * files as equivalent, so you can only open one library in a given zip file. The
- * library must not be the Chromium linker library.
- *
- * @param libFilePath The path of the library (possibly in the zip file).
- */
- void loadLibraryNoFixedAddress(String libFilePath) {
- if (DEBUG) {
- Log.i(TAG, "loadLibraryAtAnyAddress: " + libFilePath);
- }
- final boolean isFixedAddressPermitted = false;
- loadLibraryImpl(libFilePath, isFixedAddressPermitted);
- }
-
- // Used internally to initialize the linker's data. Assumes lock is held.
- // Loads JNI, and sets mMemoryDeviceConfig and mBrowserUsesSharedRelro.
- private void ensureInitializedLocked() {
- assert Thread.holdsLock(mLock);
-
- if (mInitialized) {
- return;
- }
-
- // On first call, load libchromium_android_linker.so. Cannot be done in the
- // constructor because instantiation occurs on the UI thread.
- loadLinkerJniLibrary();
-
- if (mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT) {
- if (SysUtils.isLowEndDevice()) {
- mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_LOW;
- } else {
- mMemoryDeviceConfig = MEMORY_DEVICE_CONFIG_NORMAL;
- }
- }
-
- // Cannot run in the constructor because SysUtils.isLowEndDevice() relies
- // on CommandLine, which may not be available at instantiation.
- switch (BROWSER_SHARED_RELRO_CONFIG) {
- case BROWSER_SHARED_RELRO_CONFIG_NEVER:
- mBrowserUsesSharedRelro = false;
- break;
- case BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY:
- if (mMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW) {
- mBrowserUsesSharedRelro = true;
- Log.w(TAG, "Low-memory device: shared RELROs used in all processes");
- } else {
- mBrowserUsesSharedRelro = false;
- }
- break;
- case BROWSER_SHARED_RELRO_CONFIG_ALWAYS:
- Log.w(TAG, "Beware: shared RELROs used in all processes!");
- mBrowserUsesSharedRelro = true;
- break;
- default:
- Log.wtf(TAG, "FATAL: illegal shared RELRO config");
- throw new AssertionError();
- }
-
- mInitialized = true;
- }
-
- /**
- * Call this method to determine if the linker will try to use shared RELROs
- * for the browser process.
- */
- public boolean isUsingBrowserSharedRelros() {
- synchronized (mLock) {
- ensureInitializedLocked();
- return mInBrowserProcess && mBrowserUsesSharedRelro;
- }
- }
-
- /**
- * Call this method just before loading any native shared libraries in this process.
- *
- * @param apkFilePath Optional current APK file path. If provided, the linker
- * will try to load libraries directly from it.
- */
- public void prepareLibraryLoad(@Nullable String apkFilePath) {
- if (DEBUG) {
- Log.i(TAG, "prepareLibraryLoad() called");
- }
- synchronized (mLock) {
- ensureInitializedLocked();
- if (apkFilePath != null) {
- nativeAddZipArchivePath(apkFilePath);
- }
- mPrepareLibraryLoadCalled = true;
-
- if (mInBrowserProcess) {
- // Force generation of random base load address, as well
- // as creation of shared RELRO sections in this process.
- setupBaseLoadAddressLocked();
- }
- }
- }
-
- /**
- * Call this method just after loading all native shared libraries in this process.
- * Note that when in a service process, this will block until the RELRO bundle is
- * received, i.e. when another thread calls useSharedRelros().
- */
- void finishLibraryLoad() {
- if (DEBUG) {
- Log.i(TAG, "finishLibraryLoad() called");
- }
- synchronized (mLock) {
- ensureInitializedLocked();
- if (DEBUG) {
- Log.i(TAG,
- String.format(Locale.US,
- "mInBrowserProcess=%b mBrowserUsesSharedRelro=%b mWaitForSharedRelros=%b",
- mInBrowserProcess, mBrowserUsesSharedRelro, mWaitForSharedRelros));
- }
-
- if (mLoadedLibraries == null) {
- if (DEBUG) {
- Log.i(TAG, "No libraries loaded");
- }
- } else {
- if (mInBrowserProcess) {
- // Create new Bundle containing RELRO section information
- // for all loaded libraries. Make it available to getSharedRelros().
- mSharedRelros = createBundleFromLibInfoMap(mLoadedLibraries);
- if (DEBUG) {
- Log.i(TAG, "Shared RELRO created");
- dumpBundle(mSharedRelros);
- }
-
- if (mBrowserUsesSharedRelro) {
- useSharedRelrosLocked(mSharedRelros);
- }
- }
-
- if (mWaitForSharedRelros) {
- assert !mInBrowserProcess;
-
- // Wait until the shared relro bundle is received from useSharedRelros().
- while (mSharedRelros == null) {
- try {
- mLock.wait();
- } catch (InterruptedException ie) {
- // Restore the thread's interrupt status.
- Thread.currentThread().interrupt();
- }
- }
- useSharedRelrosLocked(mSharedRelros);
- // Clear the Bundle to ensure its file descriptor references can't be reused.
- mSharedRelros.clear();
- mSharedRelros = null;
- }
- }
-
- // If testing, run tests now that all libraries are loaded and initialized.
- if (NativeLibraries.sEnableLinkerTests) {
- runTestRunnerClassForTesting(mMemoryDeviceConfig, mInBrowserProcess);
- }
- }
- if (DEBUG) {
- Log.i(TAG, "finishLibraryLoad() exiting");
- }
- }
-
- /**
- * Call this to send a Bundle containing the shared RELRO sections to be
- * used in this process. If initServiceProcess() was previously called,
- * finishLibraryLoad() will not exit until this method is called in another
- * thread with a non-null value.
- *
- * @param bundle The Bundle instance containing a map of shared RELRO sections
- * to use in this process.
- */
- public void useSharedRelros(Bundle bundle) {
- // Ensure the bundle uses the application's class loader, not the framework
- // one which doesn't know anything about LibInfo.
- // Also, hold a fresh copy of it so the caller can't recycle it.
- Bundle clonedBundle = null;
- if (bundle != null) {
- bundle.setClassLoader(LibInfo.class.getClassLoader());
- clonedBundle = new Bundle(LibInfo.class.getClassLoader());
- Parcel parcel = Parcel.obtain();
- bundle.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- clonedBundle.readFromParcel(parcel);
- parcel.recycle();
- }
- if (DEBUG) {
- Log.i(TAG, "useSharedRelros() called with " + bundle + ", cloned " + clonedBundle);
- }
- synchronized (mLock) {
- // Note that in certain cases, this can be called before
- // initServiceProcess() in service processes.
- mSharedRelros = clonedBundle;
- // Tell any listener blocked in finishLibraryLoad() about it.
- mLock.notifyAll();
- }
- }
-
- /**
- * Call this to retrieve the shared RELRO sections created in this process,
- * after loading all libraries.
- *
- * @return a new Bundle instance, or null if RELRO sharing is disabled on
- * this system, or if initServiceProcess() was called previously.
- */
- public Bundle getSharedRelros() {
- if (DEBUG) {
- Log.i(TAG, "getSharedRelros() called");
- }
- synchronized (mLock) {
- if (!mInBrowserProcess) {
- if (DEBUG) {
- Log.i(TAG, "... returning null Bundle");
- }
- return null;
- }
-
- // Return the Bundle created in finishLibraryLoad().
- if (DEBUG) {
- Log.i(TAG, "... returning " + mSharedRelros);
- }
- return mSharedRelros;
- }
- }
-
- /**
- * Call this method before loading any libraries to indicate that this
- * process shall neither create or reuse shared RELRO sections.
- */
- public void disableSharedRelros() {
- if (DEBUG) {
- Log.i(TAG, "disableSharedRelros() called");
- }
- synchronized (mLock) {
- ensureInitializedLocked();
- mInBrowserProcess = false;
- mWaitForSharedRelros = false;
- mBrowserUsesSharedRelro = false;
- }
- }
-
- /**
- * Call this method before loading any libraries to indicate that this
- * process is ready to reuse shared RELRO sections from another one.
- * Typically used when starting service processes.
- *
- * @param baseLoadAddress the base library load address to use.
- */
- public void initServiceProcess(long baseLoadAddress) {
- if (DEBUG) {
- Log.i(TAG,
- String.format(Locale.US, "initServiceProcess(0x%x) called", baseLoadAddress));
- }
- synchronized (mLock) {
- ensureInitializedLocked();
- mInBrowserProcess = false;
- mBrowserUsesSharedRelro = false;
- mWaitForSharedRelros = true;
- mBaseLoadAddress = baseLoadAddress;
- mCurrentLoadAddress = baseLoadAddress;
- }
- }
-
- /**
- * Retrieve the base load address of all shared RELRO sections.
- * This also enforces the creation of shared RELRO sections in
- * prepareLibraryLoad(), which can later be retrieved with getSharedRelros().
- *
- * @return a common, random base load address, or 0 if RELRO sharing is
- * disabled.
- */
- public long getBaseLoadAddress() {
- synchronized (mLock) {
- ensureInitializedLocked();
- if (!mInBrowserProcess) {
- Log.w(TAG, "Shared RELRO sections are disabled in this process!");
- return 0;
- }
-
- setupBaseLoadAddressLocked();
- if (DEBUG) {
- Log.i(TAG,
- String.format(
- Locale.US, "getBaseLoadAddress() returns 0x%x", mBaseLoadAddress));
- }
- return mBaseLoadAddress;
- }
- }
-
- // Used internally to lazily setup the common random base load address.
- private void setupBaseLoadAddressLocked() {
- assert Thread.holdsLock(mLock);
- if (mBaseLoadAddress == -1) {
- mBaseLoadAddress = getRandomBaseLoadAddress();
- mCurrentLoadAddress = mBaseLoadAddress;
- if (mBaseLoadAddress == 0) {
- // If the random address is 0 there are issues with finding enough
- // free address space, so disable RELRO shared / fixed load addresses.
- Log.w(TAG, "Disabling shared RELROs due address space pressure");
- mBrowserUsesSharedRelro = false;
- mWaitForSharedRelros = false;
- }
- }
- }
-
- // Used for debugging only.
- private void dumpBundle(Bundle bundle) {
- if (DEBUG) {
- Log.i(TAG, "Bundle has " + bundle.size() + " items: " + bundle);
- }
- }
-
- /**
- * Use the shared RELRO section from a Bundle received form another process.
- * Call this after calling setBaseLoadAddress() then loading all libraries
- * with loadLibrary().
- *
- * @param bundle Bundle instance generated with createSharedRelroBundle() in
- * another process.
- */
- private void useSharedRelrosLocked(Bundle bundle) {
- assert Thread.holdsLock(mLock);
-
- if (DEBUG) {
- Log.i(TAG, "Linker.useSharedRelrosLocked() called");
- }
-
- if (bundle == null) {
- if (DEBUG) {
- Log.i(TAG, "null bundle!");
- }
- return;
- }
-
- if (mLoadedLibraries == null) {
- if (DEBUG) {
- Log.i(TAG, "No libraries loaded!");
- }
- return;
- }
-
- if (DEBUG) {
- dumpBundle(bundle);
- }
- HashMap<String, LibInfo> relroMap = createLibInfoMapFromBundle(bundle);
-
- // Apply the RELRO section to all libraries that were already loaded.
- for (Map.Entry<String, LibInfo> entry : relroMap.entrySet()) {
- String libName = entry.getKey();
- LibInfo libInfo = entry.getValue();
- if (!nativeUseSharedRelro(libName, libInfo)) {
- Log.w(TAG, "Could not use shared RELRO section for " + libName);
- } else {
- if (DEBUG) {
- Log.i(TAG, "Using shared RELRO section for " + libName);
- }
- }
- }
-
- // In service processes, close all file descriptors from the map now.
- if (!mInBrowserProcess) {
- closeLibInfoMap(relroMap);
- }
-
- if (DEBUG) {
- Log.i(TAG, "Linker.useSharedRelrosLocked() exiting");
- }
- }
-
- /**
- * Implements loading a native shared library with the Chromium linker.
- *
- * Load a native shared library with the Chromium linker. If the zip file
- * is not null, the shared library must be 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. The
- * library must not be the Chromium linker library.
- *
- * @param libFilePath The path of the library (possibly in the zip file).
- * @param isFixedAddressPermitted If true, uses a fixed load address if one was
- * supplied, otherwise ignores the fixed address and loads wherever available.
- */
- void loadLibraryImpl(String libFilePath, boolean isFixedAddressPermitted) {
- if (DEBUG) {
- Log.i(TAG, "loadLibraryImpl: " + libFilePath + ", " + isFixedAddressPermitted);
- }
- synchronized (mLock) {
- ensureInitializedLocked();
-
- // Security: Ensure prepareLibraryLoad() was called before.
- // In theory, this can be done lazily here, but it's more consistent
- // to use a pair of functions (i.e. prepareLibraryLoad() + finishLibraryLoad())
- // that wrap all calls to loadLibrary() in the library loader.
- assert mPrepareLibraryLoadCalled;
-
- if (mLoadedLibraries == null) {
- mLoadedLibraries = new HashMap<String, LibInfo>();
- }
-
- if (mLoadedLibraries.containsKey(libFilePath)) {
- if (DEBUG) {
- Log.i(TAG, "Not loading " + libFilePath + " twice");
- }
- return;
- }
-
- LibInfo libInfo = new LibInfo();
- long loadAddress = 0;
- if (isFixedAddressPermitted) {
- if ((mInBrowserProcess && mBrowserUsesSharedRelro) || mWaitForSharedRelros) {
- // Load the library at a fixed address.
- loadAddress = mCurrentLoadAddress;
-
- // For multiple libraries, ensure we stay within reservation range.
- if (loadAddress > mBaseLoadAddress + ADDRESS_SPACE_RESERVATION) {
- String errorMessage =
- "Load address outside reservation, for: " + libFilePath;
- Log.e(TAG, errorMessage);
- throw new UnsatisfiedLinkError(errorMessage);
- }
- }
- }
-
- final String sharedRelRoName = libFilePath;
- if (!nativeLoadLibrary(libFilePath, loadAddress, libInfo)) {
- String errorMessage = "Unable to load library: " + libFilePath;
- Log.e(TAG, errorMessage);
- throw new UnsatisfiedLinkError(errorMessage);
- }
-
- // Print the load address to the logcat when testing the linker. The format
- // of the string is expected by the Python test_runner script as one of:
- // BROWSER_LIBRARY_ADDRESS: <library-name> <address>
- // RENDERER_LIBRARY_ADDRESS: <library-name> <address>
- // Where <library-name> is the library name, and <address> is the hexadecimal load
- // address.
- if (NativeLibraries.sEnableLinkerTests) {
- String tag =
- mInBrowserProcess ? "BROWSER_LIBRARY_ADDRESS" : "RENDERER_LIBRARY_ADDRESS";
- Log.i(TAG,
- String.format(
- Locale.US, "%s: %s %x", tag, libFilePath, libInfo.mLoadAddress));
- }
-
- if (mInBrowserProcess) {
- // Create a new shared RELRO section at the 'current' fixed load address.
- if (!nativeCreateSharedRelro(sharedRelRoName, mCurrentLoadAddress, libInfo)) {
- Log.w(TAG,
- String.format(Locale.US, "Could not create shared RELRO for %s at %x",
- libFilePath, mCurrentLoadAddress));
- } else {
- if (DEBUG) {
- Log.i(TAG,
- String.format(Locale.US, "Created shared RELRO for %s at %x: %s",
- sharedRelRoName, mCurrentLoadAddress, libInfo.toString()));
- }
- }
- }
-
- if (loadAddress != 0 && mCurrentLoadAddress != 0) {
- // Compute the next current load address. If mCurrentLoadAddress
- // is not 0, this is an explicit library load address. Otherwise,
- // this is an explicit load address for relocated RELRO sections
- // only.
- mCurrentLoadAddress =
- libInfo.mLoadAddress + libInfo.mLoadSize + BREAKPAD_GUARD_REGION_BYTES;
- }
-
- mLoadedLibraries.put(sharedRelRoName, libInfo);
- if (DEBUG) {
- Log.i(TAG, "Library details " + libInfo.toString());
- }
- }
- }
-
- /**
- * 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.
- * Also, the LibInfo instance owns the shared RELRO file descriptor.
- */
- private static class LibInfo implements Parcelable {
- LibInfo() {}
-
- // from Parcelable
- LibInfo(Parcel in) {
- mLoadAddress = in.readLong();
- mLoadSize = in.readLong();
- mRelroStart = in.readLong();
- mRelroSize = in.readLong();
- ParcelFileDescriptor fd = ParcelFileDescriptor.CREATOR.createFromParcel(in);
- // If CreateSharedRelro fails, the OS file descriptor will be -1 and |fd| will be null.
- if (fd != null) {
- mRelroFd = fd.detachFd();
- }
- }
-
- public void close() {
- if (mRelroFd >= 0) {
- StreamUtil.closeQuietly(ParcelFileDescriptor.adoptFd(mRelroFd));
- mRelroFd = -1;
- }
- }
-
- // from Parcelable
- @Override
- public void writeToParcel(Parcel out, int flags) {
- if (mRelroFd >= 0) {
- out.writeLong(mLoadAddress);
- out.writeLong(mLoadSize);
- out.writeLong(mRelroStart);
- out.writeLong(mRelroSize);
- try {
- ParcelFileDescriptor fd = ParcelFileDescriptor.fromFd(mRelroFd);
- fd.writeToParcel(out, 0);
- fd.close();
- } catch (java.io.IOException e) {
- Log.e(TAG, "Can't write LibInfo file descriptor to parcel", e);
- }
- }
- }
-
- // from Parcelable
- @Override
- public int describeContents() {
- return Parcelable.CONTENTS_FILE_DESCRIPTOR;
- }
-
- // from Parcelable
- public static final Parcelable.Creator<LibInfo> CREATOR =
- new Parcelable.Creator<LibInfo>() {
- @Override
- public LibInfo createFromParcel(Parcel in) {
- return new LibInfo(in);
- }
-
- @Override
- public LibInfo[] newArray(int size) {
- return new LibInfo[size];
- }
- };
-
- // IMPORTANT: Don't change these fields without modifying the
- // native code that accesses them directly!
- @AccessedByNative
- public long mLoadAddress; // page-aligned library load address.
- @AccessedByNative
- public long mLoadSize; // page-aligned library load size.
- @AccessedByNative
- public long mRelroStart; // page-aligned address in memory, or 0 if none.
- @AccessedByNative
- public long mRelroSize; // page-aligned size in memory, or 0.
- @AccessedByNative
- public int mRelroFd = -1; // shared RELRO file descriptor, or -1
- }
-
- // Create a Bundle from a map of LibInfo objects.
- private Bundle createBundleFromLibInfoMap(HashMap<String, LibInfo> map) {
- Bundle bundle = new Bundle(map.size());
- for (Map.Entry<String, LibInfo> entry : map.entrySet()) {
- bundle.putParcelable(entry.getKey(), entry.getValue());
- }
- return bundle;
- }
-
- // Create a new LibInfo map from a Bundle.
- private HashMap<String, LibInfo> createLibInfoMapFromBundle(Bundle bundle) {
- HashMap<String, LibInfo> map = new HashMap<String, LibInfo>();
- for (String library : bundle.keySet()) {
- LibInfo libInfo = bundle.getParcelable(library);
- map.put(library, libInfo);
- }
- return map;
- }
-
- // Call the close() method on all values of a LibInfo map.
- private void closeLibInfoMap(HashMap<String, LibInfo> map) {
- for (Map.Entry<String, LibInfo> entry : map.entrySet()) {
- entry.getValue().close();
- }
- }
-
- /**
- * 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.
- *
- * @param opaque Opaque argument.
- */
- @CalledByNative
- @MainDex
- private static void postCallbackOnMainThread(final long opaque) {
- ThreadUtils.postOnUiThread(new Runnable() {
- @Override
- public void run() {
- nativeRunCallbackOnUiThread(opaque);
- }
- });
- }
-
- /**
- * Native method to run callbacks on the main UI thread.
- * Supplied by the crazy linker and called by postCallbackOnMainThread.
- *
- * @param opaque Opaque crazy linker arguments.
- */
- private static native void nativeRunCallbackOnUiThread(long opaque);
-
- /**
- * Native method used to load a library.
- *
- * @param library Platform specific library name (e.g. libfoo.so)
- * @param loadAddress Explicit load address, or 0 for randomized one.
- * @param libInfo If not null, the mLoadAddress and mLoadSize fields
- * of this LibInfo instance will set on success.
- * @return true for success, false otherwise.
- */
- private static native boolean nativeLoadLibrary(
- String library, long loadAddress, LibInfo libInfo);
-
- /**
- * Native method used to add a zip archive or APK to the search path
- * for native libraries. Allows loading directly from it.
- *
- * @param zipfilePath Path of the zip file containing the libraries.
- * @return true for success, false otherwise.
- */
- private static native boolean nativeAddZipArchivePath(String zipFilePath);
-
- /**
- * Native method used to create a shared RELRO section.
- * If the library was already loaded at the same address using
- * nativeLoadLibrary(), this creates the RELRO for it. Otherwise,
- * this loads a new temporary library at the specified address,
- * creates and extracts the RELRO section from it, then unloads it.
- *
- * @param library Library name.
- * @param loadAddress load address, which can be different from the one
- * used to load the library in the current process!
- * @param libInfo libInfo instance. On success, the mRelroStart, mRelroSize
- * and mRelroFd will be set.
- * @return true on success, false otherwise.
- */
- private static native boolean nativeCreateSharedRelro(
- String library, long loadAddress, LibInfo libInfo);
-
- /**
- * Native method used to use a shared RELRO section.
- *
- * @param library Library name.
- * @param libInfo A LibInfo instance containing valid RELRO information
- * @return true on success.
- */
- private static native boolean nativeUseSharedRelro(String library, LibInfo libInfo);
-
- /**
- * Return a random address that should be free to be mapped with the given size.
- * Maps an area large enough for the largest library we might attempt to load,
- * and if successful then unmaps it and returns the address of the area allocated
- * by the system (with ASLR). The idea is that this area should remain free of
- * other mappings until we map our library into it.
- *
- * @return address to pass to future mmap, or 0 on error.
- */
- private static native long nativeGetRandomBaseLoadAddress();
-}
diff --git a/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java b/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java
deleted file mode 100644
index 2b94370bd8..0000000000
--- a/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.library_loader;
-
-/**
- * These are the possible failures from the LibraryLoader
- */
-public class LoaderErrors {
- public static final int LOADER_ERROR_NORMAL_COMPLETION = 0;
- public static final int LOADER_ERROR_FAILED_TO_REGISTER_JNI = 1;
- public static final int LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED = 2;
- public static final int LOADER_ERROR_NATIVE_LIBRARY_WRONG_VERSION = 3;
- public static final int LOADER_ERROR_NATIVE_STARTUP_FAILED = 4;
-}
diff --git a/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java b/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java
deleted file mode 100644
index 6f8008d645..0000000000
--- a/base/android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 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.library_loader;
-
-import android.content.Context;
-
-/**
- * This is interface to preload the native library before calling System.loadLibrary.
- *
- * Preloading shouldn't call System.loadLibrary() or otherwise cause any Chromium
- * code to be run, because it can be called before Chromium command line is known.
- * It can however open the library via dlopen() or android_dlopen_ext() so that
- * dlopen() later called by System.loadLibrary() becomes a noop. This is what the
- * only subclass (MonochromeLibraryPreloader) is doing.
- */
-public abstract class NativeLibraryPreloader {
- public abstract int loadLibrary(Context context);
-}
diff --git a/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java b/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java
deleted file mode 100644
index 106667536d..0000000000
--- a/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.library_loader;
-
-/**
- * The exception that is thrown when the intialization of a process was failed.
- */
-public class ProcessInitException extends Exception {
- private int mErrorCode = LoaderErrors.LOADER_ERROR_NORMAL_COMPLETION;
-
- /**
- * @param errorCode This will be one of the LoaderErrors error codes.
- */
- public ProcessInitException(int errorCode) {
- mErrorCode = errorCode;
- }
-
- /**
- * @param errorCode This will be one of the LoaderErrors error codes.
- * @param throwable The wrapped throwable obj.
- */
- public ProcessInitException(int errorCode, Throwable throwable) {
- super(null, throwable);
- mErrorCode = errorCode;
- }
-
- /**
- * Return the error code.
- */
- public int getErrorCode() {
- return mErrorCode;
- }
-}
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java
deleted file mode 100644
index 258aa0bbdf..0000000000
--- a/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2018 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.memory;
-
-import org.chromium.base.MemoryPressureLevel;
-
-/**
- * Memory pressure callback interface.
- */
-@FunctionalInterface
-public interface MemoryPressureCallback {
- public void onPressure(@MemoryPressureLevel int pressure);
-}
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java
deleted file mode 100644
index c8af484682..0000000000
--- a/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2018 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.memory;
-
-import android.app.ActivityManager;
-import android.content.ComponentCallbacks2;
-import android.content.res.Configuration;
-import android.os.Build;
-import android.os.SystemClock;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.MemoryPressureLevel;
-import org.chromium.base.MemoryPressureListener;
-import org.chromium.base.Supplier;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.metrics.CachedMetrics;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * This class monitors memory pressure and reports it to the native side.
- * Even though there can be other callbacks besides MemoryPressureListener (which reports
- * pressure to the native side, and is added implicitly), the class is designed to suite
- * needs of native MemoryPressureListeners.
- *
- * There are two groups of MemoryPressureListeners:
- *
- * 1. Stateless, i.e. ones that simply free memory (caches, etc.) in response to memory
- * pressure. These listeners need to be called periodically (to have effect), but not
- * too frequently (to avoid regressing performance too much).
- *
- * 2. Stateful, i.e. ones that change their behavior based on the last received memory
- * pressure (in addition to freeing memory). These listeners need to know when the
- * pressure subsides, i.e. they need to be notified about CRITICAL->MODERATE changes.
- *
- * Android notifies about memory pressure through onTrimMemory() / onLowMemory() callbacks
- * from ComponentCallbacks2, but these are unreliable (e.g. called too early, called just
- * once, not called when memory pressure subsides, etc., see https://crbug.com/813909 for
- * more examples).
- *
- * There is also ActivityManager.getMyMemoryState() API which returns current pressure for
- * the calling process. It has its caveats, for example it can't be called from isolated
- * processes (renderers). Plus we don't want to poll getMyMemoryState() unnecessarily, for
- * example there is no reason to poll it when Chrome is in the background.
- *
- * This class implements the following principles:
- *
- * 1. Throttle pressure signals sent to callbacks.
- * Callbacks are called at most once during throttling interval. If same pressure is
- * reported several times during the interval, all reports except the first one are
- * ignored.
- *
- * 2. Always report changes in pressure.
- * If pressure changes during the interval, the change is not ignored, but delayed
- * until the end of the interval.
- *
- * 3. Poll on CRITICAL memory pressure.
- * Once CRITICAL pressure is reported, getMyMemoryState API is used to periodically
- * query pressure until it subsides (becomes non-CRITICAL).
- *
- * Zooming out, the class is used as follows:
- *
- * 1. Only the browser process / WebView process poll, and it only polls when it makes
- * sense to do so (when Chrome is in the foreground / there are WebView instances
- * around).
- *
- * 2. Services (GPU, renderers) don't poll, instead they get additional pressure signals
- * from the main process.
- *
- * NOTE: This class should only be used on UiThread as defined by ThreadUtils (which is
- * Android main thread for Chrome, but can be some other thread for WebView).
- */
-@MainDex
-public class MemoryPressureMonitor {
- private static final int DEFAULT_THROTTLING_INTERVAL_MS = 60 * 1000;
-
- private final int mThrottlingIntervalMs;
-
- // Pressure reported to callbacks in the current throttling interval.
- private @MemoryPressureLevel int mLastReportedPressure = MemoryPressureLevel.NONE;
-
- // Pressure received (but not reported) during the current throttling interval,
- // or null if no pressure was received.
- private @MemoryPressureLevel Integer mThrottledPressure;
-
- // Whether we need to throttle pressure signals.
- private boolean mIsInsideThrottlingInterval;
-
- private boolean mPollingEnabled;
-
- // Changed by tests.
- private Supplier<Integer> mCurrentPressureSupplier =
- MemoryPressureMonitor::getCurrentMemoryPressure;
-
- // Changed by tests.
- private MemoryPressureCallback mReportingCallback =
- MemoryPressureListener::notifyMemoryPressure;
-
- private final Runnable mThrottlingIntervalTask = this ::onThrottlingIntervalFinished;
-
- // ActivityManager.getMyMemoryState() time histograms, recorded by getCurrentMemoryPressure().
- // Using Count1MHistogramSample because TimesHistogramSample doesn't support microsecond
- // precision.
- private static final CachedMetrics.Count1MHistogramSample sGetMyMemoryStateSucceededTime =
- new CachedMetrics.Count1MHistogramSample(
- "Android.MemoryPressureMonitor.GetMyMemoryState.Succeeded.Time");
- private static final CachedMetrics.Count1MHistogramSample sGetMyMemoryStateFailedTime =
- new CachedMetrics.Count1MHistogramSample(
- "Android.MemoryPressureMonitor.GetMyMemoryState.Failed.Time");
-
- // The only instance.
- public static final MemoryPressureMonitor INSTANCE =
- new MemoryPressureMonitor(DEFAULT_THROTTLING_INTERVAL_MS);
-
- @VisibleForTesting
- protected MemoryPressureMonitor(int throttlingIntervalMs) {
- mThrottlingIntervalMs = throttlingIntervalMs;
- }
-
- /**
- * Starts listening to ComponentCallbacks2.
- */
- public void registerComponentCallbacks() {
- ThreadUtils.assertOnUiThread();
-
- ContextUtils.getApplicationContext().registerComponentCallbacks(new ComponentCallbacks2() {
- @Override
- public void onTrimMemory(int level) {
- Integer pressure = memoryPressureFromTrimLevel(level);
- if (pressure != null) {
- notifyPressure(pressure);
- }
- }
-
- @Override
- public void onLowMemory() {
- notifyPressure(MemoryPressureLevel.CRITICAL);
- }
-
- @Override
- public void onConfigurationChanged(Configuration configuration) {}
- });
- }
-
- /**
- * Enables memory pressure polling.
- * See class comment for specifics. This method also does a single pressure check to get
- * the current pressure.
- */
- public void enablePolling() {
- ThreadUtils.assertOnUiThread();
- if (mPollingEnabled) return;
-
- mPollingEnabled = true;
- if (!mIsInsideThrottlingInterval) {
- reportCurrentPressure();
- }
- }
-
- /**
- * Disables memory pressure polling.
- */
- public void disablePolling() {
- ThreadUtils.assertOnUiThread();
- if (!mPollingEnabled) return;
-
- mPollingEnabled = false;
- }
-
- /**
- * Notifies the class about change in memory pressure.
- * Note that |pressure| might get throttled or delayed, i.e. calling this method doesn't
- * necessarily call the callbacks. See the class comment.
- */
- public void notifyPressure(@MemoryPressureLevel int pressure) {
- ThreadUtils.assertOnUiThread();
-
- if (mIsInsideThrottlingInterval) {
- // We've already reported during this interval. Save |pressure| and act on
- // it later, when the interval finishes.
- mThrottledPressure = pressure;
- return;
- }
-
- reportPressure(pressure);
- }
-
- /**
- * Last pressure that was reported to MemoryPressureListener.
- * Returns MemoryPressureLevel.NONE if nothing was reported yet.
- */
- public @MemoryPressureLevel int getLastReportedPressure() {
- ThreadUtils.assertOnUiThread();
- return mLastReportedPressure;
- }
-
- private void reportPressure(@MemoryPressureLevel int pressure) {
- assert !mIsInsideThrottlingInterval : "Can't report pressure when throttling.";
-
- startThrottlingInterval();
-
- mLastReportedPressure = pressure;
- mReportingCallback.onPressure(pressure);
- }
-
- private void onThrottlingIntervalFinished() {
- mIsInsideThrottlingInterval = false;
-
- // If there was a pressure change during the interval, report it.
- if (mThrottledPressure != null && mLastReportedPressure != mThrottledPressure) {
- int throttledPressure = mThrottledPressure;
- mThrottledPressure = null;
- reportPressure(throttledPressure);
- return;
- }
-
- // The pressure didn't change during the interval. Report current pressure
- // (starting a new interval) if we need to.
- if (mPollingEnabled && mLastReportedPressure == MemoryPressureLevel.CRITICAL) {
- reportCurrentPressure();
- }
- }
-
- private void reportCurrentPressure() {
- Integer pressure = mCurrentPressureSupplier.get();
- if (pressure != null) {
- reportPressure(pressure);
- }
- }
-
- private void startThrottlingInterval() {
- ThreadUtils.postOnUiThreadDelayed(mThrottlingIntervalTask, mThrottlingIntervalMs);
- mIsInsideThrottlingInterval = true;
- }
-
- @VisibleForTesting
- public void setCurrentPressureSupplierForTesting(Supplier<Integer> supplier) {
- mCurrentPressureSupplier = supplier;
- }
-
- @VisibleForTesting
- public void setReportingCallbackForTesting(MemoryPressureCallback callback) {
- mReportingCallback = callback;
- }
-
- /**
- * Queries current memory pressure.
- * Returns null if the pressure couldn't be determined.
- */
- private static @MemoryPressureLevel Integer getCurrentMemoryPressure() {
- long startNanos = elapsedRealtimeNanos();
- try {
- ActivityManager.RunningAppProcessInfo processInfo =
- new ActivityManager.RunningAppProcessInfo();
- ActivityManager.getMyMemoryState(processInfo);
- recordRealtimeNanosDuration(sGetMyMemoryStateSucceededTime, startNanos);
- return memoryPressureFromTrimLevel(processInfo.lastTrimLevel);
- } catch (Exception e) {
- // Defensively catch all exceptions, just in case.
- recordRealtimeNanosDuration(sGetMyMemoryStateFailedTime, startNanos);
- return null;
- }
- }
-
- private static void recordRealtimeNanosDuration(
- CachedMetrics.Count1MHistogramSample histogram, long startNanos) {
- // We're using Count1MHistogram, so we need to calculate duration in microseconds
- long durationUs = TimeUnit.NANOSECONDS.toMicros(elapsedRealtimeNanos() - startNanos);
- // record() takes int, so we need to clamp.
- histogram.record((int) Math.min(durationUs, Integer.MAX_VALUE));
- }
-
- private static long elapsedRealtimeNanos() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return SystemClock.elapsedRealtimeNanos();
- } else {
- return SystemClock.elapsedRealtime() * 1000000;
- }
- }
-
- /**
- * Maps ComponentCallbacks2.TRIM_* value to MemoryPressureLevel.
- * Returns null if |level| couldn't be mapped and should be ignored.
- */
- @VisibleForTesting
- public static @MemoryPressureLevel Integer memoryPressureFromTrimLevel(int level) {
- if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
- || level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
- return MemoryPressureLevel.CRITICAL;
- } else if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
- // Don't notify on TRIM_MEMORY_UI_HIDDEN, since this class only
- // dispatches actionable memory pressure signals to native.
- return MemoryPressureLevel.MODERATE;
- }
- return null;
- }
-}
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java
deleted file mode 100644
index dc90f5706e..0000000000
--- a/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2018 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.memory;
-
-import android.content.ComponentCallbacks2;
-import android.content.res.Configuration;
-import android.support.annotation.IntDef;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.metrics.RecordHistogram;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Centralizes UMA data collection for Android-specific memory conditions.
- */
-public class MemoryPressureUma implements ComponentCallbacks2 {
- @IntDef({
- Notification.UNKNOWN_TRIM_LEVEL, Notification.TRIM_MEMORY_COMPLETE,
- Notification.TRIM_MEMORY_MODERATE, Notification.TRIM_MEMORY_BACKGROUND,
- Notification.TRIM_MEMORY_UI_HIDDEN, Notification.TRIM_MEMORY_RUNNING_CRITICAL,
- Notification.TRIM_MEMORY_RUNNING_LOW, Notification.TRIM_MEMORY_RUNNING_MODERATE,
- Notification.ON_LOW_MEMORY, Notification.NOTIFICATION_MAX,
- })
- @Retention(RetentionPolicy.SOURCE)
- private @interface Notification {
- // WARNING: These values are persisted to logs. Entries should not be
- // renumbered and numeric values should never be reused.
- // Keep in sync with "Android.MemoryPressureNotification" UMA enum.
- int UNKNOWN_TRIM_LEVEL = 0;
- int TRIM_MEMORY_COMPLETE = 1;
- int TRIM_MEMORY_MODERATE = 2;
- int TRIM_MEMORY_BACKGROUND = 3;
- int TRIM_MEMORY_UI_HIDDEN = 4;
- int TRIM_MEMORY_RUNNING_CRITICAL = 5;
- int TRIM_MEMORY_RUNNING_LOW = 6;
- int TRIM_MEMORY_RUNNING_MODERATE = 7;
- int ON_LOW_MEMORY = 8;
-
- // Must be the last one.
- int NOTIFICATION_MAX = 9;
- }
-
- private final String mHistogramName;
-
- private static MemoryPressureUma sInstance;
-
- public static void initializeForBrowser() {
- initializeInstance("Browser");
- }
-
- public static void initializeForChildService() {
- initializeInstance("ChildService");
- }
-
- private static void initializeInstance(String processType) {
- ThreadUtils.assertOnUiThread();
- assert sInstance == null;
- sInstance = new MemoryPressureUma(processType);
- ContextUtils.getApplicationContext().registerComponentCallbacks(sInstance);
- }
-
- private MemoryPressureUma(String processType) {
- mHistogramName = "Android.MemoryPressureNotification." + processType;
- }
-
- @Override
- public void onLowMemory() {
- record(Notification.ON_LOW_MEMORY);
- }
-
- @Override
- public void onTrimMemory(int level) {
- switch (level) {
- case TRIM_MEMORY_COMPLETE:
- record(Notification.TRIM_MEMORY_COMPLETE);
- break;
- case TRIM_MEMORY_MODERATE:
- record(Notification.TRIM_MEMORY_MODERATE);
- break;
- case TRIM_MEMORY_BACKGROUND:
- record(Notification.TRIM_MEMORY_BACKGROUND);
- break;
- case TRIM_MEMORY_UI_HIDDEN:
- record(Notification.TRIM_MEMORY_UI_HIDDEN);
- break;
- case TRIM_MEMORY_RUNNING_CRITICAL:
- record(Notification.TRIM_MEMORY_RUNNING_CRITICAL);
- break;
- case TRIM_MEMORY_RUNNING_LOW:
- record(Notification.TRIM_MEMORY_RUNNING_LOW);
- break;
- case TRIM_MEMORY_RUNNING_MODERATE:
- record(Notification.TRIM_MEMORY_RUNNING_MODERATE);
- break;
- default:
- record(Notification.UNKNOWN_TRIM_LEVEL);
- break;
- }
- }
-
- @Override
- public void onConfigurationChanged(Configuration configuration) {}
-
- private void record(@Notification int notification) {
- RecordHistogram.recordEnumeratedHistogram(
- mHistogramName, notification, Notification.NOTIFICATION_MAX);
- }
-}
diff --git a/base/android/java/src/org/chromium/base/metrics/CachedMetrics.java b/base/android/java/src/org/chromium/base/metrics/CachedMetrics.java
deleted file mode 100644
index ba03e51275..0000000000
--- a/base/android/java/src/org/chromium/base/metrics/CachedMetrics.java
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2016 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.metrics;
-
-import org.chromium.base.library_loader.LibraryLoader;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Utility classes for recording UMA metrics before the native library
- * may have been loaded. Metrics are cached until the library is known
- * to be loaded, then committed to the MetricsService all at once.
- */
-public class CachedMetrics {
- /**
- * Base class for cached metric objects. Subclasses are expected to call
- * addToCache() when some metric state gets recorded that requires a later
- * commit operation when the native library is loaded.
- */
- private abstract static class CachedMetric {
- private static final List<CachedMetric> sMetrics = new ArrayList<CachedMetric>();
-
- protected final String mName;
- protected boolean mCached;
-
- /**
- * @param name Name of the metric to record.
- */
- protected CachedMetric(String name) {
- mName = name;
- }
-
- /**
- * Adds this object to the sMetrics cache, if it hasn't been added already.
- * Must be called while holding the synchronized(sMetrics) lock.
- * Note: The synchronization is not done inside this function because subclasses
- * need to increment their held values under lock to ensure thread-safety.
- */
- protected final void addToCache() {
- assert Thread.holdsLock(sMetrics);
-
- if (mCached) return;
- sMetrics.add(this);
- mCached = true;
- }
-
- /**
- * Commits the metric. Expects the native library to be loaded.
- * Must be called while holding the synchronized(sMetrics) lock.
- */
- protected abstract void commitAndClear();
- }
-
- /**
- * Caches an action that will be recorded after native side is loaded.
- */
- public static class ActionEvent extends CachedMetric {
- private int mCount;
-
- public ActionEvent(String actionName) {
- super(actionName);
- }
-
- public void record() {
- synchronized (CachedMetric.sMetrics) {
- if (LibraryLoader.getInstance().isInitialized()) {
- recordWithNative();
- } else {
- mCount++;
- addToCache();
- }
- }
- }
-
- private void recordWithNative() {
- RecordUserAction.record(mName);
- }
-
- @Override
- protected void commitAndClear() {
- while (mCount > 0) {
- recordWithNative();
- mCount--;
- }
- }
- }
-
- /** Caches a set of integer histogram samples. */
- public static class SparseHistogramSample extends CachedMetric {
- private final List<Integer> mSamples = new ArrayList<Integer>();
-
- public SparseHistogramSample(String histogramName) {
- super(histogramName);
- }
-
- public void record(int sample) {
- synchronized (CachedMetric.sMetrics) {
- if (LibraryLoader.getInstance().isInitialized()) {
- recordWithNative(sample);
- } else {
- mSamples.add(sample);
- addToCache();
- }
- }
- }
-
- private void recordWithNative(int sample) {
- RecordHistogram.recordSparseSlowlyHistogram(mName, sample);
- }
-
- @Override
- protected void commitAndClear() {
- for (Integer sample : mSamples) {
- recordWithNative(sample);
- }
- mSamples.clear();
- }
- }
-
- /** Caches a set of enumerated histogram samples. */
- public static class EnumeratedHistogramSample extends CachedMetric {
- private final List<Integer> mSamples = new ArrayList<Integer>();
- private final int mMaxValue;
-
- public EnumeratedHistogramSample(String histogramName, int maxValue) {
- super(histogramName);
- mMaxValue = maxValue;
- }
-
- public void record(int sample) {
- synchronized (CachedMetric.sMetrics) {
- if (LibraryLoader.getInstance().isInitialized()) {
- recordWithNative(sample);
- } else {
- mSamples.add(sample);
- addToCache();
- }
- }
- }
-
- private void recordWithNative(int sample) {
- RecordHistogram.recordEnumeratedHistogram(mName, sample, mMaxValue);
- }
-
- @Override
- protected void commitAndClear() {
- for (Integer sample : mSamples) {
- recordWithNative(sample);
- }
- mSamples.clear();
- }
- }
-
- /** Caches a set of times histogram samples. */
- public static class TimesHistogramSample extends CachedMetric {
- private final List<Long> mSamples = new ArrayList<Long>();
- private final TimeUnit mTimeUnit;
-
- public TimesHistogramSample(String histogramName, TimeUnit timeUnit) {
- super(histogramName);
- RecordHistogram.assertTimesHistogramSupportsUnit(timeUnit);
- mTimeUnit = timeUnit;
- }
-
- public void record(long sample) {
- synchronized (CachedMetric.sMetrics) {
- if (LibraryLoader.getInstance().isInitialized()) {
- recordWithNative(sample);
- } else {
- mSamples.add(sample);
- addToCache();
- }
- }
- }
-
- private void recordWithNative(long sample) {
- RecordHistogram.recordTimesHistogram(mName, sample, mTimeUnit);
- }
-
- @Override
- protected void commitAndClear() {
- for (Long sample : mSamples) {
- recordWithNative(sample);
- }
- mSamples.clear();
- }
- }
-
- /** Caches a set of boolean histogram samples. */
- public static class BooleanHistogramSample extends CachedMetric {
- private final List<Boolean> mSamples = new ArrayList<Boolean>();
-
- public BooleanHistogramSample(String histogramName) {
- super(histogramName);
- }
-
- public void record(boolean sample) {
- synchronized (CachedMetric.sMetrics) {
- if (LibraryLoader.getInstance().isInitialized()) {
- recordWithNative(sample);
- } else {
- mSamples.add(sample);
- addToCache();
- }
- }
- }
-
- private void recordWithNative(boolean sample) {
- RecordHistogram.recordBooleanHistogram(mName, sample);
- }
-
- @Override
- protected void commitAndClear() {
- for (Boolean sample : mSamples) {
- recordWithNative(sample);
- }
- mSamples.clear();
- }
- }
-
- /**
- * Caches a set of custom count histogram samples.
- * Corresponds to UMA_HISTOGRAM_CUSTOM_COUNTS C++ macro.
- */
- public static class CustomCountHistogramSample extends CachedMetric {
- private final List<Integer> mSamples = new ArrayList<Integer>();
- private final int mMin;
- private final int mMax;
- private final int mNumBuckets;
-
- public CustomCountHistogramSample(String histogramName, int min, int max, int numBuckets) {
- super(histogramName);
- mMin = min;
- mMax = max;
- mNumBuckets = numBuckets;
- }
-
- public void record(int sample) {
- synchronized (CachedMetric.sMetrics) {
- if (LibraryLoader.getInstance().isInitialized()) {
- recordWithNative(sample);
- } else {
- mSamples.add(sample);
- addToCache();
- }
- }
- }
-
- private void recordWithNative(int sample) {
- RecordHistogram.recordCustomCountHistogram(mName, sample, mMin, mMax, mNumBuckets);
- }
-
- @Override
- protected void commitAndClear() {
- for (Integer sample : mSamples) {
- recordWithNative(sample);
- }
- mSamples.clear();
- }
- }
-
- /**
- * Caches a set of count histogram samples in range [1, 100).
- * Corresponds to UMA_HISTOGRAM_COUNTS_100 C++ macro.
- */
- public static class Count100HistogramSample extends CustomCountHistogramSample {
- public Count100HistogramSample(String histogramName) {
- super(histogramName, 1, 100, 50);
- }
- }
-
- /**
- * Caches a set of count histogram samples in range [1, 1000).
- * Corresponds to UMA_HISTOGRAM_COUNTS_1000 C++ macro.
- */
- public static class Count1000HistogramSample extends CustomCountHistogramSample {
- public Count1000HistogramSample(String histogramName) {
- super(histogramName, 1, 1000, 50);
- }
- }
-
- /**
- * Caches a set of count histogram samples in range [1, 1000000).
- * Corresponds to UMA_HISTOGRAM_COUNTS_1M C++ macro.
- */
- public static class Count1MHistogramSample extends CustomCountHistogramSample {
- public Count1MHistogramSample(String histogramName) {
- super(histogramName, 1, 1000000, 50);
- }
- }
-
- /**
- * Calls out to native code to commit any cached histograms and events.
- * Should be called once the native library has been loaded.
- */
- public static void commitCachedMetrics() {
- synchronized (CachedMetric.sMetrics) {
- for (CachedMetric metric : CachedMetric.sMetrics) {
- metric.commitAndClear();
- }
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
deleted file mode 100644
index 898f0094ab..0000000000
--- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ /dev/null
@@ -1,331 +0,0 @@
-// 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.metrics;
-
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.MainDex;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Java API for recording UMA histograms.
- *
- * Internally, histograms objects are cached on the Java side by their pointer
- * values (converted to long). This is safe to do because C++ Histogram objects
- * are never freed. Caching them on the Java side prevents needing to do costly
- * Java String to C++ string conversions on the C++ side during lookup.
- *
- * Note: the JNI calls are relatively costly - avoid calling these methods in performance-critical
- * code.
- */
-@JNINamespace("base::android")
-@MainDex
-public class RecordHistogram {
- private static Throwable sDisabledBy;
- private static Map<String, Long> sCache =
- Collections.synchronizedMap(new HashMap<String, Long>());
-
- /**
- * Tests may not have native initialized, so they may need to disable metrics. The value should
- * be reset after the test done, to avoid carrying over state to unrelated tests.
- *
- * In JUnit tests this can be done automatically using
- * {@link org.chromium.chrome.browser.DisableHistogramsRule}
- */
- @VisibleForTesting
- public static void setDisabledForTests(boolean disabled) {
- if (disabled && sDisabledBy != null) {
- throw new IllegalStateException("Histograms are already disabled.", sDisabledBy);
- }
- sDisabledBy = disabled ? new Throwable() : null;
- }
-
- private static long getCachedHistogramKey(String name) {
- Long key = sCache.get(name);
- // Note: If key is null, we don't have it cached. In that case, pass 0
- // to the native code, which gets converted to a null histogram pointer
- // which will cause the native code to look up the object on the native
- // side.
- return (key == null ? 0 : key);
- }
-
- /**
- * Records a sample in a boolean UMA histogram of the given name. Boolean histogram has two
- * buckets, corresponding to success (true) and failure (false). This is the Java equivalent of
- * the UMA_HISTOGRAM_BOOLEAN C++ macro.
- * @param name name of the histogram
- * @param sample sample to be recorded, either true or false
- */
- public static void recordBooleanHistogram(String name, boolean sample) {
- if (sDisabledBy != null) return;
- long key = getCachedHistogramKey(name);
- long result = nativeRecordBooleanHistogram(name, key, sample);
- if (result != key) sCache.put(name, result);
- }
-
- /**
- * Records a sample in an enumerated histogram of the given name and boundary. Note that
- * |boundary| identifies the histogram - it should be the same at every invocation. This is the
- * Java equivalent of the UMA_HISTOGRAM_ENUMERATION C++ macro.
- * @param name name of the histogram
- * @param sample sample to be recorded, at least 0 and at most |boundary| - 1
- * @param boundary upper bound for legal sample values - all sample values have to be strictly
- * lower than |boundary|
- */
- public static void recordEnumeratedHistogram(String name, int sample, int boundary) {
- if (sDisabledBy != null) return;
- long key = getCachedHistogramKey(name);
- long result = nativeRecordEnumeratedHistogram(name, key, sample, boundary);
- if (result != key) sCache.put(name, result);
- }
-
- /**
- * Records a sample in a count histogram. This is the Java equivalent of the
- * UMA_HISTOGRAM_COUNTS C++ macro.
- * @param name name of the histogram
- * @param sample sample to be recorded, at least 1 and at most 999999
- */
- public static void recordCountHistogram(String name, int sample) {
- recordCustomCountHistogram(name, sample, 1, 1000000, 50);
- }
-
- /**
- * Records a sample in a count histogram. This is the Java equivalent of the
- * UMA_HISTOGRAM_COUNTS_100 C++ macro.
- * @param name name of the histogram
- * @param sample sample to be recorded, at least 1 and at most 99
- */
- public static void recordCount100Histogram(String name, int sample) {
- recordCustomCountHistogram(name, sample, 1, 100, 50);
- }
-
- /**
- * Records a sample in a count histogram. This is the Java equivalent of the
- * UMA_HISTOGRAM_COUNTS_1000 C++ macro.
- * @param name name of the histogram
- * @param sample sample to be recorded, at least 1 and at most 999
- */
- public static void recordCount1000Histogram(String name, int sample) {
- recordCustomCountHistogram(name, sample, 1, 1000, 50);
- }
-
- /**
- * Records a sample in a count histogram. This is the Java equivalent of the
- * UMA_HISTOGRAM_CUSTOM_COUNTS C++ macro.
- * @param name name of the histogram
- * @param sample sample to be recorded, at least |min| and at most |max| - 1
- * @param min lower bound for expected sample values. It must be >= 1
- * @param max upper bounds for expected sample values
- * @param numBuckets the number of buckets
- */
- public static void recordCustomCountHistogram(
- String name, int sample, int min, int max, int numBuckets) {
- if (sDisabledBy != null) return;
- long key = getCachedHistogramKey(name);
- long result = nativeRecordCustomCountHistogram(name, key, sample, min, max, numBuckets);
- if (result != key) sCache.put(name, result);
- }
-
- /**
- * Records a sample in a linear histogram. This is the Java equivalent for using
- * base::LinearHistogram.
- * @param name name of the histogram
- * @param sample sample to be recorded, at least |min| and at most |max| - 1.
- * @param min lower bound for expected sample values, should be at least 1.
- * @param max upper bounds for expected sample values
- * @param numBuckets the number of buckets
- */
- public static void recordLinearCountHistogram(
- String name, int sample, int min, int max, int numBuckets) {
- if (sDisabledBy != null) return;
- long key = getCachedHistogramKey(name);
- long result = nativeRecordLinearCountHistogram(name, key, sample, min, max, numBuckets);
- if (result != key) sCache.put(name, result);
- }
-
- /**
- * Records a sample in a percentage histogram. This is the Java equivalent of the
- * UMA_HISTOGRAM_PERCENTAGE C++ macro.
- * @param name name of the histogram
- * @param sample sample to be recorded, at least 0 and at most 100.
- */
- public static void recordPercentageHistogram(String name, int sample) {
- if (sDisabledBy != null) return;
- long key = getCachedHistogramKey(name);
- long result = nativeRecordEnumeratedHistogram(name, key, sample, 101);
- if (result != key) sCache.put(name, result);
- }
-
- /**
- * Records a sparse histogram. This is the Java equivalent of UmaHistogramSparse.
- * @param name name of the histogram
- * @param sample sample to be recorded. All values of |sample| are valid, including negative
- * values.
- */
- public static void recordSparseSlowlyHistogram(String name, int sample) {
- if (sDisabledBy != null) return;
- long key = getCachedHistogramKey(name);
- long result = nativeRecordSparseHistogram(name, key, sample);
- if (result != key) sCache.put(name, result);
- }
-
- /**
- * Records a sample in a histogram of times. Useful for recording short durations. This is the
- * Java equivalent of the UMA_HISTOGRAM_TIMES C++ macro.
- * Note that histogram samples will always be converted to milliseconds when logged.
- * @param name name of the histogram
- * @param duration duration to be recorded
- * @param timeUnit the unit of the duration argument (must be >= MILLISECONDS)
- */
- public static void recordTimesHistogram(String name, long duration, TimeUnit timeUnit) {
- assertTimesHistogramSupportsUnit(timeUnit);
- recordCustomTimesHistogramMilliseconds(
- name, timeUnit.toMillis(duration), 1, TimeUnit.SECONDS.toMillis(10), 50);
- }
-
- /**
- * Records a sample in a histogram of times. Useful for recording medium durations. This is the
- * Java equivalent of the UMA_HISTOGRAM_MEDIUM_TIMES C++ macro.
- * Note that histogram samples will always be converted to milliseconds when logged.
- * @param name name of the histogram
- * @param duration duration to be recorded
- * @param timeUnit the unit of the duration argument (must be >= MILLISECONDS)
- */
- public static void recordMediumTimesHistogram(String name, long duration, TimeUnit timeUnit) {
- assertTimesHistogramSupportsUnit(timeUnit);
- recordCustomTimesHistogramMilliseconds(
- name, timeUnit.toMillis(duration), 10, TimeUnit.MINUTES.toMillis(3), 50);
- }
-
- /**
- * Records a sample in a histogram of times. Useful for recording long durations. This is the
- * Java equivalent of the UMA_HISTOGRAM_LONG_TIMES C++ macro.
- * Note that histogram samples will always be converted to milliseconds when logged.
- * @param name name of the histogram
- * @param duration duration to be recorded
- * @param timeUnit the unit of the duration argument (must be >= MILLISECONDS)
- */
- public static void recordLongTimesHistogram(String name, long duration, TimeUnit timeUnit) {
- assertTimesHistogramSupportsUnit(timeUnit);
- recordCustomTimesHistogramMilliseconds(
- name, timeUnit.toMillis(duration), 1, TimeUnit.HOURS.toMillis(1), 50);
- }
-
- /**
- * Records a sample in a histogram of times. Useful for recording long durations. This is the
- * Java equivalent of the UMA_HISTOGRAM_LONG_TIMES_100 C++ macro.
- * Note that histogram samples will always be converted to milliseconds when logged.
- * @param name name of the histogram
- * @param duration duration to be recorded
- * @param timeUnit the unit of the duration argument (must be >= MILLISECONDS)
- */
- public static void recordLongTimesHistogram100(String name, long duration, TimeUnit timeUnit) {
- assertTimesHistogramSupportsUnit(timeUnit);
- recordCustomTimesHistogramMilliseconds(
- name, timeUnit.toMillis(duration), 1, TimeUnit.HOURS.toMillis(1), 100);
- }
-
- /**
- * Records a sample in a histogram of times with custom buckets. This is the Java equivalent of
- * the UMA_HISTOGRAM_CUSTOM_TIMES C++ macro.
- * Note that histogram samples will always be converted to milliseconds when logged.
- * @param name name of the histogram
- * @param duration duration to be recorded
- * @param min the minimum bucket value
- * @param max the maximum bucket value
- * @param timeUnit the unit of the duration, min, and max arguments (must be >= MILLISECONDS)
- * @param numBuckets the number of buckets
- */
- public static void recordCustomTimesHistogram(
- String name, long duration, long min, long max, TimeUnit timeUnit, int numBuckets) {
- assertTimesHistogramSupportsUnit(timeUnit);
- recordCustomTimesHistogramMilliseconds(name, timeUnit.toMillis(duration),
- timeUnit.toMillis(min), timeUnit.toMillis(max), numBuckets);
- }
-
- /**
- * Records a sample in a histogram of sizes in KB. This is the Java equivalent of the
- * UMA_HISTOGRAM_MEMORY_KB C++ macro.
- *
- * Good for sizes up to about 500MB.
- *
- * @param name name of the histogram.
- * @param sizeInkB Sample to record in KB.
- */
- public static void recordMemoryKBHistogram(String name, int sizeInKB) {
- recordCustomCountHistogram(name, sizeInKB, 1000, 500000, 50);
- }
-
- /**
- * Asserts that the time unit is supported by TimesHistogram.
- * @param timeUnit the unit, must be >= MILLISECONDS
- */
- /* package */ static void assertTimesHistogramSupportsUnit(TimeUnit timeUnit) {
- // Use extra variable, or else 'git cl format' produces weird results.
- boolean supported = timeUnit != TimeUnit.NANOSECONDS && timeUnit != TimeUnit.MICROSECONDS;
- assert supported : "TimesHistogram doesn't support MICROSECOND and NANOSECONDS time units. "
- + "Consider using CountHistogram instead.";
- }
-
- private static int clampToInt(long value) {
- if (value > Integer.MAX_VALUE) return Integer.MAX_VALUE;
- // Note: Clamping to MIN_VALUE rather than 0, to let base/ histograms code
- // do its own handling of negative values in the future.
- if (value < Integer.MIN_VALUE) return Integer.MIN_VALUE;
- return (int) value;
- }
-
- private static void recordCustomTimesHistogramMilliseconds(
- String name, long duration, long min, long max, int numBuckets) {
- if (sDisabledBy != null) return;
- long key = getCachedHistogramKey(name);
- // Note: Duration, min and max are clamped to int here because that's what's expected by
- // the native histograms API. Callers of these functions still pass longs because that's
- // the types returned by TimeUnit and System.currentTimeMillis() APIs, from which these
- // values come.
- assert max == clampToInt(max);
- long result = nativeRecordCustomTimesHistogramMilliseconds(
- name, key, clampToInt(duration), clampToInt(min), clampToInt(max), numBuckets);
- if (result != key) sCache.put(name, result);
- }
-
- /**
- * Returns the number of samples recorded in the given bucket of the given histogram.
- * @param name name of the histogram to look up
- * @param sample the bucket containing this sample value will be looked up
- */
- @VisibleForTesting
- public static int getHistogramValueCountForTesting(String name, int sample) {
- return nativeGetHistogramValueCountForTesting(name, sample);
- }
-
- /**
- * Returns the number of samples recorded for the given histogram.
- * @param name name of the histogram to look up.
- */
- @VisibleForTesting
- public static int getHistogramTotalCountForTesting(String name) {
- return nativeGetHistogramTotalCountForTesting(name);
- }
-
- private static native long nativeRecordCustomTimesHistogramMilliseconds(
- String name, long key, int duration, int min, int max, int numBuckets);
-
- private static native long nativeRecordBooleanHistogram(String name, long key, boolean sample);
- private static native long nativeRecordEnumeratedHistogram(
- String name, long key, int sample, int boundary);
- private static native long nativeRecordCustomCountHistogram(
- String name, long key, int sample, int min, int max, int numBuckets);
- private static native long nativeRecordLinearCountHistogram(
- String name, long key, int sample, int min, int max, int numBuckets);
- private static native long nativeRecordSparseHistogram(String name, long key, int sample);
-
- private static native int nativeGetHistogramValueCountForTesting(String name, int sample);
- private static native int nativeGetHistogramTotalCountForTesting(String name);
-}
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
deleted file mode 100644
index 0d2ba548d2..0000000000
--- a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2015 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.metrics;
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * Java API for recording UMA actions.
- *
- * WARNINGS:
- * JNI calls are relatively costly - avoid using in performance-critical code.
- *
- * We use a script (extract_actions.py) to scan the source code and extract actions. A string
- * literal (not a variable) must be passed to record().
- */
-@JNINamespace("base::android")
-public class RecordUserAction {
- private static Throwable sDisabledBy;
-
- /**
- * Tests may not have native initialized, so they may need to disable metrics. The value should
- * be reset after the test done, to avoid carrying over state to unrelated tests.
- */
- @VisibleForTesting
- public static void setDisabledForTests(boolean disabled) {
- if (disabled && sDisabledBy != null) {
- throw new IllegalStateException("UserActions are already disabled.", sDisabledBy);
- }
- sDisabledBy = disabled ? new Throwable() : null;
- }
-
- public static void record(final String action) {
- if (sDisabledBy != null) return;
-
- if (ThreadUtils.runningOnUiThread()) {
- nativeRecordUserAction(action);
- return;
- }
-
- ThreadUtils.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- nativeRecordUserAction(action);
- }
- });
- }
-
- /**
- * Interface to a class that receives a callback for each UserAction that is recorded.
- */
- public interface UserActionCallback {
- @CalledByNative("UserActionCallback")
- void onActionRecorded(String action);
- }
-
- private static long sNativeActionCallback;
-
- /**
- * Register a callback that is executed for each recorded UserAction.
- * Only one callback can be registered at a time.
- * The callback has to be unregistered using removeActionCallbackForTesting().
- */
- public static void setActionCallbackForTesting(UserActionCallback callback) {
- assert sNativeActionCallback == 0;
- sNativeActionCallback = nativeAddActionCallbackForTesting(callback);
- }
-
- /**
- * Unregister the UserActionCallback.
- */
- public static void removeActionCallbackForTesting() {
- assert sNativeActionCallback != 0;
- nativeRemoveActionCallbackForTesting(sNativeActionCallback);
- sNativeActionCallback = 0;
- }
-
- private static native void nativeRecordUserAction(String action);
- private static native long nativeAddActionCallbackForTesting(UserActionCallback callback);
- private static native void nativeRemoveActionCallbackForTesting(long callbackId);
-}
diff --git a/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java b/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java
deleted file mode 100644
index bff3fae763..0000000000
--- a/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2016 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.metrics;
-
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * Java API which exposes the registered histograms on the native side as
- * JSON test.
- */
-@JNINamespace("base::android")
-public final class StatisticsRecorderAndroid {
- private StatisticsRecorderAndroid() {}
-
- /**
- * @param verbosityLevel controls the information that should be included when dumping each of
- * the histogram.
- * @return All the registered histograms as JSON text.
- */
- public static String toJson(@JSONVerbosityLevel int verbosityLevel) {
- return nativeToJson(verbosityLevel);
- }
-
- private static native String nativeToJson(@JSONVerbosityLevel int verbosityLevel);
-} \ No newline at end of file
diff --git a/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java b/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java
deleted file mode 100644
index 5588ec5bdf..0000000000
--- a/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2015 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.multidex;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.support.multidex.MultiDex;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.annotations.MainDex;
-
-/**
- * Performs multidex installation for non-isolated processes.
- */
-@MainDex
-public class ChromiumMultiDexInstaller {
- private static final String TAG = "base_multidex";
-
- /**
- * Suffix for the meta-data tag in the AndroidManifext.xml that determines whether loading
- * secondary dexes should be skipped for a given process name.
- */
- private static final String IGNORE_MULTIDEX_KEY = ".ignore_multidex";
-
- /**
- * Installs secondary dexes if possible/necessary.
- *
- * Isolated processes (e.g. renderer processes) can't load secondary dex files on
- * K and below, so we don't even try in that case.
- *
- * In release builds of app apks (as opposed to test apks), this is a no-op because:
- * - multidex isn't necessary in release builds because we run proguard there and
- * thus aren't threatening to hit the dex limit; and
- * - calling MultiDex.install, even in the absence of secondary dexes, causes a
- * significant regression in start-up time (crbug.com/525695).
- *
- * @param context The application context.
- */
- @VisibleForTesting
- public static void install(Context context) {
- // TODO(jbudorick): Back out this version check once support for K & below works.
- // http://crbug.com/512357
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
- && !shouldInstallMultiDex(context)) {
- Log.i(TAG, "Skipping multidex installation: not needed for process.");
- } else {
- MultiDex.install(context);
- Log.i(TAG, "Completed multidex installation.");
- }
- }
-
- // Determines whether MultiDex should be installed for the current process. Isolated
- // Processes should skip MultiDex as they can not actually access the files on disk.
- // Privileged processes need ot have all of their dependencies in the MainDex for
- // performance reasons.
- private static boolean shouldInstallMultiDex(Context context) {
- if (ContextUtils.isIsolatedProcess()) {
- return false;
- }
- String currentProcessName = ContextUtils.getProcessName();
- PackageManager packageManager = context.getPackageManager();
- try {
- ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(),
- PackageManager.GET_META_DATA);
- if (appInfo == null || appInfo.metaData == null) return true;
- return !appInfo.metaData.getBoolean(currentProcessName + IGNORE_MULTIDEX_KEY, false);
- } catch (PackageManager.NameNotFoundException e) {
- return true;
- }
- }
-
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java b/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
deleted file mode 100644
index 43ae2591d4..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-
-import org.chromium.base.Log;
-import org.chromium.base.VisibleForTesting;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Queue;
-
-/**
- * This class is responsible for allocating and managing connections to child
- * process services. These connections are in a pool (the services are defined
- * in the AndroidManifest.xml).
- */
-public class ChildConnectionAllocator {
- private static final String TAG = "ChildConnAllocator";
-
- /** Factory interface. Used by tests to specialize created connections. */
- @VisibleForTesting
- public interface ConnectionFactory {
- ChildProcessConnection createConnection(Context context, ComponentName serviceName,
- boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle);
- }
-
- /** Default implementation of the ConnectionFactory that creates actual connections. */
- private static class ConnectionFactoryImpl implements ConnectionFactory {
- @Override
- public ChildProcessConnection createConnection(Context context, ComponentName serviceName,
- boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle) {
- return new ChildProcessConnection(
- context, serviceName, bindToCaller, bindAsExternalService, serviceBundle);
- }
- }
-
- // Delay between the call to freeConnection and the connection actually beeing freed.
- private static final long FREE_CONNECTION_DELAY_MILLIS = 1;
-
- // The handler of the thread on which all interations should happen.
- private final Handler mLauncherHandler;
-
- // Connections to services. Indices of the array correspond to the service numbers.
- private final ChildProcessConnection[] mChildProcessConnections;
-
- // Runnable which will be called when allocator wants to allocate a new connection, but does
- // not have any more free slots. May be null.
- private final Runnable mFreeSlotCallback;
- private final String mPackageName;
- private final String mServiceClassName;
- private final boolean mBindToCaller;
- private final boolean mBindAsExternalService;
- private final boolean mUseStrongBinding;
-
- // The list of free (not bound) service indices.
- private final ArrayList<Integer> mFreeConnectionIndices;
-
- private final Queue<Runnable> mPendingAllocations = new ArrayDeque<>();
-
- private ConnectionFactory mConnectionFactory = new ConnectionFactoryImpl();
-
- /**
- * Factory method that retrieves the service name and number of service from the
- * AndroidManifest.xml.
- */
- public static ChildConnectionAllocator create(Context context, Handler launcherHandler,
- Runnable freeSlotCallback, String packageName, String serviceClassName,
- String numChildServicesManifestKey, boolean bindToCaller, boolean bindAsExternalService,
- boolean useStrongBinding) {
- int numServices = -1;
- PackageManager packageManager = context.getPackageManager();
- try {
- ApplicationInfo appInfo =
- packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
- if (appInfo.metaData != null) {
- numServices = appInfo.metaData.getInt(numChildServicesManifestKey, -1);
- }
- } catch (PackageManager.NameNotFoundException e) {
- throw new RuntimeException("Could not get application info.");
- }
-
- if (numServices < 0) {
- throw new RuntimeException("Illegal meta data value for number of child services");
- }
-
- // Check that the service exists.
- try {
- // PackageManager#getServiceInfo() throws an exception if the service does not exist.
- packageManager.getServiceInfo(
- new ComponentName(packageName, serviceClassName + "0"), 0);
- } catch (PackageManager.NameNotFoundException e) {
- throw new RuntimeException("Illegal meta data value: the child service doesn't exist");
- }
-
- return new ChildConnectionAllocator(launcherHandler, freeSlotCallback, packageName,
- serviceClassName, bindToCaller, bindAsExternalService, useStrongBinding,
- numServices);
- }
-
- /**
- * Factory method used with some tests to create an allocator with values passed in directly
- * instead of being retrieved from the AndroidManifest.xml.
- */
- @VisibleForTesting
- public static ChildConnectionAllocator createForTest(Runnable freeSlotCallback,
- String packageName, String serviceClassName, int serviceCount, boolean bindToCaller,
- boolean bindAsExternalService, boolean useStrongBinding) {
- return new ChildConnectionAllocator(new Handler(), freeSlotCallback, packageName,
- serviceClassName, bindToCaller, bindAsExternalService, useStrongBinding,
- serviceCount);
- }
-
- private ChildConnectionAllocator(Handler launcherHandler, Runnable freeSlotCallback,
- String packageName, String serviceClassName, boolean bindToCaller,
- boolean bindAsExternalService, boolean useStrongBinding, int numChildServices) {
- mFreeSlotCallback = freeSlotCallback;
- mLauncherHandler = launcherHandler;
- assert isRunningOnLauncherThread();
- mPackageName = packageName;
- mServiceClassName = serviceClassName;
- mBindToCaller = bindToCaller;
- mBindAsExternalService = bindAsExternalService;
- mUseStrongBinding = useStrongBinding;
- mChildProcessConnections = new ChildProcessConnection[numChildServices];
- mFreeConnectionIndices = new ArrayList<Integer>(numChildServices);
- for (int i = 0; i < numChildServices; i++) {
- mFreeConnectionIndices.add(i);
- }
- }
-
- /** @return a bound connection, or null if there are no free slots. */
- public ChildProcessConnection allocate(Context context, Bundle serviceBundle,
- final ChildProcessConnection.ServiceCallback serviceCallback) {
- assert isRunningOnLauncherThread();
- if (mFreeConnectionIndices.isEmpty()) {
- Log.d(TAG, "Ran out of services to allocate.");
- return null;
- }
- int slot = mFreeConnectionIndices.remove(0);
- assert mChildProcessConnections[slot] == null;
- ComponentName serviceName = new ComponentName(mPackageName, mServiceClassName + slot);
-
- // Wrap the service callbacks so that:
- // - we can intercept onChildProcessDied and clean-up connections
- // - the callbacks are actually posted so that this method will return before the callbacks
- // are called (so that the caller may set any reference to the returned connection before
- // any callback logic potentially tries to access that connection).
- ChildProcessConnection.ServiceCallback serviceCallbackWrapper =
- new ChildProcessConnection.ServiceCallback() {
- @Override
- public void onChildStarted() {
- assert isRunningOnLauncherThread();
- if (serviceCallback != null) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- serviceCallback.onChildStarted();
- }
- });
- }
- }
-
- @Override
- public void onChildStartFailed(final ChildProcessConnection connection) {
- assert isRunningOnLauncherThread();
- if (serviceCallback != null) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- serviceCallback.onChildStartFailed(connection);
- }
- });
- }
- freeConnectionWithDelay(connection);
- }
-
- @Override
- public void onChildProcessDied(final ChildProcessConnection connection) {
- assert isRunningOnLauncherThread();
- if (serviceCallback != null) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- serviceCallback.onChildProcessDied(connection);
- }
- });
- }
- freeConnectionWithDelay(connection);
- }
-
- private void freeConnectionWithDelay(final ChildProcessConnection connection) {
- // Freeing a service should be delayed. This is so that we avoid immediately
- // reusing the freed service (see http://crbug.com/164069): the framework
- // might keep a service process alive when it's been unbound for a short
- // time. If a new connection to the same service is bound at that point, the
- // process is reused and bad things happen (mostly static variables are set
- // when we don't expect them to).
- mLauncherHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- free(connection);
- }
- }, FREE_CONNECTION_DELAY_MILLIS);
- }
- };
-
- ChildProcessConnection connection = mConnectionFactory.createConnection(
- context, serviceName, mBindToCaller, mBindAsExternalService, serviceBundle);
- mChildProcessConnections[slot] = connection;
-
- connection.start(mUseStrongBinding, serviceCallbackWrapper);
- Log.d(TAG, "Allocator allocated and bound a connection, name: %s, slot: %d",
- mServiceClassName, slot);
- return connection;
- }
-
- /** Frees a connection and notifies listeners. */
- private void free(ChildProcessConnection connection) {
- assert isRunningOnLauncherThread();
-
- // mChildProcessConnections is relatively short (20 items at max at this point).
- // We are better of iterating than caching in a map.
- int slot = Arrays.asList(mChildProcessConnections).indexOf(connection);
- if (slot == -1) {
- Log.e(TAG, "Unable to find connection to free.");
- assert false;
- } else {
- mChildProcessConnections[slot] = null;
- assert !mFreeConnectionIndices.contains(slot);
- mFreeConnectionIndices.add(slot);
- Log.d(TAG, "Allocator freed a connection, name: %s, slot: %d", mServiceClassName, slot);
- }
-
- if (mPendingAllocations.isEmpty()) return;
- mPendingAllocations.remove().run();
- assert mFreeConnectionIndices.isEmpty();
- if (!mPendingAllocations.isEmpty() && mFreeSlotCallback != null) mFreeSlotCallback.run();
- }
-
- // Can only be called once all slots are full, ie when allocate returns null.
- // The callback will be called when a slot becomes free, and should synchronous call
- // allocate to take the slot.
- public void queueAllocation(Runnable runnable) {
- assert mFreeConnectionIndices.isEmpty();
- boolean wasEmpty = mPendingAllocations.isEmpty();
- mPendingAllocations.add(runnable);
- if (wasEmpty && mFreeSlotCallback != null) mFreeSlotCallback.run();
- }
-
- public String getPackageName() {
- return mPackageName;
- }
-
- public boolean anyConnectionAllocated() {
- return mFreeConnectionIndices.size() < mChildProcessConnections.length;
- }
-
- public boolean isFreeConnectionAvailable() {
- assert isRunningOnLauncherThread();
- return !mFreeConnectionIndices.isEmpty();
- }
-
- public int getNumberOfServices() {
- return mChildProcessConnections.length;
- }
-
- public boolean isConnectionFromAllocator(ChildProcessConnection connection) {
- for (ChildProcessConnection existingConnection : mChildProcessConnections) {
- if (existingConnection == connection) return true;
- }
- return false;
- }
-
- @VisibleForTesting
- public void setConnectionFactoryForTesting(ConnectionFactory connectionFactory) {
- mConnectionFactory = connectionFactory;
- }
-
- /** @return the count of connections managed by the allocator */
- @VisibleForTesting
- public int allocatedConnectionsCountForTesting() {
- assert isRunningOnLauncherThread();
- return mChildProcessConnections.length - mFreeConnectionIndices.size();
- }
-
- @VisibleForTesting
- public ChildProcessConnection getChildProcessConnectionAtSlotForTesting(int slotNumber) {
- return mChildProcessConnections[slotNumber];
- }
-
- private boolean isRunningOnLauncherThread() {
- return mLauncherHandler.getLooper() == Looper.myLooper();
- }
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
deleted file mode 100644
index bfa5d5cc6a..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
+++ /dev/null
@@ -1,766 +0,0 @@
-// Copyright 2013 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.process_launcher;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-
-import org.chromium.base.ChildBindingState;
-import org.chromium.base.Log;
-import org.chromium.base.MemoryPressureLevel;
-import org.chromium.base.MemoryPressureListener;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.TraceEvent;
-import org.chromium.base.VisibleForTesting;
-import org.chromium.base.memory.MemoryPressureCallback;
-
-import java.util.Arrays;
-import java.util.List;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * Manages a connection between the browser activity and a child service.
- */
-public class ChildProcessConnection {
- private static final String TAG = "ChildProcessConn";
- private static final int NUM_BINDING_STATES = ChildBindingState.MAX_VALUE + 1;
-
- /**
- * Used to notify the consumer about the process start. These callbacks will be invoked before
- * the ConnectionCallbacks.
- */
- public interface ServiceCallback {
- /**
- * Called when the child process has successfully started and is ready for connection
- * setup.
- */
- void onChildStarted();
-
- /**
- * Called when the child process failed to start. This can happen if the process is already
- * in use by another client. The client will not receive any other callbacks after this one.
- */
- void onChildStartFailed(ChildProcessConnection connection);
-
- /**
- * Called when the service has been disconnected. whether it was stopped by the client or
- * if it stopped unexpectedly (process crash).
- * This is the last callback from this interface that a client will receive for a specific
- * connection.
- */
- void onChildProcessDied(ChildProcessConnection connection);
- }
-
- /**
- * Used to notify the consumer about the connection being established.
- */
- public interface ConnectionCallback {
- /**
- * Called when the connection to the service is established.
- * @param connection the connection object to the child process
- */
- void onConnected(ChildProcessConnection connection);
- }
-
- /**
- * Delegate that ChildServiceConnection should call when the service connects/disconnects.
- * These callbacks are expected to happen on a background thread.
- */
- @VisibleForTesting
- protected interface ChildServiceConnectionDelegate {
- void onServiceConnected(IBinder service);
- void onServiceDisconnected();
- }
-
- @VisibleForTesting
- protected interface ChildServiceConnectionFactory {
- ChildServiceConnection createConnection(
- Intent bindIntent, int bindFlags, ChildServiceConnectionDelegate delegate);
- }
-
- /** Interface representing a connection to the Android service. Can be mocked in unit-tests. */
- @VisibleForTesting
- protected interface ChildServiceConnection {
- boolean bind();
- void unbind();
- boolean isBound();
- }
-
- /** Implementation of ChildServiceConnection that does connect to a service. */
- private static class ChildServiceConnectionImpl
- implements ChildServiceConnection, ServiceConnection {
- private final Context mContext;
- private final Intent mBindIntent;
- private final int mBindFlags;
- private final ChildServiceConnectionDelegate mDelegate;
- private boolean mBound;
-
- private ChildServiceConnectionImpl(Context context, Intent bindIntent, int bindFlags,
- ChildServiceConnectionDelegate delegate) {
- mContext = context;
- mBindIntent = bindIntent;
- mBindFlags = bindFlags;
- mDelegate = delegate;
- }
-
- @Override
- public boolean bind() {
- if (!mBound) {
- try {
- TraceEvent.begin("ChildProcessConnection.ChildServiceConnectionImpl.bind");
- mBound = mContext.bindService(mBindIntent, this, mBindFlags);
- } finally {
- TraceEvent.end("ChildProcessConnection.ChildServiceConnectionImpl.bind");
- }
- }
- return mBound;
- }
-
- @Override
- public void unbind() {
- if (mBound) {
- mContext.unbindService(this);
- mBound = false;
- }
- }
-
- @Override
- public boolean isBound() {
- return mBound;
- }
-
- @Override
- public void onServiceConnected(ComponentName className, final IBinder service) {
- mDelegate.onServiceConnected(service);
- }
-
- // Called on the main thread to notify that the child service did not disconnect gracefully.
- @Override
- public void onServiceDisconnected(ComponentName className) {
- mDelegate.onServiceDisconnected();
- }
- }
-
- // Synchronize on this for access.
- @GuardedBy("sAllBindingStateCounts")
- private static final int[] sAllBindingStateCounts = new int[NUM_BINDING_STATES];
-
- @VisibleForTesting
- static void resetBindingStateCountsForTesting() {
- synchronized (sAllBindingStateCounts) {
- for (int i = 0; i < NUM_BINDING_STATES; ++i) {
- sAllBindingStateCounts[i] = 0;
- }
- }
- }
-
- private final Handler mLauncherHandler;
- private final ComponentName mServiceName;
-
- // Parameters passed to the child process through the service binding intent.
- // If the service gets recreated by the framework the intent will be reused, so these parameters
- // should be common to all processes of that type.
- private final Bundle mServiceBundle;
-
- // Whether bindToCaller should be called on the service after setup to check that only one
- // process is bound to the service.
- private final boolean mBindToCaller;
-
- private static class ConnectionParams {
- final Bundle mConnectionBundle;
- final List<IBinder> mClientInterfaces;
-
- ConnectionParams(Bundle connectionBundle, List<IBinder> clientInterfaces) {
- mConnectionBundle = connectionBundle;
- mClientInterfaces = clientInterfaces;
- }
- }
-
- // This is set in start() and is used in onServiceConnected().
- private ServiceCallback mServiceCallback;
-
- // This is set in setupConnection() and is later used in doConnectionSetup(), after which the
- // variable is cleared. Therefore this is only valid while the connection is being set up.
- private ConnectionParams mConnectionParams;
-
- // Callback provided in setupConnection() that will communicate the result to the caller. This
- // has to be called exactly once after setupConnection(), even if setup fails, so that the
- // caller can free up resources associated with the setup attempt. This is set to null after the
- // call.
- private ConnectionCallback mConnectionCallback;
-
- private IChildProcessService mService;
-
- // Set to true when the service connection callback runs. This differs from
- // mServiceConnectComplete, which tracks that the connection completed successfully.
- private boolean mDidOnServiceConnected;
-
- // Set to true when the service connected successfully.
- private boolean mServiceConnectComplete;
-
- // Set to true when the service disconnects, as opposed to being properly closed. This happens
- // when the process crashes or gets killed by the system out-of-memory killer.
- private boolean mServiceDisconnected;
-
- // Process ID of the corresponding child process.
- private int mPid;
-
- // Strong binding will make the service priority equal to the priority of the activity.
- private final ChildServiceConnection mStrongBinding;
-
- // Moderate binding will make the service priority equal to the priority of a visible process
- // while the app is in the foreground.
- // This is also used as the initial binding before any priorities are set.
- private final ChildServiceConnection mModerateBinding;
-
- // Low priority binding maintained in the entire lifetime of the connection, i.e. between calls
- // to start() and stop().
- private final ChildServiceConnection mWaivedBinding;
-
- // Refcount of bindings.
- private int mStrongBindingCount;
- private int mModerateBindingCount;
-
- // Set to true once unbind() was called.
- private boolean mUnbound;
-
- // Binding state of this connection.
- private @ChildBindingState int mBindingState;
-
- // Protects access to instance variables that are also accessed on the client thread.
- private final Object mClientThreadLock = new Object();
-
- // Same as above except it no longer updates after |unbind()|.
- @GuardedBy("mClientThreadLock")
- private @ChildBindingState int mBindingStateCurrentOrWhenDied;
-
- // Indicate |kill()| was called to intentionally kill this process.
- @GuardedBy("mClientThreadLock")
- private boolean mKilledByUs;
-
- // Copy of |sAllBindingStateCounts| at the time this is unbound.
- @GuardedBy("mClientThreadLock")
- private int[] mAllBindingStateCountsWhenDied;
-
- private MemoryPressureCallback mMemoryPressureCallback;
-
- public ChildProcessConnection(Context context, ComponentName serviceName, boolean bindToCaller,
- boolean bindAsExternalService, Bundle serviceBundle) {
- this(context, serviceName, bindToCaller, bindAsExternalService, serviceBundle,
- null /* connectionFactory */);
- }
-
- @VisibleForTesting
- public ChildProcessConnection(final Context context, ComponentName serviceName,
- boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle,
- ChildServiceConnectionFactory connectionFactory) {
- mLauncherHandler = new Handler();
- assert isRunningOnLauncherThread();
- mServiceName = serviceName;
- mServiceBundle = serviceBundle != null ? serviceBundle : new Bundle();
- mServiceBundle.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bindToCaller);
- mBindToCaller = bindToCaller;
-
- if (connectionFactory == null) {
- connectionFactory = new ChildServiceConnectionFactory() {
- @Override
- public ChildServiceConnection createConnection(
- Intent bindIntent, int bindFlags, ChildServiceConnectionDelegate delegate) {
- return new ChildServiceConnectionImpl(context, bindIntent, bindFlags, delegate);
- }
- };
- }
-
- ChildServiceConnectionDelegate delegate = new ChildServiceConnectionDelegate() {
- @Override
- public void onServiceConnected(final IBinder service) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- onServiceConnectedOnLauncherThread(service);
- }
- });
- }
-
- @Override
- public void onServiceDisconnected() {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- onServiceDisconnectedOnLauncherThread();
- }
- });
- }
- };
-
- Intent intent = new Intent();
- intent.setComponent(serviceName);
- if (serviceBundle != null) {
- intent.putExtras(serviceBundle);
- }
-
- int defaultFlags = Context.BIND_AUTO_CREATE
- | (bindAsExternalService ? Context.BIND_EXTERNAL_SERVICE : 0);
-
- mModerateBinding = connectionFactory.createConnection(intent, defaultFlags, delegate);
- mStrongBinding = connectionFactory.createConnection(
- intent, defaultFlags | Context.BIND_IMPORTANT, delegate);
- mWaivedBinding = connectionFactory.createConnection(
- intent, defaultFlags | Context.BIND_WAIVE_PRIORITY, delegate);
- }
-
- public final IChildProcessService getService() {
- assert isRunningOnLauncherThread();
- return mService;
- }
-
- public final ComponentName getServiceName() {
- assert isRunningOnLauncherThread();
- return mServiceName;
- }
-
- public boolean isConnected() {
- return mService != null;
- }
-
- /**
- * @return the connection pid, or 0 if not yet connected
- */
- public int getPid() {
- assert isRunningOnLauncherThread();
- return mPid;
- }
-
- /**
- * Starts a connection to an IChildProcessService. This must be followed by a call to
- * setupConnection() to setup the connection parameters. start() and setupConnection() are
- * separate to allow to pass whatever parameters are available in start(), and complete the
- * remainder addStrongBinding while reducing the connection setup latency.
- * @param useStrongBinding whether a strong binding should be bound by default. If false, an
- * initial moderate binding is used.
- * @param serviceCallback (optional) callbacks invoked when the child process starts or fails to
- * start and when the service stops.
- */
- public void start(boolean useStrongBinding, ServiceCallback serviceCallback) {
- try {
- TraceEvent.begin("ChildProcessConnection.start");
- assert isRunningOnLauncherThread();
- assert mConnectionParams
- == null : "setupConnection() called before start() in ChildProcessConnection.";
-
- mServiceCallback = serviceCallback;
-
- if (!bind(useStrongBinding)) {
- Log.e(TAG, "Failed to establish the service connection.");
- // We have to notify the caller so that they can free-up associated resources.
- // TODO(ppi): Can we hard-fail here?
- notifyChildProcessDied();
- }
- } finally {
- TraceEvent.end("ChildProcessConnection.start");
- }
- }
-
- /**
- * Sets-up the connection after it was started with start().
- * @param connectionBundle a bundle passed to the service that can be used to pass various
- * parameters to the service
- * @param clientInterfaces optional client specified interfaces that the child can use to
- * communicate with the parent process
- * @param connectionCallback will be called exactly once after the connection is set up or the
- * setup fails
- */
- public void setupConnection(Bundle connectionBundle, @Nullable List<IBinder> clientInterfaces,
- ConnectionCallback connectionCallback) {
- assert isRunningOnLauncherThread();
- assert mConnectionParams == null;
- if (mServiceDisconnected) {
- Log.w(TAG, "Tried to setup a connection that already disconnected.");
- connectionCallback.onConnected(null);
- return;
- }
- try {
- TraceEvent.begin("ChildProcessConnection.setupConnection");
- mConnectionCallback = connectionCallback;
- mConnectionParams = new ConnectionParams(connectionBundle, clientInterfaces);
- // Run the setup if the service is already connected. If not, doConnectionSetup() will
- // be called from onServiceConnected().
- if (mServiceConnectComplete) {
- doConnectionSetup();
- }
- } finally {
- TraceEvent.end("ChildProcessConnection.setupConnection");
- }
- }
-
- /**
- * Terminates the connection to IChildProcessService, closing all bindings. It is safe to call
- * this multiple times.
- */
- public void stop() {
- assert isRunningOnLauncherThread();
- unbind();
- notifyChildProcessDied();
- }
-
- public void kill() {
- assert isRunningOnLauncherThread();
- IChildProcessService service = mService;
- unbind();
- try {
- if (service != null) service.forceKill();
- } catch (RemoteException e) {
- // Intentionally ignore since we are killing it anyway.
- }
- synchronized (mClientThreadLock) {
- mKilledByUs = true;
- }
- notifyChildProcessDied();
- }
-
- private void onServiceConnectedOnLauncherThread(IBinder service) {
- assert isRunningOnLauncherThread();
- // A flag from the parent class ensures we run the post-connection logic only once
- // (instead of once per each ChildServiceConnection).
- if (mDidOnServiceConnected) {
- return;
- }
- try {
- TraceEvent.begin("ChildProcessConnection.ChildServiceConnection.onServiceConnected");
- mDidOnServiceConnected = true;
- mService = IChildProcessService.Stub.asInterface(service);
-
- if (mBindToCaller) {
- try {
- if (!mService.bindToCaller()) {
- if (mServiceCallback != null) {
- mServiceCallback.onChildStartFailed(this);
- }
- unbind();
- return;
- }
- } catch (RemoteException ex) {
- // Do not trigger the StartCallback here, since the service is already
- // dead and the onChildStopped callback will run from onServiceDisconnected().
- Log.e(TAG, "Failed to bind service to connection.", ex);
- return;
- }
- }
-
- if (mServiceCallback != null) {
- mServiceCallback.onChildStarted();
- }
-
- mServiceConnectComplete = true;
-
- if (mMemoryPressureCallback == null) {
- final MemoryPressureCallback callback = this ::onMemoryPressure;
- ThreadUtils.postOnUiThread(() -> MemoryPressureListener.addCallback(callback));
- mMemoryPressureCallback = callback;
- }
-
- // Run the setup if the connection parameters have already been provided. If
- // not, doConnectionSetup() will be called from setupConnection().
- if (mConnectionParams != null) {
- doConnectionSetup();
- }
- } finally {
- TraceEvent.end("ChildProcessConnection.ChildServiceConnection.onServiceConnected");
- }
- }
-
- private void onServiceDisconnectedOnLauncherThread() {
- assert isRunningOnLauncherThread();
- // Ensure that the disconnection logic runs only once (instead of once per each
- // ChildServiceConnection).
- if (mServiceDisconnected) {
- return;
- }
- mServiceDisconnected = true;
- Log.w(TAG, "onServiceDisconnected (crash or killed by oom): pid=%d", mPid);
- stop(); // We don't want to auto-restart on crash. Let the browser do that.
-
- // If we have a pending connection callback, we need to communicate the failure to
- // the caller.
- if (mConnectionCallback != null) {
- mConnectionCallback.onConnected(null);
- mConnectionCallback = null;
- }
- }
-
- private void onSetupConnectionResult(int pid) {
- mPid = pid;
- assert mPid != 0 : "Child service claims to be run by a process of pid=0.";
-
- if (mConnectionCallback != null) {
- mConnectionCallback.onConnected(this);
- }
- mConnectionCallback = null;
- }
-
- /**
- * Called after the connection parameters have been set (in setupConnection()) *and* a
- * connection has been established (as signaled by onServiceConnected()). These two events can
- * happen in any order.
- */
- private void doConnectionSetup() {
- try {
- TraceEvent.begin("ChildProcessConnection.doConnectionSetup");
- assert mServiceConnectComplete && mService != null;
- assert mConnectionParams != null;
-
- ICallbackInt pidCallback = new ICallbackInt.Stub() {
- @Override
- public void call(final int pid) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- onSetupConnectionResult(pid);
- }
- });
- }
- };
- try {
- mService.setupConnection(mConnectionParams.mConnectionBundle, pidCallback,
- mConnectionParams.mClientInterfaces);
- } catch (RemoteException re) {
- Log.e(TAG, "Failed to setup connection.", re);
- }
- mConnectionParams = null;
- } finally {
- TraceEvent.end("ChildProcessConnection.doConnectionSetup");
- }
- }
-
- private boolean bind(boolean useStrongBinding) {
- assert isRunningOnLauncherThread();
- assert !mUnbound;
-
- boolean success;
- if (useStrongBinding) {
- success = mStrongBinding.bind();
- } else {
- mModerateBindingCount++;
- success = mModerateBinding.bind();
- }
- if (!success) return false;
-
- mWaivedBinding.bind();
- updateBindingState();
- return true;
- }
-
- @VisibleForTesting
- protected void unbind() {
- assert isRunningOnLauncherThread();
- mService = null;
- mConnectionParams = null;
- mUnbound = true;
- mStrongBinding.unbind();
- mWaivedBinding.unbind();
- mModerateBinding.unbind();
- updateBindingState();
-
- int[] bindingStateCounts;
- synchronized (sAllBindingStateCounts) {
- bindingStateCounts = Arrays.copyOf(sAllBindingStateCounts, NUM_BINDING_STATES);
- }
- synchronized (mClientThreadLock) {
- mAllBindingStateCountsWhenDied = bindingStateCounts;
- }
-
- if (mMemoryPressureCallback != null) {
- final MemoryPressureCallback callback = mMemoryPressureCallback;
- ThreadUtils.postOnUiThread(() -> MemoryPressureListener.removeCallback(callback));
- mMemoryPressureCallback = null;
- }
- }
-
- public boolean isStrongBindingBound() {
- assert isRunningOnLauncherThread();
- return mStrongBinding.isBound();
- }
-
- public void addStrongBinding() {
- assert isRunningOnLauncherThread();
- if (!isConnected()) {
- Log.w(TAG, "The connection is not bound for %d", getPid());
- return;
- }
- if (mStrongBindingCount == 0) {
- mStrongBinding.bind();
- updateBindingState();
- }
- mStrongBindingCount++;
- }
-
- public void removeStrongBinding() {
- assert isRunningOnLauncherThread();
- if (!isConnected()) {
- Log.w(TAG, "The connection is not bound for %d", getPid());
- return;
- }
- assert mStrongBindingCount > 0;
- mStrongBindingCount--;
- if (mStrongBindingCount == 0) {
- mStrongBinding.unbind();
- updateBindingState();
- }
- }
-
- public boolean isModerateBindingBound() {
- assert isRunningOnLauncherThread();
- return mModerateBinding.isBound();
- }
-
- public void addModerateBinding() {
- assert isRunningOnLauncherThread();
- if (!isConnected()) {
- Log.w(TAG, "The connection is not bound for %d", getPid());
- return;
- }
- if (mModerateBindingCount == 0) {
- mModerateBinding.bind();
- updateBindingState();
- }
- mModerateBindingCount++;
- }
-
- public void removeModerateBinding() {
- assert isRunningOnLauncherThread();
- if (!isConnected()) {
- Log.w(TAG, "The connection is not bound for %d", getPid());
- return;
- }
- assert mModerateBindingCount > 0;
- mModerateBindingCount--;
- if (mModerateBindingCount == 0) {
- mModerateBinding.unbind();
- updateBindingState();
- }
- }
-
- /**
- * @return true if the connection is bound and only bound with the waived binding or if the
- * connection is unbound and was only bound with the waived binding when it disconnected.
- */
- public @ChildBindingState int bindingStateCurrentOrWhenDied() {
- // WARNING: this method can be called from a thread other than the launcher thread.
- // Note that it returns the current waived bound only state and is racy. This not really
- // preventable without changing the caller's API, short of blocking.
- synchronized (mClientThreadLock) {
- return mBindingStateCurrentOrWhenDied;
- }
- }
-
- /**
- * @return true if the connection is intentionally killed by calling kill().
- */
- public boolean isKilledByUs() {
- // WARNING: this method can be called from a thread other than the launcher thread.
- // Note that it returns the current waived bound only state and is racy. This not really
- // preventable without changing the caller's API, short of blocking.
- synchronized (mClientThreadLock) {
- return mKilledByUs;
- }
- }
-
- public int[] bindingStateCountsCurrentOrWhenDied() {
- // WARNING: this method can be called from a thread other than the launcher thread.
- // Note that it returns the current waived bound only state and is racy. This not really
- // preventable without changing the caller's API, short of blocking.
- synchronized (mClientThreadLock) {
- if (mAllBindingStateCountsWhenDied != null) {
- return Arrays.copyOf(mAllBindingStateCountsWhenDied, NUM_BINDING_STATES);
- }
- }
- synchronized (sAllBindingStateCounts) {
- return Arrays.copyOf(sAllBindingStateCounts, NUM_BINDING_STATES);
- }
- }
-
- // Should be called any binding is bound or unbound.
- private void updateBindingState() {
- int oldBindingState = mBindingState;
- if (mUnbound) {
- mBindingState = ChildBindingState.UNBOUND;
- } else if (mStrongBinding.isBound()) {
- mBindingState = ChildBindingState.STRONG;
- } else if (mModerateBinding.isBound()) {
- mBindingState = ChildBindingState.MODERATE;
- } else {
- assert mWaivedBinding.isBound();
- mBindingState = ChildBindingState.WAIVED;
- }
-
- if (mBindingState != oldBindingState) {
- synchronized (sAllBindingStateCounts) {
- if (oldBindingState != ChildBindingState.UNBOUND) {
- assert sAllBindingStateCounts[oldBindingState] > 0;
- sAllBindingStateCounts[oldBindingState]--;
- }
- if (mBindingState != ChildBindingState.UNBOUND) {
- sAllBindingStateCounts[mBindingState]++;
- }
- }
- }
-
- if (!mUnbound) {
- synchronized (mClientThreadLock) {
- mBindingStateCurrentOrWhenDied = mBindingState;
- }
- }
- }
-
- private void notifyChildProcessDied() {
- if (mServiceCallback != null) {
- // Guard against nested calls to this method.
- ServiceCallback serviceCallback = mServiceCallback;
- mServiceCallback = null;
- serviceCallback.onChildProcessDied(this);
- }
- }
-
- private boolean isRunningOnLauncherThread() {
- return mLauncherHandler.getLooper() == Looper.myLooper();
- }
-
- @VisibleForTesting
- public void crashServiceForTesting() throws RemoteException {
- mService.forceKill();
- }
-
- @VisibleForTesting
- public boolean didOnServiceConnectedForTesting() {
- return mDidOnServiceConnected;
- }
-
- @VisibleForTesting
- protected Handler getLauncherHandler() {
- return mLauncherHandler;
- }
-
- private void onMemoryPressure(@MemoryPressureLevel int pressure) {
- mLauncherHandler.post(() -> onMemoryPressureOnLauncherThread(pressure));
- }
-
- private void onMemoryPressureOnLauncherThread(@MemoryPressureLevel int pressure) {
- if (mService == null) return;
- try {
- mService.onMemoryPressure(pressure);
- } catch (RemoteException ex) {
- // Ignore
- }
- }
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java
deleted file mode 100644
index ec232d7c16..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-/**
- * Constants to be used by child processes.
- */
-public interface ChildProcessConstants {
- // Below are the names for the items placed in the bind or start command intent.
- // Note that because that intent maybe reused if a service is restarted, none should be process
- // specific.
-
- public static final String EXTRA_BIND_TO_CALLER =
- "org.chromium.base.process_launcher.extra.bind_to_caller";
-
- // Below are the names for the items placed in the Bundle passed in the
- // IChildProcessService.setupConnection call, once the connection has been established.
-
- // Key for the command line.
- public static final String EXTRA_COMMAND_LINE =
- "org.chromium.base.process_launcher.extra.command_line";
-
- // Key for the file descriptors that should be mapped in the child process.
- public static final String EXTRA_FILES = "org.chromium.base.process_launcher.extra.extraFiles";
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java
deleted file mode 100644
index 7cdc8528bd..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.TraceEvent;
-
-import java.io.IOException;
-import java.util.List;
-
-/**
- * This class is used to start a child process by connecting to a ChildProcessService.
- */
-public class ChildProcessLauncher {
- private static final String TAG = "ChildProcLauncher";
-
- /** Delegate that client should use to customize the process launching. */
- public abstract static class Delegate {
- /**
- * Called when the launcher is about to start. Gives the embedder a chance to provide an
- * already bound connection if it has one. (allowing for warm-up connections: connections
- * that are already bound in advance to speed up child process start-up time).
- * Note that onBeforeConnectionAllocated will not be called if this method returns a
- * connection.
- * @param connectionAllocator the allocator the returned connection should have been
- * allocated of.
- * @param serviceCallback the service callback that the connection should use.
- * @return a bound connection to use to connect to the child process service, or null if a
- * connection should be allocated and bound by the launcher.
- */
- public ChildProcessConnection getBoundConnection(
- ChildConnectionAllocator connectionAllocator,
- ChildProcessConnection.ServiceCallback serviceCallback) {
- return null;
- }
-
- /**
- * Called before a connection is allocated.
- * Note that this is only called if the ChildProcessLauncher is created with
- * {@link #createWithConnectionAllocator}.
- * @param serviceBundle the bundle passed in the service intent. Clients can add their own
- * extras to the bundle.
- */
- public void onBeforeConnectionAllocated(Bundle serviceBundle) {}
-
- /**
- * Called before setup is called on the connection.
- * @param connectionBundle the bundle passed to the {@link ChildProcessService} in the
- * setup call. Clients can add their own extras to the bundle.
- */
- public void onBeforeConnectionSetup(Bundle connectionBundle) {}
-
- /**
- * Called when the connection was successfully established, meaning the setup call on the
- * service was successful.
- * @param connection the connection over which the setup call was made.
- */
- public void onConnectionEstablished(ChildProcessConnection connection) {}
-
- /**
- * Called when a connection has been disconnected. Only invoked if onConnectionEstablished
- * was called, meaning the connection was already established.
- * @param connection the connection that got disconnected.
- */
- public void onConnectionLost(ChildProcessConnection connection) {}
- }
-
- // Represents an invalid process handle; same as base/process/process.h kNullProcessHandle.
- private static final int NULL_PROCESS_HANDLE = 0;
-
- // The handle for the thread we were created on and on which all methods should be called.
- private final Handler mLauncherHandler;
-
- private final Delegate mDelegate;
-
- private final String[] mCommandLine;
- private final FileDescriptorInfo[] mFilesToBeMapped;
-
- // The allocator used to create the connection.
- private final ChildConnectionAllocator mConnectionAllocator;
-
- // The IBinder interfaces provided to the created service.
- private final List<IBinder> mClientInterfaces;
-
- // The actual service connection. Set once we have connected to the service.
- private ChildProcessConnection mConnection;
-
- /**
- * Constructor.
- *
- * @param launcherHandler the handler for the thread where all operations should happen.
- * @param delegate the delagate that gets notified of the launch progress.
- * @param commandLine the command line that should be passed to the started process.
- * @param filesToBeMapped the files that should be passed to the started process.
- * @param connectionAllocator the allocator used to create connections to the service.
- * @param clientInterfaces the interfaces that should be passed to the started process so it can
- * communicate with the parent process.
- */
- public ChildProcessLauncher(Handler launcherHandler, Delegate delegate, String[] commandLine,
- FileDescriptorInfo[] filesToBeMapped, ChildConnectionAllocator connectionAllocator,
- List<IBinder> clientInterfaces) {
- assert connectionAllocator != null;
- mLauncherHandler = launcherHandler;
- isRunningOnLauncherThread();
- mCommandLine = commandLine;
- mConnectionAllocator = connectionAllocator;
- mDelegate = delegate;
- mFilesToBeMapped = filesToBeMapped;
- mClientInterfaces = clientInterfaces;
- }
-
- /**
- * Starts the child process and calls setup on it if {@param setupConnection} is true.
- * @param setupConnection whether the setup should be performed on the connection once
- * established
- * @param queueIfNoFreeConnection whether to queue that request if no service connection is
- * available. If the launcher was created with a connection provider, this parameter has no
- * effect.
- * @return true if the connection was started or was queued.
- */
- public boolean start(final boolean setupConnection, final boolean queueIfNoFreeConnection) {
- assert isRunningOnLauncherThread();
- try {
- TraceEvent.begin("ChildProcessLauncher.start");
- ChildProcessConnection.ServiceCallback serviceCallback =
- new ChildProcessConnection.ServiceCallback() {
- @Override
- public void onChildStarted() {}
-
- @Override
- public void onChildStartFailed(ChildProcessConnection connection) {
- assert isRunningOnLauncherThread();
- assert mConnection == connection;
- Log.e(TAG, "ChildProcessConnection.start failed, trying again");
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- // The child process may already be bound to another client
- // (this can happen if multi-process WebView is used in more
- // than one process), so try starting the process again.
- // This connection that failed to start has not been freed,
- // so a new bound connection will be allocated.
- mConnection = null;
- start(setupConnection, queueIfNoFreeConnection);
- }
- });
- }
-
- @Override
- public void onChildProcessDied(ChildProcessConnection connection) {
- assert isRunningOnLauncherThread();
- assert mConnection == connection;
- ChildProcessLauncher.this.onChildProcessDied();
- }
- };
- mConnection = mDelegate.getBoundConnection(mConnectionAllocator, serviceCallback);
- if (mConnection != null) {
- assert mConnectionAllocator.isConnectionFromAllocator(mConnection);
- setupConnection();
- return true;
- }
- if (!allocateAndSetupConnection(
- serviceCallback, setupConnection, queueIfNoFreeConnection)
- && !queueIfNoFreeConnection) {
- return false;
- }
- return true;
- } finally {
- TraceEvent.end("ChildProcessLauncher.start");
- }
- }
-
- public ChildProcessConnection getConnection() {
- return mConnection;
- }
-
- public ChildConnectionAllocator getConnectionAllocator() {
- return mConnectionAllocator;
- }
-
- private boolean allocateAndSetupConnection(
- final ChildProcessConnection.ServiceCallback serviceCallback,
- final boolean setupConnection, final boolean queueIfNoFreeConnection) {
- assert mConnection == null;
- Bundle serviceBundle = new Bundle();
- mDelegate.onBeforeConnectionAllocated(serviceBundle);
-
- mConnection = mConnectionAllocator.allocate(
- ContextUtils.getApplicationContext(), serviceBundle, serviceCallback);
- if (mConnection == null) {
- if (!queueIfNoFreeConnection) {
- Log.d(TAG, "Failed to allocate a child connection (no queuing).");
- return false;
- }
- mConnectionAllocator.queueAllocation(
- () -> allocateAndSetupConnection(
- serviceCallback, setupConnection, queueIfNoFreeConnection));
- return false;
- }
-
- if (setupConnection) {
- setupConnection();
- }
- return true;
- }
-
- private void setupConnection() {
- ChildProcessConnection.ConnectionCallback connectionCallback =
- new ChildProcessConnection.ConnectionCallback() {
- @Override
- public void onConnected(ChildProcessConnection connection) {
- assert mConnection == connection;
- onServiceConnected();
- }
- };
- Bundle connectionBundle = createConnectionBundle();
- mDelegate.onBeforeConnectionSetup(connectionBundle);
- mConnection.setupConnection(connectionBundle, getClientInterfaces(), connectionCallback);
- }
-
- private void onServiceConnected() {
- assert isRunningOnLauncherThread();
-
- Log.d(TAG, "on connect callback, pid=%d", mConnection.getPid());
-
- mDelegate.onConnectionEstablished(mConnection);
-
- // Proactively close the FDs rather than waiting for the GC to do it.
- try {
- for (FileDescriptorInfo fileInfo : mFilesToBeMapped) {
- fileInfo.fd.close();
- }
- } catch (IOException ioe) {
- Log.w(TAG, "Failed to close FD.", ioe);
- }
- }
-
- public int getPid() {
- assert isRunningOnLauncherThread();
- return mConnection == null ? NULL_PROCESS_HANDLE : mConnection.getPid();
- }
-
- public List<IBinder> getClientInterfaces() {
- return mClientInterfaces;
- }
-
- private boolean isRunningOnLauncherThread() {
- return mLauncherHandler.getLooper() == Looper.myLooper();
- }
-
- private Bundle createConnectionBundle() {
- Bundle bundle = new Bundle();
- bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, mCommandLine);
- bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, mFilesToBeMapped);
- return bundle;
- }
-
- private void onChildProcessDied() {
- assert isRunningOnLauncherThread();
- if (getPid() != 0) {
- mDelegate.onConnectionLost(mConnection);
- }
- }
-
- public void stop() {
- assert isRunningOnLauncherThread();
- Log.d(TAG, "stopping child connection: pid=%d", mConnection.getPid());
- mConnection.stop();
- }
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java
deleted file mode 100644
index 876ebbb175..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java
+++ /dev/null
@@ -1,346 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Parcelable;
-import android.os.Process;
-import android.os.RemoteException;
-import android.util.SparseArray;
-
-import org.chromium.base.BaseSwitches;
-import org.chromium.base.CommandLine;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.MemoryPressureLevel;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.memory.MemoryPressureMonitor;
-
-import java.util.List;
-import java.util.concurrent.Semaphore;
-
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * This is the base class for child services; the embedding application should contain
- * ProcessService0, 1.. etc subclasses that provide the concrete service entry points, so it can
- * connect to more than one distinct process (i.e. one process per service number, up to limit of
- * N).
- * The embedding application must declare these service instances in the application section
- * of its AndroidManifest.xml, first with some meta-data describing the services:
- * <meta-data android:name="org.chromium.test_app.SERVICES_NAME"
- * android:value="org.chromium.test_app.ProcessService"/>
- * and then N entries of the form:
- * <service android:name="org.chromium.test_app.ProcessServiceX"
- * android:process=":processX" />
- *
- * Subclasses must also provide a delegate in this class constructor. That delegate is responsible
- * for loading native libraries and running the main entry point of the service.
- */
-@JNINamespace("base::android")
-@MainDex
-public abstract class ChildProcessService extends Service {
- private static final String MAIN_THREAD_NAME = "ChildProcessMain";
- private static final String TAG = "ChildProcessService";
-
- // Only for a check that create is only called once.
- private static boolean sCreateCalled;
-
- private final ChildProcessServiceDelegate mDelegate;
-
- private final Object mBinderLock = new Object();
- private final Object mLibraryInitializedLock = new Object();
-
- // True if we should enforce that bindToCaller() is called before setupConnection().
- // Only set once in bind(), does not require synchronization.
- private boolean mBindToCallerCheck;
-
- // PID of the client of this service, set in bindToCaller(), if mBindToCallerCheck is true.
- @GuardedBy("mBinderLock")
- private int mBoundCallingPid;
-
- // This is the native "Main" thread for the renderer / utility process.
- private Thread mMainThread;
-
- // Parameters received via IPC, only accessed while holding the mMainThread monitor.
- private String[] mCommandLineParams;
-
- // File descriptors that should be registered natively.
- private FileDescriptorInfo[] mFdInfos;
-
- @GuardedBy("mLibraryInitializedLock")
- private boolean mLibraryInitialized;
-
- // Called once the service is bound and all service related member variables have been set.
- // Only set once in bind(), does not require synchronization.
- private boolean mServiceBound;
-
- private final Semaphore mActivitySemaphore = new Semaphore(1);
-
- public ChildProcessService(ChildProcessServiceDelegate delegate) {
- mDelegate = delegate;
- }
-
- // Binder object used by clients for this service.
- private final IChildProcessService.Stub mBinder = new IChildProcessService.Stub() {
- // NOTE: Implement any IChildProcessService methods here.
- @Override
- public boolean bindToCaller() {
- assert mBindToCallerCheck;
- assert mServiceBound;
- synchronized (mBinderLock) {
- int callingPid = Binder.getCallingPid();
- if (mBoundCallingPid == 0) {
- mBoundCallingPid = callingPid;
- } else if (mBoundCallingPid != callingPid) {
- Log.e(TAG, "Service is already bound by pid %d, cannot bind for pid %d",
- mBoundCallingPid, callingPid);
- return false;
- }
- }
- return true;
- }
-
- @Override
- public void setupConnection(Bundle args, ICallbackInt pidCallback, List<IBinder> callbacks)
- throws RemoteException {
- assert mServiceBound;
- synchronized (mBinderLock) {
- if (mBindToCallerCheck && mBoundCallingPid == 0) {
- Log.e(TAG, "Service has not been bound with bindToCaller()");
- pidCallback.call(-1);
- return;
- }
- }
-
- pidCallback.call(Process.myPid());
- processConnectionBundle(args, callbacks);
- }
-
- @Override
- public void forceKill() {
- assert mServiceBound;
- Process.killProcess(Process.myPid());
- }
-
- @Override
- public void onMemoryPressure(@MemoryPressureLevel int pressure) {
- // This method is called by the host process when the host process reports pressure
- // to its native side. The key difference between the host process and its services is
- // that the host process polls memory pressure when it gets CRITICAL, and periodically
- // invokes pressure listeners until pressure subsides. (See MemoryPressureMonitor for
- // more info.)
- //
- // Services don't poll, so this side-channel is used to notify services about memory
- // pressure from the host process's POV.
- //
- // However, since both host process and services listen to ComponentCallbacks2, we
- // can't be sure that the host process won't get better signals than their services.
- // I.e. we need to watch out for a situation where a service gets CRITICAL, but the
- // host process gets MODERATE - in this case we need to ignore MODERATE.
- //
- // So we're ignoring pressure from the host process if it's better than the last
- // reported pressure. I.e. the host process can drive pressure up, but it'll go
- // down only when we the service get a signal through ComponentCallbacks2.
- ThreadUtils.postOnUiThread(() -> {
- if (pressure >= MemoryPressureMonitor.INSTANCE.getLastReportedPressure()) {
- MemoryPressureMonitor.INSTANCE.notifyPressure(pressure);
- }
- });
- }
- };
-
- /**
- * Loads Chrome's native libraries and initializes a ChildProcessService.
- */
- // For sCreateCalled check.
- @Override
- public void onCreate() {
- super.onCreate();
- Log.i(TAG, "Creating new ChildProcessService pid=%d", Process.myPid());
- if (sCreateCalled) {
- throw new RuntimeException("Illegal child process reuse.");
- }
- sCreateCalled = true;
-
- // Initialize the context for the application that owns this ChildProcessService object.
- ContextUtils.initApplicationContext(getApplicationContext());
-
- mDelegate.onServiceCreated();
-
- mMainThread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- // CommandLine must be initialized before everything else.
- synchronized (mMainThread) {
- while (mCommandLineParams == null) {
- mMainThread.wait();
- }
- }
- assert mServiceBound;
- CommandLine.init(mCommandLineParams);
-
- if (CommandLine.getInstance().hasSwitch(
- BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) {
- android.os.Debug.waitForDebugger();
- }
-
- boolean nativeLibraryLoaded = false;
- try {
- nativeLibraryLoaded = mDelegate.loadNativeLibrary(getApplicationContext());
- } catch (Exception e) {
- Log.e(TAG, "Failed to load native library.", e);
- }
- if (!nativeLibraryLoaded) {
- System.exit(-1);
- }
-
- synchronized (mLibraryInitializedLock) {
- mLibraryInitialized = true;
- mLibraryInitializedLock.notifyAll();
- }
- synchronized (mMainThread) {
- mMainThread.notifyAll();
- while (mFdInfos == null) {
- mMainThread.wait();
- }
- }
-
- SparseArray<String> idsToKeys = mDelegate.getFileDescriptorsIdsToKeys();
-
- int[] fileIds = new int[mFdInfos.length];
- String[] keys = new String[mFdInfos.length];
- int[] fds = new int[mFdInfos.length];
- long[] regionOffsets = new long[mFdInfos.length];
- long[] regionSizes = new long[mFdInfos.length];
- for (int i = 0; i < mFdInfos.length; i++) {
- FileDescriptorInfo fdInfo = mFdInfos[i];
- String key = idsToKeys != null ? idsToKeys.get(fdInfo.id) : null;
- if (key != null) {
- keys[i] = key;
- } else {
- fileIds[i] = fdInfo.id;
- }
- fds[i] = fdInfo.fd.detachFd();
- regionOffsets[i] = fdInfo.offset;
- regionSizes[i] = fdInfo.size;
- }
- nativeRegisterFileDescriptors(keys, fileIds, fds, regionOffsets, regionSizes);
-
- mDelegate.onBeforeMain();
- if (mActivitySemaphore.tryAcquire()) {
- mDelegate.runMain();
- nativeExitChildProcess();
- }
- } catch (InterruptedException e) {
- Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e);
- }
- }
- }, MAIN_THREAD_NAME);
- mMainThread.start();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- Log.i(TAG, "Destroying ChildProcessService pid=%d", Process.myPid());
- if (mActivitySemaphore.tryAcquire()) {
- // TODO(crbug.com/457406): This is a bit hacky, but there is no known better solution
- // as this service will get reused (at least if not sandboxed).
- // In fact, we might really want to always exit() from onDestroy(), not just from
- // the early return here.
- System.exit(0);
- return;
- }
- synchronized (mLibraryInitializedLock) {
- try {
- while (!mLibraryInitialized) {
- // Avoid a potential race in calling through to native code before the library
- // has loaded.
- mLibraryInitializedLock.wait();
- }
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- mDelegate.onDestroy();
- }
-
- /*
- * Returns the communication channel to the service. Note that even if multiple clients were to
- * connect, we should only get one call to this method. So there is no need to synchronize
- * member variables that are only set in this method and accessed from binder methods, as binder
- * methods can't be called until this method returns.
- * @param intent The intent that was used to bind to the service.
- * @return the binder used by the client to setup the connection.
- */
- @Override
- public IBinder onBind(Intent intent) {
- assert !mServiceBound;
-
- // We call stopSelf() to request that this service be stopped as soon as the client unbinds.
- // Otherwise the system may keep it around and available for a reconnect. The child
- // processes do not currently support reconnect; they must be initialized from scratch every
- // time.
- stopSelf();
-
- mBindToCallerCheck =
- intent.getBooleanExtra(ChildProcessConstants.EXTRA_BIND_TO_CALLER, false);
- mServiceBound = true;
- mDelegate.onServiceBound(intent);
- // Don't block bind() with any extra work, post it to the application thread instead.
- new Handler(Looper.getMainLooper())
- .post(() -> mDelegate.preloadNativeLibrary(getApplicationContext()));
- return mBinder;
- }
-
- private void processConnectionBundle(Bundle bundle, List<IBinder> clientInterfaces) {
- // Required to unparcel FileDescriptorInfo.
- ClassLoader classLoader = getApplicationContext().getClassLoader();
- bundle.setClassLoader(classLoader);
- synchronized (mMainThread) {
- if (mCommandLineParams == null) {
- mCommandLineParams =
- bundle.getStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE);
- mMainThread.notifyAll();
- }
- // We must have received the command line by now
- assert mCommandLineParams != null;
- Parcelable[] fdInfosAsParcelable =
- bundle.getParcelableArray(ChildProcessConstants.EXTRA_FILES);
- if (fdInfosAsParcelable != null) {
- // For why this arraycopy is necessary:
- // http://stackoverflow.com/questions/8745893/i-dont-get-why-this-classcastexception-occurs
- mFdInfos = new FileDescriptorInfo[fdInfosAsParcelable.length];
- System.arraycopy(fdInfosAsParcelable, 0, mFdInfos, 0, fdInfosAsParcelable.length);
- }
- mDelegate.onConnectionSetup(bundle, clientInterfaces);
- mMainThread.notifyAll();
- }
- }
-
- /**
- * Helper for registering FileDescriptorInfo objects with GlobalFileDescriptors or
- * FileDescriptorStore.
- * This includes the IPC channel, the crash dump signals and resource related
- * files.
- */
- private static native void nativeRegisterFileDescriptors(
- String[] keys, int[] id, int[] fd, long[] offset, long[] size);
-
- /**
- * Force the child process to exit.
- */
- private static native void nativeExitChildProcess();
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java
deleted file mode 100644
index 7beffeffa2..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.util.SparseArray;
-
-import java.util.List;
-
-/**
- * The interface that embedders should implement to specialize child service creation.
- */
-public interface ChildProcessServiceDelegate {
- /** Invoked when the service was created. This is the first method invoked on the delegate. */
- void onServiceCreated();
-
- /**
- * Called when the service is bound. Invoked on a background thread.
- * @param intent the intent that started the service.
- */
- void onServiceBound(Intent intent);
-
- /**
- * Called once the connection has been setup. Invoked on a background thread.
- * @param connectionBundle the bundle pass to the setupConnection call
- * @param clientInterfaces the IBinders interfaces provided by the client
- */
- void onConnectionSetup(Bundle connectionBundle, List<IBinder> clientInterfaces);
-
- /**
- * Called when the service gets destroyed.
- * Note that the system might kill the process hosting the service without this method being
- * called.
- */
- void onDestroy();
-
- /**
- * Called when the delegate should load the native library.
- * @param hostContext The host context the library should be loaded with (i.e. Chrome).
- * @return true if the library was loaded successfully, false otherwise in which case the
- * service stops.
- */
- boolean loadNativeLibrary(Context hostContext);
-
- /**
- * Called when the delegate should preload the native library.
- * Preloading is automatically done during library loading, but can also be called explicitly
- * to speed up the loading. See {@link LibraryLoader.preloadNow}.
- * @param hostContext The host context the library should be preloaded with (i.e. Chrome).
- */
- void preloadNativeLibrary(Context hostContext);
-
- /**
- * Should return a map that associatesfile descriptors' IDs to keys.
- * This is needed as at the moment we use 2 different stores for the FDs in native code:
- * base::FileDescriptorStore which associates FDs with string identifiers (the key), and
- * base::GlobalDescriptors which associates FDs with int ids.
- * FDs for which the returned map contains a mapping are added to base::FileDescriptorStore with
- * the associated key, all others are added to base::GlobalDescriptors.
- */
- SparseArray<String> getFileDescriptorsIdsToKeys();
-
- /** Called before the main method is invoked. */
- void onBeforeMain();
-
- /**
- * The main entry point for the service. This method should block as long as the service should
- * be running.
- */
- void runMain();
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.aidl b/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.aidl
deleted file mode 100644
index e37d8c748d..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.aidl
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2016 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.process_launcher;
-
-parcelable FileDescriptorInfo;
diff --git a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java b/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java
deleted file mode 100644
index 3dc366389a..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.annotations.UsedByReflection;
-
-import javax.annotation.concurrent.Immutable;
-
-/**
- * Parcelable class that contains file descriptor and file region information to
- * be passed to child processes.
- */
-@Immutable
-@MainDex
-@UsedByReflection("child_process_launcher_helper_android.cc")
-public final class FileDescriptorInfo implements Parcelable {
- public final int id;
- public final ParcelFileDescriptor fd;
- public final long offset;
- public final long size;
-
- public FileDescriptorInfo(int id, ParcelFileDescriptor fd, long offset, long size) {
- this.id = id;
- this.fd = fd;
- this.offset = offset;
- this.size = size;
- }
-
- FileDescriptorInfo(Parcel in) {
- id = in.readInt();
- fd = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
- offset = in.readLong();
- size = in.readLong();
- }
-
- @Override
- public int describeContents() {
- return CONTENTS_FILE_DESCRIPTOR;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(id);
- dest.writeParcelable(fd, CONTENTS_FILE_DESCRIPTOR);
- dest.writeLong(offset);
- dest.writeLong(size);
- }
-
- public static final Parcelable.Creator<FileDescriptorInfo> CREATOR =
- new Parcelable.Creator<FileDescriptorInfo>() {
- @Override
- public FileDescriptorInfo createFromParcel(Parcel in) {
- return new FileDescriptorInfo(in);
- }
-
- @Override
- public FileDescriptorInfo[] newArray(int size) {
- return new FileDescriptorInfo[size];
- }
- };
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ICallbackInt.aidl b/base/android/java/src/org/chromium/base/process_launcher/ICallbackInt.aidl
deleted file mode 100644
index db93cb0dbd..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/ICallbackInt.aidl
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-oneway interface ICallbackInt {
- void call(int value);
-}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl b/base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl
deleted file mode 100644
index 298e0bf49a..0000000000
--- a/base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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.process_launcher;
-
-import android.os.Bundle;
-
-import org.chromium.base.process_launcher.ICallbackInt;
-
-interface IChildProcessService {
- // On the first call to this method, the service will record the calling PID
- // and return true. Subsequent calls will only return true if the calling PID
- // is the same as the recorded one.
- boolean bindToCaller();
-
- // Sets up the initial IPC channel.
- oneway void setupConnection(in Bundle args, ICallbackInt pidCallback,
- in List<IBinder> clientInterfaces);
-
- // Forcefully kills the child process.
- oneway void forceKill();
-
- // Notifies about memory pressure. The argument is MemoryPressureLevel enum.
- oneway void onMemoryPressure(int pressure);
-}
diff --git a/base/android/java/templates/BuildConfig.template b/base/android/java/templates/BuildConfig.template
deleted file mode 100644
index 1006d12ee1..0000000000
--- a/base/android/java/templates/BuildConfig.template
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2015 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;
-
-#define Q(x) #x
-#define QUOTE(x) Q(x)
-
-#if defined(USE_FINAL)
-#define MAYBE_FINAL final
-#else
-#define MAYBE_FINAL
-#endif
-
-/**
- * Build configuration. Generated on a per-target basis.
- */
-public class BuildConfig {
-
-#if defined(ENABLE_MULTIDEX)
- public static MAYBE_FINAL boolean IS_MULTIDEX_ENABLED = true;
-#else
- public static MAYBE_FINAL boolean IS_MULTIDEX_ENABLED = false;
-#endif
-
-#if defined(_FIREBASE_APP_ID)
- public static MAYBE_FINAL String FIREBASE_APP_ID = QUOTE(_FIREBASE_APP_ID);
-#else
- public static MAYBE_FINAL String FIREBASE_APP_ID = "";
-#endif
-
-#if defined(_DCHECK_IS_ON)
- public static MAYBE_FINAL boolean DCHECK_IS_ON = true;
-#else
- public static MAYBE_FINAL boolean DCHECK_IS_ON = false;
-#endif
-
-#if defined(_IS_UBSAN)
- public static MAYBE_FINAL boolean IS_UBSAN = true;
-#else
- public static MAYBE_FINAL boolean IS_UBSAN = false;
-#endif
-
- // Sorted list of locales that have a compressed .pak within assets.
- // Stored as an array because AssetManager.list() is slow.
-#if defined(COMPRESSED_LOCALE_LIST)
- public static MAYBE_FINAL String[] COMPRESSED_LOCALES = COMPRESSED_LOCALE_LIST;
-#else
- public static MAYBE_FINAL String[] COMPRESSED_LOCALES = {};
-#endif
-
- // Sorted list of locales that have an uncompressed .pak within assets.
- // Stored as an array because AssetManager.list() is slow.
-#if defined(UNCOMPRESSED_LOCALE_LIST)
- public static MAYBE_FINAL String[] UNCOMPRESSED_LOCALES = UNCOMPRESSED_LOCALE_LIST;
-#else
- public static MAYBE_FINAL String[] UNCOMPRESSED_LOCALES = {};
-#endif
-
- // The ID of the android string resource that stores the product version.
- // This layer of indirection is necessary to make the resource dependency
- // optional for android_apk targets/base_java (ex. for cronet).
-#if defined(_RESOURCES_VERSION_VARIABLE)
- public static MAYBE_FINAL int R_STRING_PRODUCT_VERSION = _RESOURCES_VERSION_VARIABLE;
-#else
- // Default value, do not use.
- public static MAYBE_FINAL int R_STRING_PRODUCT_VERSION = 0;
-#endif
-}
diff --git a/base/android/java/templates/NativeLibraries.template b/base/android/java/templates/NativeLibraries.template
deleted file mode 100644
index 68277df753..0000000000
--- a/base/android/java/templates/NativeLibraries.template
+++ /dev/null
@@ -1,109 +0,0 @@
-// 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.library_loader;
-
-public class NativeLibraries {
- /**
- * IMPORTANT NOTE: The variables defined here must _not_ be 'final'.
- *
- * The reason for this is very subtle:
- *
- * - This template is used to generate several distinct, but similar
- * files used in different contexts:
- *
- * o .../gen/templates/org/chromium/base/library_loader/NativeLibraries.java
- *
- * This file is used to build base.jar, which is the library
- * jar used by chromium projects. However, the
- * corresponding NativeLibraries.class file will _not_ be part
- * of the final base.jar.
- *
- * o .../$PROJECT/native_libraries_java/NativeLibraries.java
- *
- * This file is used to build an APK (e.g. $PROJECT
- * could be 'content_shell_apk'). Its content will depend on
- * this target's specific build configuration, and differ from
- * the source file above.
- *
- * - During the final link, all .jar files are linked together into
- * a single .dex file, and the second version of NativeLibraries.class
- * will be put into the final output file, and used at runtime.
- *
- * - If the variables were defined as 'final', their value would be
- * optimized out inside of 'base.jar', and could not be specialized
- * for every chromium program. This, however, doesn't apply to arrays of
- * strings, which can be defined as final.
- *
- * This exotic scheme is used to avoid injecting project-specific, or
- * even build-specific, values into the base layer. E.g. this is
- * how the component build is supported on Android without modifying
- * the sources of each and every Chromium-based target.
- */
-
- public static final int CPU_FAMILY_UNKNOWN = 0;
- public static final int CPU_FAMILY_ARM = 1;
- public static final int CPU_FAMILY_MIPS = 2;
- public static final int CPU_FAMILY_X86 = 3;
-
-#if defined(ENABLE_CHROMIUM_LINKER_LIBRARY_IN_ZIP_FILE) && \
- !defined(ENABLE_CHROMIUM_LINKER)
-#error "Must have ENABLE_CHROMIUM_LINKER to enable library in zip file"
-#endif
-
- // Set to true to enable the use of the Chromium Linker.
-#if defined(ENABLE_CHROMIUM_LINKER)
- public static boolean sUseLinker = true;
-#else
- public static boolean sUseLinker = false;
-#endif
-
-#if defined(ENABLE_CHROMIUM_LINKER_LIBRARY_IN_ZIP_FILE)
- public static boolean sUseLibraryInZipFile = true;
-#else
- public static boolean sUseLibraryInZipFile = false;
-#endif
-
-#if defined(ENABLE_CHROMIUM_LINKER_TESTS)
- public static boolean sEnableLinkerTests = true;
-#else
- public static boolean sEnableLinkerTests = false;
-#endif
-
- // This is the list of native libraries to be loaded (in the correct order)
- // by LibraryLoader.java. The base java library is compiled with no
- // array defined, and then the build system creates a version of the file
- // with the real list of libraries required (which changes based upon which
- // .apk is being built).
- // TODO(cjhopman): This is public since it is referenced by NativeTestActivity.java
- // directly. The two ways of library loading should be refactored into one.
- public static final String[] LIBRARIES =
-#if defined(NATIVE_LIBRARIES_LIST)
- NATIVE_LIBRARIES_LIST;
-#else
- {};
-#endif
-
- // This is the expected version of the 'main' native library, which is the one that
- // implements the initial set of base JNI functions including
- // base::android::nativeGetVersionName()
- static String sVersionNumber =
-#if defined(NATIVE_LIBRARIES_VERSION_NUMBER)
- NATIVE_LIBRARIES_VERSION_NUMBER;
-#else
- "";
-#endif
-
- public static int sCpuFamily =
-#if defined(ANDROID_APP_CPU_FAMILY_ARM)
- CPU_FAMILY_ARM;
-#elif defined(ANDROID_APP_CPU_FAMILY_X86)
- CPU_FAMILY_X86;
-#elif defined(ANDROID_APP_CPU_FAMILY_MIPS)
- CPU_FAMILY_MIPS;
-#else
- CPU_FAMILY_UNKNOWN;
-#endif
-
-}
diff --git a/base/android/java_exception_reporter.cc b/base/android/java_exception_reporter.cc
index be3e7039ac..96eb38e581 100644
--- a/base/android/java_exception_reporter.cc
+++ b/base/android/java_exception_reporter.cc
@@ -38,11 +38,8 @@ void SetJavaExceptionCallback(void (*callback)(const char*)) {
}
void SetJavaException(const char* exception) {
- // No need to print exception because they are already logged via
- // env->ExceptionDescribe() within jni_android.cc.
- if (g_java_exception_callback) {
- g_java_exception_callback(exception);
- }
+ DCHECK(g_java_exception_callback);
+ g_java_exception_callback(exception);
}
void JNI_JavaExceptionReporter_ReportJavaException(
diff --git a/base/android/java_handler_thread.cc b/base/android/java_handler_thread.cc
deleted file mode 100644
index ea87ba76d9..0000000000
--- a/base/android/java_handler_thread.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2013 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/android/java_handler_thread.h"
-
-#include <jni.h>
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread_internal_posix.h"
-#include "base/threading/thread_restrictions.h"
-#include "jni/JavaHandlerThread_jni.h"
-
-using base::android::AttachCurrentThread;
-
-namespace base {
-
-namespace android {
-
-JavaHandlerThread::JavaHandlerThread(const char* name,
- base::ThreadPriority priority)
- : JavaHandlerThread(Java_JavaHandlerThread_create(
- AttachCurrentThread(),
- ConvertUTF8ToJavaString(AttachCurrentThread(), name),
- base::internal::ThreadPriorityToNiceValue(priority))) {}
-
-JavaHandlerThread::JavaHandlerThread(
- const base::android::ScopedJavaLocalRef<jobject>& obj)
- : java_thread_(obj) {}
-
-JavaHandlerThread::~JavaHandlerThread() {
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(!Java_JavaHandlerThread_isAlive(env, java_thread_));
- DCHECK(!message_loop_ || message_loop_->IsAborted());
- // TODO(mthiesse): We shouldn't leak the MessageLoop as this could affect
- // future tests.
- if (message_loop_ && message_loop_->IsAborted()) {
- // When the message loop has been aborted due to a crash, we intentionally
- // leak the message loop because the message loop hasn't been shut down
- // properly and would trigger DCHECKS. This should only happen in tests,
- // where we handle the exception instead of letting it take down the
- // process.
- message_loop_.release();
- }
-}
-
-void JavaHandlerThread::Start() {
- // Check the thread has not already been started.
- DCHECK(!message_loop_);
-
- JNIEnv* env = base::android::AttachCurrentThread();
- base::WaitableEvent initialize_event(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- Java_JavaHandlerThread_startAndInitialize(
- env, java_thread_, reinterpret_cast<intptr_t>(this),
- reinterpret_cast<intptr_t>(&initialize_event));
- // Wait for thread to be initialized so it is ready to be used when Start
- // returns.
- base::ThreadRestrictions::ScopedAllowWait wait_allowed;
- initialize_event.Wait();
-}
-
-void JavaHandlerThread::Stop() {
- DCHECK(!task_runner()->BelongsToCurrentThread());
- task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&JavaHandlerThread::StopOnThread, base::Unretained(this)));
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_JavaHandlerThread_joinThread(env, java_thread_);
-}
-
-void JavaHandlerThread::InitializeThread(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jlong event) {
- // TYPE_JAVA to get the Android java style message loop.
- message_loop_ =
- std::make_unique<MessageLoopForUI>(base::MessageLoop::TYPE_JAVA);
- Init();
- reinterpret_cast<base::WaitableEvent*>(event)->Signal();
-}
-
-void JavaHandlerThread::OnLooperStopped(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- DCHECK(task_runner()->BelongsToCurrentThread());
- message_loop_.reset();
- CleanUp();
-}
-
-void JavaHandlerThread::StopMessageLoopForTesting() {
- DCHECK(task_runner()->BelongsToCurrentThread());
- StopOnThread();
-}
-
-void JavaHandlerThread::JoinForTesting() {
- DCHECK(!task_runner()->BelongsToCurrentThread());
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_JavaHandlerThread_joinThread(env, java_thread_);
-}
-
-void JavaHandlerThread::ListenForUncaughtExceptionsForTesting() {
- DCHECK(!task_runner()->BelongsToCurrentThread());
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_JavaHandlerThread_listenForUncaughtExceptionsForTesting(env,
- java_thread_);
-}
-
-ScopedJavaLocalRef<jthrowable> JavaHandlerThread::GetUncaughtExceptionIfAny() {
- DCHECK(!task_runner()->BelongsToCurrentThread());
- JNIEnv* env = base::android::AttachCurrentThread();
- return Java_JavaHandlerThread_getUncaughtExceptionIfAny(env, java_thread_);
-}
-
-void JavaHandlerThread::StopOnThread() {
- DCHECK(task_runner()->BelongsToCurrentThread());
- message_loop_->QuitWhenIdle(base::BindOnce(
- &JavaHandlerThread::QuitThreadSafely, base::Unretained(this)));
-}
-
-void JavaHandlerThread::QuitThreadSafely() {
- DCHECK(task_runner()->BelongsToCurrentThread());
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_JavaHandlerThread_quitThreadSafely(env, java_thread_,
- reinterpret_cast<intptr_t>(this));
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/java_handler_thread.h b/base/android/java_handler_thread.h
deleted file mode 100644
index d65dfe2987..0000000000
--- a/base/android/java_handler_thread.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_ANDROID_JAVA_HANDLER_THREAD_H_
-#define BASE_ANDROID_JAVA_HANDLER_THREAD_H_
-
-#include <jni.h>
-
-#include <memory>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-
-namespace base {
-
-class MessageLoop;
-
-namespace android {
-
-// A Java Thread with a native message loop. To run tasks, post them
-// to the message loop and they will be scheduled along with Java tasks
-// on the thread.
-// This is useful for callbacks where the receiver expects a thread
-// with a prepared Looper.
-class BASE_EXPORT JavaHandlerThread {
- public:
- // Create new thread.
- explicit JavaHandlerThread(
- const char* name,
- base::ThreadPriority priority = base::ThreadPriority::NORMAL);
- // Wrap and connect to an existing JavaHandlerThread.
- // |obj| is an instance of JavaHandlerThread.
- explicit JavaHandlerThread(
- const base::android::ScopedJavaLocalRef<jobject>& obj);
- virtual ~JavaHandlerThread();
-
- // Called from any thread.
- base::MessageLoop* message_loop() const { return message_loop_.get(); }
-
- // Gets the TaskRunner associated with the message loop.
- // Called from any thread.
- scoped_refptr<SingleThreadTaskRunner> task_runner() const {
- return message_loop_ ? message_loop_->task_runner() : nullptr;
- }
-
- // Called from the parent thread.
- void Start();
- void Stop();
-
- // Called from java on the newly created thread.
- // Start() will not return before this methods has finished.
- void InitializeThread(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jlong event);
- // Called from java on this thread.
- void OnLooperStopped(JNIEnv* env, const JavaParamRef<jobject>& obj);
-
- // Called from this thread.
- void StopMessageLoopForTesting();
- // Called from this thread.
- void JoinForTesting();
-
- // Called from this thread.
- // See comment in JavaHandlerThread.java regarding use of this function.
- void ListenForUncaughtExceptionsForTesting();
- // Called from this thread.
- ScopedJavaLocalRef<jthrowable> GetUncaughtExceptionIfAny();
-
- protected:
- // Semantically the same as base::Thread#Init(), but unlike base::Thread the
- // Android Looper will already be running. This Init() call will still run
- // before other tasks are posted to the thread.
- virtual void Init() {}
-
- // Semantically the same as base::Thread#CleanUp(), called after the message
- // loop ends. The Android Looper will also have been quit by this point.
- virtual void CleanUp() {}
-
- std::unique_ptr<base::MessageLoopForUI> message_loop_;
-
- private:
- void StartMessageLoop();
-
- void StopOnThread();
- void QuitThreadSafely();
-
- ScopedJavaGlobalRef<jobject> java_thread_;
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_JAVA_HANDLER_THREAD_H_
diff --git a/base/android/javatests/src/org/chromium/base/AdvancedMockContextTest.java b/base/android/javatests/src/org/chromium/base/AdvancedMockContextTest.java
deleted file mode 100644
index 20c626d194..0000000000
--- a/base/android/javatests/src/org/chromium/base/AdvancedMockContextTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2017 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;
-
-import android.app.Application;
-import android.content.ComponentCallbacks;
-import android.content.ComponentCallbacks2;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.AdvancedMockContext;
-
-/**
- * Tests for {@link org.chromium.base.test.util.AdvancedMockContext}.
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class AdvancedMockContextTest {
- private static class Callback1 implements ComponentCallbacks {
- protected Configuration mConfiguration;
- protected boolean mOnLowMemoryCalled;
-
- @Override
- public void onConfigurationChanged(Configuration configuration) {
- mConfiguration = configuration;
- }
-
- @Override
- public void onLowMemory() {
- mOnLowMemoryCalled = true;
- }
- }
-
- private static class Callback2 extends Callback1 implements ComponentCallbacks2 {
- private int mLevel;
-
- @Override
- public void onTrimMemory(int level) {
- mLevel = level;
- }
- }
-
- @Test
- @SmallTest
- public void testComponentCallbacksForTargetContext() {
- Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
- Application targetApplication = (Application) targetContext.getApplicationContext();
- AdvancedMockContext context = new AdvancedMockContext(targetContext);
- Callback1 callback1 = new Callback1();
- Callback2 callback2 = new Callback2();
- context.registerComponentCallbacks(callback1);
- context.registerComponentCallbacks(callback2);
-
- targetApplication.onLowMemory();
- Assert.assertTrue("onLowMemory should have been called.", callback1.mOnLowMemoryCalled);
- Assert.assertTrue("onLowMemory should have been called.", callback2.mOnLowMemoryCalled);
-
- Configuration configuration = new Configuration();
- targetApplication.onConfigurationChanged(configuration);
- Assert.assertEquals("onConfigurationChanged should have been called.", configuration,
- callback1.mConfiguration);
- Assert.assertEquals("onConfigurationChanged should have been called.", configuration,
- callback2.mConfiguration);
-
- targetApplication.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE);
- Assert.assertEquals("onTrimMemory should have been called.",
- ComponentCallbacks2.TRIM_MEMORY_MODERATE, callback2.mLevel);
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java b/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java
deleted file mode 100644
index de0858a58a..0000000000
--- a/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2017 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;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.os.Build;
-import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-
-/**
- * Test of ApiCompatibilityUtils
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class ApiCompatibilityUtilsTest {
- private static final long WAIT_TIMEOUT_IN_MS = 5000;
- private static final long SLEEP_INTERVAL_IN_MS = 50;
-
- static class MockActivity extends Activity {
- int mFinishAndRemoveTaskCallbackCount;
- int mFinishCallbackCount;
- boolean mIsFinishing;
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Override
- public void finishAndRemoveTask() {
- mFinishAndRemoveTaskCallbackCount++;
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) mIsFinishing = true;
- }
-
- @Override
- public void finish() {
- mFinishCallbackCount++;
- mIsFinishing = true;
- }
-
- @Override
- public boolean isFinishing() {
- return mIsFinishing;
- }
- }
-
- @Test
- @SmallTest
- public void testFinishAndRemoveTask() {
- InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
- @Override
- public void run() {
- MockActivity activity = new MockActivity();
- ApiCompatibilityUtils.finishAndRemoveTask(activity);
-
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
- Assert.assertEquals(1, activity.mFinishAndRemoveTaskCallbackCount);
- Assert.assertEquals(0, activity.mFinishCallbackCount);
- } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
- long startTime = SystemClock.uptimeMillis();
- while (activity.mFinishCallbackCount == 0
- && SystemClock.uptimeMillis() - startTime < WAIT_TIMEOUT_IN_MS) {
- try {
- Thread.sleep(SLEEP_INTERVAL_IN_MS);
- } catch (InterruptedException e) {
- throw new RuntimeException("Interrupted thread sleep", e);
- }
- }
-
- // MockActivity#finishAndRemoveTask() never sets isFinishing() to true for
- // LOLLIPOP to simulate an exceptional case. In that case, MockActivity#finish()
- // should be called after 3 tries.
- Assert.assertEquals(3, activity.mFinishAndRemoveTaskCallbackCount);
- Assert.assertEquals(1, activity.mFinishCallbackCount);
- } else {
- Assert.assertEquals(0, activity.mFinishAndRemoveTaskCallbackCount);
- Assert.assertEquals(1, activity.mFinishCallbackCount);
- }
- Assert.assertTrue(activity.mIsFinishing);
- }
- });
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java b/base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java
deleted file mode 100644
index a3be5dd155..0000000000
--- a/base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 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;
-
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Feature;
-
-/**
- * Test class for {@link CommandLineInitUtil}.
- */
-@RunWith(AndroidJUnit4.class)
-public class CommandLineInitUtilTest {
- /**
- * Verifies that the default command line flags get set for Chrome Public tests.
- */
- @Test
- @SmallTest
- @Feature({"CommandLine"})
- public void testDefaultCommandLineFlagsSet() {
- CommandLineInitUtil.initCommandLine(CommandLineFlags.getTestCmdLineFile());
- Assert.assertTrue("CommandLine not initialized.", CommandLine.isInitialized());
-
- final CommandLine commandLine = CommandLine.getInstance();
- Assert.assertTrue(commandLine.hasSwitch("enable-test-intents"));
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/CommandLineTest.java b/base/android/javatests/src/org/chromium/base/CommandLineTest.java
deleted file mode 100644
index 787f85d999..0000000000
--- a/base/android/javatests/src/org/chromium/base/CommandLineTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2017 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;
-
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.Feature;
-
-/**
- * Tests for {@link CommandLine}.
- * TODO(bauerb): Convert to local JUnit test
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class CommandLineTest {
- // A reference command line. Note that switch2 is [brea\d], switch3 is [and "butter"],
- // and switch4 is [a "quoted" 'food'!]
- static final String INIT_SWITCHES[] = { "init_command", "--SWITCH", "Arg",
- "--switch2=brea\\d", "--switch3=and \"butter\"",
- "--switch4=a \"quoted\" 'food'!",
- "--", "--actually_an_arg" };
-
- // The same command line, but in quoted string format.
- static final char INIT_SWITCHES_BUFFER[] =
- ("init_command --SWITCH Arg --switch2=brea\\d --switch3=\"and \\\"butt\"er\\\" "
- + "--switch4='a \"quoted\" \\'food\\'!' "
- + "-- --actually_an_arg").toCharArray();
-
- static final String CL_ADDED_SWITCH = "zappo-dappo-doggy-trainer";
- static final String CL_ADDED_SWITCH_2 = "username";
- static final String CL_ADDED_VALUE_2 = "bozo";
-
- @Before
- public void setUp() throws Exception {
- CommandLine.reset();
- }
-
- void checkInitSwitches() {
- CommandLine cl = CommandLine.getInstance();
- Assert.assertFalse(cl.hasSwitch("init_command"));
- Assert.assertFalse(cl.hasSwitch("switch"));
- Assert.assertTrue(cl.hasSwitch("SWITCH"));
- Assert.assertFalse(cl.hasSwitch("--SWITCH"));
- Assert.assertFalse(cl.hasSwitch("Arg"));
- Assert.assertFalse(cl.hasSwitch("actually_an_arg"));
- Assert.assertEquals("brea\\d", cl.getSwitchValue("switch2"));
- Assert.assertEquals("and \"butter\"", cl.getSwitchValue("switch3"));
- Assert.assertEquals("a \"quoted\" 'food'!", cl.getSwitchValue("switch4"));
- Assert.assertNull(cl.getSwitchValue("SWITCH"));
- Assert.assertNull(cl.getSwitchValue("non-existant"));
- }
-
- void checkSettingThenGetting() {
- CommandLine cl = CommandLine.getInstance();
-
- // Add a plain switch.
- Assert.assertFalse(cl.hasSwitch(CL_ADDED_SWITCH));
- cl.appendSwitch(CL_ADDED_SWITCH);
- Assert.assertTrue(cl.hasSwitch(CL_ADDED_SWITCH));
-
- // Add a switch paired with a value.
- Assert.assertFalse(cl.hasSwitch(CL_ADDED_SWITCH_2));
- Assert.assertNull(cl.getSwitchValue(CL_ADDED_SWITCH_2));
- cl.appendSwitchWithValue(CL_ADDED_SWITCH_2, CL_ADDED_VALUE_2);
- Assert.assertTrue(CL_ADDED_VALUE_2.equals(cl.getSwitchValue(CL_ADDED_SWITCH_2)));
-
- // Append a few new things.
- final String switchesAndArgs[] = { "dummy", "--superfast", "--speed=turbo" };
- Assert.assertFalse(cl.hasSwitch("dummy"));
- Assert.assertFalse(cl.hasSwitch("superfast"));
- Assert.assertNull(cl.getSwitchValue("speed"));
- cl.appendSwitchesAndArguments(switchesAndArgs);
- Assert.assertFalse(cl.hasSwitch("dummy"));
- Assert.assertFalse(cl.hasSwitch("command"));
- Assert.assertTrue(cl.hasSwitch("superfast"));
- Assert.assertTrue("turbo".equals(cl.getSwitchValue("speed")));
- }
-
- void checkTokenizer(String[] expected, String toParse) {
- String[] actual = CommandLine.tokenizeQuotedArguments(toParse.toCharArray());
- Assert.assertEquals(expected.length, actual.length);
- for (int i = 0; i < expected.length; ++i) {
- Assert.assertEquals("comparing element " + i, expected[i], actual[i]);
- }
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testJavaInitialization() {
- CommandLine.init(INIT_SWITCHES);
- checkInitSwitches();
- checkSettingThenGetting();
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testBufferInitialization() {
- CommandLine.init(CommandLine.tokenizeQuotedArguments(INIT_SWITCHES_BUFFER));
- checkInitSwitches();
- checkSettingThenGetting();
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testArgumentTokenizer() {
- String toParse = " a\"\\bc de\\\"f g\"\\h ij k\" \"lm";
- String[] expected = { "a\\bc de\"f g\\h",
- "ij",
- "k lm" };
- checkTokenizer(expected, toParse);
-
- toParse = "";
- expected = new String[0];
- checkTokenizer(expected, toParse);
-
- toParse = " \t\n";
- checkTokenizer(expected, toParse);
-
- toParse = " \"a'b\" 'c\"d' \"e\\\"f\" 'g\\'h' \"i\\'j\" 'k\\\"l'"
- + " m\"n\\'o\"p q'r\\\"s't";
- expected = new String[] { "a'b",
- "c\"d",
- "e\"f",
- "g'h",
- "i\\'j",
- "k\\\"l",
- "mn\\'op",
- "qr\\\"st"};
- checkTokenizer(expected, toParse);
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/EarlyTraceEventTest.java b/base/android/javatests/src/org/chromium/base/EarlyTraceEventTest.java
deleted file mode 100644
index 59a478ac36..0000000000
--- a/base/android/javatests/src/org/chromium/base/EarlyTraceEventTest.java
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2017 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;
-
-import static org.chromium.base.EarlyTraceEvent.AsyncEvent;
-import static org.chromium.base.EarlyTraceEvent.Event;
-
-import android.os.Process;
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.base.library_loader.LibraryProcessType;
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.Feature;
-
-/**
- * Tests for {@link EarlyTraceEvent}.
- *
- * TODO(lizeb): Move to roboelectric tests.
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class EarlyTraceEventTest {
- private static final String EVENT_NAME = "MyEvent";
- private static final String EVENT_NAME2 = "MyOtherEvent";
- private static final long EVENT_ID = 1;
- private static final long EVENT_ID2 = 2;
-
- @Before
- public void setUp() throws Exception {
- LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
- EarlyTraceEvent.resetForTesting();
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testCanRecordEvent() {
- EarlyTraceEvent.enable();
- long myThreadId = Process.myTid();
- long beforeNanos = Event.elapsedRealtimeNanos();
- EarlyTraceEvent.begin(EVENT_NAME);
- EarlyTraceEvent.end(EVENT_NAME);
- long afterNanos = Event.elapsedRealtimeNanos();
-
- Assert.assertEquals(1, EarlyTraceEvent.sCompletedEvents.size());
- Assert.assertTrue(EarlyTraceEvent.sPendingEventByKey.isEmpty());
- Event event = EarlyTraceEvent.sCompletedEvents.get(0);
- Assert.assertEquals(EVENT_NAME, event.mName);
- Assert.assertEquals(myThreadId, event.mThreadId);
- Assert.assertTrue(
- beforeNanos <= event.mBeginTimeNanos && event.mBeginTimeNanos <= afterNanos);
- Assert.assertTrue(event.mBeginTimeNanos <= event.mEndTimeNanos);
- Assert.assertTrue(beforeNanos <= event.mEndTimeNanos && event.mEndTimeNanos <= afterNanos);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testCanRecordAsyncEvent() {
- EarlyTraceEvent.enable();
- long beforeNanos = Event.elapsedRealtimeNanos();
- EarlyTraceEvent.startAsync(EVENT_NAME, EVENT_ID);
- EarlyTraceEvent.finishAsync(EVENT_NAME, EVENT_ID);
- long afterNanos = Event.elapsedRealtimeNanos();
-
- Assert.assertEquals(2, EarlyTraceEvent.sAsyncEvents.size());
- Assert.assertTrue(EarlyTraceEvent.sPendingEventByKey.isEmpty());
- AsyncEvent eventStart = EarlyTraceEvent.sAsyncEvents.get(0);
- AsyncEvent eventEnd = EarlyTraceEvent.sAsyncEvents.get(1);
- Assert.assertEquals(EVENT_NAME, eventStart.mName);
- Assert.assertEquals(EVENT_ID, eventStart.mId);
- Assert.assertEquals(EVENT_NAME, eventEnd.mName);
- Assert.assertEquals(EVENT_ID, eventEnd.mId);
- Assert.assertTrue(beforeNanos <= eventStart.mTimestampNanos
- && eventEnd.mTimestampNanos <= afterNanos);
- Assert.assertTrue(eventStart.mTimestampNanos <= eventEnd.mTimestampNanos);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testRecordAsyncFinishEventWhenFinishing() {
- EarlyTraceEvent.enable();
- EarlyTraceEvent.startAsync(EVENT_NAME, EVENT_ID);
- EarlyTraceEvent.disable();
-
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHING, EarlyTraceEvent.sState);
- Assert.assertTrue(EarlyTraceEvent.sAsyncEvents.isEmpty());
- Assert.assertEquals(1, EarlyTraceEvent.sPendingAsyncEvents.size());
- EarlyTraceEvent.finishAsync(EVENT_NAME, EVENT_ID);
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHED, EarlyTraceEvent.sState);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testCanRecordEventUsingTryWith() {
- EarlyTraceEvent.enable();
- long myThreadId = Process.myTid();
- long beforeNanos = Event.elapsedRealtimeNanos();
- try (TraceEvent e = TraceEvent.scoped(EVENT_NAME)) {
- // Required comment to pass presubmit checks.
- }
- long afterNanos = Event.elapsedRealtimeNanos();
-
- Assert.assertEquals(1, EarlyTraceEvent.sCompletedEvents.size());
- Assert.assertTrue(EarlyTraceEvent.sPendingEventByKey.isEmpty());
- Event event = EarlyTraceEvent.sCompletedEvents.get(0);
- Assert.assertEquals(EVENT_NAME, event.mName);
- Assert.assertEquals(myThreadId, event.mThreadId);
- Assert.assertTrue(
- beforeNanos <= event.mBeginTimeNanos && event.mBeginTimeNanos <= afterNanos);
- Assert.assertTrue(event.mBeginTimeNanos <= event.mEndTimeNanos);
- Assert.assertTrue(beforeNanos <= event.mEndTimeNanos && event.mEndTimeNanos <= afterNanos);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testIncompleteEvent() {
- EarlyTraceEvent.enable();
- EarlyTraceEvent.begin(EVENT_NAME);
-
- Assert.assertTrue(EarlyTraceEvent.sCompletedEvents.isEmpty());
- Assert.assertEquals(1, EarlyTraceEvent.sPendingEventByKey.size());
- EarlyTraceEvent.Event event = EarlyTraceEvent.sPendingEventByKey.get(
- EarlyTraceEvent.makeEventKeyForCurrentThread(EVENT_NAME));
- Assert.assertEquals(EVENT_NAME, event.mName);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testNoDuplicatePendingEventsFromSameThread() {
- EarlyTraceEvent.enable();
- EarlyTraceEvent.begin(EVENT_NAME);
- try {
- EarlyTraceEvent.begin(EVENT_NAME);
- } catch (IllegalArgumentException e) {
- // Expected.
- return;
- }
- Assert.fail();
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testDuplicatePendingEventsFromDifferentThreads() throws Exception {
- EarlyTraceEvent.enable();
-
- Thread otherThread = new Thread(() -> { EarlyTraceEvent.begin(EVENT_NAME); });
- otherThread.start();
- otherThread.join();
-
- // At this point we have a pending event with EVENT_NAME name. But events are per
- // thread, so we should be able to start EVENT_NAME event in a different thread.
- EarlyTraceEvent.begin(EVENT_NAME);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testIgnoreEventsWhenDisabled() {
- EarlyTraceEvent.begin(EVENT_NAME);
- EarlyTraceEvent.end(EVENT_NAME);
- try (TraceEvent e = TraceEvent.scoped(EVENT_NAME2)) {
- // Required comment to pass presubmit checks.
- }
- Assert.assertNull(EarlyTraceEvent.sCompletedEvents);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testIgnoreAsyncEventsWhenDisabled() {
- EarlyTraceEvent.startAsync(EVENT_NAME, EVENT_ID);
- EarlyTraceEvent.finishAsync(EVENT_NAME, EVENT_ID);
- Assert.assertNull(EarlyTraceEvent.sAsyncEvents);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testIgnoreNewEventsWhenFinishing() {
- EarlyTraceEvent.enable();
- EarlyTraceEvent.begin(EVENT_NAME);
- EarlyTraceEvent.disable();
-
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHING, EarlyTraceEvent.sState);
- EarlyTraceEvent.begin(EVENT_NAME2);
- EarlyTraceEvent.end(EVENT_NAME2);
-
- Assert.assertEquals(1, EarlyTraceEvent.sPendingEventByKey.size());
- Assert.assertTrue(EarlyTraceEvent.sCompletedEvents.isEmpty());
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testIgnoreNewAsyncEventsWhenFinishing() {
- EarlyTraceEvent.enable();
- EarlyTraceEvent.startAsync(EVENT_NAME, EVENT_ID);
- EarlyTraceEvent.disable();
-
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHING, EarlyTraceEvent.sState);
- EarlyTraceEvent.startAsync(EVENT_NAME2, EVENT_ID2);
-
- Assert.assertEquals(1, EarlyTraceEvent.sPendingAsyncEvents.size());
- Assert.assertTrue(EarlyTraceEvent.sAsyncEvents.isEmpty());
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testFinishingToFinished() {
- EarlyTraceEvent.enable();
- EarlyTraceEvent.begin(EVENT_NAME);
- EarlyTraceEvent.disable();
-
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHING, EarlyTraceEvent.sState);
- EarlyTraceEvent.begin(EVENT_NAME2);
- EarlyTraceEvent.end(EVENT_NAME2);
- EarlyTraceEvent.end(EVENT_NAME);
-
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHED, EarlyTraceEvent.sState);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testCannotBeReenabledOnceFinished() {
- EarlyTraceEvent.enable();
- EarlyTraceEvent.begin(EVENT_NAME);
- EarlyTraceEvent.end(EVENT_NAME);
- EarlyTraceEvent.disable();
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHED, EarlyTraceEvent.sState);
-
- EarlyTraceEvent.enable();
- Assert.assertEquals(EarlyTraceEvent.STATE_FINISHED, EarlyTraceEvent.sState);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testThreadIdIsRecorded() throws Exception {
- EarlyTraceEvent.enable();
- final long[] threadId = {0};
-
- Thread thread = new Thread() {
- @Override
- public void run() {
- TraceEvent.begin(EVENT_NAME);
- threadId[0] = Process.myTid();
- TraceEvent.end(EVENT_NAME);
- }
- };
- thread.start();
- thread.join();
-
- Assert.assertEquals(1, EarlyTraceEvent.sCompletedEvents.size());
- EarlyTraceEvent.Event event = EarlyTraceEvent.sCompletedEvents.get(0);
- Assert.assertEquals(threadId[0], event.mThreadId);
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java b/base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java
deleted file mode 100644
index fc37a1f565..0000000000
--- a/base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2017 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;
-
-import android.annotation.SuppressLint;
-import android.os.Build;
-import android.os.LocaleList;
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.MinAndroidSdkLevel;
-
-import java.util.Locale;
-
-/**
- * Tests for the LocaleUtils class.
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class LocaleUtilsTest {
- // This is also a part of test for toLanguageTag when API level is lower than 24
- @Test
- @SmallTest
- public void testGetUpdatedLanguageForChromium() {
- String language = "en";
- String updatedLanguage = LocaleUtils.getUpdatedLanguageForChromium(language);
- Assert.assertEquals(language, updatedLanguage);
-
- language = "iw";
- updatedLanguage = LocaleUtils.getUpdatedLanguageForChromium(language);
- Assert.assertEquals("he", updatedLanguage);
-
- language = "ji";
- updatedLanguage = LocaleUtils.getUpdatedLanguageForChromium(language);
- Assert.assertEquals("yi", updatedLanguage);
-
- language = "in";
- updatedLanguage = LocaleUtils.getUpdatedLanguageForChromium(language);
- Assert.assertEquals("id", updatedLanguage);
-
- language = "tl";
- updatedLanguage = LocaleUtils.getUpdatedLanguageForChromium(language);
- Assert.assertEquals("fil", updatedLanguage);
- }
-
- // This is also a part of test for toLanguageTags when API level is 24 or higher
- @Test
- @SmallTest
- @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
- public void testGetUpdatedLocaleForChromium() {
- Locale locale = new Locale("jp");
- Locale updatedLocale = LocaleUtils.getUpdatedLocaleForChromium(locale);
- Assert.assertEquals(locale, updatedLocale);
-
- locale = new Locale("iw");
- updatedLocale = LocaleUtils.getUpdatedLocaleForChromium(locale);
- Assert.assertEquals(new Locale("he"), updatedLocale);
-
- locale = new Locale("ji");
- updatedLocale = LocaleUtils.getUpdatedLocaleForChromium(locale);
- Assert.assertEquals(new Locale("yi"), updatedLocale);
-
- locale = new Locale("in");
- updatedLocale = LocaleUtils.getUpdatedLocaleForChromium(locale);
- Assert.assertEquals(new Locale("id"), updatedLocale);
-
- locale = new Locale("tl");
- updatedLocale = LocaleUtils.getUpdatedLocaleForChromium(locale);
- Assert.assertEquals(new Locale("fil"), updatedLocale);
- }
-
- // This is also a part of test for forLanguageTag when API level is lower than 21
- @Test
- @SmallTest
- public void testGetUpdatedLanguageForAndroid() {
- String language = "en";
- String updatedLanguage = LocaleUtils.getUpdatedLanguageForAndroid(language);
- Assert.assertEquals(language, updatedLanguage);
-
- language = "und";
- updatedLanguage = LocaleUtils.getUpdatedLanguageForAndroid(language);
- Assert.assertEquals("", updatedLanguage);
-
- language = "fil";
- updatedLanguage = LocaleUtils.getUpdatedLanguageForAndroid(language);
- Assert.assertEquals("tl", updatedLanguage);
- }
-
- // This is also a part of test for forLanguageTag when API level is 21 or higher
- @Test
- @SmallTest
- @MinAndroidSdkLevel(Build.VERSION_CODES.LOLLIPOP)
- public void testGetUpdatedLocaleForAndroid() {
- Locale locale = new Locale("jp");
- Locale updatedLocale = LocaleUtils.getUpdatedLocaleForAndroid(locale);
- Assert.assertEquals(locale, updatedLocale);
-
- locale = new Locale("und");
- updatedLocale = LocaleUtils.getUpdatedLocaleForAndroid(locale);
- Assert.assertEquals(new Locale(""), updatedLocale);
-
- locale = new Locale("fil");
- updatedLocale = LocaleUtils.getUpdatedLocaleForAndroid(locale);
- Assert.assertEquals(new Locale("tl"), updatedLocale);
- }
-
- // Test for toLanguageTag when API level is lower than 24
- @Test
- @SmallTest
- public void testToLanguageTag() {
- Locale locale = new Locale("en", "US");
- String localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("en-US", localeString);
-
- locale = new Locale("jp");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("jp", localeString);
-
- locale = new Locale("mas");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("mas", localeString);
-
- locale = new Locale("es", "005");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("es-005", localeString);
-
- locale = new Locale("iw");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("he", localeString);
-
- locale = new Locale("ji");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("yi", localeString);
-
- locale = new Locale("in", "ID");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("id-ID", localeString);
-
- locale = new Locale("tl", "PH");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("fil-PH", localeString);
-
- locale = new Locale("no", "NO", "NY");
- localeString = LocaleUtils.toLanguageTag(locale);
- Assert.assertEquals("nn-NO", localeString);
- }
-
- // Test for toLanguageTags when API level is 24 or higher
- @Test
- @SmallTest
- @MinAndroidSdkLevel(Build.VERSION_CODES.N)
- @SuppressLint("NewApi")
- public void testToLanguageTags() {
- Locale locale1 = new Locale("en", "US");
- Locale locale2 = new Locale("es", "005");
- LocaleList localeList = new LocaleList(locale1, locale2);
- String localeString = LocaleUtils.toLanguageTags(localeList);
- Assert.assertEquals("en-US,es-005", localeString);
-
- locale1 = new Locale("jp");
- locale2 = new Locale("mas");
- localeList = new LocaleList(locale1, locale2);
- localeString = LocaleUtils.toLanguageTags(localeList);
- Assert.assertEquals("jp,mas", localeString);
-
- locale1 = new Locale("iw");
- locale2 = new Locale("ji");
- localeList = new LocaleList(locale1, locale2);
- localeString = LocaleUtils.toLanguageTags(localeList);
- Assert.assertEquals("he,yi", localeString);
-
- locale1 = new Locale("in", "ID");
- locale2 = new Locale("tl", "PH");
- localeList = new LocaleList(locale1, locale2);
- localeString = LocaleUtils.toLanguageTags(localeList);
- Assert.assertEquals("id-ID,fil-PH", localeString);
-
- locale1 = new Locale("no", "NO", "NY");
- localeList = new LocaleList(locale1);
- localeString = LocaleUtils.toLanguageTags(localeList);
- Assert.assertEquals("nn-NO", localeString);
- }
-
- // Test for forLanguageTag when API level is lower than 21
- @Test
- @SmallTest
- public void testForLanguageTagCompat() {
- String languageTag = "";
- Locale locale = new Locale("");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "und";
- locale = new Locale("");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "en";
- locale = new Locale("en");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "mas";
- locale = new Locale("mas");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "en-GB";
- locale = new Locale("en", "GB");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "es-419";
- locale = new Locale("es", "419");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- // Tests if updated Chromium language code and deprecated language code
- // are pointing to the same Locale Object.
- languageTag = "he";
- locale = new Locale("iw");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "iw";
- locale = new Locale("he");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "ji";
- locale = new Locale("yi");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "yi";
- locale = new Locale("ji");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "in";
- locale = new Locale("id");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "id";
- locale = new Locale("in");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- // Tests for Tagalog/Filipino if updated Chromium language code and
- // language code are pointing to the same Locale Object.
- languageTag = "tl";
- locale = new Locale("tl");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "fil";
- locale = new Locale("tl");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- // Test with invalid inputs.
- languageTag = "notValidLanguage";
- locale = new Locale("");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
-
- languageTag = "en-notValidCountry";
- locale = new Locale("en");
- Assert.assertEquals(locale, LocaleUtils.forLanguageTagCompat(languageTag));
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/ObserverListTest.java b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
deleted file mode 100644
index f3b3e939bc..0000000000
--- a/base/android/javatests/src/org/chromium/base/ObserverListTest.java
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright 2017 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;
-
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.Feature;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Tests for (@link ObserverList}.
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class ObserverListTest {
- interface Observer {
- void observe(int x);
- }
-
- private static class Foo implements Observer {
- private final int mScalar;
- private int mTotal = 0;
-
- Foo(int scalar) {
- mScalar = scalar;
- }
-
- @Override
- public void observe(int x) {
- mTotal += x * mScalar;
- }
- }
-
- /**
- * An observer which add a given Observer object to the list when observe is called.
- */
- private static class FooAdder implements Observer {
- private final ObserverList<Observer> mList;
- private final Observer mLucky;
-
- FooAdder(ObserverList<Observer> list, Observer oblivious) {
- mList = list;
- mLucky = oblivious;
- }
-
- @Override
- public void observe(int x) {
- mList.addObserver(mLucky);
- }
- }
-
- /**
- * An observer which removes a given Observer object from the list when observe is called.
- */
- private static class FooRemover implements Observer {
- private final ObserverList<Observer> mList;
- private final Observer mDoomed;
-
- FooRemover(ObserverList<Observer> list, Observer innocent) {
- mList = list;
- mDoomed = innocent;
- }
-
- @Override
- public void observe(int x) {
- mList.removeObserver(mDoomed);
- }
- }
-
- private static <T> int getSizeOfIterable(Iterable<T> iterable) {
- if (iterable instanceof Collection<?>) return ((Collection<?>) iterable).size();
- int num = 0;
- for (T el : iterable) num++;
- return num;
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testRemoveWhileIteration() {
- ObserverList<Observer> observerList = new ObserverList<Observer>();
- Foo a = new Foo(1);
- Foo b = new Foo(-1);
- Foo c = new Foo(1);
- Foo d = new Foo(-1);
- Foo e = new Foo(-1);
- FooRemover evil = new FooRemover(observerList, c);
-
- observerList.addObserver(a);
- observerList.addObserver(b);
-
- for (Observer obs : observerList) obs.observe(10);
-
- // Removing an observer not in the list should do nothing.
- observerList.removeObserver(e);
-
- observerList.addObserver(evil);
- observerList.addObserver(c);
- observerList.addObserver(d);
-
- for (Observer obs : observerList) obs.observe(10);
-
- // observe should be called twice on a.
- Assert.assertEquals(20, a.mTotal);
- // observe should be called twice on b.
- Assert.assertEquals(-20, b.mTotal);
- // evil removed c from the observerList before it got any callbacks.
- Assert.assertEquals(0, c.mTotal);
- // observe should be called once on d.
- Assert.assertEquals(-10, d.mTotal);
- // e was never added to the list, observe should not be called.
- Assert.assertEquals(0, e.mTotal);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testAddWhileIteration() {
- ObserverList<Observer> observerList = new ObserverList<Observer>();
- Foo a = new Foo(1);
- Foo b = new Foo(-1);
- Foo c = new Foo(1);
- FooAdder evil = new FooAdder(observerList, c);
-
- observerList.addObserver(evil);
- observerList.addObserver(a);
- observerList.addObserver(b);
-
- for (Observer obs : observerList) obs.observe(10);
-
- Assert.assertTrue(observerList.hasObserver(c));
- Assert.assertEquals(10, a.mTotal);
- Assert.assertEquals(-10, b.mTotal);
- Assert.assertEquals(0, c.mTotal);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testIterator() {
- ObserverList<Integer> observerList = new ObserverList<Integer>();
- observerList.addObserver(5);
- observerList.addObserver(10);
- observerList.addObserver(15);
- Assert.assertEquals(3, getSizeOfIterable(observerList));
-
- observerList.removeObserver(10);
- Assert.assertEquals(2, getSizeOfIterable(observerList));
-
- Iterator<Integer> it = observerList.iterator();
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(5 == it.next());
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(15 == it.next());
- Assert.assertFalse(it.hasNext());
-
- boolean removeExceptionThrown = false;
- try {
- it.remove();
- Assert.fail("Expecting UnsupportedOperationException to be thrown here.");
- } catch (UnsupportedOperationException e) {
- removeExceptionThrown = true;
- }
- Assert.assertTrue(removeExceptionThrown);
- Assert.assertEquals(2, getSizeOfIterable(observerList));
-
- boolean noElementExceptionThrown = false;
- try {
- it.next();
- Assert.fail("Expecting NoSuchElementException to be thrown here.");
- } catch (NoSuchElementException e) {
- noElementExceptionThrown = true;
- }
- Assert.assertTrue(noElementExceptionThrown);
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testRewindableIterator() {
- ObserverList<Integer> observerList = new ObserverList<Integer>();
- observerList.addObserver(5);
- observerList.addObserver(10);
- observerList.addObserver(15);
- Assert.assertEquals(3, getSizeOfIterable(observerList));
-
- ObserverList.RewindableIterator<Integer> it = observerList.rewindableIterator();
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(5 == it.next());
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(10 == it.next());
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(15 == it.next());
- Assert.assertFalse(it.hasNext());
-
- it.rewind();
-
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(5 == it.next());
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(10 == it.next());
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(15 == it.next());
- Assert.assertEquals(5, (int) observerList.mObservers.get(0));
- observerList.removeObserver(5);
- Assert.assertEquals(null, observerList.mObservers.get(0));
-
- it.rewind();
-
- Assert.assertEquals(10, (int) observerList.mObservers.get(0));
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(10 == it.next());
- Assert.assertTrue(it.hasNext());
- Assert.assertTrue(15 == it.next());
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testAddObserverReturnValue() {
- ObserverList<Object> observerList = new ObserverList<Object>();
-
- Object a = new Object();
- Assert.assertTrue(observerList.addObserver(a));
- Assert.assertFalse(observerList.addObserver(a));
-
- Object b = new Object();
- Assert.assertTrue(observerList.addObserver(b));
- Assert.assertFalse(observerList.addObserver(null));
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testRemoveObserverReturnValue() {
- ObserverList<Object> observerList = new ObserverList<Object>();
-
- Object a = new Object();
- Object b = new Object();
- observerList.addObserver(a);
- observerList.addObserver(b);
-
- Assert.assertTrue(observerList.removeObserver(a));
- Assert.assertFalse(observerList.removeObserver(a));
- Assert.assertFalse(observerList.removeObserver(new Object()));
- Assert.assertTrue(observerList.removeObserver(b));
- Assert.assertFalse(observerList.removeObserver(null));
-
- // If we remove an object while iterating, it will be replaced by 'null'.
- observerList.addObserver(a);
- Assert.assertTrue(observerList.removeObserver(a));
- Assert.assertFalse(observerList.removeObserver(null));
- }
-
- @Test
- @SmallTest
- @Feature({"Android-AppBase"})
- public void testSize() {
- ObserverList<Object> observerList = new ObserverList<Object>();
-
- Assert.assertEquals(0, observerList.size());
- Assert.assertTrue(observerList.isEmpty());
-
- observerList.addObserver(null);
- Assert.assertEquals(0, observerList.size());
- Assert.assertTrue(observerList.isEmpty());
-
- Object a = new Object();
- observerList.addObserver(a);
- Assert.assertEquals(1, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.addObserver(a);
- Assert.assertEquals(1, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.addObserver(null);
- Assert.assertEquals(1, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- Object b = new Object();
- observerList.addObserver(b);
- Assert.assertEquals(2, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.removeObserver(null);
- Assert.assertEquals(2, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.removeObserver(new Object());
- Assert.assertEquals(2, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.removeObserver(b);
- Assert.assertEquals(1, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.removeObserver(b);
- Assert.assertEquals(1, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.removeObserver(a);
- Assert.assertEquals(0, observerList.size());
- Assert.assertTrue(observerList.isEmpty());
-
- observerList.removeObserver(a);
- observerList.removeObserver(b);
- observerList.removeObserver(null);
- observerList.removeObserver(new Object());
- Assert.assertEquals(0, observerList.size());
- Assert.assertTrue(observerList.isEmpty());
-
- observerList.addObserver(new Object());
- observerList.addObserver(new Object());
- observerList.addObserver(new Object());
- observerList.addObserver(a);
- Assert.assertEquals(4, observerList.size());
- Assert.assertFalse(observerList.isEmpty());
-
- observerList.clear();
- Assert.assertEquals(0, observerList.size());
- Assert.assertTrue(observerList.isEmpty());
-
- observerList.removeObserver(a);
- observerList.removeObserver(b);
- observerList.removeObserver(null);
- observerList.removeObserver(new Object());
- Assert.assertEquals(0, observerList.size());
- Assert.assertTrue(observerList.isEmpty());
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/StrictModeContextTest.java b/base/android/javatests/src/org/chromium/base/StrictModeContextTest.java
deleted file mode 100644
index 59f38edbf8..0000000000
--- a/base/android/javatests/src/org/chromium/base/StrictModeContextTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2017 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;
-
-import android.os.StrictMode;
-import android.support.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Tests for the StrictModeContext class.
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class StrictModeContextTest {
- private StrictMode.ThreadPolicy mOldThreadPolicy;
- private StrictMode.VmPolicy mOldVmPolicy;
- private FileOutputStream mFosForWriting;
- private FileInputStream mFisForReading;
-
- @Before
- public void setUp() throws Exception {
- mFosForWriting = new FileOutputStream(File.createTempFile("foo", "bar"));
- mFisForReading = new FileInputStream(File.createTempFile("foo", "baz"));
- enableStrictMode();
- }
-
- @After
- public void tearDown() throws Exception {
- disableStrictMode();
- mFosForWriting.close();
- mFisForReading.close();
- }
-
- private void enableStrictMode() {
- mOldThreadPolicy = StrictMode.getThreadPolicy();
- mOldVmPolicy = StrictMode.getVmPolicy();
- StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
- .detectAll()
- .penaltyLog()
- .penaltyDeath()
- .build());
- StrictMode.setVmPolicy(
- new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().penaltyDeath().build());
- }
-
- private void disableStrictMode() {
- StrictMode.setThreadPolicy(mOldThreadPolicy);
- StrictMode.setVmPolicy(mOldVmPolicy);
- }
-
- private void writeToDisk() {
- try {
- mFosForWriting.write(ApiCompatibilityUtils.getBytesUtf8("Foo"));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void assertWriteToDiskThrows() {
- boolean didThrow = false;
- try {
- writeToDisk();
- } catch (Exception e) {
- didThrow = true;
- }
- Assert.assertTrue("Expected disk write to throw.", didThrow);
- }
-
- private void readFromDisk() {
- try {
- mFisForReading.read();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void assertReadFromDiskThrows() {
- boolean didThrow = false;
- try {
- readFromDisk();
- } catch (Exception e) {
- didThrow = true;
- }
- Assert.assertTrue("Expected disk read to throw.", didThrow);
- }
-
- @Test
- @SmallTest
- public void testAllowDiskWrites() {
- try (StrictModeContext unused = StrictModeContext.allowDiskWrites()) {
- writeToDisk();
- }
- assertWriteToDiskThrows();
- }
-
- @Test
- @SmallTest
- public void testAllowDiskReads() {
- try (StrictModeContext unused = StrictModeContext.allowDiskReads()) {
- readFromDisk();
- assertWriteToDiskThrows();
- }
- assertReadFromDiskThrows();
- }
-}
diff --git a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java b/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
deleted file mode 100644
index 3ecfb3a561..0000000000
--- a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2017 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.metrics;
-
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.base.library_loader.LibraryProcessType;
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Tests for the Java API for recording UMA histograms.
- */
-@RunWith(BaseJUnit4ClassRunner.class)
-public class RecordHistogramTest {
- @Before
- public void setUp() throws Exception {
- LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
- }
-
- /**
- * Tests recording of boolean histograms.
- */
- @Test
- @SmallTest
- public void testRecordBooleanHistogram() {
- String histogram = "HelloWorld.BooleanMetric";
- HistogramDelta falseCount = new HistogramDelta(histogram, 0);
- HistogramDelta trueCount = new HistogramDelta(histogram, 1);
- Assert.assertEquals(0, trueCount.getDelta());
- Assert.assertEquals(0, falseCount.getDelta());
-
- RecordHistogram.recordBooleanHistogram(histogram, true);
- Assert.assertEquals(1, trueCount.getDelta());
- Assert.assertEquals(0, falseCount.getDelta());
-
- RecordHistogram.recordBooleanHistogram(histogram, true);
- Assert.assertEquals(2, trueCount.getDelta());
- Assert.assertEquals(0, falseCount.getDelta());
-
- RecordHistogram.recordBooleanHistogram(histogram, false);
- Assert.assertEquals(2, trueCount.getDelta());
- Assert.assertEquals(1, falseCount.getDelta());
- }
-
- /**
- * Tests recording of enumerated histograms.
- */
- @Test
- @SmallTest
- public void testRecordEnumeratedHistogram() {
- String histogram = "HelloWorld.EnumeratedMetric";
- HistogramDelta zeroCount = new HistogramDelta(histogram, 0);
- HistogramDelta oneCount = new HistogramDelta(histogram, 1);
- HistogramDelta twoCount = new HistogramDelta(histogram, 2);
- final int boundary = 3;
-
- Assert.assertEquals(0, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordEnumeratedHistogram(histogram, 0, boundary);
- Assert.assertEquals(1, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordEnumeratedHistogram(histogram, 0, boundary);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordEnumeratedHistogram(histogram, 2, boundary);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(1, twoCount.getDelta());
- }
-
- /**
- * Tests recording of count histograms.
- */
- @Test
- @SmallTest
- public void testRecordCountHistogram() {
- String histogram = "HelloWorld.CountMetric";
- HistogramDelta zeroCount = new HistogramDelta(histogram, 0);
- HistogramDelta oneCount = new HistogramDelta(histogram, 1);
- HistogramDelta twoCount = new HistogramDelta(histogram, 2);
- HistogramDelta eightThousandCount = new HistogramDelta(histogram, 8000);
-
- Assert.assertEquals(0, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
- Assert.assertEquals(0, eightThousandCount.getDelta());
-
- RecordHistogram.recordCountHistogram(histogram, 0);
- Assert.assertEquals(1, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
- Assert.assertEquals(0, eightThousandCount.getDelta());
-
- RecordHistogram.recordCountHistogram(histogram, 0);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
- Assert.assertEquals(0, eightThousandCount.getDelta());
-
- RecordHistogram.recordCountHistogram(histogram, 2);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(1, twoCount.getDelta());
- Assert.assertEquals(0, eightThousandCount.getDelta());
-
- RecordHistogram.recordCountHistogram(histogram, 8000);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(1, twoCount.getDelta());
- Assert.assertEquals(1, eightThousandCount.getDelta());
- }
-
- /**
- * Tests recording of custom times histograms.
- */
- @Test
- @SmallTest
- public void testRecordCustomTimesHistogram() {
- String histogram = "HelloWorld.CustomTimesMetric";
- HistogramDelta zeroCount = new HistogramDelta(histogram, 0);
- HistogramDelta oneCount = new HistogramDelta(histogram, 1);
- HistogramDelta twoCount = new HistogramDelta(histogram, 100);
-
- Assert.assertEquals(0, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- TimeUnit milli = TimeUnit.MILLISECONDS;
-
- RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
- Assert.assertEquals(1, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordCustomTimesHistogram(histogram, 0, 1, 100, milli, 3);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordCustomTimesHistogram(histogram, 95, 1, 100, milli, 3);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(1, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordCustomTimesHistogram(histogram, 200, 1, 100, milli, 3);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(1, oneCount.getDelta());
- Assert.assertEquals(1, twoCount.getDelta());
- }
-
- /**
- * Tests recording of linear count histograms.
- */
- @Test
- @SmallTest
- public void testRecordLinearCountHistogram() {
- String histogram = "HelloWorld.LinearCountMetric";
- HistogramDelta zeroCount = new HistogramDelta(histogram, 0);
- HistogramDelta oneCount = new HistogramDelta(histogram, 1);
- HistogramDelta twoCount = new HistogramDelta(histogram, 2);
- final int min = 1;
- final int max = 3;
- final int numBuckets = 4;
-
- Assert.assertEquals(0, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordLinearCountHistogram(histogram, 0, min, max, numBuckets);
- Assert.assertEquals(1, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordLinearCountHistogram(histogram, 0, min, max, numBuckets);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(0, twoCount.getDelta());
-
- RecordHistogram.recordLinearCountHistogram(histogram, 2, min, max, numBuckets);
- Assert.assertEquals(2, zeroCount.getDelta());
- Assert.assertEquals(0, oneCount.getDelta());
- Assert.assertEquals(1, twoCount.getDelta());
- }
-}
diff --git a/base/android/jni_array_unittest.cc b/base/android/jni_array_unittest.cc
deleted file mode 100644
index 245cd5082a..0000000000
--- a/base/android/jni_array_unittest.cc
+++ /dev/null
@@ -1,389 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/android/jni_array.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/android/jni_android.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace android {
-
-TEST(JniArray, BasicConversions) {
- const uint8_t kBytes[] = {0, 1, 2, 3};
- const size_t kLen = arraysize(kBytes);
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jbyteArray> bytes = ToJavaByteArray(env, kBytes, kLen);
- ASSERT_TRUE(bytes.obj());
-
- std::vector<uint8_t> inputVector(kBytes, kBytes + kLen);
- ScopedJavaLocalRef<jbyteArray> bytesFromVector =
- ToJavaByteArray(env, inputVector);
- ASSERT_TRUE(bytesFromVector.obj());
-
- std::vector<uint8_t> vectorFromBytes(5);
- std::vector<uint8_t> vectorFromVector(5);
- JavaByteArrayToByteVector(env, bytes.obj(), &vectorFromBytes);
- JavaByteArrayToByteVector(env, bytesFromVector.obj(), &vectorFromVector);
- EXPECT_EQ(4U, vectorFromBytes.size());
- EXPECT_EQ(4U, vectorFromVector.size());
- std::vector<uint8_t> expected_vec(kBytes, kBytes + kLen);
- EXPECT_EQ(expected_vec, vectorFromBytes);
- EXPECT_EQ(expected_vec, vectorFromVector);
-
- AppendJavaByteArrayToByteVector(env, bytes.obj(), &vectorFromBytes);
- EXPECT_EQ(8U, vectorFromBytes.size());
- expected_vec.insert(expected_vec.end(), kBytes, kBytes + kLen);
- EXPECT_EQ(expected_vec, vectorFromBytes);
-}
-
-void CheckBoolConversion(JNIEnv* env,
- const bool* bool_array,
- const size_t len,
- const ScopedJavaLocalRef<jbooleanArray>& booleans) {
- ASSERT_TRUE(booleans.obj());
-
- jsize java_array_len = env->GetArrayLength(booleans.obj());
- ASSERT_EQ(static_cast<jsize>(len), java_array_len);
-
- jboolean value;
- for (size_t i = 0; i < len; ++i) {
- env->GetBooleanArrayRegion(booleans.obj(), i, 1, &value);
- ASSERT_EQ(bool_array[i], value);
- }
-}
-
-TEST(JniArray, BoolConversions) {
- const bool kBools[] = {false, true, false};
- const size_t kLen = arraysize(kBools);
-
- JNIEnv* env = AttachCurrentThread();
- CheckBoolConversion(env, kBools, kLen, ToJavaBooleanArray(env, kBools, kLen));
-}
-
-void CheckIntConversion(
- JNIEnv* env,
- const int* int_array,
- const size_t len,
- const ScopedJavaLocalRef<jintArray>& ints) {
- ASSERT_TRUE(ints.obj());
-
- jsize java_array_len = env->GetArrayLength(ints.obj());
- ASSERT_EQ(static_cast<jsize>(len), java_array_len);
-
- jint value;
- for (size_t i = 0; i < len; ++i) {
- env->GetIntArrayRegion(ints.obj(), i, 1, &value);
- ASSERT_EQ(int_array[i], value);
- }
-}
-
-TEST(JniArray, IntConversions) {
- const int kInts[] = {0, 1, -1, std::numeric_limits<int32_t>::min(),
- std::numeric_limits<int32_t>::max()};
- const size_t kLen = arraysize(kInts);
-
- JNIEnv* env = AttachCurrentThread();
- CheckIntConversion(env, kInts, kLen, ToJavaIntArray(env, kInts, kLen));
-
- const std::vector<int> vec(kInts, kInts + kLen);
- CheckIntConversion(env, kInts, kLen, ToJavaIntArray(env, vec));
-}
-
-void CheckLongConversion(JNIEnv* env,
- const int64_t* long_array,
- const size_t len,
- const ScopedJavaLocalRef<jlongArray>& longs) {
- ASSERT_TRUE(longs.obj());
-
- jsize java_array_len = env->GetArrayLength(longs.obj());
- ASSERT_EQ(static_cast<jsize>(len), java_array_len);
-
- jlong value;
- for (size_t i = 0; i < len; ++i) {
- env->GetLongArrayRegion(longs.obj(), i, 1, &value);
- ASSERT_EQ(long_array[i], value);
- }
-}
-
-TEST(JniArray, LongConversions) {
- const int64_t kLongs[] = {0, 1, -1, std::numeric_limits<int64_t>::min(),
- std::numeric_limits<int64_t>::max()};
- const size_t kLen = arraysize(kLongs);
-
- JNIEnv* env = AttachCurrentThread();
- CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, kLongs, kLen));
-
- const std::vector<int64_t> vec(kLongs, kLongs + kLen);
- CheckLongConversion(env, kLongs, kLen, ToJavaLongArray(env, vec));
-}
-
-void CheckIntArrayConversion(JNIEnv* env,
- ScopedJavaLocalRef<jintArray> jints,
- std::vector<int> int_vector,
- const size_t len) {
- jint value;
- for (size_t i = 0; i < len; ++i) {
- env->GetIntArrayRegion(jints.obj(), i, 1, &value);
- ASSERT_EQ(int_vector[i], value);
- }
-}
-
-void CheckBoolArrayConversion(JNIEnv* env,
- ScopedJavaLocalRef<jbooleanArray> jbooleans,
- std::vector<bool> bool_vector,
- const size_t len) {
- jboolean value;
- for (size_t i = 0; i < len; ++i) {
- env->GetBooleanArrayRegion(jbooleans.obj(), i, 1, &value);
- ASSERT_EQ(bool_vector[i], value);
- }
-}
-
-void CheckFloatConversion(
- JNIEnv* env,
- const float* float_array,
- const size_t len,
- const ScopedJavaLocalRef<jfloatArray>& floats) {
- ASSERT_TRUE(floats.obj());
-
- jsize java_array_len = env->GetArrayLength(floats.obj());
- ASSERT_EQ(static_cast<jsize>(len), java_array_len);
-
- jfloat value;
- for (size_t i = 0; i < len; ++i) {
- env->GetFloatArrayRegion(floats.obj(), i, 1, &value);
- ASSERT_EQ(float_array[i], value);
- }
-}
-
-TEST(JniArray, FloatConversions) {
- const float kFloats[] = { 0.0f, 1.0f, -10.0f};
- const size_t kLen = arraysize(kFloats);
-
- JNIEnv* env = AttachCurrentThread();
- CheckFloatConversion(env, kFloats, kLen,
- ToJavaFloatArray(env, kFloats, kLen));
-
- const std::vector<float> vec(kFloats, kFloats + kLen);
- CheckFloatConversion(env, kFloats, kLen, ToJavaFloatArray(env, vec));
-}
-
-TEST(JniArray, JavaBooleanArrayToBoolVector) {
- const bool kBools[] = {false, true, false};
- const size_t kLen = arraysize(kBools);
-
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jbooleanArray> jbooleans(env, env->NewBooleanArray(kLen));
- ASSERT_TRUE(jbooleans.obj());
-
- for (size_t i = 0; i < kLen; ++i) {
- jboolean j = static_cast<jboolean>(kBools[i]);
- env->SetBooleanArrayRegion(jbooleans.obj(), i, 1, &j);
- ASSERT_FALSE(HasException(env));
- }
-
- std::vector<bool> bools;
- JavaBooleanArrayToBoolVector(env, jbooleans.obj(), &bools);
-
- ASSERT_EQ(static_cast<jsize>(bools.size()),
- env->GetArrayLength(jbooleans.obj()));
-
- CheckBoolArrayConversion(env, jbooleans, bools, kLen);
-}
-
-TEST(JniArray, JavaIntArrayToIntVector) {
- const int kInts[] = {0, 1, -1};
- const size_t kLen = arraysize(kInts);
-
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jintArray> jints(env, env->NewIntArray(kLen));
- ASSERT_TRUE(jints.obj());
-
- for (size_t i = 0; i < kLen; ++i) {
- jint j = static_cast<jint>(kInts[i]);
- env->SetIntArrayRegion(jints.obj(), i, 1, &j);
- ASSERT_FALSE(HasException(env));
- }
-
- std::vector<int> ints;
- JavaIntArrayToIntVector(env, jints.obj(), &ints);
-
- ASSERT_EQ(static_cast<jsize>(ints.size()), env->GetArrayLength(jints.obj()));
-
- CheckIntArrayConversion(env, jints, ints, kLen);
-}
-
-TEST(JniArray, JavaLongArrayToInt64Vector) {
- const int64_t kInt64s[] = {0LL, 1LL, -1LL};
- const size_t kLen = arraysize(kInt64s);
-
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jlongArray> jlongs(env, env->NewLongArray(kLen));
- ASSERT_TRUE(jlongs.obj());
-
- for (size_t i = 0; i < kLen; ++i) {
- jlong j = static_cast<jlong>(kInt64s[i]);
- env->SetLongArrayRegion(jlongs.obj(), i, 1, &j);
- ASSERT_FALSE(HasException(env));
- }
-
- std::vector<int64_t> int64s;
- JavaLongArrayToInt64Vector(env, jlongs.obj(), &int64s);
-
- ASSERT_EQ(static_cast<jsize>(int64s.size()),
- env->GetArrayLength(jlongs.obj()));
-
- jlong value;
- for (size_t i = 0; i < kLen; ++i) {
- env->GetLongArrayRegion(jlongs.obj(), i, 1, &value);
- ASSERT_EQ(int64s[i], value);
- ASSERT_EQ(kInt64s[i], int64s[i]);
- }
-}
-
-TEST(JniArray, JavaLongArrayToLongVector) {
- const int64_t kInt64s[] = {0LL, 1LL, -1LL};
- const size_t kLen = arraysize(kInt64s);
-
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jlongArray> jlongs(env, env->NewLongArray(kLen));
- ASSERT_TRUE(jlongs.obj());
-
- for (size_t i = 0; i < kLen; ++i) {
- jlong j = static_cast<jlong>(kInt64s[i]);
- env->SetLongArrayRegion(jlongs.obj(), i, 1, &j);
- ASSERT_FALSE(HasException(env));
- }
-
- std::vector<jlong> jlongs_vector;
- JavaLongArrayToLongVector(env, jlongs.obj(), &jlongs_vector);
-
- ASSERT_EQ(static_cast<jsize>(jlongs_vector.size()),
- env->GetArrayLength(jlongs.obj()));
-
- jlong value;
- for (size_t i = 0; i < kLen; ++i) {
- env->GetLongArrayRegion(jlongs.obj(), i, 1, &value);
- ASSERT_EQ(jlongs_vector[i], value);
- }
-}
-
-TEST(JniArray, JavaFloatArrayToFloatVector) {
- const float kFloats[] = {0.0, 0.5, -0.5};
- const size_t kLen = arraysize(kFloats);
-
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jfloatArray> jfloats(env, env->NewFloatArray(kLen));
- ASSERT_TRUE(jfloats.obj());
-
- for (size_t i = 0; i < kLen; ++i) {
- jfloat j = static_cast<jfloat>(kFloats[i]);
- env->SetFloatArrayRegion(jfloats.obj(), i, 1, &j);
- ASSERT_FALSE(HasException(env));
- }
-
- std::vector<float> floats;
- JavaFloatArrayToFloatVector(env, jfloats.obj(), &floats);
-
- ASSERT_EQ(static_cast<jsize>(floats.size()),
- env->GetArrayLength(jfloats.obj()));
-
- jfloat value;
- for (size_t i = 0; i < kLen; ++i) {
- env->GetFloatArrayRegion(jfloats.obj(), i, 1, &value);
- ASSERT_EQ(floats[i], value);
- }
-}
-
-TEST(JniArray, JavaArrayOfByteArrayToStringVector) {
- const int kMaxItems = 50;
- JNIEnv* env = AttachCurrentThread();
-
- // Create a byte[][] object.
- ScopedJavaLocalRef<jclass> byte_array_clazz(env, env->FindClass("[B"));
- ASSERT_TRUE(byte_array_clazz.obj());
-
- ScopedJavaLocalRef<jobjectArray> array(
- env, env->NewObjectArray(kMaxItems, byte_array_clazz.obj(), NULL));
- ASSERT_TRUE(array.obj());
-
- // Create kMaxItems byte buffers.
- char text[16];
- for (int i = 0; i < kMaxItems; ++i) {
- snprintf(text, sizeof text, "%d", i);
- ScopedJavaLocalRef<jbyteArray> byte_array =
- ToJavaByteArray(env, reinterpret_cast<uint8_t*>(text),
- static_cast<size_t>(strlen(text)));
- ASSERT_TRUE(byte_array.obj());
-
- env->SetObjectArrayElement(array.obj(), i, byte_array.obj());
- ASSERT_FALSE(HasException(env));
- }
-
- // Convert to std::vector<std::string>, check the content.
- std::vector<std::string> vec;
- JavaArrayOfByteArrayToStringVector(env, array.obj(), &vec);
-
- EXPECT_EQ(static_cast<size_t>(kMaxItems), vec.size());
- for (int i = 0; i < kMaxItems; ++i) {
- snprintf(text, sizeof text, "%d", i);
- EXPECT_STREQ(text, vec[i].c_str());
- }
-}
-
-TEST(JniArray, JavaArrayOfIntArrayToIntVector) {
- const size_t kNumItems = 4;
- JNIEnv* env = AttachCurrentThread();
-
- // Create an int[][] object.
- ScopedJavaLocalRef<jclass> int_array_clazz(env, env->FindClass("[I"));
- ASSERT_TRUE(int_array_clazz.obj());
-
- ScopedJavaLocalRef<jobjectArray> array(
- env, env->NewObjectArray(kNumItems, int_array_clazz.obj(), nullptr));
- ASSERT_TRUE(array.obj());
-
- // Populate int[][] object.
- const int kInts0[] = {0, 1, -1, std::numeric_limits<int32_t>::min(),
- std::numeric_limits<int32_t>::max()};
- const size_t kLen0 = arraysize(kInts0);
- ScopedJavaLocalRef<jintArray> int_array0 = ToJavaIntArray(env, kInts0, kLen0);
- env->SetObjectArrayElement(array.obj(), 0, int_array0.obj());
-
- const int kInts1[] = {3, 4, 5};
- const size_t kLen1 = arraysize(kInts1);
- ScopedJavaLocalRef<jintArray> int_array1 = ToJavaIntArray(env, kInts1, kLen1);
- env->SetObjectArrayElement(array.obj(), 1, int_array1.obj());
-
- const int kInts2[] = {};
- const size_t kLen2 = 0;
- ScopedJavaLocalRef<jintArray> int_array2 = ToJavaIntArray(env, kInts2, kLen2);
- env->SetObjectArrayElement(array.obj(), 2, int_array2.obj());
-
- const int kInts3[] = {16};
- const size_t kLen3 = arraysize(kInts3);
- ScopedJavaLocalRef<jintArray> int_array3 = ToJavaIntArray(env, kInts3, kLen3);
- env->SetObjectArrayElement(array.obj(), 3, int_array3.obj());
-
- // Convert to std::vector<std::vector<int>>, check the content.
- std::vector<std::vector<int>> out;
- JavaArrayOfIntArrayToIntVector(env, array.obj(), &out);
-
- EXPECT_EQ(kNumItems, out.size());
- CheckIntArrayConversion(env, int_array0, out[0], kLen0);
- CheckIntArrayConversion(env, int_array1, out[1], kLen1);
- CheckIntArrayConversion(env, int_array2, out[2], kLen2);
- CheckIntArrayConversion(env, int_array3, out[3], kLen3);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/jni_generator/PRESUBMIT.py b/base/android/jni_generator/PRESUBMIT.py
new file mode 100644
index 0000000000..bc76d5bb97
--- /dev/null
+++ b/base/android/jni_generator/PRESUBMIT.py
@@ -0,0 +1,37 @@
+# Copyright 2018 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.
+
+"""Presubmit script for android buildbot.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
+details on the presubmit API built into depot_tools.
+"""
+
+
+def CommonChecks(input_api, output_api):
+ base_android_jni_generator_dir = input_api.PresubmitLocalPath()
+
+ env = dict(input_api.environ)
+ env.update({
+ 'PYTHONPATH': base_android_jni_generator_dir,
+ 'PYTHONDONTWRITEBYTECODE': '1',
+ })
+
+ return input_api.canned_checks.RunUnitTests(
+ input_api,
+ output_api,
+ unit_tests=[
+ input_api.os_path.join(
+ base_android_jni_generator_dir, 'jni_generator_tests.py')
+ ],
+ env=env,
+ )
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return CommonChecks(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return CommonChecks(input_api, output_api)
diff --git a/base/android/jni_generator/README.md b/base/android/jni_generator/README.md
deleted file mode 100644
index 17ad150c32..0000000000
--- a/base/android/jni_generator/README.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# Overview
-JNI (Java Native Interface) is the mechanism that enables Java code to call
-native functions, and native code to call Java functions.
-
- * Native code calls into Java using apis from `<jni.h>`, which basically mirror
- Java's reflection APIs.
- * Java code calls native functions by declaring body-less functions with the
- `native` keyword, and then calling them as normal Java functions.
-
-`jni_generator` generates boiler-plate code with the goal of making our code:
- 1. easier to write, and
- 2. typesafe.
-
-`jni_generator` uses regular expressions to parse .Java files, so don't do
-anything too fancy. E.g.:
- * Classes must be either explicitly imported, or are assumed to be in
-the same package. To use `java.lang` classes, add an explicit import.
- * Inner classes need to be referenced through the outer class. E.g.:
- `void call(Outer.Inner inner)`
-
-The presense of any JNI within a class will result in ProGuard obfuscation for
-the class to be disabled.
-
-### Exposing Native Methods
-
-**Without Crazy Linker:**
- * Java->Native calls are exported from the shared library and lazily resolved
- by the runtime (via `dlsym()`).
-
-**With Crazy Linker:**
- * Java->Native calls are explicitly registered with JNI on the native side.
- Explicit registration is necessary because crazy linker provides its own
- `dlsym()`, but JNI is hardcoded to use the system's `dlsym()`.
- * The logic to explicitly register stubs is generated by
- `jni_registration_generator.py`.
- * This script finds all native methods by scanning all source `.java` files
- of an APK. Inefficient, but very convenient.
- * Since `dlsym()` is not used in this case, we use a linker script to avoid
- the cost of exporting symbols from the shared library (refer to
- `//build/config/android:hide_all_but_jni_onload`).
- * `jni_registration_generator.py` exposes two registrations methods:
- * `RegisterNonMainDexNatives` - Registers native functions needed by multiple
- process types (e.g. Rendereres, GPU process).
- * `RegisterMainDexNatives` - Registers native functions needed only by the
- browser process.
-
-### Exposing Java Methods
-
-Java methods just need to be annotated with `@CalledByNative`. The generated
-functions can be put into a namespace using `@JNINamespace("your_namespace")`.
-
-## Usage
-
-Because the generator does not generate any source files, generated headers must
-not be `#included` by multiple sources. If there are Java functions that need to
-be called by multiple sources, one source should be chosen to expose the
-functions to the others via additional wrapper functions.
-
-### Calling Java -> Native
-
- * Methods marked as `native` will have stubs generated for them that forward
- calls to C++ function (that you must write).
- * If the first parameter is a C++ object (e.g. `long mNativePointer`), then the
- bindings will automatically generate the appropriate cast and call into C++
- code (JNI itself is only C).
-
-### Calling Native -> Java
-
- * Methods annotated with `@CalledByNative` will have stubs generated for them.
- * Just call the generated stubs defined in generated `.h` files.
-
-### Java Objects and Garbage Collection
-
-All pointers to Java objects must be registered with JNI in order to prevent
-garbage collection from invalidating them.
-
-For Strings & Arrays - it's common practice to use the `//base/android/jni_*`
-helpers to convert them to `std::vectors` and `std::strings` as soon as
-possible.
-
-For other objects - use smart pointers to store them:
- * `ScopedJavaLocalRef<>` - When lifetime is the current function's scope.
- * `ScopedJavaGlobalRef<>` - When lifetime is longer than the current function's
- scope.
- * `JavaObjectWeakGlobalRef<>` - Weak reference (do not prevent garbage
- collection).
- * `JavaParamRef<>` - Use to accept any of the above as a parameter to a
- function without creating a redundant registration.
-
-### Additional Guidelines / Advice
-
-Minimize the surface API between the two sides. Rather than calling multiple
-functions across boundaries, call only one (and then on the other side, call as
-many little functions as required).
-
-If a Java object "owns" a native one, store the pointer via
-`"long mNativeClassName"`. Ensure to eventually call a native method to delete
-the object. For example, have a `close()` that deletes the native object.
-
-The best way to pass "compound" types across in either direction is to
-create an inner class with PODs and a factory function. If possible, make mark
-all the fields as "final".
-
-## Build Rules
-
- * `generate_jni` - Generates a header file with stubs for given `.java` files
- * `generate_jar_jni` - Generates a header file with stubs for a given `.jar`
- file
- * `generate_jni_registration` - Generates a header file with functions to
- register native-side JNI methods (required only when using crazy linker).
-
-Refer to [//build/config/android/rules.gni](https://cs.chromium.org/chromium/src/build/config/android/rules.gni)
-for more about the GN templates.
-
-## Changing `jni_generator`
-
- * Python unit tests live in `jni_generator_tests.py`
- * A working demo app exists as `//base/android/jni_generator:sample_jni_apk`
diff --git a/base/android/jni_generator/SampleForTests_jni.golden b/base/android/jni_generator/SampleForTests_jni.golden
deleted file mode 100644
index c3fe96851d..0000000000
--- a/base/android/jni_generator/SampleForTests_jni.golden
+++ /dev/null
@@ -1,494 +0,0 @@
-// 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.
-
-
-// This file is autogenerated by
-// base/android/jni_generator/jni_generator.py
-// For
-// org/chromium/example/jni_generator/SampleForTests
-
-#ifndef org_chromium_example_jni_generator_SampleForTests_JNI
-#define org_chromium_example_jni_generator_SampleForTests_JNI
-
-#include <jni.h>
-
-#include "base/android/jni_generator/jni_generator_helper.h"
-
-
-// Step 1: Forward declarations.
-
-JNI_REGISTRATION_EXPORT extern const char
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA[];
-const char kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA[] =
- "org/chromium/example/jni_generator/SampleForTests$InnerStructA";
-
-JNI_REGISTRATION_EXPORT extern const char
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerClass[];
-const char kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerClass[] =
- "org/chromium/example/jni_generator/SampleForTests$InnerClass";
-
-JNI_REGISTRATION_EXPORT extern const char
- kClassPath_org_chromium_example_jni_1generator_SampleForTests[];
-const char kClassPath_org_chromium_example_jni_1generator_SampleForTests[] =
- "org/chromium/example/jni_generator/SampleForTests";
-
-JNI_REGISTRATION_EXPORT extern const char
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB[];
-const char kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB[] =
- "org/chromium/example/jni_generator/SampleForTests$InnerStructB";
-// Leaking this jclass as we cannot use LazyInstance from some threads.
-JNI_REGISTRATION_EXPORT base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz = 0;
-#ifndef org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz_defined
-#define org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz_defined
-inline jclass org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(JNIEnv*
- env) {
- return base::android::LazyGetClass(env,
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA,
- &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz);
-}
-#endif
-// Leaking this jclass as we cannot use LazyInstance from some threads.
-JNI_REGISTRATION_EXPORT base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024InnerClass_clazz = 0;
-#ifndef org_chromium_example_jni_1generator_SampleForTests_00024InnerClass_clazz_defined
-#define org_chromium_example_jni_1generator_SampleForTests_00024InnerClass_clazz_defined
-inline jclass org_chromium_example_jni_1generator_SampleForTests_00024InnerClass_clazz(JNIEnv* env)
- {
- return base::android::LazyGetClass(env,
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerClass,
- &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerClass_clazz);
-}
-#endif
-// Leaking this jclass as we cannot use LazyInstance from some threads.
-JNI_REGISTRATION_EXPORT base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_clazz = 0;
-#ifndef org_chromium_example_jni_1generator_SampleForTests_clazz_defined
-#define org_chromium_example_jni_1generator_SampleForTests_clazz_defined
-inline jclass org_chromium_example_jni_1generator_SampleForTests_clazz(JNIEnv* env) {
- return base::android::LazyGetClass(env,
- kClassPath_org_chromium_example_jni_1generator_SampleForTests,
- &g_org_chromium_example_jni_1generator_SampleForTests_clazz);
-}
-#endif
-// Leaking this jclass as we cannot use LazyInstance from some threads.
-JNI_REGISTRATION_EXPORT base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz = 0;
-#ifndef org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz_defined
-#define org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz_defined
-inline jclass org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(JNIEnv*
- env) {
- return base::android::LazyGetClass(env,
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB,
- &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz);
-}
-#endif
-
-
-// Step 2: Constants (optional).
-
-
-// Step 3: Method stubs.
-namespace base {
-namespace android {
-
-static jlong JNI_SampleForTests_Init(JNIEnv* env, const base::android::JavaParamRef<jobject>&
- jcaller,
- const base::android::JavaParamRef<jstring>& param);
-
-JNI_GENERATOR_EXPORT jlong Java_org_chromium_example_jni_1generator_SampleForTests_nativeInit(
- JNIEnv* env,
- jobject jcaller,
- jstring param) {
- return JNI_SampleForTests_Init(env, base::android::JavaParamRef<jobject>(env, jcaller),
- base::android::JavaParamRef<jstring>(env, param));
-}
-
-JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeDestroy(
- JNIEnv* env,
- jobject jcaller,
- jlong nativeCPPClass) {
- CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
- CHECK_NATIVE_PTR(env, jcaller, native, "Destroy");
- return native->Destroy(env, base::android::JavaParamRef<jobject>(env, jcaller));
-}
-
-static jdouble JNI_SampleForTests_GetDoubleFunction(JNIEnv* env, const
- base::android::JavaParamRef<jobject>& jcaller);
-
-JNI_GENERATOR_EXPORT jdouble
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetDoubleFunction(
- JNIEnv* env,
- jobject jcaller) {
- return JNI_SampleForTests_GetDoubleFunction(env, base::android::JavaParamRef<jobject>(env,
- jcaller));
-}
-
-static jfloat JNI_SampleForTests_GetFloatFunction(JNIEnv* env, const
- base::android::JavaParamRef<jclass>& jcaller);
-
-JNI_GENERATOR_EXPORT jfloat
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetFloatFunction(
- JNIEnv* env,
- jclass jcaller) {
- return JNI_SampleForTests_GetFloatFunction(env, base::android::JavaParamRef<jclass>(env,
- jcaller));
-}
-
-static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv* env, const
- base::android::JavaParamRef<jobject>& jcaller,
- const base::android::JavaParamRef<jobject>& rect);
-
-JNI_GENERATOR_EXPORT void
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeSetNonPODDatatype(
- JNIEnv* env,
- jobject jcaller,
- jobject rect) {
- return JNI_SampleForTests_SetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env,
- jcaller), base::android::JavaParamRef<jobject>(env, rect));
-}
-
-static base::android::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetNonPODDatatype(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jcaller);
-
-JNI_GENERATOR_EXPORT jobject
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetNonPODDatatype(
- JNIEnv* env,
- jobject jcaller) {
- return JNI_SampleForTests_GetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env,
- jcaller)).Release();
-}
-
-JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethod(
- JNIEnv* env,
- jobject jcaller,
- jlong nativeCPPClass) {
- CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
- CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0);
- return native->Method(env, base::android::JavaParamRef<jobject>(env, jcaller));
-}
-
-JNI_GENERATOR_EXPORT jdouble
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethodOtherP0(
- JNIEnv* env,
- jobject jcaller,
- jlong nativePtr) {
- CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr);
- CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0);
- return native->MethodOtherP0(env, base::android::JavaParamRef<jobject>(env, jcaller));
-}
-
-JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeAddStructB(
- JNIEnv* env,
- jobject jcaller,
- jlong nativeCPPClass,
- jobject b) {
- CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
- CHECK_NATIVE_PTR(env, jcaller, native, "AddStructB");
- return native->AddStructB(env, base::android::JavaParamRef<jobject>(env, jcaller),
- base::android::JavaParamRef<jobject>(env, b));
-}
-
-JNI_GENERATOR_EXPORT void
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeIterateAndDoSomethingWithStructB(
- JNIEnv* env,
- jobject jcaller,
- jlong nativeCPPClass) {
- CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
- CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB");
- return native->IterateAndDoSomethingWithStructB(env, base::android::JavaParamRef<jobject>(env,
- jcaller));
-}
-
-JNI_GENERATOR_EXPORT jstring
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeReturnAString(
- JNIEnv* env,
- jobject jcaller,
- jlong nativeCPPClass) {
- CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass);
- CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", NULL);
- return native->ReturnAString(env, base::android::JavaParamRef<jobject>(env, jcaller)).Release();
-}
-
-static jint JNI_InnerClass_GetInnerIntFunction(JNIEnv* env, const
- base::android::JavaParamRef<jclass>& jcaller);
-
-JNI_GENERATOR_EXPORT jint
- Java_org_chromium_example_jni_1generator_SampleForTests_00024InnerClass_nativeGetInnerIntFunction(
- JNIEnv* env,
- jclass jcaller) {
- return JNI_InnerClass_GetInnerIntFunction(env, base::android::JavaParamRef<jclass>(env, jcaller));
-}
-
-
-static base::subtle::AtomicWord g_org_chromium_example_jni_1generator_SampleForTests_javaMethod = 0;
-static jint Java_SampleForTests_javaMethod(JNIEnv* env, const base::android::JavaRef<jobject>& obj,
- JniIntWrapper foo,
- JniIntWrapper bar) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), 0);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "javaMethod",
- "(II)I",
- &g_org_chromium_example_jni_1generator_SampleForTests_javaMethod);
-
- jint ret =
- env->CallIntMethod(obj.obj(),
- method_id, as_jint(foo), as_jint(bar));
- jni_generator::CheckException(env);
- return ret;
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_staticJavaMethod = 0;
-static jboolean Java_SampleForTests_staticJavaMethod(JNIEnv* env) {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), false);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_STATIC>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "staticJavaMethod",
- "()Z",
- &g_org_chromium_example_jni_1generator_SampleForTests_staticJavaMethod);
-
- jboolean ret =
- env->CallStaticBooleanMethod(org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- method_id);
- jni_generator::CheckException(env);
- return ret;
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_packagePrivateJavaMethod = 0;
-static void Java_SampleForTests_packagePrivateJavaMethod(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env));
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "packagePrivateJavaMethod",
- "()V",
- &g_org_chromium_example_jni_1generator_SampleForTests_packagePrivateJavaMethod);
-
- env->CallVoidMethod(obj.obj(),
- method_id);
- jni_generator::CheckException(env);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_methodWithGenericParams = 0;
-static void Java_SampleForTests_methodWithGenericParams(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj, const base::android::JavaRef<jobject>& foo,
- const base::android::JavaRef<jobject>& bar) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env));
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "methodWithGenericParams",
- "(Ljava/util/Map;Ljava/util/LinkedList;)V",
- &g_org_chromium_example_jni_1generator_SampleForTests_methodWithGenericParams);
-
- env->CallVoidMethod(obj.obj(),
- method_id, foo.obj(), bar.obj());
- jni_generator::CheckException(env);
-}
-
-static base::subtle::AtomicWord g_org_chromium_example_jni_1generator_SampleForTests_Constructor =
- 0;
-static base::android::ScopedJavaLocalRef<jobject> Java_SampleForTests_Constructor(JNIEnv* env,
- JniIntWrapper foo,
- JniIntWrapper bar) {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "<init>",
- "(II)V",
- &g_org_chromium_example_jni_1generator_SampleForTests_Constructor);
-
- jobject ret =
- env->NewObject(org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- method_id, as_jint(foo), as_jint(bar));
- jni_generator::CheckException(env);
- return base::android::ScopedJavaLocalRef<jobject>(env, ret);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_methodThatThrowsException = 0;
-static void Java_SampleForTests_methodThatThrowsException(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env));
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "methodThatThrowsException",
- "()V",
- &g_org_chromium_example_jni_1generator_SampleForTests_methodThatThrowsException);
-
- env->CallVoidMethod(obj.obj(),
- method_id);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_javaMethodWithAnnotatedParam = 0;
-static void Java_SampleForTests_javaMethodWithAnnotatedParam(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj, JniIntWrapper foo) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env));
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "javaMethodWithAnnotatedParam",
- "(I)V",
- &g_org_chromium_example_jni_1generator_SampleForTests_javaMethodWithAnnotatedParam);
-
- env->CallVoidMethod(obj.obj(),
- method_id, as_jint(foo));
- jni_generator::CheckException(env);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_create = 0;
-static base::android::ScopedJavaLocalRef<jobject> Java_InnerStructA_create(JNIEnv* env, jlong l,
- JniIntWrapper i,
- const base::android::JavaRef<jstring>& s) {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(env), NULL);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_STATIC>(
- env, org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(env),
- "create",
- "(JILjava/lang/String;)Lorg/chromium/example/jni_generator/SampleForTests$InnerStructA;",
- &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_create);
-
- jobject ret =
-env->CallStaticObjectMethod(org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(env),
- method_id, l, as_jint(i), s.obj());
- jni_generator::CheckException(env);
- return base::android::ScopedJavaLocalRef<jobject>(env, ret);
-}
-
-static base::subtle::AtomicWord g_org_chromium_example_jni_1generator_SampleForTests_addStructA = 0;
-static void Java_SampleForTests_addStructA(JNIEnv* env, const base::android::JavaRef<jobject>& obj,
- const base::android::JavaRef<jobject>& a) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env));
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "addStructA",
- "(Lorg/chromium/example/jni_generator/SampleForTests$InnerStructA;)V",
- &g_org_chromium_example_jni_1generator_SampleForTests_addStructA);
-
- env->CallVoidMethod(obj.obj(),
- method_id, a.obj());
- jni_generator::CheckException(env);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_iterateAndDoSomething = 0;
-static void Java_SampleForTests_iterateAndDoSomething(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env));
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "iterateAndDoSomething",
- "()V",
- &g_org_chromium_example_jni_1generator_SampleForTests_iterateAndDoSomething);
-
- env->CallVoidMethod(obj.obj(),
- method_id);
- jni_generator::CheckException(env);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getKey = 0;
-static jlong Java_InnerStructB_getKey(JNIEnv* env, const base::android::JavaRef<jobject>& obj) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env), 0);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env),
- "getKey",
- "()J",
- &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getKey);
-
- jlong ret =
- env->CallLongMethod(obj.obj(),
- method_id);
- jni_generator::CheckException(env);
- return ret;
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getValue = 0;
-static base::android::ScopedJavaLocalRef<jstring> Java_InnerStructB_getValue(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env), NULL);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env),
- "getValue",
- "()Ljava/lang/String;",
- &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getValue);
-
- jstring ret =
- static_cast<jstring>(env->CallObjectMethod(obj.obj(),
- method_id));
- jni_generator::CheckException(env);
- return base::android::ScopedJavaLocalRef<jstring>(env, ret);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_getInnerInterface = 0;
-static base::android::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerInterface(JNIEnv* env)
- {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_STATIC>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "getInnerInterface",
- "()Lorg/chromium/example/jni_generator/SampleForTests$InnerInterface;",
- &g_org_chromium_example_jni_1generator_SampleForTests_getInnerInterface);
-
- jobject ret =
- env->CallStaticObjectMethod(org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- method_id);
- jni_generator::CheckException(env);
- return base::android::ScopedJavaLocalRef<jobject>(env, ret);
-}
-
-static base::subtle::AtomicWord g_org_chromium_example_jni_1generator_SampleForTests_getInnerEnum =
- 0;
-static base::android::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum(JNIEnv* env) {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_STATIC>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "getInnerEnum",
- "()Lorg/chromium/example/jni_generator/SampleForTests$InnerEnum;",
- &g_org_chromium_example_jni_1generator_SampleForTests_getInnerEnum);
-
- jobject ret =
- env->CallStaticObjectMethod(org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- method_id);
- jni_generator::CheckException(env);
- return base::android::ScopedJavaLocalRef<jobject>(env, ret);
-}
-
-} // namespace android
-} // namespace base
-
-#endif // org_chromium_example_jni_generator_SampleForTests_JNI
diff --git a/base/android/jni_generator/testNativeExportsOnlyOption.golden b/base/android/jni_generator/testNativeExportsOnlyOption.golden
deleted file mode 100644
index bdc8d29e94..0000000000
--- a/base/android/jni_generator/testNativeExportsOnlyOption.golden
+++ /dev/null
@@ -1,214 +0,0 @@
-// 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.
-
-
-// This file is autogenerated by
-// base/android/jni_generator/jni_generator.py
-// For
-// org/chromium/example/jni_generator/SampleForTests
-
-#ifndef org_chromium_example_jni_generator_SampleForTests_JNI
-#define org_chromium_example_jni_generator_SampleForTests_JNI
-
-#include <jni.h>
-
-#include "base/android/jni_generator/jni_generator_helper.h"
-
-
-// Step 1: Forward declarations.
-
-JNI_REGISTRATION_EXPORT extern const char
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass[];
-const char kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass[] =
- "org/chromium/example/jni_generator/SampleForTests$MyOtherInnerClass";
-
-JNI_REGISTRATION_EXPORT extern const char
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass[];
-const char kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass[] =
- "org/chromium/example/jni_generator/SampleForTests$MyInnerClass";
-
-JNI_REGISTRATION_EXPORT extern const char
- kClassPath_org_chromium_example_jni_1generator_SampleForTests[];
-const char kClassPath_org_chromium_example_jni_1generator_SampleForTests[] =
- "org/chromium/example/jni_generator/SampleForTests";
-// Leaking this jclass as we cannot use LazyInstance from some threads.
-JNI_REGISTRATION_EXPORT base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass_clazz = 0;
-#ifndef org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass_clazz_defined
-#define org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass_clazz_defined
-inline jclass
- org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass_clazz(JNIEnv* env) {
- return base::android::LazyGetClass(env,
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass,
- &g_org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass_clazz);
-}
-#endif
-// Leaking this jclass as we cannot use LazyInstance from some threads.
-JNI_REGISTRATION_EXPORT base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass_clazz = 0;
-#ifndef org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass_clazz_defined
-#define org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass_clazz_defined
-inline jclass org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass_clazz(JNIEnv*
- env) {
- return base::android::LazyGetClass(env,
- kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass,
- &g_org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass_clazz);
-}
-#endif
-// Leaking this jclass as we cannot use LazyInstance from some threads.
-JNI_REGISTRATION_EXPORT base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_clazz = 0;
-#ifndef org_chromium_example_jni_1generator_SampleForTests_clazz_defined
-#define org_chromium_example_jni_1generator_SampleForTests_clazz_defined
-inline jclass org_chromium_example_jni_1generator_SampleForTests_clazz(JNIEnv* env) {
- return base::android::LazyGetClass(env,
- kClassPath_org_chromium_example_jni_1generator_SampleForTests,
- &g_org_chromium_example_jni_1generator_SampleForTests_clazz);
-}
-#endif
-
-
-// Step 2: Constants (optional).
-
-
-// Step 3: Method stubs.
-JNI_GENERATOR_EXPORT jint
- Java_org_chromium_example_jni_1generator_SampleForTests_nativeStaticMethod(
- JNIEnv* env,
- jobject jcaller,
- jlong nativeTest,
- jint arg1) {
- Test* native = reinterpret_cast<Test*>(nativeTest);
- CHECK_NATIVE_PTR(env, jcaller, native, "StaticMethod", 0);
- return native->StaticMethod(env, base::android::JavaParamRef<jobject>(env, jcaller), arg1);
-}
-
-JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethod(
- JNIEnv* env,
- jobject jcaller,
- jlong nativeTest,
- jint arg1) {
- Test* native = reinterpret_cast<Test*>(nativeTest);
- CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0);
- return native->Method(env, base::android::JavaParamRef<jobject>(env, jcaller), arg1);
-}
-
-static jint JNI_MyInnerClass_Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller);
-
-JNI_GENERATOR_EXPORT jint
- Java_org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass_nativeInit(
- JNIEnv* env,
- jobject jcaller) {
- return JNI_MyInnerClass_Init(env, base::android::JavaParamRef<jobject>(env, jcaller));
-}
-
-static jint JNI_MyOtherInnerClass_Init(JNIEnv* env, const base::android::JavaParamRef<jobject>&
- jcaller);
-
-JNI_GENERATOR_EXPORT jint
- Java_org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass_nativeInit(
- JNIEnv* env,
- jobject jcaller) {
- return JNI_MyOtherInnerClass_Init(env, base::android::JavaParamRef<jobject>(env, jcaller));
-}
-
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_testMethodWithParam = 0;
-static void Java_SampleForTests_testMethodWithParam(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj, JniIntWrapper iParam) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env));
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "testMethodWithParam",
- "(I)V",
- &g_org_chromium_example_jni_1generator_SampleForTests_testMethodWithParam);
-
- env->CallVoidMethod(obj.obj(),
- method_id, as_jint(iParam));
- jni_generator::CheckException(env);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_testMethodWithParamAndReturn = 0;
-static base::android::ScopedJavaLocalRef<jstring>
- Java_SampleForTests_testMethodWithParamAndReturn(JNIEnv* env, const
- base::android::JavaRef<jobject>& obj, JniIntWrapper iParam) {
- CHECK_CLAZZ(env, obj.obj(),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_INSTANCE>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "testMethodWithParamAndReturn",
- "(I)Ljava/lang/String;",
- &g_org_chromium_example_jni_1generator_SampleForTests_testMethodWithParamAndReturn);
-
- jstring ret =
- static_cast<jstring>(env->CallObjectMethod(obj.obj(),
- method_id, as_jint(iParam)));
- jni_generator::CheckException(env);
- return base::android::ScopedJavaLocalRef<jstring>(env, ret);
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_testStaticMethodWithParam = 0;
-static jint Java_SampleForTests_testStaticMethodWithParam(JNIEnv* env, JniIntWrapper iParam) {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), 0);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_STATIC>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "testStaticMethodWithParam",
- "(I)I",
- &g_org_chromium_example_jni_1generator_SampleForTests_testStaticMethodWithParam);
-
- jint ret =
- env->CallStaticIntMethod(org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- method_id, as_jint(iParam));
- jni_generator::CheckException(env);
- return ret;
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_testMethodWithNoParam = 0;
-static jdouble Java_SampleForTests_testMethodWithNoParam(JNIEnv* env) {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), 0);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_STATIC>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "testMethodWithNoParam",
- "()D",
- &g_org_chromium_example_jni_1generator_SampleForTests_testMethodWithNoParam);
-
- jdouble ret =
- env->CallStaticDoubleMethod(org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- method_id);
- jni_generator::CheckException(env);
- return ret;
-}
-
-static base::subtle::AtomicWord
- g_org_chromium_example_jni_1generator_SampleForTests_testStaticMethodWithNoParam = 0;
-static base::android::ScopedJavaLocalRef<jstring>
- Java_SampleForTests_testStaticMethodWithNoParam(JNIEnv* env) {
- CHECK_CLAZZ(env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL);
- jmethodID method_id = base::android::MethodID::LazyGet<
- base::android::MethodID::TYPE_STATIC>(
- env, org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- "testStaticMethodWithNoParam",
- "()Ljava/lang/String;",
- &g_org_chromium_example_jni_1generator_SampleForTests_testStaticMethodWithNoParam);
-
- jstring ret =
-static_cast<jstring>(env->CallStaticObjectMethod(org_chromium_example_jni_1generator_SampleForTests_clazz(env),
- method_id));
- jni_generator::CheckException(env);
- return base::android::ScopedJavaLocalRef<jstring>(env, ret);
-}
-
-#endif // org_chromium_example_jni_generator_SampleForTests_JNI
diff --git a/base/android/jni_registrar.cc b/base/android/jni_registrar.cc
deleted file mode 100644
index 8e13e60097..0000000000
--- a/base/android/jni_registrar.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/android/jni_registrar.h"
-
-#include "base/logging.h"
-#include "base/android/jni_android.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace android {
-
-bool RegisterNativeMethods(JNIEnv* env,
- const RegistrationMethod* method,
- size_t count) {
- TRACE_EVENT0("startup", "base_android::RegisterNativeMethods")
- const RegistrationMethod* end = method + count;
- while (method != end) {
- if (!method->func(env)) {
- DLOG(ERROR) << method->name << " failed registration!";
- return false;
- }
- method++;
- }
- return true;
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/jni_registrar.h b/base/android/jni_registrar.h
deleted file mode 100644
index 31a4750385..0000000000
--- a/base/android/jni_registrar.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_ANDROID_JNI_REGISTRAR_H_
-#define BASE_ANDROID_JNI_REGISTRAR_H_
-
-#include <jni.h>
-#include <stddef.h>
-
-#include "base/base_export.h"
-
-namespace base {
-namespace android {
-
-struct RegistrationMethod;
-
-// Registers the JNI bindings for the specified |method| definition containing
-// |count| elements. Returns whether the registration of the given methods
-// succeeded.
-BASE_EXPORT bool RegisterNativeMethods(JNIEnv* env,
- const RegistrationMethod* method,
- size_t count);
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_JNI_REGISTRAR_H_
diff --git a/base/android/jni_utils.cc b/base/android/jni_utils.cc
deleted file mode 100644
index c5e370c9f0..0000000000
--- a/base/android/jni_utils.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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/android/jni_utils.h"
-
-#include "base/android/scoped_java_ref.h"
-
-#include "jni/JNIUtils_jni.h"
-
-namespace base {
-namespace android {
-
-ScopedJavaLocalRef<jobject> GetClassLoader(JNIEnv* env) {
- return Java_JNIUtils_getClassLoader(env);
-}
-
-bool IsSelectiveJniRegistrationEnabled(JNIEnv* env) {
- return Java_JNIUtils_isSelectiveJniRegistrationEnabled(env);
-}
-
-} // namespace android
-} // namespace base
-
diff --git a/base/android/jni_utils.h b/base/android/jni_utils.h
deleted file mode 100644
index c626ba4602..0000000000
--- a/base/android/jni_utils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// 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.
-
-#ifndef BASE_ANDROID_JNI_UTILS_H_
-#define BASE_ANDROID_JNI_UTILS_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-
-namespace base {
-
-namespace android {
-
-// Gets a ClassLoader instance capable of loading Chromium java classes.
-// This should be called either from JNI_OnLoad or from within a method called
-// via JNI from Java.
-BASE_EXPORT ScopedJavaLocalRef<jobject> GetClassLoader(JNIEnv* env);
-
-// Returns true if the current process permits selective JNI registration.
-BASE_EXPORT bool IsSelectiveJniRegistrationEnabled(JNIEnv* env);
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_JNI_UTILS_H_
-
diff --git a/base/android/jni_weak_ref.cc b/base/android/jni_weak_ref.cc
deleted file mode 100644
index 88efa723e5..0000000000
--- a/base/android/jni_weak_ref.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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/android/jni_weak_ref.h"
-
-#include <utility>
-
-#include "base/android/jni_android.h"
-#include "base/logging.h"
-
-using base::android::AttachCurrentThread;
-
-JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef() : obj_(nullptr) {}
-
-JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef(
- const JavaObjectWeakGlobalRef& orig)
- : obj_(nullptr) {
- Assign(orig);
-}
-
-JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef(
- JavaObjectWeakGlobalRef&& orig) noexcept
- : obj_(orig.obj_) {
- orig.obj_ = nullptr;
-}
-
-JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef(JNIEnv* env, jobject obj)
- : obj_(env->NewWeakGlobalRef(obj)) {
-}
-
-JavaObjectWeakGlobalRef::JavaObjectWeakGlobalRef(
- JNIEnv* env,
- const base::android::JavaRef<jobject>& obj)
- : obj_(env->NewWeakGlobalRef(obj.obj())) {
-}
-
-JavaObjectWeakGlobalRef::~JavaObjectWeakGlobalRef() {
- reset();
-}
-
-void JavaObjectWeakGlobalRef::operator=(const JavaObjectWeakGlobalRef& rhs) {
- Assign(rhs);
-}
-
-void JavaObjectWeakGlobalRef::operator=(JavaObjectWeakGlobalRef&& rhs) {
- std::swap(obj_, rhs.obj_);
-}
-
-void JavaObjectWeakGlobalRef::reset() {
- if (obj_) {
- AttachCurrentThread()->DeleteWeakGlobalRef(obj_);
- obj_ = nullptr;
- }
-}
-
-base::android::ScopedJavaLocalRef<jobject>
- JavaObjectWeakGlobalRef::get(JNIEnv* env) const {
- return GetRealObject(env, obj_);
-}
-
-base::android::ScopedJavaLocalRef<jobject> GetRealObject(
- JNIEnv* env, jweak obj) {
- jobject real = nullptr;
- if (obj)
- real = env->NewLocalRef(obj);
- return base::android::ScopedJavaLocalRef<jobject>(env, real);
-}
-
-void JavaObjectWeakGlobalRef::Assign(const JavaObjectWeakGlobalRef& other) {
- if (&other == this)
- return;
-
- JNIEnv* env = AttachCurrentThread();
- if (obj_)
- env->DeleteWeakGlobalRef(obj_);
-
- obj_ = other.obj_ ? env->NewWeakGlobalRef(other.obj_) : nullptr;
-}
diff --git a/base/android/jni_weak_ref.h b/base/android/jni_weak_ref.h
deleted file mode 100644
index 43a26b5fe5..0000000000
--- a/base/android/jni_weak_ref.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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.
-
-#ifndef BASE_ANDROID_JNI_WEAK_REF_H_
-#define BASE_ANDROID_JNI_WEAK_REF_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/base_export.h"
-
-// Manages WeakGlobalRef lifecycle.
-// This class is not thread-safe w.r.t. get() and reset(). Multiple threads may
-// safely use get() concurrently, but if the user calls reset() (or of course,
-// calls the destructor) they'll need to provide their own synchronization.
-class BASE_EXPORT JavaObjectWeakGlobalRef {
- public:
- JavaObjectWeakGlobalRef();
- JavaObjectWeakGlobalRef(const JavaObjectWeakGlobalRef& orig);
- JavaObjectWeakGlobalRef(JavaObjectWeakGlobalRef&& orig) noexcept;
- JavaObjectWeakGlobalRef(JNIEnv* env, jobject obj);
- JavaObjectWeakGlobalRef(JNIEnv* env,
- const base::android::JavaRef<jobject>& obj);
- virtual ~JavaObjectWeakGlobalRef();
-
- void operator=(const JavaObjectWeakGlobalRef& rhs);
- void operator=(JavaObjectWeakGlobalRef&& rhs);
-
- base::android::ScopedJavaLocalRef<jobject> get(JNIEnv* env) const;
-
- // Returns true if the weak reference has not been initialized to point at
- // an object (or ḣas had reset() called).
- // Do not call this to test if the object referred to still exists! The weak
- // reference remains initialized even if the target object has been collected.
- bool is_uninitialized() const { return obj_ == nullptr; }
-
- void reset();
-
- private:
- void Assign(const JavaObjectWeakGlobalRef& rhs);
-
- jweak obj_;
-};
-
-// Get the real object stored in the weak reference returned as a
-// ScopedJavaLocalRef.
-BASE_EXPORT base::android::ScopedJavaLocalRef<jobject> GetRealObject(
- JNIEnv* env, jweak obj);
-
-#endif // BASE_ANDROID_JNI_WEAK_REF_H_
diff --git a/base/android/junit/src/org/chromium/base/ApplicationStatusTest.java b/base/android/junit/src/org/chromium/base/ApplicationStatusTest.java
deleted file mode 100644
index eb1829539d..0000000000
--- a/base/android/junit/src/org/chromium/base/ApplicationStatusTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2015 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;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.app.Activity;
-import android.view.KeyEvent;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.android.controller.ActivityController;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowActivity;
-import org.robolectric.shadows.multidex.ShadowMultiDex;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-/** Unit tests for {@link ApplicationStatus}. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE,
- shadows = {ApplicationStatusTest.TrackingShadowActivity.class, ShadowMultiDex.class})
-public class ApplicationStatusTest {
- /** Shadow that tracks calls to onWindowFocusChanged and dispatchKeyEvent. */
- @Implements(Activity.class)
- public static class TrackingShadowActivity extends ShadowActivity {
- private int mWindowFocusCalls;
- private int mDispatchKeyEventCalls;
- private boolean mReturnValueForKeyDispatch;
-
- @Implementation
- public void onWindowFocusChanged(@SuppressWarnings("unused") boolean hasFocus) {
- mWindowFocusCalls++;
- }
-
- @Implementation
- public boolean dispatchKeyEvent(@SuppressWarnings("unused") KeyEvent event) {
- mDispatchKeyEventCalls++;
- return mReturnValueForKeyDispatch;
- }
- }
-
- @Test
- public void testWindowsFocusChanged() throws Exception {
- ApplicationStatus.initialize(RuntimeEnvironment.application);
-
- ApplicationStatus.WindowFocusChangedListener mock =
- mock(ApplicationStatus.WindowFocusChangedListener.class);
- ApplicationStatus.registerWindowFocusChangedListener(mock);
-
- ActivityController<Activity> controller =
- Robolectric.buildActivity(Activity.class).create().start().visible();
- TrackingShadowActivity shadow = (TrackingShadowActivity) Shadows.shadowOf(controller.get());
-
- controller.get().getWindow().getCallback().onWindowFocusChanged(true);
- // Assert that listeners were notified.
- verify(mock).onWindowFocusChanged(controller.get(), true);
- // Also ensure that the original activity is forwarded the notification.
- Assert.assertEquals(1, shadow.mWindowFocusCalls);
- }
-}
diff --git a/base/android/junit/src/org/chromium/base/LogTest.java b/base/android/junit/src/org/chromium/base/LogTest.java
deleted file mode 100644
index a3832a0aad..0000000000
--- a/base/android/junit/src/org/chromium/base/LogTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2015 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLog;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-import java.util.List;
-
-/** Unit tests for {@link Log}. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class LogTest {
- /** Tests that the computed call origin is the correct one. */
- @Test
- public void callOriginTest() {
- Log.d("Foo", "Bar");
-
- List<ShadowLog.LogItem> logs = ShadowLog.getLogs();
- assertEquals("Only one log should be written", 1, logs.size());
-
- assertTrue("The origin of the log message (" + logs.get(0).msg + ") looks wrong.",
- logs.get(0).msg.matches("\\[LogTest.java:\\d+\\].*"));
- }
-
- @Test
- public void normalizeTagTest() {
- assertEquals("cr_foo", Log.normalizeTag("cr.foo"));
- assertEquals("cr_foo", Log.normalizeTag("cr_foo"));
- assertEquals("cr_foo", Log.normalizeTag("foo"));
- assertEquals("cr_ab_foo", Log.normalizeTag("ab_foo"));
- }
-
- /** Tests that exceptions provided to the log functions are properly recognized and printed. */
- @Test
- public void exceptionLoggingTest() {
- Throwable t = new Throwable() {
- @Override
- public String toString() {
- return "MyThrowable";
- }
- };
-
- Throwable t2 = new Throwable() {
- @Override
- public String toString() {
- return "MyOtherThrowable";
- }
- };
-
- List<ShadowLog.LogItem> logs;
-
- // The throwable gets printed out
- Log.i("Foo", "Bar", t);
- logs = ShadowLog.getLogs();
- assertEquals(t, logs.get(logs.size() - 1).throwable);
- assertEquals("Bar", logs.get(logs.size() - 1).msg);
-
- // The throwable can be both added to the message itself and printed out
- Log.i("Foo", "Bar %s", t);
- logs = ShadowLog.getLogs();
- assertEquals(t, logs.get(logs.size() - 1).throwable);
- assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg);
-
- // Non throwable are properly identified
- Log.i("Foo", "Bar %s", t, "Baz");
- logs = ShadowLog.getLogs();
- assertNull(logs.get(logs.size() - 1).throwable);
- assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg);
-
- // The last throwable is the one used that is going to be printed out
- Log.i("Foo", "Bar %s %s", t, t2);
- logs = ShadowLog.getLogs();
- assertEquals(t2, logs.get(logs.size() - 1).throwable);
- assertEquals("Bar MyThrowable MyOtherThrowable", logs.get(logs.size() - 1).msg);
- }
-}
diff --git a/base/android/junit/src/org/chromium/base/NonThreadSafeTest.java b/base/android/junit/src/org/chromium/base/NonThreadSafeTest.java
deleted file mode 100644
index 9c57199c9e..0000000000
--- a/base/android/junit/src/org/chromium/base/NonThreadSafeTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.BlockJUnit4ClassRunner;
-
-import org.chromium.base.test.util.Feature;
-
-/**
- * Tests for NonThreadSafe.
- */
-@RunWith(BlockJUnit4ClassRunner.class)
-public class NonThreadSafeTest {
- /**
- * Test for creating and using on the same thread
- */
- @Test
- @Feature({"Android-AppBase"})
- public void testCreateAndUseOnSameThread() {
- NonThreadSafe t = new NonThreadSafe();
- Assert.assertTrue(t.calledOnValidThread());
- }
-
- /**
- * Test if calledOnValidThread returns false if used on another thread.
- */
- @Test
- @Feature({"Android-AppBase"})
- public void testCreateAndUseOnDifferentThread() {
- final NonThreadSafe t = new NonThreadSafe();
-
- new Thread(new Runnable() {
- @Override
- public void run() {
- Assert.assertFalse(t.calledOnValidThread());
- }
- }).start();
- }
-
- /**
- * Test if detachFromThread reassigns the thread.
- */
- @Test
- @Feature({"Android-AppBase"})
- public void testDetachFromThread() {
- final NonThreadSafe t = new NonThreadSafe();
- Assert.assertTrue(t.calledOnValidThread());
- t.detachFromThread();
-
- new Thread(new Runnable() {
- @Override
- public void run() {
- Assert.assertTrue(t.calledOnValidThread());
- Assert.assertTrue(t.calledOnValidThread());
- }
- }).start();
- }
-}
diff --git a/base/android/junit/src/org/chromium/base/PromiseTest.java b/base/android/junit/src/org/chromium/base/PromiseTest.java
deleted file mode 100644
index 58d39564f5..0000000000
--- a/base/android/junit/src/org/chromium/base/PromiseTest.java
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright 2016 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;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import org.chromium.base.Promise.UnhandledRejectionException;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-/** Unit tests for {@link Promise}. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class PromiseTest {
- // We need a simple mutable reference type for testing.
- private static class Value {
- private int mValue;
-
- public int get() {
- return mValue;
- }
-
- public void set(int value) {
- mValue = value;
- }
- }
-
- /** Tests that the callback is called on fulfillment. */
- @Test
- public void callback() {
- final Value value = new Value();
-
- Promise<Integer> promise = new Promise<Integer>();
- promise.then(PromiseTest.<Integer>setValue(value, 1));
-
- assertEquals(value.get(), 0);
-
- promise.fulfill(new Integer(1));
- assertEquals(value.get(), 1);
- }
-
- /** Tests that multiple callbacks are called. */
- @Test
- public void multipleCallbacks() {
- final Value value = new Value();
-
- Promise<Integer> promise = new Promise<Integer>();
- Callback<Integer> callback = new Callback<Integer>() {
- @Override
- public void onResult(Integer result) {
- value.set(value.get() + 1);
- }
- };
- promise.then(callback);
- promise.then(callback);
-
- assertEquals(value.get(), 0);
-
- promise.fulfill(new Integer(0));
- assertEquals(value.get(), 2);
- }
-
- /** Tests that a callback is called immediately when given to a fulfilled Promise. */
- @Test
- public void callbackOnFulfilled() {
- final Value value = new Value();
-
- Promise<Integer> promise = Promise.fulfilled(new Integer(0));
- assertEquals(value.get(), 0);
-
- promise.then(PromiseTest.<Integer>setValue(value, 1));
-
- assertEquals(value.get(), 1);
- }
-
- /** Tests that promises can chain synchronous functions correctly. */
- @Test
- public void promiseChaining() {
- Promise<Integer> promise = new Promise<Integer>();
- final Value value = new Value();
-
- promise.then(new Promise.Function<Integer, String>(){
- @Override
- public String apply(Integer arg) {
- return arg.toString();
- }
- }).then(new Promise.Function<String, String>(){
- @Override
- public String apply(String arg) {
- return arg + arg;
- }
- }).then(new Callback<String>() {
- @Override
- public void onResult(String result) {
- value.set(result.length());
- }
- });
-
- promise.fulfill(new Integer(123));
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertEquals(6, value.get());
- }
-
- /** Tests that promises can chain asynchronous functions correctly. */
- @Test
- public void promiseChainingAsyncFunctions() {
- Promise<Integer> promise = new Promise<Integer>();
- final Value value = new Value();
-
- final Promise<String> innerPromise = new Promise<String>();
-
- promise.then(new Promise.AsyncFunction<Integer, String>() {
- @Override
- public Promise<String> apply(Integer arg) {
- return innerPromise;
- }
- }).then(new Callback<String>(){
- @Override
- public void onResult(String result) {
- value.set(result.length());
- }
- });
-
- assertEquals(0, value.get());
-
- promise.fulfill(5);
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertEquals(0, value.get());
-
- innerPromise.fulfill("abc");
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertEquals(3, value.get());
- }
-
- /** Tests that a Promise that does not use its result does not throw on rejection. */
- @Test
- public void rejectPromiseNoCallbacks() {
- Promise<Integer> promise = new Promise<Integer>();
-
- boolean caught = false;
- try {
- promise.reject();
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- } catch (UnhandledRejectionException e) {
- caught = true;
- }
- assertFalse(caught);
- }
-
- /** Tests that a Promise that uses its result throws on rejection if it has no handler. */
- @Test
- public void rejectPromiseNoHandler() {
- Promise<Integer> promise = new Promise<Integer>();
- promise.then(PromiseTest.<Integer>identity()).then(PromiseTest.<Integer>pass());
-
- boolean caught = false;
- try {
- promise.reject();
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- } catch (UnhandledRejectionException e) {
- caught = true;
- }
- assertTrue(caught);
- }
-
- /** Tests that a Promise that handles rejection does not throw on rejection. */
- @Test
- public void rejectPromiseHandled() {
- Promise<Integer> promise = new Promise<Integer>();
- promise.then(PromiseTest.<Integer>identity())
- .then(PromiseTest.<Integer>pass(), PromiseTest.<Exception>pass());
-
- boolean caught = false;
- try {
- promise.reject();
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- } catch (UnhandledRejectionException e) {
- caught = true;
- }
- assertFalse(caught);
- }
-
- /** Tests that rejections carry the exception information. */
- @Test
- public void rejectionInformation() {
- Promise<Integer> promise = new Promise<Integer>();
- promise.then(PromiseTest.<Integer>pass());
-
- String message = "Promise Test";
- try {
- promise.reject(new NegativeArraySizeException(message));
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- fail();
- } catch (UnhandledRejectionException e) {
- assertTrue(e.getCause() instanceof NegativeArraySizeException);
- assertEquals(e.getCause().getMessage(), message);
- }
- }
-
- /** Tests that rejections propagate. */
- @Test
- public void rejectionChaining() {
- final Value value = new Value();
- Promise<Integer> promise = new Promise<Integer>();
-
- Promise<Integer> result =
- promise.then(PromiseTest.<Integer>identity()).then(PromiseTest.<Integer>identity());
-
- result.then(PromiseTest.<Integer>pass(), PromiseTest.<Exception>setValue(value, 5));
-
- promise.reject(new Exception());
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
-
- assertEquals(value.get(), 5);
- assertTrue(result.isRejected());
- }
-
- /** Tests that Promises get rejected if a Function throws. */
- @Test
- public void rejectOnThrow() {
- Value value = new Value();
- Promise<Integer> promise = new Promise<Integer>();
- promise.then(new Promise.Function<Integer, Integer>() {
- @Override
- public Integer apply(Integer argument) {
- throw new IllegalArgumentException();
- }
- }).then(PromiseTest.<Integer>pass(), PromiseTest.<Exception>setValue(value, 5));
-
- promise.fulfill(0);
-
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertEquals(value.get(), 5);
- }
-
- /** Tests that Promises get rejected if an AsyncFunction throws. */
- @Test
- public void rejectOnAsyncThrow() {
- Value value = new Value();
- Promise<Integer> promise = new Promise<Integer>();
-
- promise.then(new Promise.AsyncFunction<Integer, Integer>() {
- @Override
- public Promise<Integer> apply(Integer argument) {
- throw new IllegalArgumentException();
- }
- }).then(PromiseTest.<Integer>pass(), PromiseTest.<Exception>setValue(value, 5));
-
- promise.fulfill(0);
-
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertEquals(value.get(), 5);
- }
-
- /** Tests that Promises get rejected if an AsyncFunction rejects. */
- @Test
- public void rejectOnAsyncReject() {
- Value value = new Value();
- Promise<Integer> promise = new Promise<Integer>();
- final Promise<Integer> inner = new Promise<Integer>();
-
- promise.then(new Promise.AsyncFunction<Integer, Integer>() {
- @Override
- public Promise<Integer> apply(Integer argument) {
- return inner;
- }
- }).then(PromiseTest.<Integer>pass(), PromiseTest.<Exception>setValue(value, 5));
-
- promise.fulfill(0);
-
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertEquals(value.get(), 0);
-
- inner.reject();
-
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertEquals(value.get(), 5);
- }
-
- /** Convenience method that returns a Callback that does nothing with its result. */
- private static <T> Callback<T> pass() {
- return new Callback<T>() {
- @Override
- public void onResult(T result) {}
- };
- }
-
- /** Convenience method that returns a Function that just passes through its argument. */
- private static <T> Promise.Function<T, T> identity() {
- return new Promise.Function<T, T>() {
- @Override
- public T apply(T argument) {
- return argument;
- }
- };
- }
-
- /** Convenience method that returns a Callback that sets the given Value on execution. */
- private static <T> Callback<T> setValue(final Value toSet, final int value) {
- return new Callback<T>() {
- @Override
- public void onResult(T result) {
- toSet.set(value);
- }
- };
- }
-}
diff --git a/base/android/junit/src/org/chromium/base/memory/MemoryPressureMonitorTest.java b/base/android/junit/src/org/chromium/base/memory/MemoryPressureMonitorTest.java
deleted file mode 100644
index 1249a66acd..0000000000
--- a/base/android/junit/src/org/chromium/base/memory/MemoryPressureMonitorTest.java
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2018 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.memory;
-
-import android.content.ComponentCallbacks2;
-import android.os.Looper;
-import android.support.test.filters.SmallTest;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import org.chromium.base.MemoryPressureLevel;
-import org.chromium.base.Supplier;
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test for MemoryPressureMonitor.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class MemoryPressureMonitorTest {
- private MemoryPressureMonitor mMonitor;
-
- private static class TestPressureCallback implements MemoryPressureCallback {
- private Integer mReportedPressure;
-
- public void assertCalledWith(@MemoryPressureLevel int expectedPressure) {
- Assert.assertNotNull("Callback was not called", mReportedPressure);
- Assert.assertEquals(expectedPressure, (int) mReportedPressure);
- }
-
- public void assertNotCalled() {
- Assert.assertNull(mReportedPressure);
- }
-
- public void reset() {
- mReportedPressure = null;
- }
-
- @Override
- public void onPressure(@MemoryPressureLevel int pressure) {
- assertNotCalled();
- mReportedPressure = pressure;
- }
- }
-
- private static class TestPressureSupplier implements Supplier<Integer> {
- private @MemoryPressureLevel Integer mPressure;
- private boolean mIsCalled;
-
- public TestPressureSupplier(@MemoryPressureLevel Integer pressure) {
- mPressure = pressure;
- }
-
- @Override
- public @MemoryPressureLevel Integer get() {
- assertNotCalled();
- mIsCalled = true;
- return mPressure;
- }
-
- public void assertCalled() {
- Assert.assertTrue(mIsCalled);
- }
-
- public void assertNotCalled() {
- Assert.assertFalse(mIsCalled);
- }
- }
-
- private static final int THROTTLING_INTERVAL_MS = 1000;
-
- @Before
- public void setUp() {
- // Explicitly set main thread as UiThread. Other places rely on that.
- ThreadUtils.setUiThread(Looper.getMainLooper());
-
- // Pause main thread to get control over when tasks are run (see runUiThreadFor()).
- ShadowLooper.pauseMainLooper();
-
- mMonitor = new MemoryPressureMonitor(THROTTLING_INTERVAL_MS);
- mMonitor.setCurrentPressureSupplierForTesting(null);
- }
-
- /**
- * Runs all UiThread tasks posted |delayMs| in the future.
- * @param delayMs
- */
- private void runUiThreadFor(long delayMs) {
- ShadowLooper.idleMainLooper(delayMs, TimeUnit.MILLISECONDS);
- }
-
- @Test
- @SmallTest
- public void testTrimLevelTranslation() {
- Integer[][] trimLevelToPressureMap = {//
- // Levels >= TRIM_MEMORY_COMPLETE map to CRITICAL.
- {ComponentCallbacks2.TRIM_MEMORY_COMPLETE + 1, MemoryPressureLevel.CRITICAL},
- {ComponentCallbacks2.TRIM_MEMORY_COMPLETE, MemoryPressureLevel.CRITICAL},
-
- // TRIM_MEMORY_RUNNING_CRITICAL maps to CRITICAL.
- {ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL, MemoryPressureLevel.CRITICAL},
-
- // Levels < TRIM_MEMORY_COMPLETE && >= TRIM_MEMORY_BACKGROUND map to MODERATE.
- {ComponentCallbacks2.TRIM_MEMORY_COMPLETE - 1, MemoryPressureLevel.MODERATE},
- {ComponentCallbacks2.TRIM_MEMORY_BACKGROUND + 1, MemoryPressureLevel.MODERATE},
- {ComponentCallbacks2.TRIM_MEMORY_BACKGROUND, MemoryPressureLevel.MODERATE},
-
- // Other levels are not mapped.
- {ComponentCallbacks2.TRIM_MEMORY_BACKGROUND - 1, null},
- {ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW, null},
- {ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE, null},
- {ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN, null}};
- for (Integer[] trimLevelAndPressure : trimLevelToPressureMap) {
- int trimLevel = trimLevelAndPressure[0];
- Integer expectedPressure = trimLevelAndPressure[1];
- Integer actualPressure = MemoryPressureMonitor.memoryPressureFromTrimLevel(trimLevel);
- Assert.assertEquals(expectedPressure, actualPressure);
- }
- }
-
- @Test
- @SmallTest
- public void testThrottleInterval() {
- TestPressureCallback callback = new TestPressureCallback();
- mMonitor.setReportingCallbackForTesting(callback);
-
- // First notification should go through.
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
- callback.assertCalledWith(MemoryPressureLevel.NONE);
-
- callback.reset();
-
- // This one should be throttled.
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
- callback.assertNotCalled();
-
- runUiThreadFor(THROTTLING_INTERVAL_MS - 1);
-
- // We're still within the throttling interval, so this notification should
- // still be throttled.
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
- callback.assertNotCalled();
-
- runUiThreadFor(1);
-
- // We're past the throttling interval at this point, so this notification
- // should go through.
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
- callback.assertCalledWith(MemoryPressureLevel.NONE);
- }
-
- @Test
- @SmallTest
- public void testChangeNotIgnored() {
- TestPressureCallback callback = new TestPressureCallback();
- mMonitor.setReportingCallbackForTesting(callback);
-
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
- callback.assertCalledWith(MemoryPressureLevel.NONE);
-
- callback.reset();
-
- // Second notification is throttled, but should be reported after the
- // throttling interval ends.
- mMonitor.notifyPressure(MemoryPressureLevel.MODERATE);
- callback.assertNotCalled();
-
- runUiThreadFor(THROTTLING_INTERVAL_MS - 1);
-
- // Shouldn't be reported at this point.
- callback.assertNotCalled();
-
- runUiThreadFor(1);
-
- callback.assertCalledWith(MemoryPressureLevel.MODERATE);
- }
-
- @Test
- @SmallTest
- public void testNoopChangeIgnored() {
- TestPressureCallback callback = new TestPressureCallback();
- mMonitor.setReportingCallbackForTesting(callback);
-
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
- callback.assertCalledWith(MemoryPressureLevel.NONE);
-
- callback.reset();
-
- // Report MODERATE and then NONE, so that the throttling interval finishes with the
- // same pressure that started it (i.e. NONE). In this case MODERATE should be ignored.
- mMonitor.notifyPressure(MemoryPressureLevel.MODERATE);
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
-
- runUiThreadFor(THROTTLING_INTERVAL_MS);
-
- callback.assertNotCalled();
- }
-
- @Test
- @SmallTest
- public void testPollingInitiallyDisabled() {
- TestPressureSupplier pressureSupplier =
- new TestPressureSupplier(MemoryPressureLevel.MODERATE);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.notifyPressure(MemoryPressureLevel.CRITICAL);
- runUiThreadFor(THROTTLING_INTERVAL_MS);
-
- // We finished the interval with CRITICAL, but since polling is disabled, we shouldn't
- // poll the current pressure.
- pressureSupplier.assertNotCalled();
- }
-
- @Test
- @SmallTest
- public void testEnablePollingPolls() {
- TestPressureCallback callback = new TestPressureCallback();
- mMonitor.setReportingCallbackForTesting(callback);
-
- TestPressureSupplier pressureSupplier =
- new TestPressureSupplier(MemoryPressureLevel.MODERATE);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.enablePolling();
-
- // When polling is enabled, current pressure should be retrieved and reported.
- pressureSupplier.assertCalled();
- callback.assertCalledWith(MemoryPressureLevel.MODERATE);
- }
-
- @Test
- @SmallTest
- public void testNullSupplierResultIgnored() {
- TestPressureCallback callback = new TestPressureCallback();
- mMonitor.setReportingCallbackForTesting(callback);
-
- TestPressureSupplier pressureSupplier = new TestPressureSupplier(null);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.enablePolling();
-
- // The pressure supplier should be called, but its null result should be ignored.
- pressureSupplier.assertCalled();
- callback.assertNotCalled();
- }
-
- @Test
- @SmallTest
- public void testEnablePollingRespectsThrottling() {
- TestPressureSupplier pressureSupplier =
- new TestPressureSupplier(MemoryPressureLevel.MODERATE);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.notifyPressure(MemoryPressureLevel.NONE);
-
- // The notification above started a throttling interval, so we shouldn't ask for the
- // current pressure when polling is enabled.
- mMonitor.enablePolling();
-
- pressureSupplier.assertNotCalled();
- }
-
- @Test
- @SmallTest
- public void testPollingIfCRITICAL() {
- TestPressureCallback callback = new TestPressureCallback();
- mMonitor.setReportingCallbackForTesting(callback);
-
- TestPressureSupplier pressureSupplier =
- new TestPressureSupplier(MemoryPressureLevel.MODERATE);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.notifyPressure(MemoryPressureLevel.CRITICAL);
- callback.reset();
-
- mMonitor.enablePolling();
-
- runUiThreadFor(THROTTLING_INTERVAL_MS - 1);
-
- // Pressure should be polled after the interval ends, not before.
- pressureSupplier.assertNotCalled();
-
- runUiThreadFor(1);
-
- // We started and finished the throttling interval with CRITICAL pressure, so
- // we should poll the current pressure at the end of the interval.
- pressureSupplier.assertCalled();
- callback.assertCalledWith(MemoryPressureLevel.MODERATE);
- }
-
- @Test
- @SmallTest
- public void testNoPollingIfNotCRITICAL() {
- TestPressureSupplier pressureSupplier = new TestPressureSupplier(MemoryPressureLevel.NONE);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.notifyPressure(MemoryPressureLevel.MODERATE);
-
- mMonitor.enablePolling();
-
- runUiThreadFor(THROTTLING_INTERVAL_MS);
-
- // We started and finished the throttling interval with non-CRITICAL pressure,
- // so no polling should take place.
- pressureSupplier.assertNotCalled();
- }
-
- @Test
- @SmallTest
- public void testNoPollingIfChangedToCRITICAL() {
- TestPressureSupplier pressureSupplier = new TestPressureSupplier(MemoryPressureLevel.NONE);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.notifyPressure(MemoryPressureLevel.MODERATE);
- mMonitor.notifyPressure(MemoryPressureLevel.CRITICAL);
-
- mMonitor.enablePolling();
-
- runUiThreadFor(THROTTLING_INTERVAL_MS);
-
- // We finished the throttling interval with CRITITCAL, but started with MODERATE,
- // so no polling should take place.
- pressureSupplier.assertNotCalled();
- }
-
- @Test
- @SmallTest
- public void testDisablePolling() {
- TestPressureSupplier pressureSupplier = new TestPressureSupplier(MemoryPressureLevel.NONE);
- mMonitor.setCurrentPressureSupplierForTesting(pressureSupplier);
-
- mMonitor.notifyPressure(MemoryPressureLevel.CRITICAL);
-
- mMonitor.enablePolling();
-
- runUiThreadFor(THROTTLING_INTERVAL_MS - 1);
-
- // Whether polling is enabled or not should be taken into account only after the interval
- // finishes, so disabling it here should have the same affect as if it was never enabled.
- mMonitor.disablePolling();
-
- runUiThreadFor(1);
-
- pressureSupplier.assertNotCalled();
- }
-}
diff --git a/base/android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java b/base/android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java
deleted file mode 100644
index 18fe6ce2ac..0000000000
--- a/base/android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2017 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.metrics.test;
-
-import android.util.Pair;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.Resetter;
-
-import org.chromium.base.metrics.RecordHistogram;
-
-import java.util.HashMap;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Implementation of RecordHistogram which does not rely on native and still enables testing of
- * histogram counts.
- */
-@Implements(RecordHistogram.class)
-public class ShadowRecordHistogram {
- private static HashMap<Pair<String, Integer>, Integer> sSamples =
- new HashMap<Pair<String, Integer>, Integer>();
-
- @Resetter
- public static void reset() {
- sSamples.clear();
- }
-
- @Implementation
- public static void recordCountHistogram(String name, int sample) {
- Pair<String, Integer> key = Pair.create(name, sample);
- incrementSampleCount(key);
- }
-
- @Implementation
- public static void recordLongTimesHistogram100(String name, long duration, TimeUnit timeUnit) {
- Pair<String, Integer> key = Pair.create(name, (int) timeUnit.toMillis(duration));
- incrementSampleCount(key);
- }
-
- @Implementation
- public static int getHistogramValueCountForTesting(String name, int sample) {
- Integer i = sSamples.get(Pair.create(name, sample));
- return (i != null) ? i : 0;
- }
-
- private static void incrementSampleCount(Pair<String, Integer> key) {
- Integer i = sSamples.get(key);
- if (i == null) {
- i = 0;
- }
- sSamples.put(key, i + 1);
- }
-}
diff --git a/base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java b/base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java
deleted file mode 100644
index 5c5bca9121..0000000000
--- a/base/android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Bundle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.Feature;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/** Unit tests for the ChildConnectionAllocator class. */
-@Config(manifest = Config.NONE)
-@RunWith(BaseRobolectricTestRunner.class)
-public class ChildConnectionAllocatorTest {
- private static final String TEST_PACKAGE_NAME = "org.chromium.allocator_test";
-
- private static final int MAX_CONNECTION_NUMBER = 2;
-
- private static final int FREE_CONNECTION_TEST_CALLBACK_START_FAILED = 1;
- private static final int FREE_CONNECTION_TEST_CALLBACK_PROCESS_DIED = 2;
-
- @Mock
- private ChildProcessConnection.ServiceCallback mServiceCallback;
-
- static class TestConnectionFactory implements ChildConnectionAllocator.ConnectionFactory {
- private ComponentName mLastServiceName;
-
- private ChildProcessConnection mConnection;
-
- private ChildProcessConnection.ServiceCallback mConnectionServiceCallback;
-
- @Override
- public ChildProcessConnection createConnection(Context context, ComponentName serviceName,
- boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle) {
- mLastServiceName = serviceName;
- if (mConnection == null) {
- mConnection = mock(ChildProcessConnection.class);
- // Retrieve the ServiceCallback so we can simulate the service process dying.
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) {
- mConnectionServiceCallback =
- (ChildProcessConnection.ServiceCallback) invocation.getArgument(1);
- return null;
- }
- })
- .when(mConnection)
- .start(anyBoolean(), any(ChildProcessConnection.ServiceCallback.class));
- }
- return mConnection;
- }
-
- public ComponentName getAndResetLastServiceName() {
- ComponentName serviceName = mLastServiceName;
- mLastServiceName = null;
- return serviceName;
- }
-
- // Use this method to have a callback invoked when the connection is started on the next
- // created connection.
- public void invokeCallbackOnConnectionStart(final boolean onChildStarted,
- final boolean onStartFailed, final boolean onChildProcessDied) {
- final ChildProcessConnection connection = mock(ChildProcessConnection.class);
- mConnection = connection;
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) {
- ChildProcessConnection.ServiceCallback serviceCallback =
- (ChildProcessConnection.ServiceCallback) invocation.getArgument(1);
- if (onChildStarted) {
- serviceCallback.onChildStarted();
- }
- if (onStartFailed) {
- serviceCallback.onChildStartFailed(connection);
- }
- if (onChildProcessDied) {
- serviceCallback.onChildProcessDied(connection);
- }
- return null;
- }
- })
- .when(mConnection)
- .start(anyBoolean(), any(ChildProcessConnection.ServiceCallback.class));
- }
-
- public void simulateServiceStartFailed() {
- mConnectionServiceCallback.onChildStartFailed(mConnection);
- }
-
- public void simulateServiceProcessDying() {
- mConnectionServiceCallback.onChildProcessDied(mConnection);
- }
- }
-
- private final TestConnectionFactory mTestConnectionFactory = new TestConnectionFactory();
-
- private ChildConnectionAllocator mAllocator;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mAllocator = ChildConnectionAllocator.createForTest(null, TEST_PACKAGE_NAME,
- "AllocatorTest", MAX_CONNECTION_NUMBER, true /* bindToCaller */,
- false /* bindAsExternalService */, false /* useStrongBinding */);
- mAllocator.setConnectionFactoryForTesting(mTestConnectionFactory);
- }
-
- @Test
- @Feature({"ProcessManagement"})
- public void testPlainAllocate() {
- assertFalse(mAllocator.anyConnectionAllocated());
- assertEquals(MAX_CONNECTION_NUMBER, mAllocator.getNumberOfServices());
-
- ChildProcessConnection connection =
- mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback);
- assertNotNull(connection);
-
- verify(connection, times(1))
- .start(eq(false) /* useStrongBinding */,
- any(ChildProcessConnection.ServiceCallback.class));
- assertTrue(mAllocator.anyConnectionAllocated());
- }
-
- /** Tests that different services are created until we reach the max number specified. */
- @Test
- @Feature({"ProcessManagement"})
- public void testAllocateMaxNumber() {
- assertTrue(mAllocator.isFreeConnectionAvailable());
- Set<ComponentName> serviceNames = new HashSet<>();
- for (int i = 0; i < MAX_CONNECTION_NUMBER; i++) {
- ChildProcessConnection connection = mAllocator.allocate(
- null /* context */, null /* serviceBundle */, mServiceCallback);
- assertNotNull(connection);
- ComponentName serviceName = mTestConnectionFactory.getAndResetLastServiceName();
- assertFalse(serviceNames.contains(serviceName));
- serviceNames.add(serviceName);
- }
- assertFalse(mAllocator.isFreeConnectionAvailable());
- assertNull(mAllocator.allocate(
- null /* context */, null /* serviceBundle */, mServiceCallback));
- }
-
- @Test
- @Feature({"ProcessManagement"})
- public void testQueueAllocation() {
- Runnable freeConnectionCallback = mock(Runnable.class);
- mAllocator = ChildConnectionAllocator.createForTest(freeConnectionCallback,
- TEST_PACKAGE_NAME, "AllocatorTest", 1, true /* bindToCaller */,
- false /* bindAsExternalService */, false /* useStrongBinding */);
- mAllocator.setConnectionFactoryForTesting(mTestConnectionFactory);
- // Occupy all slots.
- ChildProcessConnection connection =
- mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback);
- assertNotNull(connection);
- assertFalse(mAllocator.isFreeConnectionAvailable());
-
- final ChildProcessConnection newConnection[] = new ChildProcessConnection[2];
- Runnable allocate1 = () -> {
- newConnection[0] = mAllocator.allocate(
- null /* context */, null /* serviceBundle */, mServiceCallback);
- };
- Runnable allocate2 = () -> {
- newConnection[1] = mAllocator.allocate(
- null /* context */, null /* serviceBundle */, mServiceCallback);
- };
- mAllocator.queueAllocation(allocate1);
- mAllocator.queueAllocation(allocate2);
- verify(freeConnectionCallback, times(1)).run();
- assertNull(newConnection[0]);
-
- mTestConnectionFactory.simulateServiceProcessDying();
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertNotNull(newConnection[0]);
- assertNull(newConnection[1]);
-
- mTestConnectionFactory.simulateServiceProcessDying();
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertNotNull(newConnection[1]);
- }
-
- /**
- * Tests that the connection is created with the useStrongBinding parameter specified in the
- * allocator.
- */
- @Test
- @Feature({"ProcessManagement"})
- public void testStrongBindingParam() {
- for (boolean useStrongBinding : new boolean[] {true, false}) {
- ChildConnectionAllocator allocator = ChildConnectionAllocator.createForTest(null,
- TEST_PACKAGE_NAME, "AllocatorTest", MAX_CONNECTION_NUMBER,
- true /* bindToCaller */, false /* bindAsExternalService */, useStrongBinding);
- allocator.setConnectionFactoryForTesting(mTestConnectionFactory);
- ChildProcessConnection connection = allocator.allocate(
- null /* context */, null /* serviceBundle */, mServiceCallback);
- verify(connection, times(0)).start(useStrongBinding, mServiceCallback);
- }
- }
-
- /**
- * Tests that the various ServiceCallbacks are propagated and posted, so they happen after the
- * ChildProcessAllocator,allocate() method has returned.
- */
- public void runTestWithConnectionCallbacks(
- boolean onChildStarted, boolean onChildStartFailed, boolean onChildProcessDied) {
- // We have to pause the Roboletric looper or it'll execute the posted tasks synchronoulsy.
- ShadowLooper.pauseMainLooper();
- mTestConnectionFactory.invokeCallbackOnConnectionStart(
- onChildStarted, onChildStartFailed, onChildProcessDied);
- ChildProcessConnection connection =
- mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback);
- assertNotNull(connection);
-
- // Callbacks are posted.
- verify(mServiceCallback, never()).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, never()).onChildProcessDied(any());
- ShadowLooper.unPauseMainLooper();
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- verify(mServiceCallback, times(onChildStarted ? 1 : 0)).onChildStarted();
- verify(mServiceCallback, times(onChildStartFailed ? 1 : 0)).onChildStartFailed(any());
- verify(mServiceCallback, times(onChildProcessDied ? 1 : 0)).onChildProcessDied(any());
- }
-
- @Test
- @Feature({"ProcessManagement"})
- public void testOnChildStartedCallback() {
- runTestWithConnectionCallbacks(true /* onChildStarted */, false /* onChildStartFailed */,
- false /* onChildProcessDied */);
- }
-
- @Test
- @Feature({"ProcessManagement"})
- public void testOnChildStartFailedCallback() {
- runTestWithConnectionCallbacks(false /* onChildStarted */, true /* onChildStartFailed */,
- false /* onChildProcessDied */);
- }
-
- @Test
- @Feature({"ProcessManagement"})
- public void testOnChildProcessDiedCallback() {
- runTestWithConnectionCallbacks(false /* onChildStarted */, false /* onChildStartFailed */,
- true /* onChildProcessDied */);
- }
-
- /**
- * Tests that the allocator clears the connection when it fails to bind/process dies.
- */
- private void testFreeConnection(int callbackType) {
- ChildProcessConnection connection =
- mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback);
-
- assertNotNull(connection);
- ComponentName serviceName = mTestConnectionFactory.getAndResetLastServiceName();
- verify(connection, times(1))
- .start(eq(false) /* useStrongBinding */,
- any(ChildProcessConnection.ServiceCallback.class));
- assertTrue(mAllocator.anyConnectionAllocated());
- int onChildStartFailedExpectedCount = 0;
- int onChildProcessDiedExpectedCount = 0;
- switch (callbackType) {
- case FREE_CONNECTION_TEST_CALLBACK_START_FAILED:
- mTestConnectionFactory.simulateServiceStartFailed();
- onChildStartFailedExpectedCount = 1;
- break;
- case FREE_CONNECTION_TEST_CALLBACK_PROCESS_DIED:
- mTestConnectionFactory.simulateServiceProcessDying();
- onChildProcessDiedExpectedCount = 1;
- break;
- default:
- fail();
- break;
- }
- ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
- assertFalse(mAllocator.anyConnectionAllocated());
- verify(mServiceCallback, never()).onChildStarted();
- verify(mServiceCallback, times(onChildStartFailedExpectedCount))
- .onChildStartFailed(connection);
- verify(mServiceCallback, times(onChildProcessDiedExpectedCount))
- .onChildProcessDied(connection);
-
- // Allocate a new connection to make sure we are not getting the same connection.
- connection =
- mAllocator.allocate(null /* context */, null /* serviceBundle */, mServiceCallback);
- assertNotNull(connection);
- assertNotEquals(mTestConnectionFactory.getAndResetLastServiceName(), serviceName);
- }
-
- @Test
- @Feature({"ProcessManagement"})
- public void testFreeConnectionOnChildStartFailed() {
- testFreeConnection(FREE_CONNECTION_TEST_CALLBACK_START_FAILED);
- }
-
- @Test
- @Feature({"ProcessManagement"})
- public void testFreeConnectionOnChildProcessDied() {
- testFreeConnection(FREE_CONNECTION_TEST_CALLBACK_PROCESS_DIED);
- }
-}
diff --git a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
deleted file mode 100644
index 95474ea1e9..0000000000
--- a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
+++ /dev/null
@@ -1,425 +0,0 @@
-// Copyright 2017 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.process_launcher;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.AdditionalMatchers.or;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.isNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLooper;
-
-import org.chromium.base.ChildBindingState;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-/** Unit tests for ChildProcessConnection. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class ChildProcessConnectionTest {
- private static class ChildServiceConnectionMock
- implements ChildProcessConnection.ChildServiceConnection {
- private final Intent mBindIntent;
- private final ChildProcessConnection.ChildServiceConnectionDelegate mDelegate;
- private boolean mBound;
-
- public ChildServiceConnectionMock(
- Intent bindIntent, ChildProcessConnection.ChildServiceConnectionDelegate delegate) {
- mBindIntent = bindIntent;
- mDelegate = delegate;
- }
-
- @Override
- public boolean bind() {
- mBound = true;
- return true;
- }
-
- @Override
- public void unbind() {
- mBound = false;
- }
-
- @Override
- public boolean isBound() {
- return mBound;
- }
-
- public void notifyServiceConnected(IBinder service) {
- mDelegate.onServiceConnected(service);
- }
-
- public void notifyServiceDisconnected() {
- mDelegate.onServiceDisconnected();
- }
-
- public Intent getBindIntent() {
- return mBindIntent;
- }
- };
-
- private final ChildProcessConnection.ChildServiceConnectionFactory mServiceConnectionFactory =
- new ChildProcessConnection.ChildServiceConnectionFactory() {
- @Override
- public ChildProcessConnection.ChildServiceConnection createConnection(
- Intent bindIntent, int bindFlags,
- ChildProcessConnection.ChildServiceConnectionDelegate delegate) {
- ChildServiceConnectionMock connection =
- spy(new ChildServiceConnectionMock(bindIntent, delegate));
- if (mFirstServiceConnection == null) {
- mFirstServiceConnection = connection;
- }
- return connection;
- }
- };
-
- @Mock
- private ChildProcessConnection.ServiceCallback mServiceCallback;
-
- @Mock
- private ChildProcessConnection.ConnectionCallback mConnectionCallback;
-
- private IChildProcessService mIChildProcessService;
-
- private Binder mChildProcessServiceBinder;
-
- private ChildServiceConnectionMock mFirstServiceConnection;
-
- // Parameters captured from the IChildProcessService.setupConnection() call
- private Bundle mConnectionBundle;
- private ICallbackInt mConnectionPidCallback;
- private IBinder mConnectionIBinderCallback;
-
- @Before
- public void setUp() throws RemoteException {
- MockitoAnnotations.initMocks(this);
-
- mIChildProcessService = mock(IChildProcessService.class);
- // Capture the parameters passed to the IChildProcessService.setupConnection() call.
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) {
- mConnectionBundle = (Bundle) invocation.getArgument(0);
- mConnectionPidCallback = (ICallbackInt) invocation.getArgument(1);
- mConnectionIBinderCallback = (IBinder) invocation.getArgument(2);
- return null;
- }
- })
- .when(mIChildProcessService)
- .setupConnection(
- or(isNull(), any(Bundle.class)), or(isNull(), any()), or(isNull(), any()));
-
- mChildProcessServiceBinder = new Binder();
- mChildProcessServiceBinder.attachInterface(
- mIChildProcessService, IChildProcessService.class.getName());
- }
-
- private ChildProcessConnection createDefaultTestConnection() {
- return createTestConnection(false /* bindToCaller */, false /* bindAsExternalService */,
- null /* serviceBundle */);
- }
-
- private ChildProcessConnection createTestConnection(
- boolean bindToCaller, boolean bindAsExternalService, Bundle serviceBundle) {
- String packageName = "org.chromium.test";
- String serviceName = "TestService";
- return new ChildProcessConnection(null /* context */,
- new ComponentName(packageName, serviceName), bindToCaller, bindAsExternalService,
- serviceBundle, mServiceConnectionFactory);
- }
-
- @Test
- public void testStrongBinding() {
- ChildProcessConnection connection = createDefaultTestConnection();
- connection.start(true /* useStrongBinding */, null /* serviceCallback */);
- assertTrue(connection.isStrongBindingBound());
-
- connection = createDefaultTestConnection();
- connection.start(false /* useStrongBinding */, null /* serviceCallback */);
- assertFalse(connection.isStrongBindingBound());
- }
-
- @Test
- public void testServiceBundle() {
- Bundle serviceBundle = new Bundle();
- final String intKey = "org.chromium.myInt";
- final int intValue = 34;
- final int defaultValue = -1;
- serviceBundle.putInt(intKey, intValue);
- String stringKey = "org.chromium.myString";
- String stringValue = "thirty four";
- serviceBundle.putString(stringKey, stringValue);
-
- ChildProcessConnection connection = createTestConnection(
- false /* bindToCaller */, false /* bindAsExternalService */, serviceBundle);
- // Start the connection without the ChildServiceConnection connecting.
- connection.start(false /* useStrongBinding */, null /* serviceCallback */);
- assertNotNull(mFirstServiceConnection);
- Intent bindIntent = mFirstServiceConnection.getBindIntent();
- assertNotNull(bindIntent);
- assertEquals(intValue, bindIntent.getIntExtra(intKey, defaultValue));
- assertEquals(stringValue, bindIntent.getStringExtra(stringKey));
- }
-
- @Test
- public void testServiceStartsSuccessfully() {
- ChildProcessConnection connection = createDefaultTestConnection();
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, mServiceCallback);
- Assert.assertTrue(connection.isModerateBindingBound());
- Assert.assertFalse(connection.didOnServiceConnectedForTesting());
- verify(mServiceCallback, never()).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, never()).onChildProcessDied(any());
-
- // The service connects.
- mFirstServiceConnection.notifyServiceConnected(null /* iBinder */);
- Assert.assertTrue(connection.didOnServiceConnectedForTesting());
- verify(mServiceCallback, times(1)).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, never()).onChildProcessDied(any());
- }
-
- @Test
- public void testServiceStartsAndFailsToBind() {
- ChildProcessConnection connection = createDefaultTestConnection();
- assertNotNull(mFirstServiceConnection);
- // Note we use doReturn so the actual bind() method is not called (it would with
- // when(mFirstServiceConnection.bind()).thenReturn(false).
- doReturn(false).when(mFirstServiceConnection).bind();
- connection.start(false /* useStrongBinding */, mServiceCallback);
-
- Assert.assertFalse(connection.isModerateBindingBound());
- Assert.assertFalse(connection.didOnServiceConnectedForTesting());
- verify(mServiceCallback, never()).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, times(1)).onChildProcessDied(connection);
- }
-
- @Test
- public void testServiceStops() {
- ChildProcessConnection connection = createDefaultTestConnection();
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, mServiceCallback);
- mFirstServiceConnection.notifyServiceConnected(null /* iBinder */);
- connection.stop();
- verify(mServiceCallback, times(1)).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, times(1)).onChildProcessDied(connection);
- }
-
- @Test
- public void testServiceDisconnects() {
- ChildProcessConnection connection = createDefaultTestConnection();
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, mServiceCallback);
- mFirstServiceConnection.notifyServiceConnected(null /* iBinder */);
- mFirstServiceConnection.notifyServiceDisconnected();
- verify(mServiceCallback, times(1)).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, times(1)).onChildProcessDied(connection);
- }
-
- @Test
- public void testNotBoundToCaller() throws RemoteException {
- ChildProcessConnection connection = createTestConnection(false /* bindToCaller */,
- false /* bindAsExternalService */, null /* serviceBundle */);
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, mServiceCallback);
- mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder);
- // Service is started and bindToCallback is not called.
- verify(mServiceCallback, times(1)).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, never()).onChildProcessDied(connection);
- verify(mIChildProcessService, never()).bindToCaller();
- }
-
- @Test
- public void testBoundToCallerSuccess() throws RemoteException {
- ChildProcessConnection connection = createTestConnection(true /* bindToCaller */,
- false /* bindAsExternalService */, null /* serviceBundle */);
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, mServiceCallback);
- when(mIChildProcessService.bindToCaller()).thenReturn(true);
- mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder);
- // Service is started and bindToCallback is called.
- verify(mServiceCallback, times(1)).onChildStarted();
- verify(mServiceCallback, never()).onChildStartFailed(any());
- verify(mServiceCallback, never()).onChildProcessDied(connection);
- verify(mIChildProcessService, times(1)).bindToCaller();
- }
-
- @Test
- public void testBoundToCallerFailure() throws RemoteException {
- ChildProcessConnection connection = createTestConnection(true /* bindToCaller */,
- false /* bindAsExternalService */, null /* serviceBundle */);
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, mServiceCallback);
- // Pretend bindToCaller returns false, i.e. the service is already bound to a different
- // service.
- when(mIChildProcessService.bindToCaller()).thenReturn(false);
- mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder);
- // Service fails to start.
- verify(mServiceCallback, never()).onChildStarted();
- verify(mServiceCallback, times(1)).onChildStartFailed(any());
- verify(mServiceCallback, never()).onChildProcessDied(connection);
- verify(mIChildProcessService, times(1)).bindToCaller();
- }
-
- @Test
- public void testSetupConnectionBeforeServiceConnected() throws RemoteException {
- ChildProcessConnection connection = createDefaultTestConnection();
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, null /* serviceCallback */);
- connection.setupConnection(
- null /* connectionBundle */, null /* callback */, mConnectionCallback);
- verify(mConnectionCallback, never()).onConnected(any());
- mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder);
- ShadowLooper.runUiThreadTasks();
- assertNotNull(mConnectionPidCallback);
- mConnectionPidCallback.call(34 /* pid */);
- verify(mConnectionCallback, times(1)).onConnected(connection);
- }
-
- @Test
- public void testSetupConnectionAfterServiceConnected() throws RemoteException {
- ChildProcessConnection connection = createDefaultTestConnection();
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, null /* serviceCallback */);
- mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder);
- connection.setupConnection(
- null /* connectionBundle */, null /* callback */, mConnectionCallback);
- verify(mConnectionCallback, never()).onConnected(any());
- ShadowLooper.runUiThreadTasks();
- assertNotNull(mConnectionPidCallback);
- mConnectionPidCallback.call(34 /* pid */);
- verify(mConnectionCallback, times(1)).onConnected(connection);
- }
-
- @Test
- public void testKill() throws RemoteException {
- ChildProcessConnection connection = createDefaultTestConnection();
- assertNotNull(mFirstServiceConnection);
- connection.start(false /* useStrongBinding */, null /* serviceCallback */);
- mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder);
- connection.setupConnection(
- null /* connectionBundle */, null /* callback */, mConnectionCallback);
- verify(mConnectionCallback, never()).onConnected(any());
- ShadowLooper.runUiThreadTasks();
- assertNotNull(mConnectionPidCallback);
- mConnectionPidCallback.call(34 /* pid */);
- verify(mConnectionCallback, times(1)).onConnected(connection);
-
- // Add strong binding so that connection is oom protected.
- connection.removeModerateBinding();
- assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrentOrWhenDied());
- connection.addModerateBinding();
- assertEquals(ChildBindingState.MODERATE, connection.bindingStateCurrentOrWhenDied());
- connection.addStrongBinding();
- assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrentOrWhenDied());
-
- // Kill and verify state.
- connection.kill();
- verify(mIChildProcessService).forceKill();
- assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrentOrWhenDied());
- Assert.assertTrue(connection.isKilledByUs());
- }
-
- @Test
- public void testBindingStateCounts() throws RemoteException {
- ChildProcessConnection.resetBindingStateCountsForTesting();
- ChildProcessConnection connection0 = createDefaultTestConnection();
- ChildServiceConnectionMock connectionMock0 = mFirstServiceConnection;
- mFirstServiceConnection = null;
- ChildProcessConnection connection1 = createDefaultTestConnection();
- ChildServiceConnectionMock connectionMock1 = mFirstServiceConnection;
- mFirstServiceConnection = null;
- ChildProcessConnection connection2 = createDefaultTestConnection();
- ChildServiceConnectionMock connectionMock2 = mFirstServiceConnection;
- mFirstServiceConnection = null;
-
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 0, 0});
-
- connection0.start(false /* useStrongBinding */, null /* serviceCallback */);
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 1, 0});
-
- connection1.start(true /* useStrongBinding */, null /* serviceCallback */);
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 1, 1});
-
- connection2.start(false /* useStrongBinding */, null /* serviceCallback */);
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 2, 1});
-
- Binder binder0 = new Binder();
- Binder binder1 = new Binder();
- Binder binder2 = new Binder();
- binder0.attachInterface(mIChildProcessService, IChildProcessService.class.getName());
- binder1.attachInterface(mIChildProcessService, IChildProcessService.class.getName());
- binder2.attachInterface(mIChildProcessService, IChildProcessService.class.getName());
- connectionMock0.notifyServiceConnected(binder0);
- connectionMock1.notifyServiceConnected(binder1);
- connectionMock2.notifyServiceConnected(binder2);
- ShadowLooper.runUiThreadTasks();
-
- // Add and remove moderate binding works as expected.
- connection2.removeModerateBinding();
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 1, 1, 1});
- connection2.addModerateBinding();
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 2, 1});
-
- // Add and remove strong binding works as expected.
- connection0.addStrongBinding();
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 1, 2});
- connection0.removeStrongBinding();
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 2, 1});
-
- // Stopped connection should no longe update.
- connection0.stop();
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 1, 1});
- assertArrayEquals(
- connection1.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 1, 1});
-
- connection2.removeModerateBinding();
- assertArrayEquals(
- connection0.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 0, 1, 1});
- assertArrayEquals(
- connection1.bindingStateCountsCurrentOrWhenDied(), new int[] {0, 1, 0, 1});
- }
-}
diff --git a/base/android/library_loader/library_load_from_apk_status_codes.h b/base/android/library_loader/library_load_from_apk_status_codes.h
deleted file mode 100644
index 8910d4800d..0000000000
--- a/base/android/library_loader/library_load_from_apk_status_codes.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-#ifndef BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
-#define BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
-
-namespace base {
-namespace android {
-
-namespace {
-
-// This enum must be kept in sync with the LibraryLoadFromApkStatus enum in
-// tools/metrics/histograms/histograms.xml.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.library_loader
-enum LibraryLoadFromApkStatusCodes {
- // The loader was unable to determine whether the functionality is supported.
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_UNKNOWN = 0,
-
- // The device does not support loading a library directly from the APK file
- // (obsolete).
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_NOT_SUPPORTED_OBSOLETE = 1,
-
- // The device supports loading a library directly from the APK file.
- // (obsolete).
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_SUPPORTED_OBSOLETE = 2,
-
- // The Chromium library was successfully loaded directly from the APK file.
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_SUCCESSFUL = 3,
-
- // The Chromium library was successfully loaded using the unpack library
- // fallback because it was compressed or not page aligned in the APK file.
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_USED_UNPACK_LIBRARY_FALLBACK = 4,
-
- // The Chromium library was successfully loaded using the no map executable
- // support fallback (obsolete).
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_USED_NO_MAP_EXEC_SUPPORT_FALLBACK_OBSOLETE
- = 5,
-
- // End sentinel.
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX = 6,
-};
-
-} // namespace
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOAD_FROM_APK_STATUS_CODES_H_
diff --git a/base/android/library_loader/library_loader_hooks.cc b/base/android/library_loader/library_loader_hooks.cc
deleted file mode 100644
index 40bff5e337..0000000000
--- a/base/android/library_loader/library_loader_hooks.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-// 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/android/library_loader/library_loader_hooks.h"
-
-#include "base/android/jni_string.h"
-#include "base/android/library_loader/anchor_functions_buildflags.h"
-#include "base/android/library_loader/library_load_from_apk_status_codes.h"
-#include "base/android/library_loader/library_prefetcher.h"
-#include "base/android/orderfile/orderfile_buildflags.h"
-#include "base/at_exit.h"
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
-#include "jni/LibraryLoader_jni.h"
-
-#if BUILDFLAG(ORDERFILE_INSTRUMENTATION)
-#include "base/android/orderfile/orderfile_instrumentation.h"
-#endif
-
-namespace base {
-namespace android {
-
-namespace {
-
-base::AtExitManager* g_at_exit_manager = NULL;
-const char* g_library_version_number = "";
-LibraryLoadedHook* g_registration_callback = NULL;
-NativeInitializationHook* g_native_initialization_hook = NULL;
-
-enum RendererHistogramCode {
- // Renderer load at fixed address success, fail, or not attempted.
- // Renderers do not attempt to load at at fixed address if on a
- // low-memory device on which browser load at fixed address has already
- // failed.
- LFA_SUCCESS = 0,
- LFA_BACKOFF_USED = 1,
- LFA_NOT_ATTEMPTED = 2,
-
- // End sentinel, also used as nothing-pending indicator.
- MAX_RENDERER_HISTOGRAM_CODE = 3,
- NO_PENDING_HISTOGRAM_CODE = MAX_RENDERER_HISTOGRAM_CODE
-};
-
-enum BrowserHistogramCode {
- // Non-low-memory random address browser loads.
- NORMAL_LRA_SUCCESS = 0,
-
- // Low-memory browser loads at fixed address, success or fail.
- LOW_MEMORY_LFA_SUCCESS = 1,
- LOW_MEMORY_LFA_BACKOFF_USED = 2,
-
- MAX_BROWSER_HISTOGRAM_CODE = 3,
-};
-
-RendererHistogramCode g_renderer_histogram_code = NO_PENDING_HISTOGRAM_CODE;
-
-// Indicate whether g_library_preloader_renderer_histogram_code is valid
-bool g_library_preloader_renderer_histogram_code_registered = false;
-
-// The return value of NativeLibraryPreloader.loadLibrary() in child processes,
-// it is initialized to the invalid value which shouldn't showup in UMA report.
-int g_library_preloader_renderer_histogram_code = -1;
-
-// The amount of time, in milliseconds, that it took to load the shared
-// libraries in the renderer. Set in
-// RegisterChromiumAndroidLinkerRendererHistogram.
-long g_renderer_library_load_time_ms = 0;
-
-void RecordChromiumAndroidLinkerRendererHistogram() {
- if (g_renderer_histogram_code == NO_PENDING_HISTOGRAM_CODE)
- return;
- // Record and release the pending histogram value.
- UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.RendererStates",
- g_renderer_histogram_code,
- MAX_RENDERER_HISTOGRAM_CODE);
- g_renderer_histogram_code = NO_PENDING_HISTOGRAM_CODE;
-
- // Record how long it took to load the shared libraries.
- UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.RendererLoadTime",
- base::TimeDelta::FromMilliseconds(g_renderer_library_load_time_ms));
-}
-
-void RecordLibraryPreloaderRendereHistogram() {
- if (g_library_preloader_renderer_histogram_code_registered) {
- UmaHistogramSparse("Android.NativeLibraryPreloader.Result.Renderer",
- g_library_preloader_renderer_histogram_code);
- }
-}
-
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
-bool ShouldDoOrderfileMemoryOptimization() {
- return CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kOrderfileMemoryOptimization);
-}
-#endif
-
-} // namespace
-
-static void JNI_LibraryLoader_RegisterChromiumAndroidLinkerRendererHistogram(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jboolean requested_shared_relro,
- jboolean load_at_fixed_address_failed,
- jlong library_load_time_ms) {
- // Note a pending histogram value for later recording.
- if (requested_shared_relro) {
- g_renderer_histogram_code = load_at_fixed_address_failed
- ? LFA_BACKOFF_USED : LFA_SUCCESS;
- } else {
- g_renderer_histogram_code = LFA_NOT_ATTEMPTED;
- }
-
- g_renderer_library_load_time_ms = library_load_time_ms;
-}
-
-static void JNI_LibraryLoader_RecordChromiumAndroidLinkerBrowserHistogram(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jboolean is_using_browser_shared_relros,
- jboolean load_at_fixed_address_failed,
- jint library_load_from_apk_status,
- jlong library_load_time_ms) {
- // For low-memory devices, record whether or not we successfully loaded the
- // browser at a fixed address. Otherwise just record a normal invocation.
- BrowserHistogramCode histogram_code;
- if (is_using_browser_shared_relros) {
- histogram_code = load_at_fixed_address_failed
- ? LOW_MEMORY_LFA_BACKOFF_USED : LOW_MEMORY_LFA_SUCCESS;
- } else {
- histogram_code = NORMAL_LRA_SUCCESS;
- }
- UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.BrowserStates",
- histogram_code,
- MAX_BROWSER_HISTOGRAM_CODE);
-
- // Record the device support for loading a library directly from the APK file.
- UMA_HISTOGRAM_ENUMERATION(
- "ChromiumAndroidLinker.LibraryLoadFromApkStatus",
- static_cast<LibraryLoadFromApkStatusCodes>(library_load_from_apk_status),
- LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX);
-
- // Record how long it took to load the shared libraries.
- UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.BrowserLoadTime",
- base::TimeDelta::FromMilliseconds(library_load_time_ms));
-}
-
-static void JNI_LibraryLoader_RecordLibraryPreloaderBrowserHistogram(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jint status) {
- UmaHistogramSparse("Android.NativeLibraryPreloader.Result.Browser", status);
-}
-
-static void JNI_LibraryLoader_RegisterLibraryPreloaderRendererHistogram(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jint status) {
- g_library_preloader_renderer_histogram_code = status;
- g_library_preloader_renderer_histogram_code_registered = true;
-}
-
-void SetNativeInitializationHook(
- NativeInitializationHook native_initialization_hook) {
- g_native_initialization_hook = native_initialization_hook;
-}
-
-void RecordLibraryLoaderRendererHistograms() {
- RecordChromiumAndroidLinkerRendererHistogram();
- RecordLibraryPreloaderRendereHistogram();
-}
-
-void SetLibraryLoadedHook(LibraryLoadedHook* func) {
- g_registration_callback = func;
-}
-
-static jboolean JNI_LibraryLoader_LibraryLoaded(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller,
- jint library_process_type) {
-#if BUILDFLAG(ORDERFILE_INSTRUMENTATION)
- orderfile::StartDelayedDump();
-#endif
-
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
- if (ShouldDoOrderfileMemoryOptimization()) {
- NativeLibraryPrefetcher::MadviseForOrderfile();
- }
-#endif
-
- if (g_native_initialization_hook &&
- !g_native_initialization_hook(
- static_cast<LibraryProcessType>(library_process_type)))
- return false;
- if (g_registration_callback && !g_registration_callback(env, nullptr))
- return false;
- return true;
-}
-
-void LibraryLoaderExitHook() {
- if (g_at_exit_manager) {
- delete g_at_exit_manager;
- g_at_exit_manager = NULL;
- }
-}
-
-static void JNI_LibraryLoader_ForkAndPrefetchNativeLibrary(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
- return NativeLibraryPrefetcher::ForkAndPrefetchNativeLibrary(
- ShouldDoOrderfileMemoryOptimization());
-#endif
-}
-
-static jint JNI_LibraryLoader_PercentageOfResidentNativeLibraryCode(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
- return NativeLibraryPrefetcher::PercentageOfResidentNativeLibraryCode();
-#else
- return -1;
-#endif
-}
-
-static void JNI_LibraryLoader_PeriodicallyCollectResidency(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
- NativeLibraryPrefetcher::PeriodicallyCollectResidency();
-#else
- LOG(WARNING) << "Collecting residency is not supported.";
-#endif
-}
-
-void SetVersionNumber(const char* version_number) {
- g_library_version_number = strdup(version_number);
-}
-
-ScopedJavaLocalRef<jstring> JNI_LibraryLoader_GetVersionNumber(
- JNIEnv* env,
- const JavaParamRef<jobject>& jcaller) {
- return ConvertUTF8ToJavaString(env, g_library_version_number);
-}
-
-void InitAtExitManager() {
- g_at_exit_manager = new base::AtExitManager();
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/library_loader/library_loader_hooks.h b/base/android/library_loader/library_loader_hooks.h
deleted file mode 100644
index 9dff26ac24..0000000000
--- a/base/android/library_loader/library_loader_hooks.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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.
-
-#ifndef BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_
-#define BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_
-
-#include <jni.h>
-
-#include "base/base_export.h"
-#include "base/callback.h"
-
-namespace base {
-namespace android {
-
-// The process the shared library is loaded in.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.library_loader
-enum LibraryProcessType {
- // The LibraryLoad has not been initialized.
- PROCESS_UNINITIALIZED = 0,
- // Shared library is running in browser process.
- PROCESS_BROWSER = 1,
- // Shared library is running in child process.
- PROCESS_CHILD = 2,
- // Shared library is running in the app that uses webview.
- PROCESS_WEBVIEW = 3,
- // Shared library is running in child process as part of webview.
- PROCESS_WEBVIEW_CHILD = 4,
-};
-
-typedef bool NativeInitializationHook(LibraryProcessType library_process_type);
-
-BASE_EXPORT void SetNativeInitializationHook(
- NativeInitializationHook native_initialization_hook);
-
-// Record any pending renderer histogram value as histograms. Pending values
-// are set by RegisterChromiumAndroidLinkerRendererHistogram and
-// RegisterLibraryPreloaderRendererHistogram.
-BASE_EXPORT void RecordLibraryLoaderRendererHistograms();
-
-// Typedef for hook function to be called (indirectly from Java) once the
-// libraries are loaded. The hook function should register the JNI bindings
-// required to start the application. It should return true for success and
-// false for failure.
-// Note: this can't use base::Callback because there is no way of initializing
-// the default callback without using static objects, which we forbid.
-typedef bool LibraryLoadedHook(JNIEnv* env,
- jclass clazz);
-
-// Set the hook function to be called (from Java) once the libraries are loaded.
-// SetLibraryLoadedHook may only be called from JNI_OnLoad. The hook function
-// should register the JNI bindings required to start the application.
-
-BASE_EXPORT void SetLibraryLoadedHook(LibraryLoadedHook* func);
-
-// Pass the version name to the loader. This used to check that the library
-// version matches the version expected by Java before completing JNI
-// registration.
-// Note: argument must remain valid at least until library loading is complete.
-BASE_EXPORT void SetVersionNumber(const char* version_number);
-
-// Call on exit to delete the AtExitManager which OnLibraryLoadedOnUIThread
-// created.
-BASE_EXPORT void LibraryLoaderExitHook();
-
-// Initialize AtExitManager, this must be done at the begining of loading
-// shared library.
-void InitAtExitManager();
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_LIBRARY_LOADER_LIBRARY_LOADER_HOOKS_H_
diff --git a/base/android/library_loader/library_prefetcher.cc b/base/android/library_loader/library_prefetcher.cc
deleted file mode 100644
index 2ccf6a080a..0000000000
--- a/base/android/library_loader/library_prefetcher.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright 2015 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/android/library_loader/library_prefetcher.h"
-
-#include <stddef.h>
-#include <sys/mman.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <algorithm>
-#include <atomic>
-#include <cstdlib>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/android/library_loader/anchor_functions.h"
-#include "base/android/orderfile/orderfile_buildflags.h"
-#include "base/bits.h"
-#include "base/files/file.h"
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "build/build_config.h"
-
-#if BUILDFLAG(ORDERFILE_INSTRUMENTATION)
-#include "base/android/orderfile/orderfile_instrumentation.h"
-#endif
-
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
-
-namespace base {
-namespace android {
-
-namespace {
-
-// Android defines the background priority to this value since at least 2009
-// (see Process.java).
-constexpr int kBackgroundPriority = 10;
-// Valid for all Android architectures.
-constexpr size_t kPageSize = 4096;
-
-// Reads a byte per page between |start| and |end| to force it into the page
-// cache.
-// Heap allocations, syscalls and library functions are not allowed in this
-// function.
-// Returns true for success.
-#if defined(ADDRESS_SANITIZER)
-// Disable AddressSanitizer instrumentation for this function. It is touching
-// memory that hasn't been allocated by the app, though the addresses are
-// valid. Furthermore, this takes place in a child process. See crbug.com/653372
-// for the context.
-__attribute__((no_sanitize_address))
-#endif
-void Prefetch(size_t start, size_t end) {
- unsigned char* start_ptr = reinterpret_cast<unsigned char*>(start);
- unsigned char* end_ptr = reinterpret_cast<unsigned char*>(end);
- unsigned char dummy = 0;
- for (unsigned char* ptr = start_ptr; ptr < end_ptr; ptr += kPageSize) {
- // Volatile is required to prevent the compiler from eliminating this
- // loop.
- dummy ^= *static_cast<volatile unsigned char*>(ptr);
- }
-}
-
-// Populates the per-page residency between |start| and |end| in |residency|. If
-// successful, |residency| has the size of |end| - |start| in pages.
-// Returns true for success.
-bool Mincore(size_t start, size_t end, std::vector<unsigned char>* residency) {
- if (start % kPageSize || end % kPageSize)
- return false;
- size_t size = end - start;
- size_t size_in_pages = size / kPageSize;
- if (residency->size() != size_in_pages)
- residency->resize(size_in_pages);
- int err = HANDLE_EINTR(
- mincore(reinterpret_cast<void*>(start), size, &(*residency)[0]));
- PLOG_IF(ERROR, err) << "mincore() failed";
- return !err;
-}
-
-// Returns the start and end of .text, aligned to the lower and upper page
-// boundaries, respectively.
-std::pair<size_t, size_t> GetTextRange() {
- // |kStartOfText| may not be at the beginning of a page, since .plt can be
- // before it, yet in the same mapping for instance.
- size_t start_page = kStartOfText - kStartOfText % kPageSize;
- // Set the end to the page on which the beginning of the last symbol is. The
- // actual symbol may spill into the next page by a few bytes, but this is
- // outside of the executable code range anyway.
- size_t end_page = base::bits::Align(kEndOfText, kPageSize);
- return {start_page, end_page};
-}
-
-// Returns the start and end pages of the unordered section of .text, aligned to
-// lower and upper page boundaries, respectively.
-std::pair<size_t, size_t> GetOrderedTextRange() {
- size_t start_page = kStartOfOrderedText - kStartOfOrderedText % kPageSize;
- // kEndOfUnorderedText is not considered ordered, but the byte immediately
- // before is considered ordered and so can not be contained in the start page.
- size_t end_page = base::bits::Align(kEndOfOrderedText, kPageSize);
- return {start_page, end_page};
-}
-
-// Calls madvise(advice) on the specified range. Does nothing if the range is
-// empty.
-void MadviseOnRange(const std::pair<size_t, size_t>& range, int advice) {
- if (range.first >= range.second) {
- return;
- }
- size_t size = range.second - range.first;
- int err = madvise(reinterpret_cast<void*>(range.first), size, advice);
- if (err) {
- PLOG(ERROR) << "madvise() failed";
- }
-}
-
-// Timestamp in ns since Unix Epoch, and residency, as returned by mincore().
-struct TimestampAndResidency {
- uint64_t timestamp_nanos;
- std::vector<unsigned char> residency;
-
- TimestampAndResidency(uint64_t timestamp_nanos,
- std::vector<unsigned char>&& residency)
- : timestamp_nanos(timestamp_nanos), residency(residency) {}
-};
-
-// Returns true for success.
-bool CollectResidency(size_t start,
- size_t end,
- std::vector<TimestampAndResidency>* data) {
- // Not using base::TimeTicks() to not call too many base:: symbol that would
- // pollute the reached symbols dumps.
- struct timespec ts;
- if (HANDLE_EINTR(clock_gettime(CLOCK_MONOTONIC, &ts))) {
- PLOG(ERROR) << "Cannot get the time.";
- return false;
- }
- uint64_t now =
- static_cast<uint64_t>(ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec;
- std::vector<unsigned char> residency;
- if (!Mincore(start, end, &residency))
- return false;
-
- data->emplace_back(now, std::move(residency));
- return true;
-}
-
-void DumpResidency(size_t start,
- size_t end,
- std::unique_ptr<std::vector<TimestampAndResidency>> data) {
- auto path = base::FilePath(
- base::StringPrintf("/data/local/tmp/chrome/residency-%d.txt", getpid()));
- auto file =
- base::File(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- if (!file.IsValid()) {
- PLOG(ERROR) << "Cannot open file to dump the residency data "
- << path.value();
- return;
- }
-
- // First line: start-end of text range.
- CHECK(IsOrderingSane());
- CHECK_LT(start, kStartOfText);
- CHECK_LT(kEndOfText, end);
- auto start_end = base::StringPrintf("%" PRIuS " %" PRIuS "\n",
- kStartOfText - start, kEndOfText - start);
- file.WriteAtCurrentPos(start_end.c_str(), start_end.size());
-
- for (const auto& data_point : *data) {
- auto timestamp =
- base::StringPrintf("%" PRIu64 " ", data_point.timestamp_nanos);
- file.WriteAtCurrentPos(timestamp.c_str(), timestamp.size());
-
- std::vector<char> dump;
- dump.reserve(data_point.residency.size() + 1);
- for (auto c : data_point.residency)
- dump.push_back(c ? '1' : '0');
- dump[dump.size() - 1] = '\n';
- file.WriteAtCurrentPos(&dump[0], dump.size());
- }
-}
-
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-// Used for "LibraryLoader.PrefetchDetailedStatus".
-enum class PrefetchStatus {
- kSuccess = 0,
- kWrongOrdering = 1,
- kForkFailed = 2,
- kChildProcessCrashed = 3,
- kChildProcessKilled = 4,
- kMaxValue = kChildProcessKilled
-};
-
-PrefetchStatus ForkAndPrefetch(bool ordered_only) {
- if (!IsOrderingSane()) {
- LOG(WARNING) << "Incorrect code ordering";
- return PrefetchStatus::kWrongOrdering;
- }
-
- // Looking for ranges is done before the fork, to avoid syscalls and/or memory
- // allocations in the forked process. The child process inherits the lock
- // state of its parent thread. It cannot rely on being able to acquire any
- // lock (unless special care is taken in a pre-fork handler), including being
- // able to call malloc().
- //
- // Always prefetch the ordered section first, as it's reached early during
- // startup, and not necessarily located at the beginning of .text.
- std::vector<std::pair<size_t, size_t>> ranges = {GetOrderedTextRange()};
- if (!ordered_only)
- ranges.push_back(GetTextRange());
-
- pid_t pid = fork();
- if (pid == 0) {
- setpriority(PRIO_PROCESS, 0, kBackgroundPriority);
- // _exit() doesn't call the atexit() handlers.
- for (const auto& range : ranges) {
- Prefetch(range.first, range.second);
- }
- _exit(EXIT_SUCCESS);
- } else {
- if (pid < 0) {
- return PrefetchStatus::kForkFailed;
- }
- int status;
- const pid_t result = HANDLE_EINTR(waitpid(pid, &status, 0));
- if (result == pid) {
- if (WIFEXITED(status))
- return PrefetchStatus::kSuccess;
- if (WIFSIGNALED(status)) {
- int signal = WTERMSIG(status);
- switch (signal) {
- case SIGSEGV:
- case SIGBUS:
- return PrefetchStatus::kChildProcessCrashed;
- break;
- case SIGKILL:
- case SIGTERM:
- default:
- return PrefetchStatus::kChildProcessKilled;
- }
- }
- }
- // Should not happen. Per man waitpid(2), errors are:
- // - EINTR: handled.
- // - ECHILD if the process doesn't have an unwaited-for child with this PID.
- // - EINVAL.
- return PrefetchStatus::kChildProcessKilled;
- }
-}
-
-} // namespace
-
-// static
-void NativeLibraryPrefetcher::ForkAndPrefetchNativeLibrary(bool ordered_only) {
-#if BUILDFLAG(ORDERFILE_INSTRUMENTATION)
- // Avoid forking with orderfile instrumentation because the child process
- // would create a dump as well.
- return;
-#endif
-
- PrefetchStatus status = ForkAndPrefetch(ordered_only);
- UMA_HISTOGRAM_BOOLEAN("LibraryLoader.PrefetchStatus",
- status == PrefetchStatus::kSuccess);
- UMA_HISTOGRAM_ENUMERATION("LibraryLoader.PrefetchDetailedStatus", status);
- if (status != PrefetchStatus::kSuccess) {
- LOG(WARNING) << "Cannot prefetch the library. status = "
- << static_cast<int>(status);
- }
-}
-
-// static
-int NativeLibraryPrefetcher::PercentageOfResidentCode(size_t start,
- size_t end) {
- size_t total_pages = 0;
- size_t resident_pages = 0;
-
- std::vector<unsigned char> residency;
- bool ok = Mincore(start, end, &residency);
- if (!ok)
- return -1;
- total_pages += residency.size();
- resident_pages += std::count_if(residency.begin(), residency.end(),
- [](unsigned char x) { return x & 1; });
- if (total_pages == 0)
- return -1;
- return static_cast<int>((100 * resident_pages) / total_pages);
-}
-
-// static
-int NativeLibraryPrefetcher::PercentageOfResidentNativeLibraryCode() {
- if (!IsOrderingSane()) {
- LOG(WARNING) << "Incorrect code ordering";
- return -1;
- }
- const auto& range = GetTextRange();
- return PercentageOfResidentCode(range.first, range.second);
-}
-
-// static
-void NativeLibraryPrefetcher::PeriodicallyCollectResidency() {
- CHECK_EQ(static_cast<long>(kPageSize), sysconf(_SC_PAGESIZE));
-
- const auto& range = GetTextRange();
- auto data = std::make_unique<std::vector<TimestampAndResidency>>();
- for (int i = 0; i < 60; ++i) {
- if (!CollectResidency(range.first, range.second, data.get()))
- return;
- usleep(2e5);
- }
- DumpResidency(range.first, range.second, std::move(data));
-}
-
-// static
-void NativeLibraryPrefetcher::MadviseForOrderfile() {
- CHECK(IsOrderingSane());
- LOG(WARNING) << "Performing experimental madvise from orderfile information";
- // First MADV_RANDOM on all of text, then turn the ordered text range back to
- // normal. The ordered range may be placed anywhere within .text.
- MadviseOnRange(GetTextRange(), MADV_RANDOM);
- MadviseOnRange(GetOrderedTextRange(), MADV_NORMAL);
-}
-
-} // namespace android
-} // namespace base
-#endif // BUILDFLAG(SUPPORTS_CODE_ORDERING)
diff --git a/base/android/library_loader/library_prefetcher.h b/base/android/library_loader/library_prefetcher.h
deleted file mode 100644
index 29f294ef62..0000000000
--- a/base/android/library_loader/library_prefetcher.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_ANDROID_LIBRARY_LOADER_LIBRARY_PREFETCHER_H_
-#define BASE_ANDROID_LIBRARY_LOADER_LIBRARY_PREFETCHER_H_
-
-#include <jni.h>
-
-#include <stdint.h>
-
-#include "base/android/library_loader/anchor_functions_buildflags.h"
-#include "base/base_export.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
-
-namespace base {
-namespace android {
-
-// Forks and waits for a process prefetching the native library. This is done in
-// a forked process for the following reasons:
-// - Isolating the main process from mistakes in getting the address range, only
-// crashing the forked process in case of mistake.
-// - Not inflating the memory used by the main process uselessly, which could
-// increase its likelihood to be killed.
-// The forked process has background priority and, since it is not declared to
-// the Android runtime, can be killed at any time, which is not an issue here.
-class BASE_EXPORT NativeLibraryPrefetcher {
- public:
- // Finds the executable code range, forks a low priority process pre-fetching
- // it wait()s for the process to exit or die. If ordered_only is true, only
- // the ordered section is prefetched. See GetOrdrderedTextRange() in
- // library_prefetcher.cc.
- static void ForkAndPrefetchNativeLibrary(bool ordered_only);
-
- // Returns the percentage of the native library code currently resident in
- // memory, or -1 in case of error.
- static int PercentageOfResidentNativeLibraryCode();
-
- // Collects residency for the native library executable multiple times, then
- // dumps it to disk.
- static void PeriodicallyCollectResidency();
-
- // Calls madvise() on the native library executable, using orderfile
- // information to decide how to advise each part of the library.
- static void MadviseForOrderfile();
-
- private:
- // Returns the percentage of [start, end] currently resident in
- // memory, or -1 in case of error.
- static int PercentageOfResidentCode(size_t start, size_t end);
-
- FRIEND_TEST_ALL_PREFIXES(NativeLibraryPrefetcherTest,
- TestPercentageOfResidentCode);
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(NativeLibraryPrefetcher);
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BUILDFLAG(SUPPORTS_CODE_ORDERING)
-
-#endif // BASE_ANDROID_LIBRARY_LOADER_LIBRARY_PREFETCHER_H_
diff --git a/base/android/library_loader/library_prefetcher_unittest.cc b/base/android/library_loader/library_prefetcher_unittest.cc
deleted file mode 100644
index ebb0d48faf..0000000000
--- a/base/android/library_loader/library_prefetcher_unittest.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 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/android/library_loader/library_prefetcher.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/mman.h>
-#include "base/android/library_loader/anchor_functions_buildflags.h"
-#include "base/memory/shared_memory.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
-namespace base {
-namespace android {
-
-// Fails with ASAN, crbug.com/570423.
-#if !defined(ADDRESS_SANITIZER)
-namespace {
-const size_t kPageSize = 4096;
-} // namespace
-
-TEST(NativeLibraryPrefetcherTest, TestPercentageOfResidentCode) {
- size_t length = 4 * kPageSize;
- base::SharedMemory shared_mem;
- ASSERT_TRUE(shared_mem.CreateAndMapAnonymous(length));
- void* address = shared_mem.memory();
- size_t start = reinterpret_cast<size_t>(address);
- size_t end = start + length;
-
- // Remove everything.
- ASSERT_EQ(0, madvise(address, length, MADV_DONTNEED));
- EXPECT_EQ(0, NativeLibraryPrefetcher::PercentageOfResidentCode(start, end));
-
- // Get everything back.
- ASSERT_EQ(0, mlock(address, length));
- EXPECT_EQ(100, NativeLibraryPrefetcher::PercentageOfResidentCode(start, end));
- munlock(address, length);
-}
-#endif // !defined(ADDRESS_SANITIZER)
-
-} // namespace android
-} // namespace base
-#endif // BUILDFLAG(SUPPORTS_CODE_ORDERING)
diff --git a/base/android/linker/config.gni b/base/android/linker/config.gni
deleted file mode 100644
index 27793ffe6e..0000000000
--- a/base/android/linker/config.gni
+++ /dev/null
@@ -1,13 +0,0 @@
-# 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.
-
-import("//build/config/android/config.gni")
-import("//build/config/compiler/compiler.gni")
-import("//build/config/sanitizers/sanitizers.gni")
-
-# Chromium linker doesn't reliably support loading multiple libraries;
-# disable for component builds, see crbug.com/657093.
-# Chromium linker causes instrumentation to return incorrect results.
-chromium_linker_supported =
- !is_component_build && !enable_profiling && !use_order_profiling && !is_asan
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc
deleted file mode 100644
index ba632db683..0000000000
--- a/base/android/linker/linker_jni.cc
+++ /dev/null
@@ -1,696 +0,0 @@
-// Copyright 2015 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.
-
-// This is the Android-specific Chromium linker, a tiny shared library
-// implementing a custom dynamic linker that can be used to load the
-// real Chromium libraries.
-
-// The main point of this linker is to be able to share the RELRO
-// section of libchrome.so (or equivalent) between renderer processes.
-
-// This source code *cannot* depend on anything from base/ or the C++
-// STL, to keep the final library small, and avoid ugly dependency issues.
-
-#include <android/log.h>
-#include <jni.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-
-#include "build/build_config.h"
-
-#include <crazy_linker.h>
-
-// Set this to 1 to enable debug traces to the Android log.
-// Note that LOG() from "base/logging.h" cannot be used, since it is
-// in base/ which hasn't been loaded yet.
-#define DEBUG 0
-
-#define TAG "cr_ChromiumAndroidLinker"
-
-#if DEBUG
-#define LOG_INFO(FORMAT, ...) \
- __android_log_print(ANDROID_LOG_INFO, TAG, "%s: " FORMAT, __FUNCTION__, \
- ##__VA_ARGS__)
-#else
-#define LOG_INFO(FORMAT, ...) ((void)0)
-#endif
-#define LOG_ERROR(FORMAT, ...) \
- __android_log_print(ANDROID_LOG_ERROR, TAG, "%s: " FORMAT, __FUNCTION__, \
- ##__VA_ARGS__)
-
-#define UNUSED __attribute__((unused))
-
-// See commentary in crazy_linker_elf_loader.cpp for the effect of setting
-// this. If changing there, change here also.
-//
-// For more, see:
-// https://crbug.com/504410
-#define RESERVE_BREAKPAD_GUARD_REGION 1
-
-#if defined(ARCH_CPU_X86)
-// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on
-// x86 - use force_align_arg_pointer to realign the stack at the JNI
-// boundary. https://crbug.com/655248
-#define JNI_GENERATOR_EXPORT \
- extern "C" __attribute__((visibility("default"), force_align_arg_pointer))
-#else
-#define JNI_GENERATOR_EXPORT extern "C" __attribute__((visibility("default")))
-#endif
-
-namespace chromium_android_linker {
-
-namespace {
-
-// Larger than the largest library we might attempt to load.
-constexpr size_t kAddressSpaceReservationSize = 192 * 1024 * 1024;
-
-// Size of any Breakpad guard region. 16MB is comfortably larger than the
-// ~6MB relocation packing of the current 64-bit libchrome.so, the largest we
-// expect to encounter.
-#if RESERVE_BREAKPAD_GUARD_REGION
-constexpr size_t kBreakpadGuardRegionBytes = 16 * 1024 * 1024;
-#endif
-
-// A simple scoped UTF String class that can be initialized from
-// a Java jstring handle. Modeled like std::string, which cannot
-// be used here.
-class String {
- public:
- String(JNIEnv* env, jstring str);
-
- inline ~String() { ::free(ptr_); }
-
- inline const char* c_str() const { return ptr_ ? ptr_ : ""; }
- inline size_t size() const { return size_; }
-
- private:
- char* ptr_;
- size_t size_;
-};
-
-// Simple scoped UTF String class constructor.
-String::String(JNIEnv* env, jstring str) {
- size_ = env->GetStringUTFLength(str);
- ptr_ = static_cast<char*>(::malloc(size_ + 1));
-
- // Note: This runs before browser native code is loaded, and so cannot
- // rely on anything from base/. This means that we must use
- // GetStringUTFChars() and not base::android::ConvertJavaStringToUTF8().
- //
- // GetStringUTFChars() suffices because the only strings used here are
- // paths to APK files or names of shared libraries, all of which are
- // plain ASCII, defined and hard-coded by the Chromium Android build.
- //
- // For more: see
- // https://crbug.com/508876
- //
- // Note: GetStringUTFChars() returns Java UTF-8 bytes. This is good
- // enough for the linker though.
- const char* bytes = env->GetStringUTFChars(str, nullptr);
- ::memcpy(ptr_, bytes, size_);
- ptr_[size_] = '\0';
-
- env->ReleaseStringUTFChars(str, bytes);
-}
-
-// Find the jclass JNI reference corresponding to a given |class_name|.
-// |env| is the current JNI environment handle.
-// On success, return true and set |*clazz|.
-bool InitClassReference(JNIEnv* env, const char* class_name, jclass* clazz) {
- *clazz = env->FindClass(class_name);
- if (!*clazz) {
- LOG_ERROR("Could not find class for %s", class_name);
- return false;
- }
- return true;
-}
-
-// Initialize a jfieldID corresponding to the field of a given |clazz|,
-// with name |field_name| and signature |field_sig|.
-// |env| is the current JNI environment handle.
-// On success, return true and set |*field_id|.
-bool InitFieldId(JNIEnv* env,
- jclass clazz,
- const char* field_name,
- const char* field_sig,
- jfieldID* field_id) {
- *field_id = env->GetFieldID(clazz, field_name, field_sig);
- if (!*field_id) {
- LOG_ERROR("Could not find ID for field '%s'", field_name);
- return false;
- }
- LOG_INFO("Found ID %p for field '%s'", *field_id, field_name);
- return true;
-}
-
-// Initialize a jmethodID corresponding to the static method of a given
-// |clazz|, with name |method_name| and signature |method_sig|.
-// |env| is the current JNI environment handle.
-// On success, return true and set |*method_id|.
-bool InitStaticMethodId(JNIEnv* env,
- jclass clazz,
- const char* method_name,
- const char* method_sig,
- jmethodID* method_id) {
- *method_id = env->GetStaticMethodID(clazz, method_name, method_sig);
- if (!*method_id) {
- LOG_ERROR("Could not find ID for static method '%s'", method_name);
- return false;
- }
- LOG_INFO("Found ID %p for static method '%s'", *method_id, method_name);
- return true;
-}
-
-// Initialize a jfieldID corresponding to the static field of a given |clazz|,
-// with name |field_name| and signature |field_sig|.
-// |env| is the current JNI environment handle.
-// On success, return true and set |*field_id|.
-bool InitStaticFieldId(JNIEnv* env,
- jclass clazz,
- const char* field_name,
- const char* field_sig,
- jfieldID* field_id) {
- *field_id = env->GetStaticFieldID(clazz, field_name, field_sig);
- if (!*field_id) {
- LOG_ERROR("Could not find ID for static field '%s'", field_name);
- return false;
- }
- LOG_INFO("Found ID %p for static field '%s'", *field_id, field_name);
- return true;
-}
-
-// Initialize a jint corresponding to the static integer field of a class
-// with class name |class_name| and field name |field_name|.
-// |env| is the current JNI environment handle.
-// On success, return true and set |*value|.
-bool InitStaticInt(JNIEnv* env,
- const char* class_name,
- const char* field_name,
- jint* value) {
- jclass clazz;
- if (!InitClassReference(env, class_name, &clazz))
- return false;
-
- jfieldID field_id;
- if (!InitStaticFieldId(env, clazz, field_name, "I", &field_id))
- return false;
-
- *value = env->GetStaticIntField(clazz, field_id);
- LOG_INFO("Found value %d for class '%s', static field '%s'",
- *value, class_name, field_name);
-
- return true;
-}
-
-// A class used to model the field IDs of the org.chromium.base.Linker
-// LibInfo inner class, used to communicate data with the Java side
-// of the linker.
-struct LibInfo_class {
- jfieldID load_address_id;
- jfieldID load_size_id;
- jfieldID relro_start_id;
- jfieldID relro_size_id;
- jfieldID relro_fd_id;
-
- // Initialize an instance.
- bool Init(JNIEnv* env) {
- jclass clazz;
- if (!InitClassReference(
- env, "org/chromium/base/library_loader/Linker$LibInfo", &clazz)) {
- return false;
- }
-
- return InitFieldId(env, clazz, "mLoadAddress", "J", &load_address_id) &&
- InitFieldId(env, clazz, "mLoadSize", "J", &load_size_id) &&
- InitFieldId(env, clazz, "mRelroStart", "J", &relro_start_id) &&
- InitFieldId(env, clazz, "mRelroSize", "J", &relro_size_id) &&
- InitFieldId(env, clazz, "mRelroFd", "I", &relro_fd_id);
- }
-
- void SetLoadInfo(JNIEnv* env,
- jobject library_info_obj,
- size_t load_address,
- size_t load_size) {
- env->SetLongField(library_info_obj, load_address_id, load_address);
- env->SetLongField(library_info_obj, load_size_id, load_size);
- }
-
- void SetRelroInfo(JNIEnv* env,
- jobject library_info_obj,
- size_t relro_start,
- size_t relro_size,
- int relro_fd) {
- env->SetLongField(library_info_obj, relro_start_id, relro_start);
- env->SetLongField(library_info_obj, relro_size_id, relro_size);
- env->SetIntField(library_info_obj, relro_fd_id, relro_fd);
- }
-
- // Use this instance to convert a RelroInfo reference into
- // a crazy_library_info_t.
- void GetRelroInfo(JNIEnv* env,
- jobject library_info_obj,
- size_t* relro_start,
- size_t* relro_size,
- int* relro_fd) {
- if (relro_start) {
- *relro_start = static_cast<size_t>(
- env->GetLongField(library_info_obj, relro_start_id));
- }
-
- if (relro_size) {
- *relro_size = static_cast<size_t>(
- env->GetLongField(library_info_obj, relro_size_id));
- }
-
- if (relro_fd) {
- *relro_fd = env->GetIntField(library_info_obj, relro_fd_id);
- }
- }
-};
-
-// Variable containing LibInfo for the loaded library.
-LibInfo_class s_lib_info_fields;
-
-// Return true iff |address| is a valid address for the target CPU.
-inline bool IsValidAddress(jlong address) {
- return static_cast<jlong>(static_cast<size_t>(address)) == address;
-}
-
-// The linker uses a single crazy_context_t object created on demand.
-// There is no need to protect this against concurrent access, locking
-// is already handled on the Java side.
-crazy_context_t* GetCrazyContext() {
- static crazy_context_t* s_crazy_context = nullptr;
-
- if (!s_crazy_context) {
- // Create new context.
- s_crazy_context = crazy_context_create();
-
- // Ensure libraries located in the same directory as the linker
- // can be loaded before system ones.
- crazy_context_add_search_path_for_address(
- s_crazy_context, reinterpret_cast<void*>(&GetCrazyContext));
- }
-
- return s_crazy_context;
-}
-
-// A scoped crazy_library_t that automatically closes the handle
-// on scope exit, unless Release() has been called.
-class ScopedLibrary {
- public:
- ScopedLibrary() : lib_(nullptr) {}
-
- ~ScopedLibrary() {
- if (lib_)
- crazy_library_close_with_context(lib_, GetCrazyContext());
- }
-
- crazy_library_t* Get() { return lib_; }
-
- crazy_library_t** GetPtr() { return &lib_; }
-
- crazy_library_t* Release() {
- crazy_library_t* ret = lib_;
- lib_ = nullptr;
- return ret;
- }
-
- private:
- crazy_library_t* lib_;
-};
-
-// Retrieve the SDK build version and pass it into the crazy linker. This
-// needs to be done early in initialization, before any other crazy linker
-// code is run.
-// |env| is the current JNI environment handle.
-// On success, return true.
-bool InitSDKVersionInfo(JNIEnv* env) {
- jint value = 0;
- if (!InitStaticInt(env, "android/os/Build$VERSION", "SDK_INT", &value))
- return false;
-
- crazy_set_sdk_build_version(static_cast<int>(value));
- LOG_INFO("Set SDK build version to %d", static_cast<int>(value));
-
- return true;
-}
-
-} // namespace
-
-// Use Android ASLR to create a random address into which we expect to be
-// able to load libraries. Note that this is probabilistic; we unmap the
-// address we get from mmap and assume we can re-map into it later. This
-// works the majority of the time. If it doesn't, client code backs out and
-// then loads the library normally at any available address.
-// |env| is the current JNI environment handle, and |clazz| a class.
-// Returns the address selected by ASLR, or 0 on error.
-JNI_GENERATOR_EXPORT jlong
-Java_org_chromium_base_library_1loader_Linker_nativeGetRandomBaseLoadAddress(
- JNIEnv* env,
- jclass clazz) {
- size_t bytes = kAddressSpaceReservationSize;
-
-#if RESERVE_BREAKPAD_GUARD_REGION
- // Pad the requested address space size for a Breakpad guard region.
- bytes += kBreakpadGuardRegionBytes;
-#endif
-
- void* address =
- mmap(nullptr, bytes, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (address == MAP_FAILED) {
- LOG_INFO("Random base load address not determinable");
- return 0;
- }
- munmap(address, bytes);
-
-#if RESERVE_BREAKPAD_GUARD_REGION
- // Allow for a Breakpad guard region ahead of the returned address.
- address = reinterpret_cast<void*>(
- reinterpret_cast<uintptr_t>(address) + kBreakpadGuardRegionBytes);
-#endif
-
- LOG_INFO("Random base load address is %p", address);
- return static_cast<jlong>(reinterpret_cast<uintptr_t>(address));
-}
-
-// We identify the abi tag for which the linker is running. This allows
-// us to select the library which matches the abi of the linker.
-
-#if defined(__arm__) && defined(__ARM_ARCH_7A__)
-#define CURRENT_ABI "armeabi-v7a"
-#elif defined(__arm__)
-#define CURRENT_ABI "armeabi"
-#elif defined(__i386__)
-#define CURRENT_ABI "x86"
-#elif defined(__mips__)
-#define CURRENT_ABI "mips"
-#elif defined(__x86_64__)
-#define CURRENT_ABI "x86_64"
-#elif defined(__aarch64__)
-#define CURRENT_ABI "arm64-v8a"
-#else
-#error "Unsupported target abi"
-#endif
-
-// Add a zip archive file path to the context's current search path
-// list. Making it possible to load libraries directly from it.
-JNI_GENERATOR_EXPORT bool
-Java_org_chromium_base_library_1loader_Linker_nativeAddZipArchivePath(
- JNIEnv* env,
- jclass clazz,
- jstring apk_path_obj) {
- String apk_path(env, apk_path_obj);
-
- char search_path[512];
- snprintf(search_path, sizeof(search_path), "%s!lib/" CURRENT_ABI "/",
- apk_path.c_str());
-
- crazy_context_t* context = GetCrazyContext();
- crazy_context_add_search_path(context, search_path);
- return true;
-}
-
-// Load a library with the chromium linker. This will also call its
-// JNI_OnLoad() method, which shall register its methods. Note that
-// lazy native method resolution will _not_ work after this, because
-// Dalvik uses the system's dlsym() which won't see the new library,
-// so explicit registration is mandatory.
-//
-// |env| is the current JNI environment handle.
-// |clazz| is the static class handle for org.chromium.base.Linker,
-// and is ignored here.
-// |library_name| is the library name (e.g. libfoo.so).
-// |load_address| is an explicit load address.
-// |lib_info_obj| is a LibInfo handle used to communicate information
-// with the Java side.
-// Return true on success.
-JNI_GENERATOR_EXPORT bool
-Java_org_chromium_base_library_1loader_Linker_nativeLoadLibrary(
- JNIEnv* env,
- jclass clazz,
- jstring lib_name_obj,
- jlong load_address,
- jobject lib_info_obj) {
- String library_name(env, lib_name_obj);
- LOG_INFO("Called for %s, at address 0x%llx", library_name, load_address);
- crazy_context_t* context = GetCrazyContext();
-
- if (!IsValidAddress(load_address)) {
- LOG_ERROR("Invalid address 0x%llx",
- static_cast<unsigned long long>(load_address));
- return false;
- }
-
- // Set the desired load address (0 means randomize it).
- crazy_context_set_load_address(context, static_cast<size_t>(load_address));
-
- ScopedLibrary library;
- if (!crazy_library_open(library.GetPtr(), library_name.c_str(), context)) {
- return false;
- }
-
- crazy_library_info_t info;
- if (!crazy_library_get_info(library.Get(), context, &info)) {
- LOG_ERROR("Could not get library information for %s: %s",
- library_name.c_str(), crazy_context_get_error(context));
- return false;
- }
-
- // Release library object to keep it alive after the function returns.
- library.Release();
-
- s_lib_info_fields.SetLoadInfo(env, lib_info_obj, info.load_address,
- info.load_size);
- LOG_INFO("Success loading library %s", library_name.c_str());
- return true;
-}
-
-// Class holding the Java class and method ID for the Java side Linker
-// postCallbackOnMainThread method.
-struct JavaCallbackBindings_class {
- jclass clazz;
- jmethodID method_id;
-
- // Initialize an instance.
- bool Init(JNIEnv* env, jclass linker_class) {
- clazz = reinterpret_cast<jclass>(env->NewGlobalRef(linker_class));
- return InitStaticMethodId(env, linker_class, "postCallbackOnMainThread",
- "(J)V", &method_id);
- }
-};
-
-static JavaCallbackBindings_class s_java_callback_bindings;
-
-// Designated receiver function for callbacks from Java. Its name is known
-// to the Java side.
-// |env| is the current JNI environment handle and is ignored here.
-// |clazz| is the static class handle for org.chromium.base.Linker,
-// and is ignored here.
-// |arg| is a pointer to an allocated crazy_callback_t, deleted after use.
-JNI_GENERATOR_EXPORT void
-Java_org_chromium_base_library_1loader_Linker_nativeRunCallbackOnUiThread(
- JNIEnv* env,
- jclass clazz,
- jlong arg) {
- crazy_callback_t* callback = reinterpret_cast<crazy_callback_t*>(arg);
-
- LOG_INFO("Called back from java with handler %p, opaque %p",
- callback->handler, callback->opaque);
-
- crazy_callback_run(callback);
- delete callback;
-}
-
-// Request a callback from Java. The supplied crazy_callback_t is valid only
-// for the duration of this call, so we copy it to a newly allocated
-// crazy_callback_t and then call the Java side's postCallbackOnMainThread.
-// This will call back to to our RunCallbackOnUiThread some time
-// later on the UI thread.
-// |callback_request| is a crazy_callback_t.
-// |poster_opaque| is unused.
-// Returns true if the callback request succeeds.
-static bool PostForLaterExecution(crazy_callback_t* callback_request,
- void* poster_opaque UNUSED) {
- crazy_context_t* context = GetCrazyContext();
-
- JavaVM* vm;
- int minimum_jni_version;
- crazy_context_get_java_vm(context, reinterpret_cast<void**>(&vm),
- &minimum_jni_version);
-
- // Do not reuse JNIEnv from JNI_OnLoad, but retrieve our own.
- JNIEnv* env;
- if (JNI_OK !=
- vm->GetEnv(reinterpret_cast<void**>(&env), minimum_jni_version)) {
- LOG_ERROR("Could not create JNIEnv");
- return false;
- }
-
- // Copy the callback; the one passed as an argument may be temporary.
- crazy_callback_t* callback = new crazy_callback_t();
- *callback = *callback_request;
-
- LOG_INFO("Calling back to java with handler %p, opaque %p", callback->handler,
- callback->opaque);
-
- jlong arg = static_cast<jlong>(reinterpret_cast<uintptr_t>(callback));
-
- env->CallStaticVoidMethod(s_java_callback_bindings.clazz,
- s_java_callback_bindings.method_id, arg);
-
- // Back out and return false if we encounter a JNI exception.
- if (env->ExceptionCheck() == JNI_TRUE) {
- env->ExceptionDescribe();
- env->ExceptionClear();
- delete callback;
- return false;
- }
-
- return true;
-}
-
-JNI_GENERATOR_EXPORT jboolean
-Java_org_chromium_base_library_1loader_Linker_nativeCreateSharedRelro(
- JNIEnv* env,
- jclass clazz,
- jstring library_name,
- jlong load_address,
- jobject lib_info_obj) {
- String lib_name(env, library_name);
-
- LOG_INFO("Called for %s", lib_name.c_str());
-
- if (!IsValidAddress(load_address)) {
- LOG_ERROR("Invalid address 0x%llx",
- static_cast<unsigned long long>(load_address));
- return false;
- }
-
- ScopedLibrary library;
- if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) {
- LOG_ERROR("Could not find %s", lib_name.c_str());
- return false;
- }
-
- crazy_context_t* context = GetCrazyContext();
- size_t relro_start = 0;
- size_t relro_size = 0;
- int relro_fd = -1;
-
- if (!crazy_library_create_shared_relro(
- library.Get(), context, static_cast<size_t>(load_address),
- &relro_start, &relro_size, &relro_fd)) {
- LOG_ERROR("Could not create shared RELRO sharing for %s: %s\n",
- lib_name.c_str(), crazy_context_get_error(context));
- return false;
- }
-
- s_lib_info_fields.SetRelroInfo(env, lib_info_obj, relro_start, relro_size,
- relro_fd);
- return true;
-}
-
-JNI_GENERATOR_EXPORT jboolean
-Java_org_chromium_base_library_1loader_Linker_nativeUseSharedRelro(
- JNIEnv* env,
- jclass clazz,
- jstring library_name,
- jobject lib_info_obj) {
- String lib_name(env, library_name);
-
- LOG_INFO("Called for %s, lib_info_ref=%p", lib_name.c_str(), lib_info_obj);
-
- ScopedLibrary library;
- if (!crazy_library_find_by_name(lib_name.c_str(), library.GetPtr())) {
- LOG_ERROR("Could not find %s", lib_name.c_str());
- return false;
- }
-
- crazy_context_t* context = GetCrazyContext();
- size_t relro_start = 0;
- size_t relro_size = 0;
- int relro_fd = -1;
- s_lib_info_fields.GetRelroInfo(env, lib_info_obj, &relro_start, &relro_size,
- &relro_fd);
-
- LOG_INFO("library=%s relro start=%p size=%p fd=%d", lib_name.c_str(),
- (void*)relro_start, (void*)relro_size, relro_fd);
-
- if (!crazy_library_use_shared_relro(library.Get(), context, relro_start,
- relro_size, relro_fd)) {
- LOG_ERROR("Could not use shared RELRO for %s: %s", lib_name.c_str(),
- crazy_context_get_error(context));
- return false;
- }
-
- LOG_INFO("Library %s using shared RELRO section!", lib_name.c_str());
-
- return true;
-}
-
-static bool LinkerJNIInit(JavaVM* vm, JNIEnv* env) {
- LOG_INFO("Entering");
-
- // Initialize SDK version info.
- LOG_INFO("Retrieving SDK version info");
- if (!InitSDKVersionInfo(env))
- return false;
-
- // Find LibInfo field ids.
- LOG_INFO("Caching field IDs");
- if (!s_lib_info_fields.Init(env)) {
- return false;
- }
-
- // Register native methods.
- jclass linker_class;
- if (!InitClassReference(env, "org/chromium/base/library_loader/Linker",
- &linker_class))
- return false;
-
- // Resolve and save the Java side Linker callback class and method.
- LOG_INFO("Resolving callback bindings");
- if (!s_java_callback_bindings.Init(env, linker_class)) {
- return false;
- }
-
- // Save JavaVM* handle into context.
- crazy_context_t* context = GetCrazyContext();
- crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4);
-
- // Register the function that the crazy linker can call to post code
- // for later execution.
- crazy_context_set_callback_poster(context, &PostForLaterExecution, nullptr);
-
- return true;
-}
-
-// JNI_OnLoad() hook called when the linker library is loaded through
-// the regular System.LoadLibrary) API. This shall save the Java VM
-// handle and initialize LibInfo fields.
-jint JNI_OnLoad(JavaVM* vm, void* reserved) {
- LOG_INFO("Entering");
- // Get new JNIEnv
- JNIEnv* env;
- if (JNI_OK != vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_4)) {
- LOG_ERROR("Could not create JNIEnv");
- return -1;
- }
-
- // Initialize linker base and implementations.
- if (!LinkerJNIInit(vm, env)) {
- return -1;
- }
-
- LOG_INFO("Done");
- return JNI_VERSION_1_4;
-}
-
-} // namespace chromium_android_linker
-
-jint JNI_OnLoad(JavaVM* vm, void* reserved) {
- return chromium_android_linker::JNI_OnLoad(vm, reserved);
-}
diff --git a/base/android/locale_utils.cc b/base/android/locale_utils.cc
deleted file mode 100644
index b3a2346366..0000000000
--- a/base/android/locale_utils.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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/android/locale_utils.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "jni/LocaleUtils_jni.h"
-
-namespace base {
-namespace android {
-
-std::string GetDefaultCountryCode() {
- JNIEnv* env = base::android::AttachCurrentThread();
- return ConvertJavaStringToUTF8(Java_LocaleUtils_getDefaultCountryCode(env));
-}
-
-std::string GetDefaultLocaleString() {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> locale =
- Java_LocaleUtils_getDefaultLocaleString(env);
- return ConvertJavaStringToUTF8(locale);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/locale_utils.h b/base/android/locale_utils.h
deleted file mode 100644
index be68890dfe..0000000000
--- a/base/android/locale_utils.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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.
-
-#ifndef BASE_ANDROID_LOCALE_UTILS_H_
-#define BASE_ANDROID_LOCALE_UTILS_H_
-
-#include <jni.h>
-
-#include <string>
-
-#include "base/base_export.h"
-
-namespace base {
-namespace android {
-
-BASE_EXPORT std::string GetDefaultCountryCode();
-
-// Return the current default locale of the device as string.
-BASE_EXPORT std::string GetDefaultLocaleString();
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_LOCALE_UTILS_H_
diff --git a/base/android/memory_pressure_listener_android.cc b/base/android/memory_pressure_listener_android.cc
deleted file mode 100644
index cab66e1c65..0000000000
--- a/base/android/memory_pressure_listener_android.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 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/android/memory_pressure_listener_android.h"
-
-#include "base/memory/memory_pressure_listener.h"
-#include "jni/MemoryPressureListener_jni.h"
-
-using base::android::JavaParamRef;
-
-// Defined and called by JNI.
-static void JNI_MemoryPressureListener_OnMemoryPressure(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- jint memory_pressure_level) {
- base::MemoryPressureListener::NotifyMemoryPressure(
- static_cast<base::MemoryPressureListener::MemoryPressureLevel>(
- memory_pressure_level));
-}
-
-namespace base {
-namespace android {
-
-void MemoryPressureListenerAndroid::Initialize(JNIEnv* env) {
- Java_MemoryPressureListener_addNativeCallback(env);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/memory_pressure_listener_android.h b/base/android/memory_pressure_listener_android.h
deleted file mode 100644
index 9edfd421ab..0000000000
--- a/base/android/memory_pressure_listener_android.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_ANDROID_MEMORY_PRESSURE_LISTENER_ANDROID_H_
-#define BASE_ANDROID_MEMORY_PRESSURE_LISTENER_ANDROID_H_
-
-#include "base/android/jni_android.h"
-#include "base/macros.h"
-
-namespace base {
-namespace android {
-
-// Implements the C++ counter part of MemoryPressureListener.java
-class BASE_EXPORT MemoryPressureListenerAndroid {
- public:
- static void Initialize(JNIEnv* env);
-
- // Called by JNI.
- static void OnMemoryPressure(int memory_pressure_type);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MemoryPressureListenerAndroid);
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_MEMORY_PRESSURE_LISTENER_ANDROID_H_
diff --git a/base/android/orderfile/BUILD.gn b/base/android/orderfile/BUILD.gn
new file mode 100644
index 0000000000..ff0bfff147
--- /dev/null
+++ b/base/android/orderfile/BUILD.gn
@@ -0,0 +1,34 @@
+# Copyright 2018 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.
+
+import("//build/config/android/config.gni")
+
+if (use_order_profiling && target_cpu == "arm") {
+ static_library("orderfile_instrumentation") {
+ sources = [
+ "orderfile_instrumentation.cc",
+ "orderfile_instrumentation.h",
+ ]
+ deps = [
+ "//base",
+ ]
+ }
+
+ executable("orderfile_instrumentation_perftest") {
+ testonly = true
+
+ sources = [
+ "orderfile_instrumentation_perftest.cc",
+ ]
+
+ deps = [
+ ":orderfile_instrumentation",
+ "//base",
+ "//testing/gtest",
+ "//testing/perf",
+ ]
+
+ configs -= [ "//build/config/android:default_orderfile_instrumentation" ]
+ }
+}
diff --git a/base/android/path_service_android.cc b/base/android/path_service_android.cc
deleted file mode 100644
index 51be530ea3..0000000000
--- a/base/android/path_service_android.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "jni/PathService_jni.h"
-
-namespace base {
-namespace android {
-
-void JNI_PathService_Override(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- jint what,
- const JavaParamRef<jstring>& path) {
- FilePath file_path(ConvertJavaStringToUTF8(env, path));
- PathService::Override(what, file_path);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/path_utils.cc b/base/android/path_utils.cc
deleted file mode 100644
index d1f6d43e9d..0000000000
--- a/base/android/path_utils.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/android/path_utils.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/files/file_path.h"
-
-#include "jni/PathUtils_jni.h"
-
-namespace base {
-namespace android {
-
-bool GetDataDirectory(FilePath* result) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> path = Java_PathUtils_getDataDirectory(env);
- FilePath data_path(ConvertJavaStringToUTF8(path));
- *result = data_path;
- return true;
-}
-
-bool GetCacheDirectory(FilePath* result) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> path = Java_PathUtils_getCacheDirectory(env);
- FilePath cache_path(ConvertJavaStringToUTF8(path));
- *result = cache_path;
- return true;
-}
-
-bool GetThumbnailCacheDirectory(FilePath* result) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> path =
- Java_PathUtils_getThumbnailCacheDirectory(env);
- FilePath thumbnail_cache_path(ConvertJavaStringToUTF8(path));
- *result = thumbnail_cache_path;
- return true;
-}
-
-bool GetDownloadsDirectory(FilePath* result) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> path = Java_PathUtils_getDownloadsDirectory(env);
- FilePath downloads_path(ConvertJavaStringToUTF8(path));
- *result = downloads_path;
- return true;
-}
-
-std::vector<FilePath> GetAllPrivateDownloadsDirectories() {
- std::vector<std::string> dirs;
- JNIEnv* env = AttachCurrentThread();
- auto jarray = Java_PathUtils_getAllPrivateDownloadsDirectories(env);
- base::android::AppendJavaStringArrayToStringVector(env, jarray.obj(), &dirs);
-
- std::vector<base::FilePath> file_paths;
- for (const auto& dir : dirs)
- file_paths.emplace_back(dir);
- return file_paths;
-}
-
-bool GetNativeLibraryDirectory(FilePath* result) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> path =
- Java_PathUtils_getNativeLibraryDirectory(env);
- FilePath library_path(ConvertJavaStringToUTF8(path));
- *result = library_path;
- return true;
-}
-
-bool GetExternalStorageDirectory(FilePath* result) {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jstring> path =
- Java_PathUtils_getExternalStorageDirectory(env);
- FilePath storage_path(ConvertJavaStringToUTF8(path));
- *result = storage_path;
- return true;
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/path_utils.h b/base/android/path_utils.h
deleted file mode 100644
index 650999d49a..0000000000
--- a/base/android/path_utils.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_ANDROID_PATH_UTILS_H_
-#define BASE_ANDROID_PATH_UTILS_H_
-
-#include <jni.h>
-#include <vector>
-
-#include "base/base_export.h"
-
-namespace base {
-
-class FilePath;
-
-namespace android {
-
-// Retrieves the absolute path to the data directory of the current
-// application. The result is placed in the FilePath pointed to by 'result'.
-// This method is dedicated for base_paths_android.c, Using
-// PathService::Get(base::DIR_ANDROID_APP_DATA, ...) gets the data dir.
-BASE_EXPORT bool GetDataDirectory(FilePath* result);
-
-// Retrieves the absolute path to the cache directory. The result is placed in
-// the FilePath pointed to by 'result'. This method is dedicated for
-// base_paths_android.c, Using PathService::Get(base::DIR_CACHE, ...) gets the
-// cache dir.
-BASE_EXPORT bool GetCacheDirectory(FilePath* result);
-
-// Retrieves the path to the thumbnail cache directory. The result is placed
-// in the FilePath pointed to by 'result'.
-BASE_EXPORT bool GetThumbnailCacheDirectory(FilePath* result);
-
-// Retrieves the path to the public downloads directory. The result is placed
-// in the FilePath pointed to by 'result'.
-BASE_EXPORT bool GetDownloadsDirectory(FilePath* result);
-
-// Retrieves the paths to all download directories, including default storage
-// directory, and a private directory on external SD card.
-BASE_EXPORT std::vector<FilePath> GetAllPrivateDownloadsDirectories();
-
-// Retrieves the path to the native JNI libraries via
-// ApplicationInfo.nativeLibraryDir on the Java side. The result is placed in
-// the FilePath pointed to by 'result'.
-BASE_EXPORT bool GetNativeLibraryDirectory(FilePath* result);
-
-// Retrieves the absolute path to the external storage directory. The result
-// is placed in the FilePath pointed to by 'result'.
-BASE_EXPORT bool GetExternalStorageDirectory(FilePath* result);
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_PATH_UTILS_H_
diff --git a/base/android/path_utils_unittest.cc b/base/android/path_utils_unittest.cc
deleted file mode 100644
index dca8ca13ac..0000000000
--- a/base/android/path_utils_unittest.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/android/path_utils.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_util.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace android {
-
-typedef testing::Test PathUtilsTest;
-
-namespace {
-void ExpectEither(const std::string& expected1,
- const std::string& expected2,
- const std::string& actual) {
- EXPECT_TRUE(expected1 == actual || expected2 == actual)
- << "Value of: " << actual << std::endl
- << "Expected either: " << expected1 << std::endl
- << "or: " << expected2;
-}
-} // namespace
-
-TEST_F(PathUtilsTest, TestGetDataDirectory) {
- // The string comes from the Java side and depends on the APK
- // we are running in. Assumes that we are packaged in
- // org.chromium.native_test
- FilePath path;
- GetDataDirectory(&path);
-
- ExpectEither("/data/data/org.chromium.native_test/app_chrome",
- "/data/user/0/org.chromium.native_test/app_chrome",
- path.value());
-}
-
-TEST_F(PathUtilsTest, TestGetCacheDirectory) {
- // The string comes from the Java side and depends on the APK
- // we are running in. Assumes that we are packaged in
- // org.chromium.native_test
- FilePath path;
- GetCacheDirectory(&path);
- ExpectEither("/data/data/org.chromium.native_test/cache",
- "/data/user/0/org.chromium.native_test/cache",
- path.value());
-}
-
-TEST_F(PathUtilsTest, TestGetNativeLibraryDirectory) {
- // The string comes from the Java side and depends on the APK
- // we are running in. Assumes that the directory contains
- // the base tests shared object.
- FilePath path;
- GetNativeLibraryDirectory(&path);
- EXPECT_TRUE(
- base::PathExists(path.Append("libbase_unittests.so")) ||
- base::PathExists(path.Append("libbase_unittests.cr.so")) ||
- base::PathExists(path.Append("lib_base_unittests__library.so")) ||
- base::PathExists(path.Append("lib_base_unittests__library.cr.so")));
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/proguard/chromium_apk.flags b/base/android/proguard/chromium_apk.flags
deleted file mode 100644
index ac3d7f8200..0000000000
--- a/base/android/proguard/chromium_apk.flags
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2016 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.
-
-# Contains flags that we'd like all Chromium .apks to use.
-
-# Not needed for Android and saves a bit of processing time.
--dontpreverify
-
-# Keep line number information, useful for stack traces.
--keepattributes SourceFile,LineNumberTable
-
-# Keep all CREATOR fields within Parcelable that are kept.
--keepclassmembers class * implements android.os.Parcelable {
- public static *** CREATOR;
-}
-
-# Don't obfuscate Parcelables as they might be marshalled outside Chrome.
-# If we annotated all Parcelables that get put into Bundles other than
-# for saveInstanceState (e.g. PendingIntents), then we could actually keep the
-# names of just those ones. For now, we'll just keep them all.
--keepnames class * implements android.os.Parcelable
-
-# Keep all enum values and valueOf methods. See
-# http://proguard.sourceforge.net/index.html#manual/examples.html
-# for the reason for this. Also, see http://crbug.com/248037.
--keepclassmembers enum * {
- public static **[] values();
-}
-
-# Keep classes implementing ParameterProvider -- these will be instantiated
-# via reflection.
--keep class * implements org.chromium.base.test.params.ParameterProvider
-
-# Allows Proguard freedom in removing these log related calls. We ask for debug
-# and verbose logs to be stripped out in base.Log, so we are just ensuring we
-# get rid of all other debug/verbose logs.
--assumenosideeffects class android.util.Log {
- static *** d(...);
- static *** v(...);
- static *** isLoggable(...);
-}
-
-# The following chart was created on July 20, 2016, to decide on 3 optimization
-# passes for Chrome.
-# optimization passes | time | .dex size | dirty memory per process
-# -----------------------------------------------------------------
-# 1 | 0:48 | 5805676 | 488972
-# 2 | 1:07 | 5777376 | 487092
-# 3 | 1:24 | 5772192 | 486596
-# 4 | 1:42 | 5771124 | 486484
-# 5 | 1:56 | 5770504 | 486432
--optimizationpasses 3
-
-# Horizontal class merging marginally increases dex size (as of Mar 2018).
--optimizations !class/merging/horizontal
-
-# Allowing Proguard to change modifiers. This change shrinks the .dex size by
-# ~1%, and reduces the method count by ~4%.
--allowaccessmodification
-
-# The support library contains references to newer platform versions.
-# Don't warn about those in case this app is linking against an older
-# platform version. We know about them, and they are safe.
--dontwarn android.support.**
diff --git a/base/android/proguard/chromium_code.flags b/base/android/proguard/chromium_code.flags
deleted file mode 100644
index 8a3ec58b17..0000000000
--- a/base/android/proguard/chromium_code.flags
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2016 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.
-
-# Contains flags that can be safely shared with Cronet, and thus would be
-# appropriate for third-party apps to include.
-
-# Keep all annotation related attributes that can affect runtime
--keepattributes RuntimeVisible*Annotations
--keepattributes AnnotationDefault
-
-# Keep the annotations, because if we don't, the ProGuard rules that use them
-# will not be respected. These classes then show up in our final dex, which we
-# do not want - see crbug.com/628226.
--keep @interface org.chromium.base.annotations.AccessedByNative
--keep @interface org.chromium.base.annotations.CalledByNative
--keep @interface org.chromium.base.annotations.CalledByNativeUnchecked
--keep @interface org.chromium.base.annotations.DoNotInline
--keep @interface org.chromium.base.annotations.RemovableInRelease
--keep @interface org.chromium.base.annotations.UsedByReflection
-
-# Keeps for class level annotations.
--keep @org.chromium.base.annotations.UsedByReflection class *
-
-# Keeps for method level annotations.
--keepclasseswithmembers class * {
- @org.chromium.base.annotations.AccessedByNative <fields>;
-}
--keepclasseswithmembers,includedescriptorclasses class * {
- @org.chromium.base.annotations.CalledByNative <methods>;
-}
--keepclasseswithmembers,includedescriptorclasses class * {
- @org.chromium.base.annotations.CalledByNativeUnchecked <methods>;
-}
--keepclasseswithmembers class * {
- @org.chromium.base.annotations.UsedByReflection <methods>;
-}
--keepclasseswithmembers class * {
- @org.chromium.base.annotations.UsedByReflection <fields>;
-}
--keepclasseswithmembers,includedescriptorclasses class * {
- native <methods>;
-}
-
-# Remove methods annotated with this if their return value is unused.
--assumenosideeffects class ** {
- @org.chromium.base.annotations.RemovableInRelease <methods>;
-}
-
-# Never inline classes or methods with this annotation, but allow shrinking and
-# obfuscation.
--keepnames,allowobfuscation @org.chromium.base.annotations.DoNotInline class * {
- *;
-}
--keepclassmembernames,allowobfuscation class * {
- @org.chromium.base.annotations.DoNotInline <methods>;
-}
-
-# Keep all CREATOR fields within Parcelable that are kept.
--keepclassmembers class org.chromium.** implements android.os.Parcelable {
- public static *** CREATOR;
-}
-
-# Don't obfuscate Parcelables as they might be marshalled outside Chrome.
-# If we annotated all Parcelables that get put into Bundles other than
-# for saveInstanceState (e.g. PendingIntents), then we could actually keep the
-# names of just those ones. For now, we'll just keep them all.
--keepnames class org.chromium.** implements android.os.Parcelable
-
-# Keep all enum values and valueOf methods. See
-# http://proguard.sourceforge.net/index.html#manual/examples.html
-# for the reason for this. Also, see http://crbug.com/248037.
--keepclassmembers enum org.chromium.** {
- public static **[] values();
-}
diff --git a/base/android/record_histogram.cc b/base/android/record_histogram.cc
deleted file mode 100644
index f41ec99d18..0000000000
--- a/base/android/record_histogram.cc
+++ /dev/null
@@ -1,343 +0,0 @@
-// 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 <stdint.h>
-
-#include <map>
-#include <string>
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "jni/RecordHistogram_jni.h"
-
-namespace base {
-namespace android {
-namespace {
-
-// Simple thread-safe wrapper for caching histograms. This avoids
-// relatively expensive JNI string translation for each recording.
-class HistogramCache {
- public:
- HistogramCache() {}
-
- std::string HistogramConstructionParamsToString(HistogramBase* histogram) {
- std::string params_str = histogram->histogram_name();
- switch (histogram->GetHistogramType()) {
- case HISTOGRAM:
- case LINEAR_HISTOGRAM:
- case BOOLEAN_HISTOGRAM:
- case CUSTOM_HISTOGRAM: {
- Histogram* hist = static_cast<Histogram*>(histogram);
- params_str += StringPrintf("/%d/%d/%d", hist->declared_min(),
- hist->declared_max(), hist->bucket_count());
- break;
- }
- case SPARSE_HISTOGRAM:
- case DUMMY_HISTOGRAM:
- break;
- }
- return params_str;
- }
-
- void JNI_RecordHistogram_CheckHistogramArgs(JNIEnv* env,
- jstring j_histogram_name,
- int32_t expected_min,
- int32_t expected_max,
- uint32_t expected_bucket_count,
- HistogramBase* histogram) {
- std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- bool valid_arguments = Histogram::InspectConstructionArguments(
- histogram_name, &expected_min, &expected_max, &expected_bucket_count);
- DCHECK(valid_arguments);
- DCHECK(histogram->HasConstructionArguments(expected_min, expected_max,
- expected_bucket_count))
- << histogram_name << "/" << expected_min << "/" << expected_max << "/"
- << expected_bucket_count << " vs. "
- << HistogramConstructionParamsToString(histogram);
- }
-
- HistogramBase* JNI_RecordHistogram_BooleanHistogram(JNIEnv* env,
- jstring j_histogram_name,
- jlong j_histogram_key) {
- DCHECK(j_histogram_name);
- HistogramBase* histogram = HistogramFromKey(j_histogram_key);
- if (histogram)
- return histogram;
-
- std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- histogram = BooleanHistogram::FactoryGet(
- histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
- return histogram;
- }
-
- HistogramBase* JNI_RecordHistogram_EnumeratedHistogram(
- JNIEnv* env,
- jstring j_histogram_name,
- jlong j_histogram_key,
- jint j_boundary) {
- DCHECK(j_histogram_name);
- HistogramBase* histogram = HistogramFromKey(j_histogram_key);
- int32_t boundary = static_cast<int32_t>(j_boundary);
- if (histogram) {
- JNI_RecordHistogram_CheckHistogramArgs(env, j_histogram_name, 1, boundary,
- boundary + 1, histogram);
- return histogram;
- }
-
- std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- histogram =
- LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1,
- HistogramBase::kUmaTargetedHistogramFlag);
- return histogram;
- }
-
- HistogramBase* JNI_RecordHistogram_CustomCountHistogram(
- JNIEnv* env,
- jstring j_histogram_name,
- jlong j_histogram_key,
- jint j_min,
- jint j_max,
- jint j_num_buckets) {
- DCHECK(j_histogram_name);
- int32_t min = static_cast<int32_t>(j_min);
- int32_t max = static_cast<int32_t>(j_max);
- int32_t num_buckets = static_cast<int32_t>(j_num_buckets);
- HistogramBase* histogram = HistogramFromKey(j_histogram_key);
- if (histogram) {
- JNI_RecordHistogram_CheckHistogramArgs(env, j_histogram_name, min, max,
- num_buckets, histogram);
- return histogram;
- }
-
- DCHECK_GE(min, 1) << "The min expected sample must be >= 1";
-
- std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- histogram =
- Histogram::FactoryGet(histogram_name, min, max, num_buckets,
- HistogramBase::kUmaTargetedHistogramFlag);
- return histogram;
- }
-
- HistogramBase* JNI_RecordHistogram_LinearCountHistogram(
- JNIEnv* env,
- jstring j_histogram_name,
- jlong j_histogram_key,
- jint j_min,
- jint j_max,
- jint j_num_buckets) {
- DCHECK(j_histogram_name);
- int32_t min = static_cast<int32_t>(j_min);
- int32_t max = static_cast<int32_t>(j_max);
- int32_t num_buckets = static_cast<int32_t>(j_num_buckets);
- HistogramBase* histogram = HistogramFromKey(j_histogram_key);
- if (histogram) {
- JNI_RecordHistogram_CheckHistogramArgs(env, j_histogram_name, min, max,
- num_buckets, histogram);
- return histogram;
- }
-
- std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- histogram =
- LinearHistogram::FactoryGet(histogram_name, min, max, num_buckets,
- HistogramBase::kUmaTargetedHistogramFlag);
- return histogram;
- }
-
- HistogramBase* JNI_RecordHistogram_SparseHistogram(JNIEnv* env,
- jstring j_histogram_name,
- jlong j_histogram_key) {
- DCHECK(j_histogram_name);
- HistogramBase* histogram = HistogramFromKey(j_histogram_key);
- if (histogram)
- return histogram;
-
- std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- histogram = SparseHistogram::FactoryGet(
- histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
- return histogram;
- }
-
- HistogramBase* JNI_RecordHistogram_CustomTimesHistogram(
- JNIEnv* env,
- jstring j_histogram_name,
- jlong j_histogram_key,
- jint j_min,
- jint j_max,
- jint j_bucket_count) {
- DCHECK(j_histogram_name);
- HistogramBase* histogram = HistogramFromKey(j_histogram_key);
- int32_t min = static_cast<int32_t>(j_min);
- int32_t max = static_cast<int32_t>(j_max);
- int32_t bucket_count = static_cast<int32_t>(j_bucket_count);
- if (histogram) {
- JNI_RecordHistogram_CheckHistogramArgs(env, j_histogram_name, min, max,
- bucket_count, histogram);
- return histogram;
- }
-
- std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
- // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet
- // is just a convenience for constructing the underlying Histogram with
- // TimeDelta arguments.
- histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count,
- HistogramBase::kUmaTargetedHistogramFlag);
- return histogram;
- }
-
- private:
- // Convert a jlong |histogram_key| from Java to a HistogramBase* via a cast.
- // The Java side caches these in a map (see RecordHistogram.java), which is
- // safe to do since C++ Histogram objects are never freed.
- static HistogramBase* HistogramFromKey(jlong j_histogram_key) {
- return reinterpret_cast<HistogramBase*>(j_histogram_key);
- }
-
- DISALLOW_COPY_AND_ASSIGN(HistogramCache);
-};
-
-LazyInstance<HistogramCache>::Leaky g_histograms;
-
-} // namespace
-
-jlong JNI_RecordHistogram_RecordBooleanHistogram(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_histogram_name,
- jlong j_histogram_key,
- jboolean j_sample) {
- bool sample = static_cast<bool>(j_sample);
- HistogramBase* histogram =
- g_histograms.Get().JNI_RecordHistogram_BooleanHistogram(
- env, j_histogram_name, j_histogram_key);
- histogram->AddBoolean(sample);
- return reinterpret_cast<jlong>(histogram);
-}
-
-jlong JNI_RecordHistogram_RecordEnumeratedHistogram(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_histogram_name,
- jlong j_histogram_key,
- jint j_sample,
- jint j_boundary) {
- int sample = static_cast<int>(j_sample);
-
- HistogramBase* histogram =
- g_histograms.Get().JNI_RecordHistogram_EnumeratedHistogram(
- env, j_histogram_name, j_histogram_key, j_boundary);
- histogram->Add(sample);
- return reinterpret_cast<jlong>(histogram);
-}
-
-jlong JNI_RecordHistogram_RecordCustomCountHistogram(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_histogram_name,
- jlong j_histogram_key,
- jint j_sample,
- jint j_min,
- jint j_max,
- jint j_num_buckets) {
- int sample = static_cast<int>(j_sample);
-
- HistogramBase* histogram =
- g_histograms.Get().JNI_RecordHistogram_CustomCountHistogram(
- env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets);
- histogram->Add(sample);
- return reinterpret_cast<jlong>(histogram);
-}
-
-jlong JNI_RecordHistogram_RecordLinearCountHistogram(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_histogram_name,
- jlong j_histogram_key,
- jint j_sample,
- jint j_min,
- jint j_max,
- jint j_num_buckets) {
- int sample = static_cast<int>(j_sample);
-
- HistogramBase* histogram =
- g_histograms.Get().JNI_RecordHistogram_LinearCountHistogram(
- env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets);
- histogram->Add(sample);
- return reinterpret_cast<jlong>(histogram);
-}
-
-jlong JNI_RecordHistogram_RecordSparseHistogram(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_histogram_name,
- jlong j_histogram_key,
- jint j_sample) {
- int sample = static_cast<int>(j_sample);
- HistogramBase* histogram =
- g_histograms.Get().JNI_RecordHistogram_SparseHistogram(
- env, j_histogram_name, j_histogram_key);
- histogram->Add(sample);
- return reinterpret_cast<jlong>(histogram);
-}
-
-jlong JNI_RecordHistogram_RecordCustomTimesHistogramMilliseconds(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_histogram_name,
- jlong j_histogram_key,
- jint j_duration,
- jint j_min,
- jint j_max,
- jint j_num_buckets) {
- HistogramBase* histogram =
- g_histograms.Get().JNI_RecordHistogram_CustomTimesHistogram(
- env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets);
- histogram->AddTime(
- TimeDelta::FromMilliseconds(static_cast<int64_t>(j_duration)));
- return reinterpret_cast<jlong>(histogram);
-}
-
-// This backs a Java test util for testing histograms -
-// MetricsUtils.HistogramDelta. It should live in a test-specific file, but we
-// currently can't have test-specific native code packaged in test-specific Java
-// targets - see http://crbug.com/415945.
-jint JNI_RecordHistogram_GetHistogramValueCountForTesting(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& histogram_name,
- jint sample) {
- HistogramBase* histogram = StatisticsRecorder::FindHistogram(
- android::ConvertJavaStringToUTF8(env, histogram_name));
- if (histogram == nullptr) {
- // No samples have been recorded for this histogram (yet?).
- return 0;
- }
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
- return samples->GetCount(static_cast<int>(sample));
-}
-
-jint JNI_RecordHistogram_GetHistogramTotalCountForTesting(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& histogram_name) {
- HistogramBase* histogram = StatisticsRecorder::FindHistogram(
- android::ConvertJavaStringToUTF8(env, histogram_name));
- if (histogram == nullptr) {
- // No samples have been recorded for this histogram.
- return 0;
- }
-
- return histogram->SnapshotSamples()->TotalCount();
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/record_user_action.cc b/base/android/record_user_action.cc
deleted file mode 100644
index 683add6b9b..0000000000
--- a/base/android/record_user_action.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2015 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/android/jni_string.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/metrics/user_metrics.h"
-#include "jni/RecordUserAction_jni.h"
-
-namespace {
-
-struct ActionCallbackWrapper {
- base::ActionCallback action_callback;
-};
-
-} // namespace
-
-namespace base {
-namespace android {
-
-static void JNI_RecordUserAction_RecordUserAction(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& j_action) {
- RecordComputedAction(ConvertJavaStringToUTF8(env, j_action));
-}
-
-static void OnActionRecorded(const JavaRef<jobject>& callback,
- const std::string& action) {
- JNIEnv* env = AttachCurrentThread();
- Java_UserActionCallback_onActionRecorded(
- env, callback, ConvertUTF8ToJavaString(env, action));
-}
-
-static jlong JNI_RecordUserAction_AddActionCallbackForTesting(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jobject>& callback) {
- // Create a wrapper for the ActionCallback, so it can life on the heap until
- // RemoveActionCallbackForTesting() is called.
- auto* wrapper = new ActionCallbackWrapper{base::Bind(
- &OnActionRecorded, ScopedJavaGlobalRef<jobject>(env, callback))};
- base::AddActionCallback(wrapper->action_callback);
- return reinterpret_cast<intptr_t>(wrapper);
-}
-
-static void JNI_RecordUserAction_RemoveActionCallbackForTesting(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- jlong callback_id) {
- DCHECK(callback_id);
- auto* wrapper = reinterpret_cast<ActionCallbackWrapper*>(callback_id);
- base::RemoveActionCallback(wrapper->action_callback);
- delete wrapper;
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/statistics_recorder_android.cc b/base/android/statistics_recorder_android.cc
deleted file mode 100644
index 346a7c7383..0000000000
--- a/base/android/statistics_recorder_android.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 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 <string>
-
-#include "base/android/jni_string.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/sys_info.h"
-#include "jni/StatisticsRecorderAndroid_jni.h"
-
-using base::android::JavaParamRef;
-using base::android::ConvertUTF8ToJavaString;
-
-namespace base {
-namespace android {
-
-static ScopedJavaLocalRef<jstring> JNI_StatisticsRecorderAndroid_ToJson(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- jint verbosityLevel) {
- return ConvertUTF8ToJavaString(
- env, base::StatisticsRecorder::ToJSON(
- static_cast<JSONVerbosityLevel>(verbosityLevel)));
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/sys_utils.cc b/base/android/sys_utils.cc
deleted file mode 100644
index 7872b2f7d5..0000000000
--- a/base/android/sys_utils.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2013 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/android/sys_utils.h"
-
-#include <memory>
-
-#include "base/android/build_info.h"
-#include "base/process/process_metrics.h"
-#include "base/sys_info.h"
-#include "base/trace_event/trace_event.h"
-#include "jni/SysUtils_jni.h"
-
-namespace base {
-namespace android {
-
-bool SysUtils::IsLowEndDeviceFromJni() {
- JNIEnv* env = AttachCurrentThread();
- return Java_SysUtils_isLowEndDevice(env);
-}
-
-bool SysUtils::IsCurrentlyLowMemory() {
- JNIEnv* env = AttachCurrentThread();
- return Java_SysUtils_isCurrentlyLowMemory(env);
-}
-
-// Logs the number of minor / major page faults to tracing (and also the time to
-// collect) the metrics. Does nothing if tracing is not enabled.
-static void JNI_SysUtils_LogPageFaultCountToTracing(
- JNIEnv* env,
- const base::android::JavaParamRef<jclass>& jcaller) {
- // This is racy, but we are OK losing data, and collecting it is potentially
- // expensive (reading and parsing a file).
- bool enabled;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED("startup", &enabled);
- if (!enabled)
- return;
- TRACE_EVENT_BEGIN2("memory", "CollectPageFaultCount", "minor", 0, "major", 0);
- std::unique_ptr<base::ProcessMetrics> process_metrics(
- base::ProcessMetrics::CreateProcessMetrics(
- base::GetCurrentProcessHandle()));
- base::PageFaultCounts counts;
- process_metrics->GetPageFaultCounts(&counts);
- TRACE_EVENT_END2("memory", "CollectPageFaults", "minor", counts.minor,
- "major", counts.major);
-}
-
-} // namespace android
-
-} // namespace base
diff --git a/base/android/sys_utils.h b/base/android/sys_utils.h
deleted file mode 100644
index b1e368bac9..0000000000
--- a/base/android/sys_utils.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_ANDROID_SYS_UTILS_H_
-#define BASE_ANDROID_SYS_UTILS_H_
-
-#include "base/android/jni_android.h"
-
-namespace base {
-namespace android {
-
-class BASE_EXPORT SysUtils {
- public:
- // Returns true iff this is a low-end device.
- static bool IsLowEndDeviceFromJni();
- // Returns true if system has low available memory.
- static bool IsCurrentlyLowMemory();
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_SYS_UTILS_H_
diff --git a/base/android/sys_utils_unittest.cc b/base/android/sys_utils_unittest.cc
deleted file mode 100644
index d16e2368de..0000000000
--- a/base/android/sys_utils_unittest.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 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 <stddef.h>
-#include <unistd.h>
-
-#include "base/sys_info.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace android {
-
-TEST(SysUtils, AmountOfPhysicalMemory) {
- // Check that the RAM size reported by sysconf() matches the one
- // computed by base::SysInfo::AmountOfPhysicalMemory().
- size_t sys_ram_size =
- static_cast<size_t>(sysconf(_SC_PHYS_PAGES) * PAGE_SIZE);
- EXPECT_EQ(sys_ram_size,
- static_cast<size_t>(SysInfo::AmountOfPhysicalMemory()));
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/throw_uncaught_exception.cc b/base/android/throw_uncaught_exception.cc
deleted file mode 100644
index 68627cc20f..0000000000
--- a/base/android/throw_uncaught_exception.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 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/android/throw_uncaught_exception.h"
-
-#include "base/android/jni_android.h"
-
-#include "jni/ThrowUncaughtException_jni.h"
-
-namespace base {
-namespace android {
-
-void ThrowUncaughtException() {
- Java_ThrowUncaughtException_post(AttachCurrentThread());
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/throw_uncaught_exception.h b/base/android/throw_uncaught_exception.h
deleted file mode 100644
index 57bd9088ff..0000000000
--- a/base/android/throw_uncaught_exception.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_ANDROID_THROW_UNCAUGHT_EXCEPTION_H_
-#define BASE_ANDROID_THROW_UNCAUGHT_EXCEPTION_H_
-
-#include "base/base_export.h"
-
-namespace base {
-namespace android {
-
-// Throw that completely unwinds the java stack. In particular, this will not
-// trigger a jni CheckException crash.
-BASE_EXPORT void ThrowUncaughtException();
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_THROW_UNCAUGHT_EXCEPTION_H_
diff --git a/base/android/time_utils.cc b/base/android/time_utils.cc
deleted file mode 100644
index 632dfb7a4e..0000000000
--- a/base/android/time_utils.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 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 <stdint.h>
-
-#include "base/time/time.h"
-#include "jni/TimeUtils_jni.h"
-
-namespace base {
-namespace android {
-
-static jlong JNI_TimeUtils_GetTimeTicksNowUs(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- return (TimeTicks::Now() - TimeTicks()).InMicroseconds();
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/trace_event_binding.cc b/base/android/trace_event_binding.cc
deleted file mode 100644
index 623ca75296..0000000000
--- a/base/android/trace_event_binding.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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 <jni.h>
-
-#include <set>
-
-#include "base/android/jni_string.h"
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "jni/TraceEvent_jni.h"
-
-namespace base {
-namespace android {
-
-namespace {
-
-const char kJavaCategory[] = "Java";
-const char kToplevelCategory[] = "toplevel";
-const char kLooperDispatchMessage[] = "Looper.dispatchMessage";
-
-// Boilerplate for safely converting Java data to TRACE_EVENT data.
-class TraceEventDataConverter {
- public:
- TraceEventDataConverter(JNIEnv* env, jstring jname, jstring jarg)
- : name_(ConvertJavaStringToUTF8(env, jname)),
- has_arg_(jarg != nullptr),
- arg_(jarg ? ConvertJavaStringToUTF8(env, jarg) : "") {}
- ~TraceEventDataConverter() {
- }
-
- // Return saves values to pass to TRACE_EVENT macros.
- const char* name() { return name_.c_str(); }
- const char* arg_name() { return has_arg_ ? "arg" : nullptr; }
- const char* arg() { return has_arg_ ? arg_.c_str() : nullptr; }
-
- private:
- std::string name_;
- bool has_arg_;
- std::string arg_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceEventDataConverter);
-};
-
-class TraceEnabledObserver
- : public trace_event::TraceLog::EnabledStateObserver {
- public:
- void OnTraceLogEnabled() override {
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::Java_TraceEvent_setEnabled(env, true);
- }
- void OnTraceLogDisabled() override {
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::Java_TraceEvent_setEnabled(env, false);
- }
-};
-
-base::LazyInstance<TraceEnabledObserver>::Leaky g_trace_enabled_state_observer_;
-
-} // namespace
-
-static void JNI_TraceEvent_RegisterEnabledObserver(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- bool enabled = trace_event::TraceLog::GetInstance()->IsEnabled();
- base::android::Java_TraceEvent_setEnabled(env, enabled);
- trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(
- g_trace_enabled_state_observer_.Pointer());
-}
-
-static void JNI_TraceEvent_StartATrace(JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- base::trace_event::TraceLog::GetInstance()->StartATrace();
-}
-
-static void JNI_TraceEvent_StopATrace(JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- base::trace_event::TraceLog::GetInstance()->StopATrace();
-}
-
-static void JNI_TraceEvent_Instant(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- const JavaParamRef<jstring>& jarg) {
- TraceEventDataConverter converter(env, jname, jarg);
- if (converter.arg()) {
- TRACE_EVENT_COPY_INSTANT1(kJavaCategory, converter.name(),
- TRACE_EVENT_SCOPE_THREAD,
- converter.arg_name(), converter.arg());
- } else {
- TRACE_EVENT_COPY_INSTANT0(kJavaCategory, converter.name(),
- TRACE_EVENT_SCOPE_THREAD);
- }
-}
-
-static void JNI_TraceEvent_Begin(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- const JavaParamRef<jstring>& jarg) {
- TraceEventDataConverter converter(env, jname, jarg);
- if (converter.arg()) {
- TRACE_EVENT_COPY_BEGIN1(kJavaCategory, converter.name(),
- converter.arg_name(), converter.arg());
- } else {
- TRACE_EVENT_COPY_BEGIN0(kJavaCategory, converter.name());
- }
-}
-
-static void JNI_TraceEvent_End(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- const JavaParamRef<jstring>& jarg) {
- TraceEventDataConverter converter(env, jname, jarg);
- if (converter.arg()) {
- TRACE_EVENT_COPY_END1(kJavaCategory, converter.name(),
- converter.arg_name(), converter.arg());
- } else {
- TRACE_EVENT_COPY_END0(kJavaCategory, converter.name());
- }
-}
-
-static void JNI_TraceEvent_BeginToplevel(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jtarget) {
- std::string target = ConvertJavaStringToUTF8(env, jtarget);
- TRACE_EVENT_BEGIN1(kToplevelCategory, kLooperDispatchMessage, "target",
- target);
-}
-
-static void JNI_TraceEvent_EndToplevel(JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- TRACE_EVENT_END0(kToplevelCategory, kLooperDispatchMessage);
-}
-
-static void JNI_TraceEvent_StartAsync(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- jlong jid) {
- TraceEventDataConverter converter(env, jname, nullptr);
- TRACE_EVENT_COPY_ASYNC_BEGIN0(kJavaCategory, converter.name(), jid);
-}
-
-static void JNI_TraceEvent_FinishAsync(JNIEnv* env,
- const JavaParamRef<jclass>& clazz,
- const JavaParamRef<jstring>& jname,
- jlong jid) {
- TraceEventDataConverter converter(env, jname, nullptr);
- TRACE_EVENT_COPY_ASYNC_END0(kJavaCategory, converter.name(), jid);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/unguessable_token_android.cc b/base/android/unguessable_token_android.cc
deleted file mode 100644
index d041557419..0000000000
--- a/base/android/unguessable_token_android.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 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/android/unguessable_token_android.h"
-
-#include "jni/UnguessableToken_jni.h"
-
-namespace base {
-namespace android {
-
-ScopedJavaLocalRef<jobject> UnguessableTokenAndroid::Create(
- JNIEnv* env,
- const base::UnguessableToken& token) {
- const uint64_t high = token.GetHighForSerialization();
- const uint64_t low = token.GetLowForSerialization();
- DCHECK(high);
- DCHECK(low);
- return Java_UnguessableToken_create(env, high, low);
-}
-
-base::UnguessableToken UnguessableTokenAndroid::FromJavaUnguessableToken(
- JNIEnv* env,
- const JavaRef<jobject>& token) {
- const uint64_t high =
- Java_UnguessableToken_getHighForSerialization(env, token);
- const uint64_t low = Java_UnguessableToken_getLowForSerialization(env, token);
- DCHECK(high);
- DCHECK(low);
- return base::UnguessableToken::Deserialize(high, low);
-}
-
-ScopedJavaLocalRef<jobject>
-UnguessableTokenAndroid::ParcelAndUnparcelForTesting(
- JNIEnv* env,
- const JavaRef<jobject>& token) {
- return Java_UnguessableToken_parcelAndUnparcelForTesting(env, token);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/android/unguessable_token_android.h b/base/android/unguessable_token_android.h
deleted file mode 100644
index bb91f0e500..0000000000
--- a/base/android/unguessable_token_android.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_ANDROID_UNGUESSABLE_TOKEN_ANDROID_H_
-#define BASE_ANDROID_UNGUESSABLE_TOKEN_ANDROID_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/base_export.h"
-#include "base/unguessable_token.h"
-
-namespace base {
-namespace android {
-
-class BASE_EXPORT UnguessableTokenAndroid {
- public:
- // Create a Java UnguessableToken with the same value as |token|.
- static ScopedJavaLocalRef<jobject> Create(
- JNIEnv* env,
- const base::UnguessableToken& token);
-
- // Create a native UnguessableToken from Java UnguessableToken |token|.
- static base::UnguessableToken FromJavaUnguessableToken(
- JNIEnv* env,
- const JavaRef<jobject>& token);
-
- // Parcel UnguessableToken |token| and unparcel it, and return the result.
- // While this method is intended for facilitating unit tests, it results only
- // in a clone of |token|.
- static ScopedJavaLocalRef<jobject> ParcelAndUnparcelForTesting(
- JNIEnv* env,
- const JavaRef<jobject>& token);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(UnguessableTokenAndroid);
-};
-
-} // namespace android
-} // namespace base
-
-#endif // BASE_ANDROID_UNGUESSABLE_TOKEN_ANDROID_H_
diff --git a/base/android/unguessable_token_android_unittest.cc b/base/android/unguessable_token_android_unittest.cc
deleted file mode 100644
index bdad746d55..0000000000
--- a/base/android/unguessable_token_android_unittest.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 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/android/unguessable_token_android.h"
-
-#include "base/android/jni_android.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace android {
-
-TEST(UnguessableTokenAndroid, BasicCreateToken) {
- JNIEnv* env = AttachCurrentThread();
- uint64_t high = 0x1234567812345678;
- uint64_t low = 0x0583503029282304;
- base::UnguessableToken token = base::UnguessableToken::Deserialize(high, low);
- ScopedJavaLocalRef<jobject> jtoken =
- UnguessableTokenAndroid::Create(env, token);
- base::UnguessableToken result =
- UnguessableTokenAndroid::FromJavaUnguessableToken(env, jtoken);
-
- EXPECT_EQ(token, result);
-}
-
-TEST(UnguessableTokenAndroid, ParcelAndUnparcel) {
- JNIEnv* env = AttachCurrentThread();
- uint64_t high = 0x1234567812345678;
- uint64_t low = 0x0583503029282304;
- base::UnguessableToken token = base::UnguessableToken::Deserialize(high, low);
- ScopedJavaLocalRef<jobject> jtoken =
- UnguessableTokenAndroid::Create(env, token);
- ScopedJavaLocalRef<jobject> jtoken_clone =
- UnguessableTokenAndroid::ParcelAndUnparcelForTesting(env, jtoken);
- base::UnguessableToken token_clone =
- UnguessableTokenAndroid::FromJavaUnguessableToken(env, jtoken_clone);
-
- EXPECT_EQ(token, token_clone);
-}
-
-} // namespace android
-} // namespace base
diff --git a/base/barrier_closure_unittest.cc b/base/barrier_closure_unittest.cc
deleted file mode 100644
index 819f6ac2c2..0000000000
--- a/base/barrier_closure_unittest.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2013 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/barrier_closure.h"
-
-#include "base/bind.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-void Increment(int* count) { (*count)++; }
-
-TEST(BarrierClosureTest, RunImmediatelyForZeroClosures) {
- int count = 0;
- base::Closure done_closure(base::Bind(&Increment, base::Unretained(&count)));
-
- base::Closure barrier_closure = base::BarrierClosure(0, done_closure);
- EXPECT_EQ(1, count);
-}
-
-TEST(BarrierClosureTest, RunAfterNumClosures) {
- int count = 0;
- base::Closure done_closure(base::Bind(&Increment, base::Unretained(&count)));
-
- base::Closure barrier_closure = base::BarrierClosure(2, done_closure);
- EXPECT_EQ(0, count);
-
- barrier_closure.Run();
- EXPECT_EQ(0, count);
-
- barrier_closure.Run();
- EXPECT_EQ(1, count);
-}
-
-class DestructionIndicator {
- public:
- // Sets |*destructed| to true in destructor.
- DestructionIndicator(bool* destructed) : destructed_(destructed) {
- *destructed_ = false;
- }
-
- ~DestructionIndicator() { *destructed_ = true; }
-
- void DoNothing() {}
-
- private:
- bool* destructed_;
-};
-
-TEST(BarrierClosureTest, ReleasesDoneClosureWhenDone) {
- bool done_destructed = false;
- base::Closure barrier_closure = base::BarrierClosure(
- 1,
- base::BindOnce(&DestructionIndicator::DoNothing,
- base::Owned(new DestructionIndicator(&done_destructed))));
- EXPECT_FALSE(done_destructed);
- barrier_closure.Run();
- EXPECT_TRUE(done_destructed);
-}
-
-void ResetBarrierClosure(base::Closure* closure) {
- *closure = base::Closure();
-}
-
-// Tests a case when |done_closure| resets a |barrier_closure|.
-// |barrier_closure| is a Closure holding the |done_closure|. |done_closure|
-// holds a pointer back to the |barrier_closure|. When |barrier_closure| is
-// Run() it calls ResetBarrierClosure() which erases the |barrier_closure| while
-// still inside of its Run(). The Run() implementation (in base::BarrierClosure)
-// must not try use itself after executing ResetBarrierClosure() or this test
-// would crash inside Run().
-TEST(BarrierClosureTest, KeepingClosureAliveUntilDone) {
- base::Closure barrier_closure;
- base::Closure done_closure =
- base::Bind(ResetBarrierClosure, &barrier_closure);
- barrier_closure = base::BarrierClosure(1, done_closure);
- barrier_closure.Run();
-}
-
-} // namespace
diff --git a/base/base_paths_android.cc b/base/base_paths_android.cc
deleted file mode 100644
index 078f565a5c..0000000000
--- a/base/base_paths_android.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 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.
-
-// Defines base::PathProviderAndroid which replaces base::PathProviderPosix for
-// Android in base/path_service.cc.
-
-#include <limits.h>
-#include <unistd.h>
-
-#include "base/android/jni_android.h"
-#include "base/android/path_utils.h"
-#include "base/base_paths.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/process/process_metrics.h"
-
-namespace base {
-
-bool PathProviderAndroid(int key, FilePath* result) {
- switch (key) {
- case base::FILE_EXE: {
- FilePath bin_dir;
- if (!ReadSymbolicLink(FilePath(kProcSelfExe), &bin_dir)) {
- NOTREACHED() << "Unable to resolve " << kProcSelfExe << ".";
- return false;
- }
- *result = bin_dir;
- return true;
- }
- case base::FILE_MODULE:
- // dladdr didn't work in Android as only the file name was returned.
- NOTIMPLEMENTED();
- return false;
- case base::DIR_MODULE:
- return base::android::GetNativeLibraryDirectory(result);
- case base::DIR_SOURCE_ROOT:
- // Used only by tests.
- // In that context, hooked up via base/test/test_support_android.cc.
- NOTIMPLEMENTED();
- return false;
- case base::DIR_USER_DESKTOP:
- // Android doesn't support GetUserDesktop.
- NOTIMPLEMENTED();
- return false;
- case base::DIR_CACHE:
- return base::android::GetCacheDirectory(result);
- case base::DIR_ASSETS:
- // On Android assets are normally loaded from the APK using
- // base::android::OpenApkAsset(). In tests, since the assets are no
- // packaged, DIR_ASSETS is overridden to point to the build directory.
- return false;
- case base::DIR_ANDROID_APP_DATA:
- return base::android::GetDataDirectory(result);
- case base::DIR_ANDROID_EXTERNAL_STORAGE:
- return base::android::GetExternalStorageDirectory(result);
- default:
- // Note: the path system expects this function to override the default
- // behavior. So no need to log an error if we don't support a given
- // path. The system will just use the default.
- return false;
- }
-}
-
-} // namespace base
diff --git a/base/base_paths_android.h b/base/base_paths_android.h
deleted file mode 100644
index 7a9ac4a674..0000000000
--- a/base/base_paths_android.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_BASE_PATHS_ANDROID_H_
-#define BASE_BASE_PATHS_ANDROID_H_
-
-// This file declares Android-specific path keys for the base module.
-// These can be used with the PathService to access various special
-// directories and files.
-
-namespace base {
-
-enum {
- PATH_ANDROID_START = 300,
-
- DIR_ANDROID_APP_DATA, // Directory where to put Android app's data.
- DIR_ANDROID_EXTERNAL_STORAGE, // Android external storage directory.
-
- PATH_ANDROID_END
-};
-
-} // namespace base
-
-#endif // BASE_BASE_PATHS_ANDROID_H_
diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc
deleted file mode 100644
index d549d2e8ae..0000000000
--- a/base/bind_unittest.nc
+++ /dev/null
@@ -1,322 +0,0 @@
-// Copyright (c) 2011 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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/test/bind_test_util.h"
-
-namespace base {
-
-// Do not put everything inside an anonymous namespace. If you do, many of the
-// helper function declarations will generate unused definition warnings.
-
-static const int kParentValue = 1;
-static const int kChildValue = 2;
-
-class NoRef {
- public:
- void VoidMethod0() {}
- void VoidConstMethod0() const {}
- int IntMethod0() { return 1; }
-};
-
-class HasRef : public NoRef, public base::RefCounted<HasRef> {
-};
-
-class Parent {
- public:
- void AddRef() const {}
- void Release() const {}
- virtual void VirtualSet() { value = kParentValue; }
- void NonVirtualSet() { value = kParentValue; }
- int value;
-};
-
-class Child : public Parent {
- public:
- virtual void VirtualSet() { value = kChildValue; }
- void NonVirtualSet() { value = kChildValue; }
-};
-
-class NoRefParent {
- public:
- virtual void VirtualSet() { value = kParentValue; }
- void NonVirtualSet() { value = kParentValue; }
- int value;
-};
-
-class NoRefChild : public NoRefParent {
- virtual void VirtualSet() { value = kChildValue; }
- void NonVirtualSet() { value = kChildValue; }
-};
-
-template <typename T>
-T PolymorphicIdentity(T t) {
- return t;
-}
-
-int UnwrapParentRef(Parent& p) {
- return p.value;
-}
-
-template <typename T>
-void VoidPolymorphic1(T t) {
-}
-
-void TakesMoveOnly(std::unique_ptr<int>) {
-}
-
-struct NonEmptyFunctor {
- int x;
- void operator()() const {}
-};
-
-// TODO(hans): Remove .* and update the static_assert expectations once we roll
-// past Clang r313315. https://crbug.com/765692.
-
-#if defined(NCTEST_METHOD_ON_CONST_OBJECT) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""]
-
-// Method bound to const-object.
-//
-// Only const methods should be allowed to work with const objects.
-void WontCompile() {
- HasRef has_ref;
- const HasRef* const_has_ref_ptr_ = &has_ref;
- Callback<void()> method_to_const_cb =
- Bind(&HasRef::VoidMethod0, const_has_ref_ptr_);
- method_to_const_cb.Run();
-}
-
-#elif defined(NCTEST_METHOD_BIND_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed \"Receivers may not be raw pointers\."]
-
-
-// Method bound to non-refcounted object.
-//
-// We require refcounts unless you have Unretained().
-void WontCompile() {
- NoRef no_ref;
- Callback<void()> no_ref_cb =
- Bind(&NoRef::VoidMethod0, &no_ref);
- no_ref_cb.Run();
-}
-
-#elif defined(NCTEST_CONST_METHOD_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: static_assert failed \"Receivers may not be raw pointers\."]
-
-// Const Method bound to non-refcounted object.
-//
-// We require refcounts unless you have Unretained().
-void WontCompile() {
- NoRef no_ref;
- Callback<void()> no_ref_const_cb =
- Bind(&NoRef::VoidConstMethod0, &no_ref);
- no_ref_const_cb.Run();
-}
-
-#elif defined(NCTEST_CONST_POINTER) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""]
-
-// Const argument used with non-const pointer parameter of same type.
-//
-// This is just a const-correctness check.
-void WontCompile() {
- const NoRef* const_no_ref_ptr;
- Callback<NoRef*()> pointer_same_cb =
- Bind(&PolymorphicIdentity<NoRef*>, const_no_ref_ptr);
- pointer_same_cb.Run();
-}
-
-#elif defined(NCTEST_CONST_POINTER_SUBTYPE) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""]
-
-// Const argument used with non-const pointer parameter of super type.
-//
-// This is just a const-correctness check.
-void WontCompile() {
- const NoRefChild* const_child_ptr;
- Callback<NoRefParent*()> pointer_super_cb =
- Bind(&PolymorphicIdentity<NoRefParent*>, const_child_ptr);
- pointer_super_cb.Run();
-}
-
-#elif defined(DISABLED_NCTEST_DISALLOW_NON_CONST_REF_PARAM) // [r"fatal error: no member named 'AddRef' in 'base::NoRef'"]
-// TODO(dcheng): I think there's a type safety promotion issue here where we can
-// pass a const ref to a non const-ref function, or vice versa accidentally. Or
-// we make a copy accidentally. Check.
-
-// Functions with reference parameters, unsupported.
-//
-// First, non-const reference parameters are disallowed by the Google
-// style guide. Second, since we are doing argument forwarding it becomes
-// very tricky to avoid copies, maintain const correctness, and not
-// accidentally have the function be modifying a temporary, or a copy.
-void WontCompile() {
- Parent p;
- Callback<int(Parent&)> ref_arg_cb = Bind(&UnwrapParentRef);
- ref_arg_cb.Run(p);
-}
-
-#elif defined(NCTEST_DISALLOW_BIND_TO_NON_CONST_REF_PARAM) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| of type \|Arg\| cannot be forwarded as \|Unwrapped\| to the bound functor, which declares it as \|Param\|\.\""]
-
-// Binding functions with reference parameters, unsupported.
-//
-// See comment in NCTEST_DISALLOW_NON_CONST_REF_PARAM
-void WontCompile() {
- Parent p;
- Callback<int()> ref_cb = Bind(&UnwrapParentRef, p);
- ref_cb.Run();
-}
-
-#elif defined(NCTEST_NO_IMPLICIT_ARRAY_PTR_CONVERSION) // [r"fatal error: static_assert failed .*\"First bound argument to a method cannot be an array\.\""]
-
-// A method should not be bindable with an array of objects.
-//
-// This is likely not wanted behavior. We specifically check for it though
-// because it is possible, depending on how you implement prebinding, to
-// implicitly convert an array type to a pointer type.
-void WontCompile() {
- HasRef p[10];
- Callback<void()> method_bound_to_array_cb =
- Bind(&HasRef::VoidMethod0, p);
- method_bound_to_array_cb.Run();
-}
-
-#elif defined(NCTEST_NO_RVALUE_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""]
-
-// Refcounted types should not be bound as a raw pointer.
-void WontCompile() {
- HasRef for_raw_ptr;
- int a;
- Callback<void()> ref_count_as_raw_ptr_a =
- Bind(&VoidPolymorphic1<int*>, &a);
- Callback<void()> ref_count_as_raw_ptr =
- Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr);
-}
-
-#elif defined(NCTEST_NO_LVALUE_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""]
-
-// Refcounted types should not be bound as a raw pointer.
-void WontCompile() {
- HasRef* for_raw_ptr = nullptr;
- Callback<void()> ref_count_as_raw_ptr =
- Bind(&VoidPolymorphic1<HasRef*>, for_raw_ptr);
-}
-
-#elif defined(NCTEST_NO_RVALUE_CONST_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""]
-
-// Refcounted types should not be bound as a raw pointer.
-void WontCompile() {
- const HasRef for_raw_ptr;
- Callback<void()> ref_count_as_raw_ptr =
- Bind(&VoidPolymorphic1<const HasRef*>, &for_raw_ptr);
-}
-
-#elif defined(NCTEST_NO_LVALUE_CONST_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed .*\"A parameter is a refcounted type and needs scoped_refptr\.\""]
-
-// Refcounted types should not be bound as a raw pointer.
-void WontCompile() {
- const HasRef* for_raw_ptr = nullptr;
- Callback<void()> ref_count_as_raw_ptr =
- Bind(&VoidPolymorphic1<const HasRef*>, for_raw_ptr);
-}
-
-#elif defined(NCTEST_WEAKPTR_BIND_MUST_RETURN_VOID) // [r"fatal error: static_assert failed .*\"weak_ptrs can only bind to methods without return values\""]
-
-// WeakPtrs cannot be bound to methods with return types.
-void WontCompile() {
- NoRef no_ref;
- WeakPtrFactory<NoRef> weak_factory(&no_ref);
- Callback<int()> weak_ptr_with_non_void_return_type =
- Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr());
- weak_ptr_with_non_void_return_type.Run();
-}
-
-#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES) // [r"fatal error: no viable conversion from 'Callback<MakeUnboundRunType<void \(\*\)\(int\)>>' to 'Callback<void \(\)>'"]
-
-// Bind result cannot be assigned to Callbacks with a mismatching type.
-void WontCompile() {
- Closure callback_mismatches_bind_type = Bind(&VoidPolymorphic1<int>);
-}
-
-#elif defined(NCTEST_DISALLOW_CAPTURING_LAMBDA) // [r"fatal error: implicit instantiation of undefined template 'base::internal::FunctorTraits<\(lambda at (\.\./)+base/bind_unittest.nc:[0-9]+:[0-9]+\), void>'"]
-
-void WontCompile() {
- int i = 0, j = 0;
- Bind([i,&j]() {j = i;});
-}
-
-#elif defined(NCTEST_DISALLOW_ONCECALLBACK_RUN_ON_LVALUE) // [r"static_assert failed .*\"OnceCallback::Run\(\) may only be invoked on a non-const rvalue, i\.e\. std::move\(callback\)\.Run\(\)\.\""]
-
-void WontCompile() {
- OnceClosure cb = Bind([] {});
- cb.Run();
-}
-
-#elif defined(NCTEST_DISALLOW_ONCECALLBACK_RUN_ON_CONST_LVALUE) // [r"static_assert failed .*\"OnceCallback::Run\(\) may only be invoked on a non-const rvalue, i\.e\. std::move\(callback\)\.Run\(\)\.\""]
-
-void WontCompile() {
- const OnceClosure cb = Bind([] {});
- cb.Run();
-}
-
-#elif defined(NCTEST_DISALLOW_ONCECALLBACK_RUN_ON_CONST_RVALUE) // [r"static_assert failed .*\"OnceCallback::Run\(\) may only be invoked on a non-const rvalue, i\.e\. std::move\(callback\)\.Run\(\)\.\""]
-
-void WontCompile() {
- const OnceClosure cb = Bind([] {});
- std::move(cb).Run();
-}
-
-#elif defined(NCTEST_DISALLOW_BIND_ONCECALLBACK) // [r"fatal error: static_assert failed .*\"BindRepeating cannot bind OnceCallback. Use BindOnce with std::move\(\)\.\""]
-
-void WontCompile() {
- Bind(BindOnce([](int) {}), 42);
-}
-
-#elif defined(NCTEST_DISALLOW_BINDONCE_LVALUE_ONCECALLBACK) // [r"fatal error: static_assert failed .*\"BindOnce requires non-const rvalue for OnceCallback binding\."]
-void WontCompile() {
- auto cb = BindOnce([](int) {});
- BindOnce(cb, 42);
-}
-
-#elif defined(NCTEST_DISALLOW_BINDONCE_RVALUE_CONST_ONCECALLBACK) // [r"fatal error: static_assert failed .*\"BindOnce requires non-const rvalue for OnceCallback binding\."]
-
-void WontCompile() {
- const auto cb = BindOnce([](int) {});
- BindOnce(std::move(cb), 42);
-}
-
-#elif defined(NCTEST_BINDONCE_MOVEONLY_TYPE_BY_VALUE) // [r"fatal error: static_assert failed .*\"Bound argument \|i\| is move-only but will be bound by copy\. Ensure \|Arg\| is mutable and bound using std::move\(\)\.\""]
-
-void WontCompile() {
- std::unique_ptr<int> x;
- BindOnce(&TakesMoveOnly, x);
-}
-
-#elif defined(NCTEST_BIND_MOVEONLY_TYPE_BY_VALUE) // [r"Bound argument \|i\| is move-only but will be forwarded by copy\. Ensure \|Arg\| is bound using base::Passed\(\), not std::move\(\)."]
-
-void WontCompile() {
- std::unique_ptr<int> x;
- Bind(&TakesMoveOnly, x);
-}
-
-#elif defined(NCTEST_BIND_MOVEONLY_TYPE_WITH_STDMOVE) // [r"Bound argument \|i\| is move-only but will be forwarded by copy\. Ensure \|Arg\| is bound using base::Passed\(\), not std::move\(\)."]
-
-void WontCompile() {
- std::unique_ptr<int> x;
- Bind(&TakesMoveOnly, std::move(x));
-}
-
-#elif defined(NCTEST_BIND_NON_EMPTY_FUNCTOR) // [r"fatal error: implicit instantiation of undefined template 'base::internal::FunctorTraits<base::NonEmptyFunctor, void>'"]
-
-void WontCompile() {
- Bind(NonEmptyFunctor());
-}
-
-#endif
-
-} // namespace base
diff --git a/base/bit_cast_unittest.cc b/base/bit_cast_unittest.cc
deleted file mode 100644
index f36d3fe64c..0000000000
--- a/base/bit_cast_unittest.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2016 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/bit_cast.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-TEST(BitCastTest, FloatIntFloat) {
- float f = 3.1415926f;
- int i = bit_cast<int32_t>(f);
- float f2 = bit_cast<float>(i);
- EXPECT_EQ(f, f2);
-}
-
-struct A {
- int x;
-};
-
-TEST(BitCastTest, StructureInt) {
- A a = { 1 };
- int b = bit_cast<int>(a);
- EXPECT_EQ(1, b);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/build_time.cc b/base/build_time.cc
index 15782e368d..866840d49f 100644
--- a/base/build_time.cc
+++ b/base/build_time.cc
@@ -7,7 +7,7 @@
#include "base/logging.h"
#include "base/time/time.h"
-#if defined(OS_ANDROID)
+#ifdef __ANDROID__
#include <cutils/properties.h>
#endif
@@ -20,7 +20,7 @@ Time GetBuildTime() {
//
// __DATE__ is exactly "Mmm DD YYYY".
// __TIME__ is exactly "hh:mm:ss".
-#if defined(OS_ANDROID)
+#if defined(__ANDROID__)
char kDateTime[PROPERTY_VALUE_MAX];
property_get("ro.build.date", kDateTime, "Sep 02 2008 08:00:00 PST");
#elif defined(DONT_EMBED_BUILD_METADATA) && !defined(OFFICIAL_BUILD)
diff --git a/base/callback_list_unittest.nc b/base/callback_list_unittest.nc
deleted file mode 100644
index 7347f765dc..0000000000
--- a/base/callback_list_unittest.nc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2013 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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/callback_list.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-
-namespace base {
-
-class Foo {
- public:
- Foo() {}
- ~Foo() {}
-};
-
-class FooListener {
- public:
- FooListener() {}
-
- void GotAScopedFoo(std::unique_ptr<Foo> f) { foo_ = std::move(f); }
-
- std::unique_ptr<Foo> foo_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FooListener);
-};
-
-
-#if defined(NCTEST_MOVE_ONLY_TYPE_PARAMETER) // [r"fatal error: call to (implicitly-)?deleted( copy)? constructor"]
-
-// Callbacks run with a move-only typed parameter.
-//
-// CallbackList does not support move-only typed parameters. Notify() is
-// designed to take zero or more parameters, and run each registered callback
-// with them. With move-only types, the parameter will be set to NULL after the
-// first callback has been run.
-void WontCompile() {
- FooListener f;
- CallbackList<void(std::unique_ptr<Foo>)> c1;
- std::unique_ptr<CallbackList<void(std::unique_ptr<Foo>)>::Subscription> sub =
- c1.Add(Bind(&FooListener::GotAScopedFoo, Unretained(&f)));
- c1.Notify(std::unique_ptr<Foo>(new Foo()));
-}
-
-#endif
-
-} // namespace base
diff --git a/base/callback_unittest.nc b/base/callback_unittest.nc
deleted file mode 100644
index 3261529341..0000000000
--- a/base/callback_unittest.nc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2011 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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/callback.h"
-
-namespace base {
-
-class Parent {
-};
-
-class Child : Parent {
-};
-
-#if defined(NCTEST_EQUALS_REQUIRES_SAMETYPE) // [r"fatal error: no viable conversion from 'RepeatingCallback<int \(\)>' to 'const RepeatingCallback<void \(\)>'"]
-
-// Attempting to call comparison function on two callbacks of different type.
-//
-// This should be a compile time failure because each callback type should be
-// considered distinct.
-void WontCompile() {
- Closure c1;
- Callback<int()> c2;
- c1.Equals(c2);
-}
-
-#elif defined(NCTEST_CONSTRUCTION_FROM_SUBTYPE) // [r"fatal error: no viable conversion from 'Callback<base::Parent \(\)>' to 'Callback<base::Child \(\)>'"]
-
-// Construction of Callback<A> from Callback<B> if A is supertype of B.
-//
-// While this is technically safe, most people aren't used to it when coding
-// C++ so if this is happening, it is almost certainly an error.
-void WontCompile() {
- Callback<Parent()> cb_a;
- Callback<Child()> cb_b = cb_a;
-}
-
-#elif defined(NCTEST_ASSIGNMENT_FROM_SUBTYPE) // [r"fatal error: no viable overloaded '='"]
-
-// Assignment of Callback<A> from Callback<B> if A is supertype of B.
-// See explanation for NCTEST_CONSTRUCTION_FROM_SUBTYPE
-void WontCompile() {
- Callback<Parent()> cb_a;
- Callback<Child()> cb_b;
- cb_a = cb_b;
-}
-
-#endif
-
-} // namespace base
diff --git a/base/check_example.cc b/base/check_example.cc
deleted file mode 100644
index 7b9d8e6a80..0000000000
--- a/base/check_example.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2011 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.
-
-// This file is meant for analyzing the code generated by the CHECK
-// macros in a small executable file that's easy to disassemble.
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-
-// An official build shouldn't generate code to print out messages for
-// the CHECK* macros, nor should it have the strings in the
-// executable. It is also important that the CHECK() function collapse to the
-// same implementation as RELEASE_ASSERT(), in particular on Windows x86.
-// Historically, the stream eating caused additional unnecessary instructions.
-// See https://crbug.com/672699.
-
-#define BLINK_RELEASE_ASSERT_EQUIVALENT(assertion) \
- (UNLIKELY(!(assertion)) ? (IMMEDIATE_CRASH()) : (void)0)
-
-void DoCheck(bool b) {
- CHECK(b) << "DoCheck " << b;
-}
-
-void DoBlinkReleaseAssert(bool b) {
- BLINK_RELEASE_ASSERT_EQUIVALENT(b);
-}
-
-void DoCheckEq(int x, int y) {
- CHECK_EQ(x, y);
-}
-
-int main(int argc, const char* argv[]) {
- DoCheck(argc > 1);
- DoCheckEq(argc, 1);
- DoBlinkReleaseAssert(argc > 1);
-}
diff --git a/base/containers/adapters_unittest.cc b/base/containers/adapters_unittest.cc
deleted file mode 100644
index 92554b7e1e..0000000000
--- a/base/containers/adapters_unittest.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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/containers/adapters.h"
-
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-TEST(AdaptersTest, Reversed) {
- std::vector<int> v;
- v.push_back(3);
- v.push_back(2);
- v.push_back(1);
- int j = 0;
- for (int& i : base::Reversed(v)) {
- EXPECT_EQ(++j, i);
- i += 100;
- }
- EXPECT_EQ(103, v[0]);
- EXPECT_EQ(102, v[1]);
- EXPECT_EQ(101, v[2]);
-}
-
-TEST(AdaptersTest, ReversedArray) {
- int v[3] = {3, 2, 1};
- int j = 0;
- for (int& i : base::Reversed(v)) {
- EXPECT_EQ(++j, i);
- i += 100;
- }
- EXPECT_EQ(103, v[0]);
- EXPECT_EQ(102, v[1]);
- EXPECT_EQ(101, v[2]);
-}
-
-TEST(AdaptersTest, ReversedConst) {
- std::vector<int> v;
- v.push_back(3);
- v.push_back(2);
- v.push_back(1);
- const std::vector<int>& cv = v;
- int j = 0;
- for (int i : base::Reversed(cv)) {
- EXPECT_EQ(++j, i);
- }
-}
-
-} // namespace
diff --git a/base/containers/flat_map_unittest.cc b/base/containers/flat_map_unittest.cc
deleted file mode 100644
index 87958bde41..0000000000
--- a/base/containers/flat_map_unittest.cc
+++ /dev/null
@@ -1,369 +0,0 @@
-// Copyright 2017 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/containers/flat_map.h"
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/test/move_only_int.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// A flat_map is basically a interface to flat_tree. So several basic
-// operations are tested to make sure things are set up properly, but the bulk
-// of the tests are in flat_tree_unittests.cc.
-
-using ::testing::ElementsAre;
-
-namespace base {
-
-TEST(FlatMap, IncompleteType) {
- struct A {
- using Map = flat_map<A, A>;
- int data;
- Map set_with_incomplete_type;
- Map::iterator it;
- Map::const_iterator cit;
-
- // We do not declare operator< because clang complains that it's unused.
- };
-
- A a;
-}
-
-TEST(FlatMap, RangeConstructor) {
- flat_map<int, int>::value_type input_vals[] = {
- {1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2}, {2, 3}, {3, 1}, {3, 2}, {3, 3}};
-
- flat_map<int, int> first(std::begin(input_vals), std::end(input_vals));
- EXPECT_THAT(first, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 1),
- std::make_pair(3, 1)));
-
- flat_map<int, int> last(std::begin(input_vals), std::end(input_vals),
- KEEP_LAST_OF_DUPES);
- EXPECT_THAT(last, ElementsAre(std::make_pair(1, 3), std::make_pair(2, 3),
- std::make_pair(3, 3)));
-}
-
-TEST(FlatMap, MoveConstructor) {
- using pair = std::pair<MoveOnlyInt, MoveOnlyInt>;
-
- flat_map<MoveOnlyInt, MoveOnlyInt> original;
- original.insert(pair(MoveOnlyInt(1), MoveOnlyInt(1)));
- original.insert(pair(MoveOnlyInt(2), MoveOnlyInt(2)));
- original.insert(pair(MoveOnlyInt(3), MoveOnlyInt(3)));
- original.insert(pair(MoveOnlyInt(4), MoveOnlyInt(4)));
-
- flat_map<MoveOnlyInt, MoveOnlyInt> moved(std::move(original));
-
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(1)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(2)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(3)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(4)));
-}
-
-TEST(FlatMap, VectorConstructor) {
- using IntPair = std::pair<int, int>;
- using IntMap = flat_map<int, int>;
- {
- std::vector<IntPair> vect{{1, 1}, {1, 2}, {2, 1}};
- IntMap map(std::move(vect));
- EXPECT_THAT(map, ElementsAre(IntPair(1, 1), IntPair(2, 1)));
- }
- {
- std::vector<IntPair> vect{{1, 1}, {1, 2}, {2, 1}};
- IntMap map(std::move(vect), KEEP_LAST_OF_DUPES);
- EXPECT_THAT(map, ElementsAre(IntPair(1, 2), IntPair(2, 1)));
- }
-}
-
-TEST(FlatMap, InitializerListConstructor) {
- {
- flat_map<int, int> cont(
- {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {1, 2}, {10, 10}, {8, 8}});
- EXPECT_THAT(cont, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2),
- std::make_pair(3, 3), std::make_pair(4, 4),
- std::make_pair(5, 5), std::make_pair(8, 8),
- std::make_pair(10, 10)));
- }
- {
- flat_map<int, int> cont(
- {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {1, 2}, {10, 10}, {8, 8}},
- KEEP_LAST_OF_DUPES);
- EXPECT_THAT(cont, ElementsAre(std::make_pair(1, 2), std::make_pair(2, 2),
- std::make_pair(3, 3), std::make_pair(4, 4),
- std::make_pair(5, 5), std::make_pair(8, 8),
- std::make_pair(10, 10)));
- }
-}
-
-TEST(FlatMap, InitializerListAssignment) {
- flat_map<int, int> cont;
- cont = {{1, 1}, {2, 2}};
- EXPECT_THAT(cont, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
-}
-
-TEST(FlatMap, InsertFindSize) {
- base::flat_map<int, int> s;
- s.insert(std::make_pair(1, 1));
- s.insert(std::make_pair(1, 1));
- s.insert(std::make_pair(2, 2));
-
- EXPECT_EQ(2u, s.size());
- EXPECT_EQ(std::make_pair(1, 1), *s.find(1));
- EXPECT_EQ(std::make_pair(2, 2), *s.find(2));
- EXPECT_EQ(s.end(), s.find(7));
-}
-
-TEST(FlatMap, CopySwap) {
- base::flat_map<int, int> original;
- original.insert({1, 1});
- original.insert({2, 2});
- EXPECT_THAT(original,
- ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
-
- base::flat_map<int, int> copy(original);
- EXPECT_THAT(copy, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
-
- copy.erase(copy.begin());
- copy.insert({10, 10});
- EXPECT_THAT(copy, ElementsAre(std::make_pair(2, 2), std::make_pair(10, 10)));
-
- original.swap(copy);
- EXPECT_THAT(original,
- ElementsAre(std::make_pair(2, 2), std::make_pair(10, 10)));
- EXPECT_THAT(copy, ElementsAre(std::make_pair(1, 1), std::make_pair(2, 2)));
-}
-
-// operator[](const Key&)
-TEST(FlatMap, SubscriptConstKey) {
- base::flat_map<std::string, int> m;
-
- // Default construct elements that don't exist yet.
- int& s = m["a"];
- EXPECT_EQ(0, s);
- EXPECT_EQ(1u, m.size());
-
- // The returned mapped reference should refer into the map.
- s = 22;
- EXPECT_EQ(22, m["a"]);
-
- // Overwrite existing elements.
- m["a"] = 44;
- EXPECT_EQ(44, m["a"]);
-}
-
-// operator[](Key&&)
-TEST(FlatMap, SubscriptMoveOnlyKey) {
- base::flat_map<MoveOnlyInt, int> m;
-
- // Default construct elements that don't exist yet.
- int& s = m[MoveOnlyInt(1)];
- EXPECT_EQ(0, s);
- EXPECT_EQ(1u, m.size());
-
- // The returned mapped reference should refer into the map.
- s = 22;
- EXPECT_EQ(22, m[MoveOnlyInt(1)]);
-
- // Overwrite existing elements.
- m[MoveOnlyInt(1)] = 44;
- EXPECT_EQ(44, m[MoveOnlyInt(1)]);
-}
-
-// insert_or_assign(K&&, M&&)
-TEST(FlatMap, InsertOrAssignMoveOnlyKey) {
- base::flat_map<MoveOnlyInt, MoveOnlyInt> m;
-
- // Initial insertion should return an iterator to the element and set the
- // second pair member to |true|. The inserted key and value should be moved
- // from.
- MoveOnlyInt key(1);
- MoveOnlyInt val(22);
- auto result = m.insert_or_assign(std::move(key), std::move(val));
- EXPECT_EQ(1, result.first->first.data());
- EXPECT_EQ(22, result.first->second.data());
- EXPECT_TRUE(result.second);
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(0, key.data()); // moved from
- EXPECT_EQ(0, val.data()); // moved from
-
- // Second call with same key should result in an assignment, overwriting the
- // old value. Assignment should be indicated by setting the second pair member
- // to |false|. Only the inserted value should be moved from, the key should be
- // left intact.
- key = MoveOnlyInt(1);
- val = MoveOnlyInt(44);
- result = m.insert_or_assign(std::move(key), std::move(val));
- EXPECT_EQ(1, result.first->first.data());
- EXPECT_EQ(44, result.first->second.data());
- EXPECT_FALSE(result.second);
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(1, key.data()); // not moved from
- EXPECT_EQ(0, val.data()); // moved from
-
- // Check that random insertion results in sorted range.
- base::flat_map<MoveOnlyInt, int> map;
- for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
- map.insert_or_assign(MoveOnlyInt(i), i);
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
- }
-}
-
-// insert_or_assign(const_iterator hint, K&&, M&&)
-TEST(FlatMap, InsertOrAssignMoveOnlyKeyWithHint) {
- base::flat_map<MoveOnlyInt, MoveOnlyInt> m;
-
- // Initial insertion should return an iterator to the element. The inserted
- // key and value should be moved from.
- MoveOnlyInt key(1);
- MoveOnlyInt val(22);
- auto result = m.insert_or_assign(m.end(), std::move(key), std::move(val));
- EXPECT_EQ(1, result->first.data());
- EXPECT_EQ(22, result->second.data());
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(0, key.data()); // moved from
- EXPECT_EQ(0, val.data()); // moved from
-
- // Second call with same key should result in an assignment, overwriting the
- // old value. Only the inserted value should be moved from, the key should be
- // left intact.
- key = MoveOnlyInt(1);
- val = MoveOnlyInt(44);
- result = m.insert_or_assign(m.end(), std::move(key), std::move(val));
- EXPECT_EQ(1, result->first.data());
- EXPECT_EQ(44, result->second.data());
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(1, key.data()); // not moved from
- EXPECT_EQ(0, val.data()); // moved from
-
- // Check that random insertion results in sorted range.
- base::flat_map<MoveOnlyInt, int> map;
- for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
- map.insert_or_assign(map.end(), MoveOnlyInt(i), i);
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
- }
-}
-
-// try_emplace(K&&, Args&&...)
-TEST(FlatMap, TryEmplaceMoveOnlyKey) {
- base::flat_map<MoveOnlyInt, std::pair<MoveOnlyInt, MoveOnlyInt>> m;
-
- // Trying to emplace into an empty map should succeed. Insertion should return
- // an iterator to the element and set the second pair member to |true|. The
- // inserted key and value should be moved from.
- MoveOnlyInt key(1);
- MoveOnlyInt val1(22);
- MoveOnlyInt val2(44);
- // Test piecewise construction of mapped_type.
- auto result = m.try_emplace(std::move(key), std::move(val1), std::move(val2));
- EXPECT_EQ(1, result.first->first.data());
- EXPECT_EQ(22, result.first->second.first.data());
- EXPECT_EQ(44, result.first->second.second.data());
- EXPECT_TRUE(result.second);
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(0, key.data()); // moved from
- EXPECT_EQ(0, val1.data()); // moved from
- EXPECT_EQ(0, val2.data()); // moved from
-
- // Second call with same key should result in a no-op, returning an iterator
- // to the existing element and returning false as the second pair member.
- // Key and values that were attempted to be inserted should be left intact.
- key = MoveOnlyInt(1);
- auto paired_val = std::make_pair(MoveOnlyInt(33), MoveOnlyInt(55));
- // Test construction of mapped_type from pair.
- result = m.try_emplace(std::move(key), std::move(paired_val));
- EXPECT_EQ(1, result.first->first.data());
- EXPECT_EQ(22, result.first->second.first.data());
- EXPECT_EQ(44, result.first->second.second.data());
- EXPECT_FALSE(result.second);
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(1, key.data()); // not moved from
- EXPECT_EQ(33, paired_val.first.data()); // not moved from
- EXPECT_EQ(55, paired_val.second.data()); // not moved from
-
- // Check that random insertion results in sorted range.
- base::flat_map<MoveOnlyInt, int> map;
- for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
- map.try_emplace(MoveOnlyInt(i), i);
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
- }
-}
-
-// try_emplace(const_iterator hint, K&&, Args&&...)
-TEST(FlatMap, TryEmplaceMoveOnlyKeyWithHint) {
- base::flat_map<MoveOnlyInt, std::pair<MoveOnlyInt, MoveOnlyInt>> m;
-
- // Trying to emplace into an empty map should succeed. Insertion should return
- // an iterator to the element. The inserted key and value should be moved
- // from.
- MoveOnlyInt key(1);
- MoveOnlyInt val1(22);
- MoveOnlyInt val2(44);
- // Test piecewise construction of mapped_type.
- auto result =
- m.try_emplace(m.end(), std::move(key), std::move(val1), std::move(val2));
- EXPECT_EQ(1, result->first.data());
- EXPECT_EQ(22, result->second.first.data());
- EXPECT_EQ(44, result->second.second.data());
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(0, key.data()); // moved from
- EXPECT_EQ(0, val1.data()); // moved from
- EXPECT_EQ(0, val2.data()); // moved from
-
- // Second call with same key should result in a no-op, returning an iterator
- // to the existing element. Key and values that were attempted to be inserted
- // should be left intact.
- key = MoveOnlyInt(1);
- val1 = MoveOnlyInt(33);
- val2 = MoveOnlyInt(55);
- auto paired_val = std::make_pair(MoveOnlyInt(33), MoveOnlyInt(55));
- // Test construction of mapped_type from pair.
- result = m.try_emplace(m.end(), std::move(key), std::move(paired_val));
- EXPECT_EQ(1, result->first.data());
- EXPECT_EQ(22, result->second.first.data());
- EXPECT_EQ(44, result->second.second.data());
- EXPECT_EQ(1u, m.size());
- EXPECT_EQ(1, key.data()); // not moved from
- EXPECT_EQ(33, paired_val.first.data()); // not moved from
- EXPECT_EQ(55, paired_val.second.data()); // not moved from
-
- // Check that random insertion results in sorted range.
- base::flat_map<MoveOnlyInt, int> map;
- for (int i : {3, 1, 5, 6, 8, 7, 0, 9, 4, 2}) {
- map.try_emplace(map.end(), MoveOnlyInt(i), i);
- EXPECT_TRUE(std::is_sorted(map.begin(), map.end()));
- }
-}
-
-TEST(FlatMap, UsingTransparentCompare) {
- using ExplicitInt = base::MoveOnlyInt;
- base::flat_map<ExplicitInt, int> m;
- const auto& m1 = m;
- int x = 0;
-
- // Check if we can use lookup functions without converting to key_type.
- // Correctness is checked in flat_tree tests.
- m.count(x);
- m1.count(x);
- m.find(x);
- m1.find(x);
- m.equal_range(x);
- m1.equal_range(x);
- m.lower_bound(x);
- m1.lower_bound(x);
- m.upper_bound(x);
- m1.upper_bound(x);
- m.erase(x);
-
- // Check if we broke overload resolution.
- m.emplace(ExplicitInt(0), 0);
- m.emplace(ExplicitInt(1), 0);
- m.erase(m.begin());
- m.erase(m.cbegin());
-}
-
-} // namespace base
diff --git a/base/containers/flat_set_unittest.cc b/base/containers/flat_set_unittest.cc
deleted file mode 100644
index 4596975498..0000000000
--- a/base/containers/flat_set_unittest.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2017 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/containers/flat_set.h"
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/test/move_only_int.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// A flat_set is basically a interface to flat_tree. So several basic
-// operations are tested to make sure things are set up properly, but the bulk
-// of the tests are in flat_tree_unittests.cc.
-
-using ::testing::ElementsAre;
-
-namespace base {
-
-TEST(FlatSet, IncompleteType) {
- struct A {
- using Set = flat_set<A>;
- int data;
- Set set_with_incomplete_type;
- Set::iterator it;
- Set::const_iterator cit;
-
- // We do not declare operator< because clang complains that it's unused.
- };
-
- A a;
-}
-
-TEST(FlatSet, RangeConstructor) {
- flat_set<int>::value_type input_vals[] = {1, 1, 1, 2, 2, 2, 3, 3, 3};
-
- flat_set<int> cont(std::begin(input_vals), std::end(input_vals),
- base::KEEP_FIRST_OF_DUPES);
- EXPECT_THAT(cont, ElementsAre(1, 2, 3));
-}
-
-TEST(FlatSet, MoveConstructor) {
- int input_range[] = {1, 2, 3, 4};
-
- flat_set<MoveOnlyInt> original(std::begin(input_range), std::end(input_range),
- base::KEEP_FIRST_OF_DUPES);
- flat_set<MoveOnlyInt> moved(std::move(original));
-
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(1)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(2)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(3)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(4)));
-}
-
-TEST(FlatSet, InitializerListConstructor) {
- flat_set<int> cont({1, 2, 3, 4, 5, 6, 10, 8}, KEEP_FIRST_OF_DUPES);
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10));
-}
-
-TEST(FlatSet, InsertFindSize) {
- base::flat_set<int> s;
- s.insert(1);
- s.insert(1);
- s.insert(2);
-
- EXPECT_EQ(2u, s.size());
- EXPECT_EQ(1, *s.find(1));
- EXPECT_EQ(2, *s.find(2));
- EXPECT_EQ(s.end(), s.find(7));
-}
-
-TEST(FlatSet, CopySwap) {
- base::flat_set<int> original;
- original.insert(1);
- original.insert(2);
- EXPECT_THAT(original, ElementsAre(1, 2));
-
- base::flat_set<int> copy(original);
- EXPECT_THAT(copy, ElementsAre(1, 2));
-
- copy.erase(copy.begin());
- copy.insert(10);
- EXPECT_THAT(copy, ElementsAre(2, 10));
-
- original.swap(copy);
- EXPECT_THAT(original, ElementsAre(2, 10));
- EXPECT_THAT(copy, ElementsAre(1, 2));
-}
-
-TEST(FlatSet, UsingTransparentCompare) {
- using ExplicitInt = base::MoveOnlyInt;
- base::flat_set<ExplicitInt> s;
- const auto& s1 = s;
- int x = 0;
-
- // Check if we can use lookup functions without converting to key_type.
- // Correctness is checked in flat_tree tests.
- s.count(x);
- s1.count(x);
- s.find(x);
- s1.find(x);
- s.equal_range(x);
- s1.equal_range(x);
- s.lower_bound(x);
- s1.lower_bound(x);
- s.upper_bound(x);
- s1.upper_bound(x);
- s.erase(x);
-
- // Check if we broke overload resolution.
- s.emplace(0);
- s.emplace(1);
- s.erase(s.begin());
- s.erase(s.cbegin());
-}
-
-} // namespace base
diff --git a/base/containers/flat_tree_unittest.cc b/base/containers/flat_tree_unittest.cc
deleted file mode 100644
index 5b788d506b..0000000000
--- a/base/containers/flat_tree_unittest.cc
+++ /dev/null
@@ -1,1385 +0,0 @@
-// Copyright 2017 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/containers/flat_tree.h"
-
-// Following tests are ported and extended tests from libcpp for std::set.
-// They can be found here:
-// https://github.com/llvm-mirror/libcxx/tree/master/test/std/containers/associative/set
-//
-// Not ported tests:
-// * No tests with PrivateConstructor and std::less<> changed to std::less<T>
-// These tests have to do with C++14 std::less<>
-// http://en.cppreference.com/w/cpp/utility/functional/less_void
-// and add support for templated versions of lookup functions.
-// Because we use same implementation, we figured that it's OK just to check
-// compilation and this is what we do in flat_set_unittest/flat_map_unittest.
-// * No tests for max_size()
-// Has to do with allocator support.
-// * No tests with DefaultOnly.
-// Standard containers allocate each element in the separate node on the heap
-// and then manipulate these nodes. Flat containers store their elements in
-// contiguous memory and move them around, type is required to be movable.
-// * No tests for N3644.
-// This proposal suggests that all default constructed iterators compare
-// equal. Currently we use std::vector iterators and they don't implement
-// this.
-// * No tests with min_allocator and no tests counting allocations.
-// Flat sets currently don't support allocators.
-
-#include <forward_list>
-#include <functional>
-#include <iterator>
-#include <list>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/template_util.h"
-#include "base/test/move_only_int.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-template <class It>
-class InputIterator {
- public:
- using iterator_category = std::input_iterator_tag;
- using value_type = typename std::iterator_traits<It>::value_type;
- using difference_type = typename std::iterator_traits<It>::difference_type;
- using pointer = It;
- using reference = typename std::iterator_traits<It>::reference;
-
- InputIterator() : it_() {}
- explicit InputIterator(It it) : it_(it) {}
-
- reference operator*() const { return *it_; }
- pointer operator->() const { return it_; }
-
- InputIterator& operator++() {
- ++it_;
- return *this;
- }
- InputIterator operator++(int) {
- InputIterator tmp(*this);
- ++(*this);
- return tmp;
- }
-
- friend bool operator==(const InputIterator& lhs, const InputIterator& rhs) {
- return lhs.it_ == rhs.it_;
- }
- friend bool operator!=(const InputIterator& lhs, const InputIterator& rhs) {
- return !(lhs == rhs);
- }
-
- private:
- It it_;
-};
-
-template <typename It>
-InputIterator<It> MakeInputIterator(It it) {
- return InputIterator<It>(it);
-}
-
-class Emplaceable {
- public:
- Emplaceable() : Emplaceable(0, 0.0) {}
- Emplaceable(int i, double d) : int_(i), double_(d) {}
- Emplaceable(Emplaceable&& other) : int_(other.int_), double_(other.double_) {
- other.int_ = 0;
- other.double_ = 0.0;
- }
-
- Emplaceable& operator=(Emplaceable&& other) {
- int_ = other.int_;
- other.int_ = 0;
- double_ = other.double_;
- other.double_ = 0.0;
- return *this;
- }
-
- friend bool operator==(const Emplaceable& lhs, const Emplaceable& rhs) {
- return std::tie(lhs.int_, lhs.double_) == std::tie(rhs.int_, rhs.double_);
- }
-
- friend bool operator<(const Emplaceable& lhs, const Emplaceable& rhs) {
- return std::tie(lhs.int_, lhs.double_) < std::tie(rhs.int_, rhs.double_);
- }
-
- private:
- int int_;
- double double_;
-
- DISALLOW_COPY_AND_ASSIGN(Emplaceable);
-};
-
-struct TemplateConstructor {
- template <typename T>
- TemplateConstructor(const T&) {}
-
- friend bool operator<(const TemplateConstructor&,
- const TemplateConstructor&) {
- return false;
- }
-};
-
-class NonDefaultConstructibleCompare {
- public:
- explicit NonDefaultConstructibleCompare(int) {}
-
- template <typename T>
- bool operator()(const T& lhs, const T& rhs) const {
- return std::less<T>()(lhs, rhs);
- }
-};
-
-template <class PairType>
-struct LessByFirst {
- bool operator()(const PairType& lhs, const PairType& rhs) const {
- return lhs.first < rhs.first;
- }
-};
-
-// Common test trees.
-using IntTree =
- flat_tree<int, int, GetKeyFromValueIdentity<int>, std::less<int>>;
-using IntPair = std::pair<int, int>;
-using IntPairTree = flat_tree<IntPair,
- IntPair,
- GetKeyFromValueIdentity<IntPair>,
- LessByFirst<IntPair>>;
-using MoveOnlyTree = flat_tree<MoveOnlyInt,
- MoveOnlyInt,
- GetKeyFromValueIdentity<MoveOnlyInt>,
- std::less<MoveOnlyInt>>;
-using EmplaceableTree = flat_tree<Emplaceable,
- Emplaceable,
- GetKeyFromValueIdentity<Emplaceable>,
- std::less<Emplaceable>>;
-using ReversedTree =
- flat_tree<int, int, GetKeyFromValueIdentity<int>, std::greater<int>>;
-
-using TreeWithStrangeCompare = flat_tree<int,
- int,
- GetKeyFromValueIdentity<int>,
- NonDefaultConstructibleCompare>;
-
-using ::testing::ElementsAre;
-
-} // namespace
-
-TEST(FlatTree, IsMultipass) {
- static_assert(!is_multipass<std::istream_iterator<int>>(),
- "InputIterator is not multipass");
- static_assert(!is_multipass<std::ostream_iterator<int>>(),
- "OutputIterator is not multipass");
-
- static_assert(is_multipass<std::forward_list<int>::iterator>(),
- "ForwardIterator is multipass");
- static_assert(is_multipass<std::list<int>::iterator>(),
- "BidirectionalIterator is multipass");
- static_assert(is_multipass<std::vector<int>::iterator>(),
- "RandomAccessIterator is multipass");
-}
-
-TEST(FlatTree, LastUnique) {
- using Pair = std::pair<int, int>;
- using Vect = std::vector<Pair>;
-
- auto cmp = [](const Pair& lhs, const Pair& rhs) {
- return lhs.first == rhs.first;
- };
-
- // Empty case.
- Vect empty;
- EXPECT_EQ(empty.end(), LastUnique(empty.begin(), empty.end(), cmp));
-
- // Single element.
- Vect one;
- one.push_back(Pair(1, 1));
- EXPECT_EQ(one.end(), LastUnique(one.begin(), one.end(), cmp));
- ASSERT_EQ(1u, one.size());
- EXPECT_THAT(one, ElementsAre(Pair(1, 1)));
-
- // Two elements, already unique.
- Vect two_u;
- two_u.push_back(Pair(1, 1));
- two_u.push_back(Pair(2, 2));
- EXPECT_EQ(two_u.end(), LastUnique(two_u.begin(), two_u.end(), cmp));
- EXPECT_THAT(two_u, ElementsAre(Pair(1, 1), Pair(2, 2)));
-
- // Two elements, dupes.
- Vect two_d;
- two_d.push_back(Pair(1, 1));
- two_d.push_back(Pair(1, 2));
- auto last = LastUnique(two_d.begin(), two_d.end(), cmp);
- EXPECT_EQ(two_d.begin() + 1, last);
- two_d.erase(last, two_d.end());
- EXPECT_THAT(two_d, ElementsAre(Pair(1, 2)));
-
- // Non-dupes, dupes, non-dupes.
- Vect ndn;
- ndn.push_back(Pair(1, 1));
- ndn.push_back(Pair(2, 1));
- ndn.push_back(Pair(2, 2));
- ndn.push_back(Pair(2, 3));
- ndn.push_back(Pair(3, 1));
- last = LastUnique(ndn.begin(), ndn.end(), cmp);
- EXPECT_EQ(ndn.begin() + 3, last);
- ndn.erase(last, ndn.end());
- EXPECT_THAT(ndn, ElementsAre(Pair(1, 1), Pair(2, 3), Pair(3, 1)));
-
- // Dupes, non-dupes, dupes.
- Vect dnd;
- dnd.push_back(Pair(1, 1));
- dnd.push_back(Pair(1, 2));
- dnd.push_back(Pair(1, 3));
- dnd.push_back(Pair(2, 1));
- dnd.push_back(Pair(3, 1));
- dnd.push_back(Pair(3, 2));
- dnd.push_back(Pair(3, 3));
- last = LastUnique(dnd.begin(), dnd.end(), cmp);
- EXPECT_EQ(dnd.begin() + 3, last);
- dnd.erase(last, dnd.end());
- EXPECT_THAT(dnd, ElementsAre(Pair(1, 3), Pair(2, 1), Pair(3, 3)));
-}
-
-// ----------------------------------------------------------------------------
-// Class.
-
-// Check that flat_tree and its iterators can be instantiated with an
-// incomplete type.
-
-TEST(FlatTree, IncompleteType) {
- struct A {
- using Tree = flat_tree<A, A, GetKeyFromValueIdentity<A>, std::less<A>>;
- int data;
- Tree set_with_incomplete_type;
- Tree::iterator it;
- Tree::const_iterator cit;
-
- // We do not declare operator< because clang complains that it's unused.
- };
-
- A a;
-}
-
-TEST(FlatTree, Stability) {
- using Pair = std::pair<int, int>;
-
- using Tree =
- flat_tree<Pair, Pair, GetKeyFromValueIdentity<Pair>, LessByFirst<Pair>>;
-
- // Constructors are stable.
- Tree cont({{0, 0}, {1, 0}, {0, 1}, {2, 0}, {0, 2}, {1, 1}});
-
- auto AllOfSecondsAreZero = [&cont] {
- return std::all_of(cont.begin(), cont.end(),
- [](const Pair& elem) { return elem.second == 0; });
- };
-
- EXPECT_TRUE(AllOfSecondsAreZero()) << "constructor should be stable";
-
- // Should not replace existing.
- cont.insert(Pair(0, 2));
- cont.insert(Pair(1, 2));
- cont.insert(Pair(2, 2));
-
- EXPECT_TRUE(AllOfSecondsAreZero()) << "insert should be stable";
-
- cont.insert(Pair(3, 0));
- cont.insert(Pair(3, 2));
-
- EXPECT_TRUE(AllOfSecondsAreZero()) << "insert should be stable";
-}
-
-// ----------------------------------------------------------------------------
-// Types.
-
-// key_type
-// key_compare
-// value_type
-// value_compare
-// pointer
-// const_pointer
-// reference
-// const_reference
-// size_type
-// difference_type
-// iterator
-// const_iterator
-// reverse_iterator
-// const_reverse_iterator
-
-TEST(FlatTree, Types) {
- // These are guaranteed to be portable.
- static_assert((std::is_same<int, IntTree::key_type>::value), "");
- static_assert((std::is_same<int, IntTree::value_type>::value), "");
- static_assert((std::is_same<std::less<int>, IntTree::key_compare>::value),
- "");
- static_assert((std::is_same<int&, IntTree::reference>::value), "");
- static_assert((std::is_same<const int&, IntTree::const_reference>::value),
- "");
- static_assert((std::is_same<int*, IntTree::pointer>::value), "");
- static_assert((std::is_same<const int*, IntTree::const_pointer>::value), "");
-}
-
-// ----------------------------------------------------------------------------
-// Lifetime.
-
-// flat_tree()
-// flat_tree(const Compare& comp)
-
-TEST(FlatTree, DefaultConstructor) {
- {
- IntTree cont;
- EXPECT_THAT(cont, ElementsAre());
- }
-
- {
- TreeWithStrangeCompare cont(NonDefaultConstructibleCompare(0));
- EXPECT_THAT(cont, ElementsAre());
- }
-}
-
-// flat_tree(InputIterator first,
-// InputIterator last,
-// FlatContainerDupes dupe_handling,
-// const Compare& comp = Compare())
-
-TEST(FlatTree, RangeConstructor) {
- {
- IntPair input_vals[] = {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {1, 3},
- {2, 3}, {3, 1}, {3, 2}, {3, 3}};
-
- IntPairTree first_of(MakeInputIterator(std::begin(input_vals)),
- MakeInputIterator(std::end(input_vals)));
- EXPECT_THAT(first_of,
- ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1)));
-
- IntPairTree last_of(MakeInputIterator(std::begin(input_vals)),
- MakeInputIterator(std::end(input_vals)),
- KEEP_LAST_OF_DUPES);
- EXPECT_THAT(last_of,
- ElementsAre(IntPair(1, 3), IntPair(2, 3), IntPair(3, 3)));
- }
- {
- TreeWithStrangeCompare::value_type input_vals[] = {1, 1, 1, 2, 2,
- 2, 3, 3, 3};
-
- TreeWithStrangeCompare cont(MakeInputIterator(std::begin(input_vals)),
- MakeInputIterator(std::end(input_vals)),
- KEEP_FIRST_OF_DUPES,
- NonDefaultConstructibleCompare(0));
- EXPECT_THAT(cont, ElementsAre(1, 2, 3));
- }
-}
-
-// flat_tree(const flat_tree& x)
-
-TEST(FlatTree, CopyConstructor) {
- IntTree original({1, 2, 3, 4});
- IntTree copied(original);
-
- EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4));
-
- EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4));
- EXPECT_THAT(original, ElementsAre(1, 2, 3, 4));
- EXPECT_EQ(original, copied);
-}
-
-// flat_tree(flat_tree&& x)
-
-TEST(FlatTree, MoveConstructor) {
- int input_range[] = {1, 2, 3, 4};
-
- MoveOnlyTree original(std::begin(input_range), std::end(input_range));
- MoveOnlyTree moved(std::move(original));
-
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(1)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(2)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(3)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(4)));
-}
-
-// flat_tree(std::vector<value_type>, FlatContainerDupes dupe_handling)
-
-TEST(FlatTree, VectorConstructor) {
- using Pair = std::pair<int, MoveOnlyInt>;
-
- // Construct an unsorted vector with a duplicate item in it. Sorted by the
- // first item, the second allows us to test for stability. Using a move
- // only type to ensure the vector is not copied.
- std::vector<Pair> storage;
- storage.push_back(Pair(2, MoveOnlyInt(0)));
- storage.push_back(Pair(1, MoveOnlyInt(0)));
- storage.push_back(Pair(2, MoveOnlyInt(1)));
-
- using Tree =
- flat_tree<Pair, Pair, GetKeyFromValueIdentity<Pair>, LessByFirst<Pair>>;
- Tree tree(std::move(storage));
-
- // The list should be two items long, with only the first "2" saved.
- ASSERT_EQ(2u, tree.size());
- const Pair& zeroth = *tree.begin();
- ASSERT_EQ(1, zeroth.first);
- ASSERT_EQ(0, zeroth.second.data());
-
- const Pair& first = *(tree.begin() + 1);
- ASSERT_EQ(2, first.first);
- ASSERT_EQ(0, first.second.data());
-
- // Test KEEP_LAST_OF_DUPES with a simple vector constructor.
- std::vector<IntPair> int_storage{{1, 1}, {1, 2}, {2, 1}};
- IntPairTree int_tree(std::move(int_storage), KEEP_LAST_OF_DUPES);
- EXPECT_THAT(int_tree, ElementsAre(IntPair(1, 2), IntPair(2, 1)));
-}
-
-// flat_tree(std::initializer_list<value_type> ilist,
-// FlatContainerDupes dupe_handling,
-// const Compare& comp = Compare())
-
-TEST(FlatTree, InitializerListConstructor) {
- {
- IntTree cont({1, 2, 3, 4, 5, 6, 10, 8});
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10));
- }
- {
- IntTree cont({1, 2, 3, 4, 5, 6, 10, 8});
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10));
- }
- {
- TreeWithStrangeCompare cont({1, 2, 3, 4, 5, 6, 10, 8}, KEEP_FIRST_OF_DUPES,
- NonDefaultConstructibleCompare(0));
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10));
- }
- {
- IntPairTree first_of({{1, 1}, {2, 1}, {1, 2}});
- EXPECT_THAT(first_of, ElementsAre(IntPair(1, 1), IntPair(2, 1)));
- }
- {
- IntPairTree last_of({{1, 1}, {2, 1}, {1, 2}}, KEEP_LAST_OF_DUPES);
- EXPECT_THAT(last_of, ElementsAre(IntPair(1, 2), IntPair(2, 1)));
- }
-}
-
-// ----------------------------------------------------------------------------
-// Assignments.
-
-// flat_tree& operator=(const flat_tree&)
-
-TEST(FlatTree, CopyAssignable) {
- IntTree original({1, 2, 3, 4});
- IntTree copied;
- copied = original;
-
- EXPECT_THAT(copied, ElementsAre(1, 2, 3, 4));
- EXPECT_THAT(original, ElementsAre(1, 2, 3, 4));
- EXPECT_EQ(original, copied);
-}
-
-// flat_tree& operator=(flat_tree&&)
-
-TEST(FlatTree, MoveAssignable) {
- int input_range[] = {1, 2, 3, 4};
-
- MoveOnlyTree original(std::begin(input_range), std::end(input_range));
- MoveOnlyTree moved;
- moved = std::move(original);
-
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(1)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(2)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(3)));
- EXPECT_EQ(1U, moved.count(MoveOnlyInt(4)));
-}
-
-// flat_tree& operator=(std::initializer_list<value_type> ilist)
-
-TEST(FlatTree, InitializerListAssignable) {
- IntTree cont({0});
- cont = {1, 2, 3, 4, 5, 6, 10, 8};
-
- EXPECT_EQ(0U, cont.count(0));
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 8, 10));
-}
-
-// --------------------------------------------------------------------------
-// Memory management.
-
-// void reserve(size_type new_capacity)
-
-TEST(FlatTree, Reserve) {
- IntTree cont({1, 2, 3});
-
- cont.reserve(5);
- EXPECT_LE(5U, cont.capacity());
-}
-
-// size_type capacity() const
-
-TEST(FlatTree, Capacity) {
- IntTree cont({1, 2, 3});
-
- EXPECT_LE(cont.size(), cont.capacity());
- cont.reserve(5);
- EXPECT_LE(cont.size(), cont.capacity());
-}
-
-// void shrink_to_fit()
-
-TEST(FlatTree, ShrinkToFit) {
- IntTree cont({1, 2, 3});
-
- IntTree::size_type capacity_before = cont.capacity();
- cont.shrink_to_fit();
- EXPECT_GE(capacity_before, cont.capacity());
-}
-
-// ----------------------------------------------------------------------------
-// Size management.
-
-// void clear()
-
-TEST(FlatTree, Clear) {
- IntTree cont({1, 2, 3, 4, 5, 6, 7, 8});
- cont.clear();
- EXPECT_THAT(cont, ElementsAre());
-}
-
-// size_type size() const
-
-TEST(FlatTree, Size) {
- IntTree cont;
-
- EXPECT_EQ(0U, cont.size());
- cont.insert(2);
- EXPECT_EQ(1U, cont.size());
- cont.insert(1);
- EXPECT_EQ(2U, cont.size());
- cont.insert(3);
- EXPECT_EQ(3U, cont.size());
- cont.erase(cont.begin());
- EXPECT_EQ(2U, cont.size());
- cont.erase(cont.begin());
- EXPECT_EQ(1U, cont.size());
- cont.erase(cont.begin());
- EXPECT_EQ(0U, cont.size());
-}
-
-// bool empty() const
-
-TEST(FlatTree, Empty) {
- IntTree cont;
-
- EXPECT_TRUE(cont.empty());
- cont.insert(1);
- EXPECT_FALSE(cont.empty());
- cont.clear();
- EXPECT_TRUE(cont.empty());
-}
-
-// ----------------------------------------------------------------------------
-// Iterators.
-
-// iterator begin()
-// const_iterator begin() const
-// iterator end()
-// const_iterator end() const
-//
-// reverse_iterator rbegin()
-// const_reverse_iterator rbegin() const
-// reverse_iterator rend()
-// const_reverse_iterator rend() const
-//
-// const_iterator cbegin() const
-// const_iterator cend() const
-// const_reverse_iterator crbegin() const
-// const_reverse_iterator crend() const
-
-TEST(FlatTree, Iterators) {
- IntTree cont({1, 2, 3, 4, 5, 6, 7, 8});
-
- auto size = static_cast<IntTree::difference_type>(cont.size());
-
- EXPECT_EQ(size, std::distance(cont.begin(), cont.end()));
- EXPECT_EQ(size, std::distance(cont.cbegin(), cont.cend()));
- EXPECT_EQ(size, std::distance(cont.rbegin(), cont.rend()));
- EXPECT_EQ(size, std::distance(cont.crbegin(), cont.crend()));
-
- {
- IntTree::iterator it = cont.begin();
- IntTree::const_iterator c_it = cont.cbegin();
- EXPECT_EQ(it, c_it);
- for (int j = 1; it != cont.end(); ++it, ++c_it, ++j) {
- EXPECT_EQ(j, *it);
- EXPECT_EQ(j, *c_it);
- }
- }
- {
- IntTree::reverse_iterator rit = cont.rbegin();
- IntTree::const_reverse_iterator c_rit = cont.crbegin();
- EXPECT_EQ(rit, c_rit);
- for (int j = static_cast<int>(size); rit != cont.rend();
- ++rit, ++c_rit, --j) {
- EXPECT_EQ(j, *rit);
- EXPECT_EQ(j, *c_rit);
- }
- }
-}
-
-// ----------------------------------------------------------------------------
-// Insert operations.
-
-// pair<iterator, bool> insert(const value_type& val)
-
-TEST(FlatTree, InsertLValue) {
- IntTree cont;
-
- int value = 2;
- std::pair<IntTree::iterator, bool> result = cont.insert(value);
- EXPECT_TRUE(result.second);
- EXPECT_EQ(cont.begin(), result.first);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(2, *result.first);
-
- value = 1;
- result = cont.insert(value);
- EXPECT_TRUE(result.second);
- EXPECT_EQ(cont.begin(), result.first);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(1, *result.first);
-
- value = 3;
- result = cont.insert(value);
- EXPECT_TRUE(result.second);
- EXPECT_EQ(std::prev(cont.end()), result.first);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, *result.first);
-
- value = 3;
- result = cont.insert(value);
- EXPECT_FALSE(result.second);
- EXPECT_EQ(std::prev(cont.end()), result.first);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, *result.first);
-}
-
-// pair<iterator, bool> insert(value_type&& val)
-
-TEST(FlatTree, InsertRValue) {
- MoveOnlyTree cont;
-
- std::pair<MoveOnlyTree::iterator, bool> result = cont.insert(MoveOnlyInt(2));
- EXPECT_TRUE(result.second);
- EXPECT_EQ(cont.begin(), result.first);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(2, result.first->data());
-
- result = cont.insert(MoveOnlyInt(1));
- EXPECT_TRUE(result.second);
- EXPECT_EQ(cont.begin(), result.first);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(1, result.first->data());
-
- result = cont.insert(MoveOnlyInt(3));
- EXPECT_TRUE(result.second);
- EXPECT_EQ(std::prev(cont.end()), result.first);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, result.first->data());
-
- result = cont.insert(MoveOnlyInt(3));
- EXPECT_FALSE(result.second);
- EXPECT_EQ(std::prev(cont.end()), result.first);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, result.first->data());
-}
-
-// iterator insert(const_iterator position_hint, const value_type& val)
-
-TEST(FlatTree, InsertPositionLValue) {
- IntTree cont;
-
- IntTree::iterator result = cont.insert(cont.cend(), 2);
- EXPECT_EQ(cont.begin(), result);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(2, *result);
-
- result = cont.insert(cont.cend(), 1);
- EXPECT_EQ(cont.begin(), result);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(1, *result);
-
- result = cont.insert(cont.cend(), 3);
- EXPECT_EQ(std::prev(cont.end()), result);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, *result);
-
- result = cont.insert(cont.cend(), 3);
- EXPECT_EQ(std::prev(cont.end()), result);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, *result);
-}
-
-// iterator insert(const_iterator position_hint, value_type&& val)
-
-TEST(FlatTree, InsertPositionRValue) {
- MoveOnlyTree cont;
-
- MoveOnlyTree::iterator result = cont.insert(cont.cend(), MoveOnlyInt(2));
- EXPECT_EQ(cont.begin(), result);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(2, result->data());
-
- result = cont.insert(cont.cend(), MoveOnlyInt(1));
- EXPECT_EQ(cont.begin(), result);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(1, result->data());
-
- result = cont.insert(cont.cend(), MoveOnlyInt(3));
- EXPECT_EQ(std::prev(cont.end()), result);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, result->data());
-
- result = cont.insert(cont.cend(), MoveOnlyInt(3));
- EXPECT_EQ(std::prev(cont.end()), result);
- EXPECT_EQ(3U, cont.size());
- EXPECT_EQ(3, result->data());
-}
-
-// template <class InputIterator>
-// void insert(InputIterator first, InputIterator last);
-
-TEST(FlatTree, InsertIterIter) {
- struct GetKeyFromIntIntPair {
- const int& operator()(const std::pair<int, int>& p) const {
- return p.first;
- }
- };
-
- using IntIntMap =
- flat_tree<int, IntPair, GetKeyFromIntIntPair, std::less<int>>;
-
- {
- IntIntMap cont;
- IntPair int_pairs[] = {{3, 1}, {1, 1}, {4, 1}, {2, 1}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs));
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- std::vector<IntPair> int_pairs;
- cont.insert(std::begin(int_pairs), std::end(int_pairs));
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{1, 1}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs));
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{1, 2}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs), KEEP_LAST_OF_DUPES);
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 2), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{5, 1}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs));
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1), IntPair(5, 1)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{5, 1}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs), KEEP_LAST_OF_DUPES);
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1), IntPair(5, 1)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs));
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs), KEEP_LAST_OF_DUPES);
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 2), IntPair(2, 2), IntPair(3, 2),
- IntPair(4, 2)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}, {7, 2}, {6, 2},
- {8, 2}, {5, 2}, {5, 3}, {6, 3}, {7, 3}, {8, 3}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs));
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 1), IntPair(2, 1), IntPair(3, 1),
- IntPair(4, 1), IntPair(5, 2), IntPair(6, 2),
- IntPair(7, 2), IntPair(8, 2)));
- }
-
- {
- IntIntMap cont({{1, 1}, {2, 1}, {3, 1}, {4, 1}});
- IntPair int_pairs[] = {{3, 2}, {1, 2}, {4, 2}, {2, 2}, {7, 2}, {6, 2},
- {8, 2}, {5, 2}, {5, 3}, {6, 3}, {7, 3}, {8, 3}};
- cont.insert(std::begin(int_pairs), std::end(int_pairs), KEEP_LAST_OF_DUPES);
- EXPECT_THAT(cont, ElementsAre(IntPair(1, 2), IntPair(2, 2), IntPair(3, 2),
- IntPair(4, 2), IntPair(5, 3), IntPair(6, 3),
- IntPair(7, 3), IntPair(8, 3)));
- }
-}
-
-// template <class... Args>
-// pair<iterator, bool> emplace(Args&&... args)
-
-TEST(FlatTree, Emplace) {
- {
- EmplaceableTree cont;
-
- std::pair<EmplaceableTree::iterator, bool> result = cont.emplace();
- EXPECT_TRUE(result.second);
- EXPECT_EQ(cont.begin(), result.first);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(Emplaceable(), *cont.begin());
-
- result = cont.emplace(2, 3.5);
- EXPECT_TRUE(result.second);
- EXPECT_EQ(std::next(cont.begin()), result.first);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(Emplaceable(2, 3.5), *result.first);
-
- result = cont.emplace(2, 3.5);
- EXPECT_FALSE(result.second);
- EXPECT_EQ(std::next(cont.begin()), result.first);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(Emplaceable(2, 3.5), *result.first);
- }
- {
- IntTree cont;
-
- std::pair<IntTree::iterator, bool> result = cont.emplace(2);
- EXPECT_TRUE(result.second);
- EXPECT_EQ(cont.begin(), result.first);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(2, *result.first);
- }
-}
-
-// template <class... Args>
-// iterator emplace_hint(const_iterator position_hint, Args&&... args)
-
-TEST(FlatTree, EmplacePosition) {
- {
- EmplaceableTree cont;
-
- EmplaceableTree::iterator result = cont.emplace_hint(cont.cend());
- EXPECT_EQ(cont.begin(), result);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(Emplaceable(), *cont.begin());
-
- result = cont.emplace_hint(cont.cend(), 2, 3.5);
- EXPECT_EQ(std::next(cont.begin()), result);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(Emplaceable(2, 3.5), *result);
-
- result = cont.emplace_hint(cont.cbegin(), 2, 3.5);
- EXPECT_EQ(std::next(cont.begin()), result);
- EXPECT_EQ(2U, cont.size());
- EXPECT_EQ(Emplaceable(2, 3.5), *result);
- }
- {
- IntTree cont;
-
- IntTree::iterator result = cont.emplace_hint(cont.cend(), 2);
- EXPECT_EQ(cont.begin(), result);
- EXPECT_EQ(1U, cont.size());
- EXPECT_EQ(2, *result);
- }
-}
-
-// ----------------------------------------------------------------------------
-// Erase operations.
-
-// iterator erase(const_iterator position_hint)
-
-TEST(FlatTree, ErasePosition) {
- {
- IntTree cont({1, 2, 3, 4, 5, 6, 7, 8});
-
- IntTree::iterator it = cont.erase(std::next(cont.cbegin(), 3));
- EXPECT_EQ(std::next(cont.begin(), 3), it);
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8));
-
- it = cont.erase(std::next(cont.cbegin(), 0));
- EXPECT_EQ(cont.begin(), it);
- EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7, 8));
-
- it = cont.erase(std::next(cont.cbegin(), 5));
- EXPECT_EQ(cont.end(), it);
- EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7));
-
- it = cont.erase(std::next(cont.cbegin(), 1));
- EXPECT_EQ(std::next(cont.begin()), it);
- EXPECT_THAT(cont, ElementsAre(2, 5, 6, 7));
-
- it = cont.erase(std::next(cont.cbegin(), 2));
- EXPECT_EQ(std::next(cont.begin(), 2), it);
- EXPECT_THAT(cont, ElementsAre(2, 5, 7));
-
- it = cont.erase(std::next(cont.cbegin(), 2));
- EXPECT_EQ(std::next(cont.begin(), 2), it);
- EXPECT_THAT(cont, ElementsAre(2, 5));
-
- it = cont.erase(std::next(cont.cbegin(), 0));
- EXPECT_EQ(std::next(cont.begin(), 0), it);
- EXPECT_THAT(cont, ElementsAre(5));
-
- it = cont.erase(cont.cbegin());
- EXPECT_EQ(cont.begin(), it);
- EXPECT_EQ(cont.end(), it);
- }
- // This is LWG #2059.
- // There is a potential ambiguity between erase with an iterator and erase
- // with a key, if key has a templated constructor.
- {
- using T = TemplateConstructor;
-
- flat_tree<T, T, GetKeyFromValueIdentity<T>, std::less<>> cont;
- T v(0);
-
- auto it = cont.find(v);
- if (it != cont.end())
- cont.erase(it);
- }
-}
-
-// iterator erase(const_iterator first, const_iterator last)
-
-TEST(FlatTree, EraseRange) {
- IntTree cont({1, 2, 3, 4, 5, 6, 7, 8});
-
- IntTree::iterator it =
- cont.erase(std::next(cont.cbegin(), 5), std::next(cont.cbegin(), 5));
- EXPECT_EQ(std::next(cont.begin(), 5), it);
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
-
- it = cont.erase(std::next(cont.cbegin(), 3), std::next(cont.cbegin(), 4));
- EXPECT_EQ(std::next(cont.begin(), 3), it);
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8));
-
- it = cont.erase(std::next(cont.cbegin(), 2), std::next(cont.cbegin(), 5));
- EXPECT_EQ(std::next(cont.begin(), 2), it);
- EXPECT_THAT(cont, ElementsAre(1, 2, 7, 8));
-
- it = cont.erase(std::next(cont.cbegin(), 0), std::next(cont.cbegin(), 2));
- EXPECT_EQ(std::next(cont.begin(), 0), it);
- EXPECT_THAT(cont, ElementsAre(7, 8));
-
- it = cont.erase(cont.cbegin(), cont.cend());
- EXPECT_EQ(cont.begin(), it);
- EXPECT_EQ(cont.end(), it);
-}
-
-// size_type erase(const key_type& key)
-
-TEST(FlatTree, EraseKey) {
- IntTree cont({1, 2, 3, 4, 5, 6, 7, 8});
-
- EXPECT_EQ(0U, cont.erase(9));
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
-
- EXPECT_EQ(1U, cont.erase(4));
- EXPECT_THAT(cont, ElementsAre(1, 2, 3, 5, 6, 7, 8));
-
- EXPECT_EQ(1U, cont.erase(1));
- EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7, 8));
-
- EXPECT_EQ(1U, cont.erase(8));
- EXPECT_THAT(cont, ElementsAre(2, 3, 5, 6, 7));
-
- EXPECT_EQ(1U, cont.erase(3));
- EXPECT_THAT(cont, ElementsAre(2, 5, 6, 7));
-
- EXPECT_EQ(1U, cont.erase(6));
- EXPECT_THAT(cont, ElementsAre(2, 5, 7));
-
- EXPECT_EQ(1U, cont.erase(7));
- EXPECT_THAT(cont, ElementsAre(2, 5));
-
- EXPECT_EQ(1U, cont.erase(2));
- EXPECT_THAT(cont, ElementsAre(5));
-
- EXPECT_EQ(1U, cont.erase(5));
- EXPECT_THAT(cont, ElementsAre());
-}
-
-// ----------------------------------------------------------------------------
-// Comparators.
-
-// key_compare key_comp() const
-
-TEST(FlatTree, KeyComp) {
- ReversedTree cont({1, 2, 3, 4, 5});
-
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.key_comp()));
- int new_elements[] = {6, 7, 8, 9, 10};
- std::copy(std::begin(new_elements), std::end(new_elements),
- std::inserter(cont, cont.end()));
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.key_comp()));
-}
-
-// value_compare value_comp() const
-
-TEST(FlatTree, ValueComp) {
- ReversedTree cont({1, 2, 3, 4, 5});
-
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.value_comp()));
- int new_elements[] = {6, 7, 8, 9, 10};
- std::copy(std::begin(new_elements), std::end(new_elements),
- std::inserter(cont, cont.end()));
- EXPECT_TRUE(std::is_sorted(cont.begin(), cont.end(), cont.value_comp()));
-}
-
-// ----------------------------------------------------------------------------
-// Search operations.
-
-// size_type count(const key_type& key) const
-
-TEST(FlatTree, Count) {
- const IntTree cont({5, 6, 7, 8, 9, 10, 11, 12});
-
- EXPECT_EQ(1U, cont.count(5));
- EXPECT_EQ(1U, cont.count(6));
- EXPECT_EQ(1U, cont.count(7));
- EXPECT_EQ(1U, cont.count(8));
- EXPECT_EQ(1U, cont.count(9));
- EXPECT_EQ(1U, cont.count(10));
- EXPECT_EQ(1U, cont.count(11));
- EXPECT_EQ(1U, cont.count(12));
- EXPECT_EQ(0U, cont.count(4));
-}
-
-// iterator find(const key_type& key)
-// const_iterator find(const key_type& key) const
-
-TEST(FlatTree, Find) {
- {
- IntTree cont({5, 6, 7, 8, 9, 10, 11, 12});
-
- EXPECT_EQ(cont.begin(), cont.find(5));
- EXPECT_EQ(std::next(cont.begin()), cont.find(6));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.find(7));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.find(8));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.find(9));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.find(10));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.find(11));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.find(12));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.find(4));
- }
- {
- const IntTree cont({5, 6, 7, 8, 9, 10, 11, 12});
-
- EXPECT_EQ(cont.begin(), cont.find(5));
- EXPECT_EQ(std::next(cont.begin()), cont.find(6));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.find(7));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.find(8));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.find(9));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.find(10));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.find(11));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.find(12));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.find(4));
- }
-}
-
-// pair<iterator, iterator> equal_range(const key_type& key)
-// pair<const_iterator, const_iterator> equal_range(const key_type& key) const
-
-TEST(FlatTree, EqualRange) {
- {
- IntTree cont({5, 7, 9, 11, 13, 15, 17, 19});
-
- std::pair<IntTree::iterator, IntTree::iterator> result =
- cont.equal_range(5);
- EXPECT_EQ(std::next(cont.begin(), 0), result.first);
- EXPECT_EQ(std::next(cont.begin(), 1), result.second);
- result = cont.equal_range(7);
- EXPECT_EQ(std::next(cont.begin(), 1), result.first);
- EXPECT_EQ(std::next(cont.begin(), 2), result.second);
- result = cont.equal_range(9);
- EXPECT_EQ(std::next(cont.begin(), 2), result.first);
- EXPECT_EQ(std::next(cont.begin(), 3), result.second);
- result = cont.equal_range(11);
- EXPECT_EQ(std::next(cont.begin(), 3), result.first);
- EXPECT_EQ(std::next(cont.begin(), 4), result.second);
- result = cont.equal_range(13);
- EXPECT_EQ(std::next(cont.begin(), 4), result.first);
- EXPECT_EQ(std::next(cont.begin(), 5), result.second);
- result = cont.equal_range(15);
- EXPECT_EQ(std::next(cont.begin(), 5), result.first);
- EXPECT_EQ(std::next(cont.begin(), 6), result.second);
- result = cont.equal_range(17);
- EXPECT_EQ(std::next(cont.begin(), 6), result.first);
- EXPECT_EQ(std::next(cont.begin(), 7), result.second);
- result = cont.equal_range(19);
- EXPECT_EQ(std::next(cont.begin(), 7), result.first);
- EXPECT_EQ(std::next(cont.begin(), 8), result.second);
- result = cont.equal_range(4);
- EXPECT_EQ(std::next(cont.begin(), 0), result.first);
- EXPECT_EQ(std::next(cont.begin(), 0), result.second);
- result = cont.equal_range(6);
- EXPECT_EQ(std::next(cont.begin(), 1), result.first);
- EXPECT_EQ(std::next(cont.begin(), 1), result.second);
- result = cont.equal_range(8);
- EXPECT_EQ(std::next(cont.begin(), 2), result.first);
- EXPECT_EQ(std::next(cont.begin(), 2), result.second);
- result = cont.equal_range(10);
- EXPECT_EQ(std::next(cont.begin(), 3), result.first);
- EXPECT_EQ(std::next(cont.begin(), 3), result.second);
- result = cont.equal_range(12);
- EXPECT_EQ(std::next(cont.begin(), 4), result.first);
- EXPECT_EQ(std::next(cont.begin(), 4), result.second);
- result = cont.equal_range(14);
- EXPECT_EQ(std::next(cont.begin(), 5), result.first);
- EXPECT_EQ(std::next(cont.begin(), 5), result.second);
- result = cont.equal_range(16);
- EXPECT_EQ(std::next(cont.begin(), 6), result.first);
- EXPECT_EQ(std::next(cont.begin(), 6), result.second);
- result = cont.equal_range(18);
- EXPECT_EQ(std::next(cont.begin(), 7), result.first);
- EXPECT_EQ(std::next(cont.begin(), 7), result.second);
- result = cont.equal_range(20);
- EXPECT_EQ(std::next(cont.begin(), 8), result.first);
- EXPECT_EQ(std::next(cont.begin(), 8), result.second);
- }
- {
- const IntTree cont({5, 7, 9, 11, 13, 15, 17, 19});
-
- std::pair<IntTree::const_iterator, IntTree::const_iterator> result =
- cont.equal_range(5);
- EXPECT_EQ(std::next(cont.begin(), 0), result.first);
- EXPECT_EQ(std::next(cont.begin(), 1), result.second);
- result = cont.equal_range(7);
- EXPECT_EQ(std::next(cont.begin(), 1), result.first);
- EXPECT_EQ(std::next(cont.begin(), 2), result.second);
- result = cont.equal_range(9);
- EXPECT_EQ(std::next(cont.begin(), 2), result.first);
- EXPECT_EQ(std::next(cont.begin(), 3), result.second);
- result = cont.equal_range(11);
- EXPECT_EQ(std::next(cont.begin(), 3), result.first);
- EXPECT_EQ(std::next(cont.begin(), 4), result.second);
- result = cont.equal_range(13);
- EXPECT_EQ(std::next(cont.begin(), 4), result.first);
- EXPECT_EQ(std::next(cont.begin(), 5), result.second);
- result = cont.equal_range(15);
- EXPECT_EQ(std::next(cont.begin(), 5), result.first);
- EXPECT_EQ(std::next(cont.begin(), 6), result.second);
- result = cont.equal_range(17);
- EXPECT_EQ(std::next(cont.begin(), 6), result.first);
- EXPECT_EQ(std::next(cont.begin(), 7), result.second);
- result = cont.equal_range(19);
- EXPECT_EQ(std::next(cont.begin(), 7), result.first);
- EXPECT_EQ(std::next(cont.begin(), 8), result.second);
- result = cont.equal_range(4);
- EXPECT_EQ(std::next(cont.begin(), 0), result.first);
- EXPECT_EQ(std::next(cont.begin(), 0), result.second);
- result = cont.equal_range(6);
- EXPECT_EQ(std::next(cont.begin(), 1), result.first);
- EXPECT_EQ(std::next(cont.begin(), 1), result.second);
- result = cont.equal_range(8);
- EXPECT_EQ(std::next(cont.begin(), 2), result.first);
- EXPECT_EQ(std::next(cont.begin(), 2), result.second);
- result = cont.equal_range(10);
- EXPECT_EQ(std::next(cont.begin(), 3), result.first);
- EXPECT_EQ(std::next(cont.begin(), 3), result.second);
- result = cont.equal_range(12);
- EXPECT_EQ(std::next(cont.begin(), 4), result.first);
- EXPECT_EQ(std::next(cont.begin(), 4), result.second);
- result = cont.equal_range(14);
- EXPECT_EQ(std::next(cont.begin(), 5), result.first);
- EXPECT_EQ(std::next(cont.begin(), 5), result.second);
- result = cont.equal_range(16);
- EXPECT_EQ(std::next(cont.begin(), 6), result.first);
- EXPECT_EQ(std::next(cont.begin(), 6), result.second);
- result = cont.equal_range(18);
- EXPECT_EQ(std::next(cont.begin(), 7), result.first);
- EXPECT_EQ(std::next(cont.begin(), 7), result.second);
- result = cont.equal_range(20);
- EXPECT_EQ(std::next(cont.begin(), 8), result.first);
- EXPECT_EQ(std::next(cont.begin(), 8), result.second);
- }
-}
-
-// iterator lower_bound(const key_type& key);
-// const_iterator lower_bound(const key_type& key) const;
-
-TEST(FlatTree, LowerBound) {
- {
- IntTree cont({5, 7, 9, 11, 13, 15, 17, 19});
-
- EXPECT_EQ(cont.begin(), cont.lower_bound(5));
- EXPECT_EQ(std::next(cont.begin()), cont.lower_bound(7));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(9));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(11));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(13));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(15));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(17));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(19));
- EXPECT_EQ(std::next(cont.begin(), 0), cont.lower_bound(4));
- EXPECT_EQ(std::next(cont.begin(), 1), cont.lower_bound(6));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(8));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(10));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(12));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(14));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(16));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(18));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.lower_bound(20));
- }
- {
- const IntTree cont({5, 7, 9, 11, 13, 15, 17, 19});
-
- EXPECT_EQ(cont.begin(), cont.lower_bound(5));
- EXPECT_EQ(std::next(cont.begin()), cont.lower_bound(7));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(9));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(11));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(13));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(15));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(17));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(19));
- EXPECT_EQ(std::next(cont.begin(), 0), cont.lower_bound(4));
- EXPECT_EQ(std::next(cont.begin(), 1), cont.lower_bound(6));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.lower_bound(8));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.lower_bound(10));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.lower_bound(12));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.lower_bound(14));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.lower_bound(16));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.lower_bound(18));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.lower_bound(20));
- }
-}
-
-// iterator upper_bound(const key_type& key)
-// const_iterator upper_bound(const key_type& key) const
-
-TEST(FlatTree, UpperBound) {
- {
- IntTree cont({5, 7, 9, 11, 13, 15, 17, 19});
-
- EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(5));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(7));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(9));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(11));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(13));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(15));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(17));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(19));
- EXPECT_EQ(std::next(cont.begin(), 0), cont.upper_bound(4));
- EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(6));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(8));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(10));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(12));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(14));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(16));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(18));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(20));
- }
- {
- const IntTree cont({5, 7, 9, 11, 13, 15, 17, 19});
-
- EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(5));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(7));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(9));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(11));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(13));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(15));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(17));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(19));
- EXPECT_EQ(std::next(cont.begin(), 0), cont.upper_bound(4));
- EXPECT_EQ(std::next(cont.begin(), 1), cont.upper_bound(6));
- EXPECT_EQ(std::next(cont.begin(), 2), cont.upper_bound(8));
- EXPECT_EQ(std::next(cont.begin(), 3), cont.upper_bound(10));
- EXPECT_EQ(std::next(cont.begin(), 4), cont.upper_bound(12));
- EXPECT_EQ(std::next(cont.begin(), 5), cont.upper_bound(14));
- EXPECT_EQ(std::next(cont.begin(), 6), cont.upper_bound(16));
- EXPECT_EQ(std::next(cont.begin(), 7), cont.upper_bound(18));
- EXPECT_EQ(std::next(cont.begin(), 8), cont.upper_bound(20));
- }
-}
-
-// ----------------------------------------------------------------------------
-// General operations.
-
-// void swap(flat_tree& other)
-// void swap(flat_tree& lhs, flat_tree& rhs)
-
-TEST(FlatTreeOurs, Swap) {
- IntTree x({1, 2, 3});
- IntTree y({4});
- swap(x, y);
- EXPECT_THAT(x, ElementsAre(4));
- EXPECT_THAT(y, ElementsAre(1, 2, 3));
-
- y.swap(x);
- EXPECT_THAT(x, ElementsAre(1, 2, 3));
- EXPECT_THAT(y, ElementsAre(4));
-}
-
-// bool operator==(const flat_tree& lhs, const flat_tree& rhs)
-// bool operator!=(const flat_tree& lhs, const flat_tree& rhs)
-// bool operator<(const flat_tree& lhs, const flat_tree& rhs)
-// bool operator>(const flat_tree& lhs, const flat_tree& rhs)
-// bool operator<=(const flat_tree& lhs, const flat_tree& rhs)
-// bool operator>=(const flat_tree& lhs, const flat_tree& rhs)
-
-TEST(FlatTree, Comparison) {
- // Provided comparator does not participate in comparison.
- ReversedTree biggest({3});
- ReversedTree smallest({1});
- ReversedTree middle({1, 2});
-
- EXPECT_EQ(biggest, biggest);
- EXPECT_NE(biggest, smallest);
- EXPECT_LT(smallest, middle);
- EXPECT_LE(smallest, middle);
- EXPECT_LE(middle, middle);
- EXPECT_GT(biggest, middle);
- EXPECT_GE(biggest, middle);
- EXPECT_GE(biggest, biggest);
-}
-
-TEST(FlatSet, EraseIf) {
- IntTree x;
- EraseIf(x, [](int) { return false; });
- EXPECT_THAT(x, ElementsAre());
-
- x = {1, 2, 3};
- EraseIf(x, [](int elem) { return !(elem & 1); });
- EXPECT_THAT(x, ElementsAre(1, 3));
-
- x = {1, 2, 3, 4};
- EraseIf(x, [](int elem) { return elem & 1; });
- EXPECT_THAT(x, ElementsAre(2, 4));
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/containers/hash_tables_unittest.cc b/base/containers/hash_tables_unittest.cc
deleted file mode 100644
index 6072e5dc91..0000000000
--- a/base/containers/hash_tables_unittest.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2013 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/containers/hash_tables.h"
-
-#include <stdint.h>
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class HashPairTest : public testing::Test {
-};
-
-#define INSERT_PAIR_TEST(Type, value1, value2) \
- { \
- Type pair(value1, value2); \
- base::hash_map<Type, int> map; \
- map[pair] = 1; \
- }
-
-// Verify that a hash_map can be constructed for pairs of integers of various
-// sizes.
-TEST_F(HashPairTest, IntegerPairs) {
- typedef std::pair<int16_t, int16_t> Int16Int16Pair;
- typedef std::pair<int16_t, int32_t> Int16Int32Pair;
- typedef std::pair<int16_t, int64_t> Int16Int64Pair;
-
- INSERT_PAIR_TEST(Int16Int16Pair, 4, 6);
- INSERT_PAIR_TEST(Int16Int32Pair, 9, (1 << 29) + 378128932);
- INSERT_PAIR_TEST(Int16Int64Pair, 10,
- (INT64_C(1) << 60) + INT64_C(78931732321));
-
- typedef std::pair<int32_t, int16_t> Int32Int16Pair;
- typedef std::pair<int32_t, int32_t> Int32Int32Pair;
- typedef std::pair<int32_t, int64_t> Int32Int64Pair;
-
- INSERT_PAIR_TEST(Int32Int16Pair, 4, 6);
- INSERT_PAIR_TEST(Int32Int32Pair, 9, (1 << 29) + 378128932);
- INSERT_PAIR_TEST(Int32Int64Pair, 10,
- (INT64_C(1) << 60) + INT64_C(78931732321));
-
- typedef std::pair<int64_t, int16_t> Int64Int16Pair;
- typedef std::pair<int64_t, int32_t> Int64Int32Pair;
- typedef std::pair<int64_t, int64_t> Int64Int64Pair;
-
- INSERT_PAIR_TEST(Int64Int16Pair, 4, 6);
- INSERT_PAIR_TEST(Int64Int32Pair, 9, (1 << 29) + 378128932);
- INSERT_PAIR_TEST(Int64Int64Pair, 10,
- (INT64_C(1) << 60) + INT64_C(78931732321));
-}
-
-// Verify that base::hash_set<const char*> compares by pointer value, not as C
-// strings.
-TEST(HashTableTest, CharPointers) {
- std::string str1("hello");
- std::string str2("hello");
- base::hash_set<const char*> set;
-
- set.insert(str1.c_str());
- EXPECT_EQ(1u, set.count(str1.c_str()));
- EXPECT_EQ(0u, set.count(str2.c_str()));
-}
-
-} // namespace
diff --git a/base/containers/id_map.h b/base/containers/id_map.h
deleted file mode 100644
index 4c816da376..0000000000
--- a/base/containers/id_map.h
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_CONTAINERS_ID_MAP_H_
-#define BASE_CONTAINERS_ID_MAP_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-#include <type_traits>
-#include <unordered_map>
-#include <utility>
-
-#include "base/containers/flat_set.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/sequence_checker.h"
-
-namespace base {
-
-// This object maintains a list of IDs that can be quickly converted to
-// pointers to objects. It is implemented as a hash table, optimized for
-// relatively small data sets (in the common case, there will be exactly one
-// item in the list).
-//
-// Items can be inserted into the container with arbitrary ID, but the caller
-// must ensure they are unique. Inserting IDs and relying on automatically
-// generated ones is not allowed because they can collide.
-
-// The map's value type (the V param) can be any dereferenceable type, such as a
-// raw pointer or smart pointer
-template <typename V, typename K = int32_t>
-class IDMap final {
- public:
- using KeyType = K;
-
- private:
- using T = typename std::remove_reference<decltype(*V())>::type;
-
- using HashTable = std::unordered_map<KeyType, V>;
-
- public:
- IDMap() : iteration_depth_(0), next_id_(1), check_on_null_data_(false) {
- // A number of consumers of IDMap create it on one thread but always
- // access it from a different, but consistent, thread (or sequence)
- // post-construction. The first call to CalledOnValidSequence() will re-bind
- // it.
- DETACH_FROM_SEQUENCE(sequence_checker_);
- }
-
- ~IDMap() {
- // Many IDMap's are static, and hence will be destroyed on the main
- // thread. However, all the accesses may take place on another thread (or
- // sequence), such as the IO thread. Detaching again to clean this up.
- DETACH_FROM_SEQUENCE(sequence_checker_);
- }
-
- // Sets whether Add and Replace should DCHECK if passed in NULL data.
- // Default is false.
- void set_check_on_null_data(bool value) { check_on_null_data_ = value; }
-
- // Adds a view with an automatically generated unique ID. See AddWithID.
- KeyType Add(V data) { return AddInternal(std::move(data)); }
-
- // Adds a new data member with the specified ID. The ID must not be in
- // the list. The caller either must generate all unique IDs itself and use
- // this function, or allow this object to generate IDs and call Add. These
- // two methods may not be mixed, or duplicate IDs may be generated.
- void AddWithID(V data, KeyType id) { AddWithIDInternal(std::move(data), id); }
-
- void Remove(KeyType id) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- typename HashTable::iterator i = data_.find(id);
- if (i == data_.end() || IsRemoved(id)) {
- NOTREACHED() << "Attempting to remove an item not in the list";
- return;
- }
-
- if (iteration_depth_ == 0) {
- data_.erase(i);
- } else {
- removed_ids_.insert(id);
- }
- }
-
- // Replaces the value for |id| with |new_data| and returns the existing value.
- // Should only be called with an already added id.
- V Replace(KeyType id, V new_data) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!check_on_null_data_ || new_data);
- typename HashTable::iterator i = data_.find(id);
- DCHECK(i != data_.end());
- DCHECK(!IsRemoved(id));
-
- using std::swap;
- swap(i->second, new_data);
- return new_data;
- }
-
- void Clear() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (iteration_depth_ == 0) {
- data_.clear();
- } else {
- removed_ids_.reserve(data_.size());
- removed_ids_.insert(KeyIterator(data_.begin()), KeyIterator(data_.end()));
- }
- }
-
- bool IsEmpty() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return size() == 0u;
- }
-
- T* Lookup(KeyType id) const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- typename HashTable::const_iterator i = data_.find(id);
- if (i == data_.end() || !i->second || IsRemoved(id))
- return nullptr;
- return &*i->second;
- }
-
- size_t size() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return data_.size() - removed_ids_.size();
- }
-
-#if defined(UNIT_TEST)
- int iteration_depth() const {
- return iteration_depth_;
- }
-#endif // defined(UNIT_TEST)
-
- // It is safe to remove elements from the map during iteration. All iterators
- // will remain valid.
- template<class ReturnType>
- class Iterator {
- public:
- Iterator(IDMap<V, K>* map) : map_(map), iter_(map_->data_.begin()) {
- Init();
- }
-
- Iterator(const Iterator& iter)
- : map_(iter.map_),
- iter_(iter.iter_) {
- Init();
- }
-
- const Iterator& operator=(const Iterator& iter) {
- map_ = iter.map;
- iter_ = iter.iter;
- Init();
- return *this;
- }
-
- ~Iterator() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(map_->sequence_checker_);
-
- // We're going to decrement iteration depth. Make sure it's greater than
- // zero so that it doesn't become negative.
- DCHECK_LT(0, map_->iteration_depth_);
-
- if (--map_->iteration_depth_ == 0)
- map_->Compact();
- }
-
- bool IsAtEnd() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(map_->sequence_checker_);
- return iter_ == map_->data_.end();
- }
-
- KeyType GetCurrentKey() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(map_->sequence_checker_);
- return iter_->first;
- }
-
- ReturnType* GetCurrentValue() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(map_->sequence_checker_);
- if (!iter_->second || map_->IsRemoved(iter_->first))
- return nullptr;
- return &*iter_->second;
- }
-
- void Advance() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(map_->sequence_checker_);
- ++iter_;
- SkipRemovedEntries();
- }
-
- private:
- void Init() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(map_->sequence_checker_);
- ++map_->iteration_depth_;
- SkipRemovedEntries();
- }
-
- void SkipRemovedEntries() {
- while (iter_ != map_->data_.end() && map_->IsRemoved(iter_->first))
- ++iter_;
- }
-
- IDMap<V, K>* map_;
- typename HashTable::const_iterator iter_;
- };
-
- typedef Iterator<T> iterator;
- typedef Iterator<const T> const_iterator;
-
- private:
- // Transforms a map iterator to an iterator on the keys of the map.
- // Used by Clear() to populate |removed_ids_| in bulk.
- struct KeyIterator : std::iterator<std::forward_iterator_tag, KeyType> {
- using inner_iterator = typename HashTable::iterator;
- inner_iterator iter_;
-
- KeyIterator(inner_iterator iter) : iter_(iter) {}
- KeyType operator*() const { return iter_->first; }
- KeyIterator& operator++() {
- ++iter_;
- return *this;
- }
- KeyIterator operator++(int) { return KeyIterator(iter_++); }
- bool operator==(const KeyIterator& other) const {
- return iter_ == other.iter_;
- }
- bool operator!=(const KeyIterator& other) const {
- return iter_ != other.iter_;
- }
- };
-
- KeyType AddInternal(V data) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!check_on_null_data_ || data);
- KeyType this_id = next_id_;
- DCHECK(data_.find(this_id) == data_.end()) << "Inserting duplicate item";
- data_[this_id] = std::move(data);
- next_id_++;
- return this_id;
- }
-
- void AddWithIDInternal(V data, KeyType id) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(!check_on_null_data_ || data);
- if (IsRemoved(id)) {
- removed_ids_.erase(id);
- } else {
- DCHECK(data_.find(id) == data_.end()) << "Inserting duplicate item";
- }
- data_[id] = std::move(data);
- }
-
- bool IsRemoved(KeyType key) const {
- return removed_ids_.find(key) != removed_ids_.end();
- }
-
- void Compact() {
- DCHECK_EQ(0, iteration_depth_);
- for (const auto& i : removed_ids_)
- data_.erase(i);
- removed_ids_.clear();
- }
-
- // Keep track of how many iterators are currently iterating on us to safely
- // handle removing items during iteration.
- int iteration_depth_;
-
- // Keep set of IDs that should be removed after the outermost iteration has
- // finished. This way we manage to not invalidate the iterator when an element
- // is removed.
- base::flat_set<KeyType> removed_ids_;
-
- // The next ID that we will return from Add()
- KeyType next_id_;
-
- HashTable data_;
-
- // See description above setter.
- bool check_on_null_data_;
-
- SEQUENCE_CHECKER(sequence_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(IDMap);
-};
-
-} // namespace base
-
-#endif // BASE_CONTAINERS_ID_MAP_H_
diff --git a/base/containers/id_map_unittest.cc b/base/containers/id_map_unittest.cc
deleted file mode 100644
index 346b69f2bb..0000000000
--- a/base/containers/id_map_unittest.cc
+++ /dev/null
@@ -1,399 +0,0 @@
-// Copyright (c) 2011 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/containers/id_map.h"
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class TestObject {
-};
-
-class DestructorCounter {
- public:
- explicit DestructorCounter(int* counter) : counter_(counter) {}
- ~DestructorCounter() { ++(*counter_); }
-
- private:
- int* counter_;
-};
-
-} // namespace
-
-TEST(IDMapTest, Basic) {
- IDMap<TestObject*> map;
- EXPECT_TRUE(map.IsEmpty());
- EXPECT_EQ(0U, map.size());
-
- TestObject obj1;
- TestObject obj2;
-
- int32_t id1 = map.Add(&obj1);
- EXPECT_FALSE(map.IsEmpty());
- EXPECT_EQ(1U, map.size());
- EXPECT_EQ(&obj1, map.Lookup(id1));
-
- int32_t id2 = map.Add(&obj2);
- EXPECT_FALSE(map.IsEmpty());
- EXPECT_EQ(2U, map.size());
-
- EXPECT_EQ(&obj1, map.Lookup(id1));
- EXPECT_EQ(&obj2, map.Lookup(id2));
-
- map.Remove(id1);
- EXPECT_FALSE(map.IsEmpty());
- EXPECT_EQ(1U, map.size());
-
- map.Remove(id2);
- EXPECT_TRUE(map.IsEmpty());
- EXPECT_EQ(0U, map.size());
-
- map.AddWithID(&obj1, 1);
- map.AddWithID(&obj2, 2);
- EXPECT_EQ(&obj1, map.Lookup(1));
- EXPECT_EQ(&obj2, map.Lookup(2));
-
- EXPECT_EQ(&obj2, map.Replace(2, &obj1));
- EXPECT_EQ(&obj1, map.Lookup(2));
-
- EXPECT_EQ(0, map.iteration_depth());
-}
-
-TEST(IDMapTest, IteratorRemainsValidWhenRemovingCurrentElement) {
- IDMap<TestObject*> map;
-
- TestObject obj1;
- TestObject obj2;
- TestObject obj3;
-
- map.Add(&obj1);
- map.Add(&obj2);
- map.Add(&obj3);
-
- {
- IDMap<TestObject*>::const_iterator iter(&map);
-
- EXPECT_EQ(1, map.iteration_depth());
-
- while (!iter.IsAtEnd()) {
- map.Remove(iter.GetCurrentKey());
- iter.Advance();
- }
-
- // Test that while an iterator is still in scope, we get the map emptiness
- // right (http://crbug.com/35571).
- EXPECT_TRUE(map.IsEmpty());
- EXPECT_EQ(0U, map.size());
- }
-
- EXPECT_TRUE(map.IsEmpty());
- EXPECT_EQ(0U, map.size());
-
- EXPECT_EQ(0, map.iteration_depth());
-}
-
-TEST(IDMapTest, IteratorRemainsValidWhenRemovingOtherElements) {
- IDMap<TestObject*> map;
-
- const int kCount = 5;
- TestObject obj[kCount];
-
- for (int i = 0; i < kCount; i++)
- map.Add(&obj[i]);
-
- // IDMap has no predictable iteration order.
- int32_t ids_in_iteration_order[kCount];
- const TestObject* objs_in_iteration_order[kCount];
- int counter = 0;
- for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
- iter.Advance()) {
- ids_in_iteration_order[counter] = iter.GetCurrentKey();
- objs_in_iteration_order[counter] = iter.GetCurrentValue();
- counter++;
- }
-
- counter = 0;
- for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
- iter.Advance()) {
- EXPECT_EQ(1, map.iteration_depth());
-
- switch (counter) {
- case 0:
- EXPECT_EQ(ids_in_iteration_order[0], iter.GetCurrentKey());
- EXPECT_EQ(objs_in_iteration_order[0], iter.GetCurrentValue());
- map.Remove(ids_in_iteration_order[1]);
- break;
- case 1:
- EXPECT_EQ(ids_in_iteration_order[2], iter.GetCurrentKey());
- EXPECT_EQ(objs_in_iteration_order[2], iter.GetCurrentValue());
- map.Remove(ids_in_iteration_order[3]);
- break;
- case 2:
- EXPECT_EQ(ids_in_iteration_order[4], iter.GetCurrentKey());
- EXPECT_EQ(objs_in_iteration_order[4], iter.GetCurrentValue());
- map.Remove(ids_in_iteration_order[0]);
- break;
- default:
- FAIL() << "should not have that many elements";
- break;
- }
-
- counter++;
- }
-
- EXPECT_EQ(0, map.iteration_depth());
-}
-
-TEST(IDMapTest, CopyIterator) {
- IDMap<TestObject*> map;
-
- TestObject obj1;
- TestObject obj2;
- TestObject obj3;
-
- map.Add(&obj1);
- map.Add(&obj2);
- map.Add(&obj3);
-
- EXPECT_EQ(0, map.iteration_depth());
-
- {
- IDMap<TestObject*>::const_iterator iter1(&map);
- EXPECT_EQ(1, map.iteration_depth());
-
- // Make sure that copying the iterator correctly increments
- // map's iteration depth.
- IDMap<TestObject*>::const_iterator iter2(iter1);
- EXPECT_EQ(2, map.iteration_depth());
- }
-
- // Make sure after destroying all iterators the map's iteration depth
- // returns to initial state.
- EXPECT_EQ(0, map.iteration_depth());
-}
-
-TEST(IDMapTest, AssignIterator) {
- IDMap<TestObject*> map;
-
- TestObject obj1;
- TestObject obj2;
- TestObject obj3;
-
- map.Add(&obj1);
- map.Add(&obj2);
- map.Add(&obj3);
-
- EXPECT_EQ(0, map.iteration_depth());
-
- {
- IDMap<TestObject*>::const_iterator iter1(&map);
- EXPECT_EQ(1, map.iteration_depth());
-
- IDMap<TestObject*>::const_iterator iter2(&map);
- EXPECT_EQ(2, map.iteration_depth());
-
- // Make sure that assigning the iterator correctly updates
- // map's iteration depth (-1 for destruction, +1 for assignment).
- EXPECT_EQ(2, map.iteration_depth());
- }
-
- // Make sure after destroying all iterators the map's iteration depth
- // returns to initial state.
- EXPECT_EQ(0, map.iteration_depth());
-}
-
-TEST(IDMapTest, IteratorRemainsValidWhenClearing) {
- IDMap<TestObject*> map;
-
- const int kCount = 5;
- TestObject obj[kCount];
-
- for (int i = 0; i < kCount; i++)
- map.Add(&obj[i]);
-
- // IDMap has no predictable iteration order.
- int32_t ids_in_iteration_order[kCount];
- const TestObject* objs_in_iteration_order[kCount];
- int counter = 0;
- for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
- iter.Advance()) {
- ids_in_iteration_order[counter] = iter.GetCurrentKey();
- objs_in_iteration_order[counter] = iter.GetCurrentValue();
- counter++;
- }
-
- counter = 0;
- for (IDMap<TestObject*>::const_iterator iter(&map); !iter.IsAtEnd();
- iter.Advance()) {
- switch (counter) {
- case 0:
- EXPECT_EQ(ids_in_iteration_order[0], iter.GetCurrentKey());
- EXPECT_EQ(objs_in_iteration_order[0], iter.GetCurrentValue());
- break;
- case 1:
- EXPECT_EQ(ids_in_iteration_order[1], iter.GetCurrentKey());
- EXPECT_EQ(objs_in_iteration_order[1], iter.GetCurrentValue());
- map.Clear();
- EXPECT_TRUE(map.IsEmpty());
- EXPECT_EQ(0U, map.size());
- break;
- default:
- FAIL() << "should not have that many elements";
- break;
- }
- counter++;
- }
-
- EXPECT_TRUE(map.IsEmpty());
- EXPECT_EQ(0U, map.size());
-}
-
-TEST(IDMapTest, OwningPointersDeletesThemOnRemove) {
- const int kCount = 3;
-
- int external_del_count = 0;
- DestructorCounter* external_obj[kCount];
- int map_external_ids[kCount];
-
- int owned_del_count = 0;
- int map_owned_ids[kCount];
-
- IDMap<DestructorCounter*> map_external;
- IDMap<std::unique_ptr<DestructorCounter>> map_owned;
-
- for (int i = 0; i < kCount; ++i) {
- external_obj[i] = new DestructorCounter(&external_del_count);
- map_external_ids[i] = map_external.Add(external_obj[i]);
-
- map_owned_ids[i] =
- map_owned.Add(std::make_unique<DestructorCounter>(&owned_del_count));
- }
-
- for (int i = 0; i < kCount; ++i) {
- EXPECT_EQ(external_del_count, 0);
- EXPECT_EQ(owned_del_count, i);
-
- map_external.Remove(map_external_ids[i]);
- map_owned.Remove(map_owned_ids[i]);
- }
-
- for (int i = 0; i < kCount; ++i) {
- delete external_obj[i];
- }
-
- EXPECT_EQ(external_del_count, kCount);
- EXPECT_EQ(owned_del_count, kCount);
-}
-
-TEST(IDMapTest, OwningPointersDeletesThemOnClear) {
- const int kCount = 3;
-
- int external_del_count = 0;
- DestructorCounter* external_obj[kCount];
-
- int owned_del_count = 0;
-
- IDMap<DestructorCounter*> map_external;
- IDMap<std::unique_ptr<DestructorCounter>> map_owned;
-
- for (int i = 0; i < kCount; ++i) {
- external_obj[i] = new DestructorCounter(&external_del_count);
- map_external.Add(external_obj[i]);
-
- map_owned.Add(std::make_unique<DestructorCounter>(&owned_del_count));
- }
-
- EXPECT_EQ(external_del_count, 0);
- EXPECT_EQ(owned_del_count, 0);
-
- map_external.Clear();
- map_owned.Clear();
-
- EXPECT_EQ(external_del_count, 0);
- EXPECT_EQ(owned_del_count, kCount);
-
- for (int i = 0; i < kCount; ++i) {
- delete external_obj[i];
- }
-
- EXPECT_EQ(external_del_count, kCount);
- EXPECT_EQ(owned_del_count, kCount);
-}
-
-TEST(IDMapTest, OwningPointersDeletesThemOnDestruct) {
- const int kCount = 3;
-
- int external_del_count = 0;
- DestructorCounter* external_obj[kCount];
-
- int owned_del_count = 0;
-
- {
- IDMap<DestructorCounter*> map_external;
- IDMap<std::unique_ptr<DestructorCounter>> map_owned;
-
- for (int i = 0; i < kCount; ++i) {
- external_obj[i] = new DestructorCounter(&external_del_count);
- map_external.Add(external_obj[i]);
-
- map_owned.Add(std::make_unique<DestructorCounter>(&owned_del_count));
- }
- }
-
- EXPECT_EQ(external_del_count, 0);
-
- for (int i = 0; i < kCount; ++i) {
- delete external_obj[i];
- }
-
- EXPECT_EQ(external_del_count, kCount);
- EXPECT_EQ(owned_del_count, kCount);
-}
-
-TEST(IDMapTest, Int64KeyType) {
- IDMap<TestObject*, int64_t> map;
- TestObject obj1;
- const int64_t kId1 = 999999999999999999;
-
- map.AddWithID(&obj1, kId1);
- EXPECT_EQ(&obj1, map.Lookup(kId1));
-
- IDMap<TestObject*, int64_t>::const_iterator iter(&map);
- ASSERT_FALSE(iter.IsAtEnd());
- EXPECT_EQ(kId1, iter.GetCurrentKey());
- EXPECT_EQ(&obj1, iter.GetCurrentValue());
- iter.Advance();
- ASSERT_TRUE(iter.IsAtEnd());
-
- map.Remove(kId1);
- EXPECT_TRUE(map.IsEmpty());
-}
-
-TEST(IDMapTest, RemovedValueHandling) {
- TestObject obj;
- IDMap<TestObject*> map;
- int key = map.Add(&obj);
-
- IDMap<TestObject*>::iterator itr(&map);
- map.Clear();
- EXPECT_DCHECK_DEATH(map.Remove(key));
- EXPECT_DCHECK_DEATH(map.Replace(key, &obj));
- EXPECT_FALSE(map.Lookup(key));
- EXPECT_FALSE(itr.IsAtEnd());
- EXPECT_FALSE(itr.GetCurrentValue());
-
- EXPECT_TRUE(map.IsEmpty());
- map.AddWithID(&obj, key);
- EXPECT_EQ(1u, map.size());
-}
-
-} // namespace base
diff --git a/base/containers/linked_list_unittest.cc b/base/containers/linked_list_unittest.cc
deleted file mode 100644
index 8e547ba3fe..0000000000
--- a/base/containers/linked_list_unittest.cc
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright (c) 2009 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/containers/linked_list.h"
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class Node : public LinkNode<Node> {
- public:
- explicit Node(int id) : id_(id) {}
-
- int id() const { return id_; }
-
- private:
- int id_;
-};
-
-class MultipleInheritanceNodeBase {
- public:
- MultipleInheritanceNodeBase() : field_taking_up_space_(0) {}
- int field_taking_up_space_;
-};
-
-class MultipleInheritanceNode : public MultipleInheritanceNodeBase,
- public LinkNode<MultipleInheritanceNode> {
- public:
- MultipleInheritanceNode() = default;
-};
-
-class MovableNode : public LinkNode<MovableNode> {
- public:
- explicit MovableNode(int id) : id_(id) {}
-
- MovableNode(MovableNode&&) = default;
-
- int id() const { return id_; }
-
- private:
- int id_;
-};
-
-// Checks that when iterating |list| (either from head to tail, or from
-// tail to head, as determined by |forward|), we get back |node_ids|,
-// which is an array of size |num_nodes|.
-void ExpectListContentsForDirection(const LinkedList<Node>& list,
- int num_nodes, const int* node_ids, bool forward) {
- int i = 0;
- for (const LinkNode<Node>* node = (forward ? list.head() : list.tail());
- node != list.end();
- node = (forward ? node->next() : node->previous())) {
- ASSERT_LT(i, num_nodes);
- int index_of_id = forward ? i : num_nodes - i - 1;
- EXPECT_EQ(node_ids[index_of_id], node->value()->id());
- ++i;
- }
- EXPECT_EQ(num_nodes, i);
-}
-
-void ExpectListContents(const LinkedList<Node>& list,
- int num_nodes,
- const int* node_ids) {
- {
- SCOPED_TRACE("Iterating forward (from head to tail)");
- ExpectListContentsForDirection(list, num_nodes, node_ids, true);
- }
- {
- SCOPED_TRACE("Iterating backward (from tail to head)");
- ExpectListContentsForDirection(list, num_nodes, node_ids, false);
- }
-}
-
-TEST(LinkedList, Empty) {
- LinkedList<Node> list;
- EXPECT_EQ(list.end(), list.head());
- EXPECT_EQ(list.end(), list.tail());
- ExpectListContents(list, 0, nullptr);
-}
-
-TEST(LinkedList, Append) {
- LinkedList<Node> list;
- ExpectListContents(list, 0, nullptr);
-
- Node n1(1);
- list.Append(&n1);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n1, list.tail());
- {
- const int expected[] = {1};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- Node n2(2);
- list.Append(&n2);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n2, list.tail());
- {
- const int expected[] = {1, 2};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- Node n3(3);
- list.Append(&n3);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n3, list.tail());
- {
- const int expected[] = {1, 2, 3};
- ExpectListContents(list, arraysize(expected), expected);
- }
-}
-
-TEST(LinkedList, RemoveFromList) {
- LinkedList<Node> list;
-
- Node n1(1);
- Node n2(2);
- Node n3(3);
- Node n4(4);
- Node n5(5);
-
- list.Append(&n1);
- list.Append(&n2);
- list.Append(&n3);
- list.Append(&n4);
- list.Append(&n5);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n5, list.tail());
- {
- const int expected[] = {1, 2, 3, 4, 5};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- // Remove from the middle.
- n3.RemoveFromList();
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n5, list.tail());
- {
- const int expected[] = {1, 2, 4, 5};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- // Remove from the tail.
- n5.RemoveFromList();
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n4, list.tail());
- {
- const int expected[] = {1, 2, 4};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- // Remove from the head.
- n1.RemoveFromList();
-
- EXPECT_EQ(&n2, list.head());
- EXPECT_EQ(&n4, list.tail());
- {
- const int expected[] = {2, 4};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- // Empty the list.
- n2.RemoveFromList();
- n4.RemoveFromList();
-
- ExpectListContents(list, 0, nullptr);
- EXPECT_EQ(list.end(), list.head());
- EXPECT_EQ(list.end(), list.tail());
-
- // Fill the list once again.
- list.Append(&n1);
- list.Append(&n2);
- list.Append(&n3);
- list.Append(&n4);
- list.Append(&n5);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n5, list.tail());
- {
- const int expected[] = {1, 2, 3, 4, 5};
- ExpectListContents(list, arraysize(expected), expected);
- }
-}
-
-TEST(LinkedList, InsertBefore) {
- LinkedList<Node> list;
-
- Node n1(1);
- Node n2(2);
- Node n3(3);
- Node n4(4);
-
- list.Append(&n1);
- list.Append(&n2);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n2, list.tail());
- {
- const int expected[] = {1, 2};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- n3.InsertBefore(&n2);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n2, list.tail());
- {
- const int expected[] = {1, 3, 2};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- n4.InsertBefore(&n1);
-
- EXPECT_EQ(&n4, list.head());
- EXPECT_EQ(&n2, list.tail());
- {
- const int expected[] = {4, 1, 3, 2};
- ExpectListContents(list, arraysize(expected), expected);
- }
-}
-
-TEST(LinkedList, InsertAfter) {
- LinkedList<Node> list;
-
- Node n1(1);
- Node n2(2);
- Node n3(3);
- Node n4(4);
-
- list.Append(&n1);
- list.Append(&n2);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n2, list.tail());
- {
- const int expected[] = {1, 2};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- n3.InsertAfter(&n2);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n3, list.tail());
- {
- const int expected[] = {1, 2, 3};
- ExpectListContents(list, arraysize(expected), expected);
- }
-
- n4.InsertAfter(&n1);
-
- EXPECT_EQ(&n1, list.head());
- EXPECT_EQ(&n3, list.tail());
- {
- const int expected[] = {1, 4, 2, 3};
- ExpectListContents(list, arraysize(expected), expected);
- }
-}
-
-TEST(LinkedList, MultipleInheritanceNode) {
- MultipleInheritanceNode node;
- EXPECT_EQ(&node, node.value());
-}
-
-TEST(LinkedList, EmptyListIsEmpty) {
- LinkedList<Node> list;
- EXPECT_TRUE(list.empty());
-}
-
-TEST(LinkedList, NonEmptyListIsNotEmpty) {
- LinkedList<Node> list;
-
- Node n(1);
- list.Append(&n);
-
- EXPECT_FALSE(list.empty());
-}
-
-TEST(LinkedList, EmptiedListIsEmptyAgain) {
- LinkedList<Node> list;
-
- Node n(1);
- list.Append(&n);
- n.RemoveFromList();
-
- EXPECT_TRUE(list.empty());
-}
-
-TEST(LinkedList, NodesCanBeReused) {
- LinkedList<Node> list1;
- LinkedList<Node> list2;
-
- Node n(1);
- list1.Append(&n);
- n.RemoveFromList();
- list2.Append(&n);
-
- EXPECT_EQ(list2.head()->value(), &n);
-}
-
-TEST(LinkedList, RemovedNodeHasNullNextPrevious) {
- LinkedList<Node> list;
-
- Node n(1);
- list.Append(&n);
- n.RemoveFromList();
-
- EXPECT_EQ(nullptr, n.next());
- EXPECT_EQ(nullptr, n.previous());
-}
-
-TEST(LinkedList, NodeMoveConstructor) {
- LinkedList<MovableNode> list;
-
- MovableNode n1(1);
- MovableNode n2(2);
- MovableNode n3(3);
-
- list.Append(&n1);
- list.Append(&n2);
- list.Append(&n3);
-
- EXPECT_EQ(&n1, n2.previous());
- EXPECT_EQ(&n2, n1.next());
- EXPECT_EQ(&n3, n2.next());
- EXPECT_EQ(&n2, n3.previous());
- EXPECT_EQ(2, n2.id());
-
- MovableNode n2_new(std::move(n2));
-
- EXPECT_EQ(nullptr, n2.next());
- EXPECT_EQ(nullptr, n2.previous());
-
- EXPECT_EQ(&n1, n2_new.previous());
- EXPECT_EQ(&n2_new, n1.next());
- EXPECT_EQ(&n3, n2_new.next());
- EXPECT_EQ(&n2_new, n3.previous());
- EXPECT_EQ(2, n2_new.id());
-}
-
-} // namespace
-} // namespace base
diff --git a/base/containers/mru_cache_unittest.cc b/base/containers/mru_cache_unittest.cc
deleted file mode 100644
index 28e6f0d66b..0000000000
--- a/base/containers/mru_cache_unittest.cc
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright (c) 2011 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/containers/mru_cache.h"
-
-#include <cstddef>
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "base/trace_event/memory_usage_estimator.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-int cached_item_live_count = 0;
-
-struct CachedItem {
- CachedItem() : value(0) {
- cached_item_live_count++;
- }
-
- explicit CachedItem(int new_value) : value(new_value) {
- cached_item_live_count++;
- }
-
- explicit CachedItem(const CachedItem& other) : value(other.value) {
- cached_item_live_count++;
- }
-
- ~CachedItem() {
- cached_item_live_count--;
- }
-
- int value;
-};
-
-} // namespace
-
-TEST(MRUCacheTest, Basic) {
- typedef base::MRUCache<int, CachedItem> Cache;
- Cache cache(Cache::NO_AUTO_EVICT);
-
- // Check failure conditions
- {
- CachedItem test_item;
- EXPECT_TRUE(cache.Get(0) == cache.end());
- EXPECT_TRUE(cache.Peek(0) == cache.end());
- }
-
- static const int kItem1Key = 5;
- CachedItem item1(10);
- Cache::iterator inserted_item = cache.Put(kItem1Key, item1);
- EXPECT_EQ(1U, cache.size());
-
- // Check that item1 was properly inserted.
- {
- Cache::iterator found = cache.Get(kItem1Key);
- EXPECT_TRUE(inserted_item == cache.begin());
- EXPECT_TRUE(found != cache.end());
-
- found = cache.Peek(kItem1Key);
- EXPECT_TRUE(found != cache.end());
-
- EXPECT_EQ(kItem1Key, found->first);
- EXPECT_EQ(item1.value, found->second.value);
- }
-
- static const int kItem2Key = 7;
- CachedItem item2(12);
- cache.Put(kItem2Key, item2);
- EXPECT_EQ(2U, cache.size());
-
- // Check that item1 is the oldest since item2 was added afterwards.
- {
- Cache::reverse_iterator oldest = cache.rbegin();
- ASSERT_TRUE(oldest != cache.rend());
- EXPECT_EQ(kItem1Key, oldest->first);
- EXPECT_EQ(item1.value, oldest->second.value);
- }
-
- // Check that item1 is still accessible by key.
- {
- Cache::iterator test_item = cache.Get(kItem1Key);
- ASSERT_TRUE(test_item != cache.end());
- EXPECT_EQ(kItem1Key, test_item->first);
- EXPECT_EQ(item1.value, test_item->second.value);
- }
-
- // Check that retrieving item1 pushed item2 to oldest.
- {
- Cache::reverse_iterator oldest = cache.rbegin();
- ASSERT_TRUE(oldest != cache.rend());
- EXPECT_EQ(kItem2Key, oldest->first);
- EXPECT_EQ(item2.value, oldest->second.value);
- }
-
- // Remove the oldest item and check that item1 is now the only member.
- {
- Cache::reverse_iterator next = cache.Erase(cache.rbegin());
-
- EXPECT_EQ(1U, cache.size());
-
- EXPECT_TRUE(next == cache.rbegin());
- EXPECT_EQ(kItem1Key, next->first);
- EXPECT_EQ(item1.value, next->second.value);
-
- cache.Erase(cache.begin());
- EXPECT_EQ(0U, cache.size());
- }
-
- // Check that Clear() works properly.
- cache.Put(kItem1Key, item1);
- cache.Put(kItem2Key, item2);
- EXPECT_EQ(2U, cache.size());
- cache.Clear();
- EXPECT_EQ(0U, cache.size());
-}
-
-TEST(MRUCacheTest, GetVsPeek) {
- typedef base::MRUCache<int, CachedItem> Cache;
- Cache cache(Cache::NO_AUTO_EVICT);
-
- static const int kItem1Key = 1;
- CachedItem item1(10);
- cache.Put(kItem1Key, item1);
-
- static const int kItem2Key = 2;
- CachedItem item2(20);
- cache.Put(kItem2Key, item2);
-
- // This should do nothing since the size is bigger than the number of items.
- cache.ShrinkToSize(100);
-
- // Check that item1 starts out as oldest
- {
- Cache::reverse_iterator iter = cache.rbegin();
- ASSERT_TRUE(iter != cache.rend());
- EXPECT_EQ(kItem1Key, iter->first);
- EXPECT_EQ(item1.value, iter->second.value);
- }
-
- // Check that Peek doesn't change ordering
- {
- Cache::iterator peekiter = cache.Peek(kItem1Key);
- ASSERT_TRUE(peekiter != cache.end());
-
- Cache::reverse_iterator iter = cache.rbegin();
- ASSERT_TRUE(iter != cache.rend());
- EXPECT_EQ(kItem1Key, iter->first);
- EXPECT_EQ(item1.value, iter->second.value);
- }
-}
-
-TEST(MRUCacheTest, KeyReplacement) {
- typedef base::MRUCache<int, CachedItem> Cache;
- Cache cache(Cache::NO_AUTO_EVICT);
-
- static const int kItem1Key = 1;
- CachedItem item1(10);
- cache.Put(kItem1Key, item1);
-
- static const int kItem2Key = 2;
- CachedItem item2(20);
- cache.Put(kItem2Key, item2);
-
- static const int kItem3Key = 3;
- CachedItem item3(30);
- cache.Put(kItem3Key, item3);
-
- static const int kItem4Key = 4;
- CachedItem item4(40);
- cache.Put(kItem4Key, item4);
-
- CachedItem item5(50);
- cache.Put(kItem3Key, item5);
-
- EXPECT_EQ(4U, cache.size());
- for (int i = 0; i < 3; ++i) {
- Cache::reverse_iterator iter = cache.rbegin();
- ASSERT_TRUE(iter != cache.rend());
- }
-
- // Make it so only the most important element is there.
- cache.ShrinkToSize(1);
-
- Cache::iterator iter = cache.begin();
- EXPECT_EQ(kItem3Key, iter->first);
- EXPECT_EQ(item5.value, iter->second.value);
-}
-
-// Make sure that the owning version release its pointers properly.
-TEST(MRUCacheTest, Owning) {
- using Cache = base::MRUCache<int, std::unique_ptr<CachedItem>>;
- Cache cache(Cache::NO_AUTO_EVICT);
-
- int initial_count = cached_item_live_count;
-
- // First insert and item and then overwrite it.
- static const int kItem1Key = 1;
- cache.Put(kItem1Key, WrapUnique(new CachedItem(20)));
- cache.Put(kItem1Key, WrapUnique(new CachedItem(22)));
-
- // There should still be one item, and one extra live item.
- Cache::iterator iter = cache.Get(kItem1Key);
- EXPECT_EQ(1U, cache.size());
- EXPECT_TRUE(iter != cache.end());
- EXPECT_EQ(initial_count + 1, cached_item_live_count);
-
- // Now remove it.
- cache.Erase(cache.begin());
- EXPECT_EQ(initial_count, cached_item_live_count);
-
- // Now try another cache that goes out of scope to make sure its pointers
- // go away.
- {
- Cache cache2(Cache::NO_AUTO_EVICT);
- cache2.Put(1, WrapUnique(new CachedItem(20)));
- cache2.Put(2, WrapUnique(new CachedItem(20)));
- }
-
- // There should be no objects leaked.
- EXPECT_EQ(initial_count, cached_item_live_count);
-
- // Check that Clear() also frees things correctly.
- {
- Cache cache2(Cache::NO_AUTO_EVICT);
- cache2.Put(1, WrapUnique(new CachedItem(20)));
- cache2.Put(2, WrapUnique(new CachedItem(20)));
- EXPECT_EQ(initial_count + 2, cached_item_live_count);
- cache2.Clear();
- EXPECT_EQ(initial_count, cached_item_live_count);
- }
-}
-
-TEST(MRUCacheTest, AutoEvict) {
- using Cache = base::MRUCache<int, std::unique_ptr<CachedItem>>;
- static const Cache::size_type kMaxSize = 3;
-
- int initial_count = cached_item_live_count;
-
- {
- Cache cache(kMaxSize);
-
- static const int kItem1Key = 1, kItem2Key = 2, kItem3Key = 3, kItem4Key = 4;
- cache.Put(kItem1Key, std::make_unique<CachedItem>(20));
- cache.Put(kItem2Key, std::make_unique<CachedItem>(21));
- cache.Put(kItem3Key, std::make_unique<CachedItem>(22));
- cache.Put(kItem4Key, std::make_unique<CachedItem>(23));
-
- // The cache should only have kMaxSize items in it even though we inserted
- // more.
- EXPECT_EQ(kMaxSize, cache.size());
- }
-
- // There should be no objects leaked.
- EXPECT_EQ(initial_count, cached_item_live_count);
-}
-
-TEST(MRUCacheTest, HashingMRUCache) {
- // Very simple test to make sure that the hashing cache works correctly.
- typedef base::HashingMRUCache<std::string, CachedItem> Cache;
- Cache cache(Cache::NO_AUTO_EVICT);
-
- CachedItem one(1);
- cache.Put("First", one);
-
- CachedItem two(2);
- cache.Put("Second", two);
-
- EXPECT_EQ(one.value, cache.Get("First")->second.value);
- EXPECT_EQ(two.value, cache.Get("Second")->second.value);
- cache.ShrinkToSize(1);
- EXPECT_EQ(two.value, cache.Get("Second")->second.value);
- EXPECT_TRUE(cache.Get("First") == cache.end());
-}
-
-TEST(MRUCacheTest, Swap) {
- typedef base::MRUCache<int, CachedItem> Cache;
- Cache cache1(Cache::NO_AUTO_EVICT);
-
- // Insert two items into cache1.
- static const int kItem1Key = 1;
- CachedItem item1(2);
- Cache::iterator inserted_item = cache1.Put(kItem1Key, item1);
- EXPECT_EQ(1U, cache1.size());
-
- static const int kItem2Key = 3;
- CachedItem item2(4);
- cache1.Put(kItem2Key, item2);
- EXPECT_EQ(2U, cache1.size());
-
- // Verify cache1's elements.
- {
- Cache::iterator iter = cache1.begin();
- ASSERT_TRUE(iter != cache1.end());
- EXPECT_EQ(kItem2Key, iter->first);
- EXPECT_EQ(item2.value, iter->second.value);
-
- ++iter;
- ASSERT_TRUE(iter != cache1.end());
- EXPECT_EQ(kItem1Key, iter->first);
- EXPECT_EQ(item1.value, iter->second.value);
- }
-
- // Create another cache2.
- Cache cache2(Cache::NO_AUTO_EVICT);
-
- // Insert three items into cache2.
- static const int kItem3Key = 5;
- CachedItem item3(6);
- inserted_item = cache2.Put(kItem3Key, item3);
- EXPECT_EQ(1U, cache2.size());
-
- static const int kItem4Key = 7;
- CachedItem item4(8);
- cache2.Put(kItem4Key, item4);
- EXPECT_EQ(2U, cache2.size());
-
- static const int kItem5Key = 9;
- CachedItem item5(10);
- cache2.Put(kItem5Key, item5);
- EXPECT_EQ(3U, cache2.size());
-
- // Verify cache2's elements.
- {
- Cache::iterator iter = cache2.begin();
- ASSERT_TRUE(iter != cache2.end());
- EXPECT_EQ(kItem5Key, iter->first);
- EXPECT_EQ(item5.value, iter->second.value);
-
- ++iter;
- ASSERT_TRUE(iter != cache2.end());
- EXPECT_EQ(kItem4Key, iter->first);
- EXPECT_EQ(item4.value, iter->second.value);
-
- ++iter;
- ASSERT_TRUE(iter != cache2.end());
- EXPECT_EQ(kItem3Key, iter->first);
- EXPECT_EQ(item3.value, iter->second.value);
- }
-
- // Swap cache1 and cache2 and verify cache2 has cache1's elements and cache1
- // has cache2's elements.
- cache2.Swap(cache1);
-
- EXPECT_EQ(3U, cache1.size());
- EXPECT_EQ(2U, cache2.size());
-
- // Verify cache1's elements.
- {
- Cache::iterator iter = cache1.begin();
- ASSERT_TRUE(iter != cache1.end());
- EXPECT_EQ(kItem5Key, iter->first);
- EXPECT_EQ(item5.value, iter->second.value);
-
- ++iter;
- ASSERT_TRUE(iter != cache1.end());
- EXPECT_EQ(kItem4Key, iter->first);
- EXPECT_EQ(item4.value, iter->second.value);
-
- ++iter;
- ASSERT_TRUE(iter != cache1.end());
- EXPECT_EQ(kItem3Key, iter->first);
- EXPECT_EQ(item3.value, iter->second.value);
- }
-
- // Verify cache2's elements.
- {
- Cache::iterator iter = cache2.begin();
- ASSERT_TRUE(iter != cache2.end());
- EXPECT_EQ(kItem2Key, iter->first);
- EXPECT_EQ(item2.value, iter->second.value);
-
- ++iter;
- ASSERT_TRUE(iter != cache2.end());
- EXPECT_EQ(kItem1Key, iter->first);
- EXPECT_EQ(item1.value, iter->second.value);
- }
-}
-
-TEST(MRUCacheTest, EstimateMemory) {
- base::MRUCache<std::string, int> cache(10);
-
- const std::string key(100u, 'a');
- cache.Put(key, 1);
-
- EXPECT_GT(trace_event::EstimateMemoryUsage(cache),
- trace_event::EstimateMemoryUsage(key));
-}
-
-} // namespace base
diff --git a/base/containers/small_map_unittest.cc b/base/containers/small_map_unittest.cc
deleted file mode 100644
index 6561851f9d..0000000000
--- a/base/containers/small_map_unittest.cc
+++ /dev/null
@@ -1,603 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/containers/small_map.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <functional>
-#include <map>
-#include <unordered_map>
-
-#include "base/logging.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(SmallMap, General) {
- small_map<std::unordered_map<int, int>> m;
-
- EXPECT_TRUE(m.empty());
-
- m[0] = 5;
-
- EXPECT_FALSE(m.empty());
- EXPECT_EQ(m.size(), 1u);
-
- m[9] = 2;
-
- EXPECT_FALSE(m.empty());
- EXPECT_EQ(m.size(), 2u);
-
- EXPECT_EQ(m[9], 2);
- EXPECT_EQ(m[0], 5);
- EXPECT_FALSE(m.UsingFullMap());
-
- small_map<std::unordered_map<int, int>>::iterator iter(m.begin());
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 0);
- EXPECT_EQ(iter->second, 5);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ((*iter).first, 9);
- EXPECT_EQ((*iter).second, 2);
- ++iter;
- EXPECT_TRUE(iter == m.end());
-
- m[8] = 23;
- m[1234] = 90;
- m[-5] = 6;
-
- EXPECT_EQ(m[ 9], 2);
- EXPECT_EQ(m[ 0], 5);
- EXPECT_EQ(m[1234], 90);
- EXPECT_EQ(m[ 8], 23);
- EXPECT_EQ(m[ -5], 6);
- EXPECT_EQ(m.size(), 5u);
- EXPECT_FALSE(m.empty());
- EXPECT_TRUE(m.UsingFullMap());
-
- iter = m.begin();
- for (int i = 0; i < 5; i++) {
- EXPECT_TRUE(iter != m.end());
- ++iter;
- }
- EXPECT_TRUE(iter == m.end());
-
- const small_map<std::unordered_map<int, int>>& ref = m;
- EXPECT_TRUE(ref.find(1234) != m.end());
- EXPECT_TRUE(ref.find(5678) == m.end());
-}
-
-TEST(SmallMap, PostFixIteratorIncrement) {
- small_map<std::unordered_map<int, int>> m;
- m[0] = 5;
- m[2] = 3;
-
- {
- small_map<std::unordered_map<int, int>>::iterator iter(m.begin());
- small_map<std::unordered_map<int, int>>::iterator last(iter++);
- ++last;
- EXPECT_TRUE(last == iter);
- }
-
- {
- small_map<std::unordered_map<int, int>>::const_iterator iter(m.begin());
- small_map<std::unordered_map<int, int>>::const_iterator last(iter++);
- ++last;
- EXPECT_TRUE(last == iter);
- }
-}
-
-// Based on the General testcase.
-TEST(SmallMap, CopyConstructor) {
- small_map<std::unordered_map<int, int>> src;
-
- {
- small_map<std::unordered_map<int, int>> m(src);
- EXPECT_TRUE(m.empty());
- }
-
- src[0] = 5;
-
- {
- small_map<std::unordered_map<int, int>> m(src);
- EXPECT_FALSE(m.empty());
- EXPECT_EQ(m.size(), 1u);
- }
-
- src[9] = 2;
-
- {
- small_map<std::unordered_map<int, int>> m(src);
- EXPECT_FALSE(m.empty());
- EXPECT_EQ(m.size(), 2u);
-
- EXPECT_EQ(m[9], 2);
- EXPECT_EQ(m[0], 5);
- EXPECT_FALSE(m.UsingFullMap());
- }
-
- src[8] = 23;
- src[1234] = 90;
- src[-5] = 6;
-
- {
- small_map<std::unordered_map<int, int>> m(src);
- EXPECT_EQ(m[ 9], 2);
- EXPECT_EQ(m[ 0], 5);
- EXPECT_EQ(m[1234], 90);
- EXPECT_EQ(m[ 8], 23);
- EXPECT_EQ(m[ -5], 6);
- EXPECT_EQ(m.size(), 5u);
- EXPECT_FALSE(m.empty());
- EXPECT_TRUE(m.UsingFullMap());
- }
-}
-
-template <class inner>
-static bool SmallMapIsSubset(small_map<inner> const& a,
- small_map<inner> const& b) {
- typename small_map<inner>::const_iterator it;
- for (it = a.begin(); it != a.end(); ++it) {
- typename small_map<inner>::const_iterator it_in_b = b.find(it->first);
- if (it_in_b == b.end() || it_in_b->second != it->second)
- return false;
- }
- return true;
-}
-
-template <class inner>
-static bool SmallMapEqual(small_map<inner> const& a,
- small_map<inner> const& b) {
- return SmallMapIsSubset(a, b) && SmallMapIsSubset(b, a);
-}
-
-TEST(SmallMap, AssignmentOperator) {
- small_map<std::unordered_map<int, int>> src_small;
- small_map<std::unordered_map<int, int>> src_large;
-
- src_small[1] = 20;
- src_small[2] = 21;
- src_small[3] = 22;
- EXPECT_FALSE(src_small.UsingFullMap());
-
- src_large[1] = 20;
- src_large[2] = 21;
- src_large[3] = 22;
- src_large[5] = 23;
- src_large[6] = 24;
- src_large[7] = 25;
- EXPECT_TRUE(src_large.UsingFullMap());
-
- // Assignments to empty.
- small_map<std::unordered_map<int, int>> dest_small;
- dest_small = src_small;
- EXPECT_TRUE(SmallMapEqual(dest_small, src_small));
- EXPECT_EQ(dest_small.UsingFullMap(),
- src_small.UsingFullMap());
-
- small_map<std::unordered_map<int, int>> dest_large;
- dest_large = src_large;
- EXPECT_TRUE(SmallMapEqual(dest_large, src_large));
- EXPECT_EQ(dest_large.UsingFullMap(),
- src_large.UsingFullMap());
-
- // Assignments which assign from full to small, and vice versa.
- dest_small = src_large;
- EXPECT_TRUE(SmallMapEqual(dest_small, src_large));
- EXPECT_EQ(dest_small.UsingFullMap(),
- src_large.UsingFullMap());
-
- dest_large = src_small;
- EXPECT_TRUE(SmallMapEqual(dest_large, src_small));
- EXPECT_EQ(dest_large.UsingFullMap(),
- src_small.UsingFullMap());
-
- // Double check that SmallMapEqual works:
- dest_large[42] = 666;
- EXPECT_FALSE(SmallMapEqual(dest_large, src_small));
-}
-
-TEST(SmallMap, Insert) {
- small_map<std::unordered_map<int, int>> sm;
-
- // loop through the transition from small map to map.
- for (int i = 1; i <= 10; ++i) {
- VLOG(1) << "Iteration " << i;
- // insert an element
- std::pair<small_map<std::unordered_map<int, int>>::iterator, bool> ret;
- ret = sm.insert(std::make_pair(i, 100*i));
- EXPECT_TRUE(ret.second);
- EXPECT_TRUE(ret.first == sm.find(i));
- EXPECT_EQ(ret.first->first, i);
- EXPECT_EQ(ret.first->second, 100*i);
-
- // try to insert it again with different value, fails, but we still get an
- // iterator back with the original value.
- ret = sm.insert(std::make_pair(i, -i));
- EXPECT_FALSE(ret.second);
- EXPECT_TRUE(ret.first == sm.find(i));
- EXPECT_EQ(ret.first->first, i);
- EXPECT_EQ(ret.first->second, 100*i);
-
- // check the state of the map.
- for (int j = 1; j <= i; ++j) {
- small_map<std::unordered_map<int, int>>::iterator it = sm.find(j);
- EXPECT_TRUE(it != sm.end());
- EXPECT_EQ(it->first, j);
- EXPECT_EQ(it->second, j * 100);
- }
- EXPECT_EQ(sm.size(), static_cast<size_t>(i));
- EXPECT_FALSE(sm.empty());
- }
-}
-
-TEST(SmallMap, InsertRange) {
- // loop through the transition from small map to map.
- for (int elements = 0; elements <= 10; ++elements) {
- VLOG(1) << "Elements " << elements;
- std::unordered_map<int, int> normal_map;
- for (int i = 1; i <= elements; ++i) {
- normal_map.insert(std::make_pair(i, 100*i));
- }
-
- small_map<std::unordered_map<int, int>> sm;
- sm.insert(normal_map.begin(), normal_map.end());
- EXPECT_EQ(normal_map.size(), sm.size());
- for (int i = 1; i <= elements; ++i) {
- VLOG(1) << "Iteration " << i;
- EXPECT_TRUE(sm.find(i) != sm.end());
- EXPECT_EQ(sm.find(i)->first, i);
- EXPECT_EQ(sm.find(i)->second, 100*i);
- }
- }
-}
-
-TEST(SmallMap, Erase) {
- small_map<std::unordered_map<std::string, int>> m;
- small_map<std::unordered_map<std::string, int>>::iterator iter;
-
- m["monday"] = 1;
- m["tuesday"] = 2;
- m["wednesday"] = 3;
-
- EXPECT_EQ(m["monday" ], 1);
- EXPECT_EQ(m["tuesday" ], 2);
- EXPECT_EQ(m["wednesday"], 3);
- EXPECT_EQ(m.count("tuesday"), 1u);
- EXPECT_FALSE(m.UsingFullMap());
-
- iter = m.begin();
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, "monday");
- EXPECT_EQ(iter->second, 1);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, "tuesday");
- EXPECT_EQ(iter->second, 2);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, "wednesday");
- EXPECT_EQ(iter->second, 3);
- ++iter;
- EXPECT_TRUE(iter == m.end());
-
- EXPECT_EQ(m.erase("tuesday"), 1u);
-
- EXPECT_EQ(m["monday" ], 1);
- EXPECT_EQ(m["wednesday"], 3);
- EXPECT_EQ(m.count("tuesday"), 0u);
- EXPECT_EQ(m.erase("tuesday"), 0u);
-
- iter = m.begin();
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, "monday");
- EXPECT_EQ(iter->second, 1);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, "wednesday");
- EXPECT_EQ(iter->second, 3);
- ++iter;
- EXPECT_TRUE(iter == m.end());
-
- m["thursday"] = 4;
- m["friday"] = 5;
- EXPECT_EQ(m.size(), 4u);
- EXPECT_FALSE(m.empty());
- EXPECT_FALSE(m.UsingFullMap());
-
- m["saturday"] = 6;
- EXPECT_TRUE(m.UsingFullMap());
-
- EXPECT_EQ(m.count("friday"), 1u);
- EXPECT_EQ(m.erase("friday"), 1u);
- EXPECT_TRUE(m.UsingFullMap());
- EXPECT_EQ(m.count("friday"), 0u);
- EXPECT_EQ(m.erase("friday"), 0u);
-
- EXPECT_EQ(m.size(), 4u);
- EXPECT_FALSE(m.empty());
- EXPECT_EQ(m.erase("monday"), 1u);
- EXPECT_EQ(m.size(), 3u);
- EXPECT_FALSE(m.empty());
-
- m.clear();
- EXPECT_FALSE(m.UsingFullMap());
- EXPECT_EQ(m.size(), 0u);
- EXPECT_TRUE(m.empty());
-}
-
-TEST(SmallMap, EraseReturnsIteratorFollowingRemovedElement) {
- small_map<std::unordered_map<std::string, int>> m;
- small_map<std::unordered_map<std::string, int>>::iterator iter;
-
- m["a"] = 0;
- m["b"] = 1;
- m["c"] = 2;
-
- // Erase first item.
- auto following_iter = m.erase(m.begin());
- EXPECT_EQ(m.begin(), following_iter);
- EXPECT_EQ(2u, m.size());
- EXPECT_EQ(m.count("a"), 0u);
- EXPECT_EQ(m.count("b"), 1u);
- EXPECT_EQ(m.count("c"), 1u);
-
- // Iterate to last item and erase it.
- ++following_iter;
- following_iter = m.erase(following_iter);
- ASSERT_EQ(1u, m.size());
- EXPECT_EQ(m.end(), following_iter);
- EXPECT_EQ(m.count("b"), 0u);
- EXPECT_EQ(m.count("c"), 1u);
-
- // Erase remaining item.
- following_iter = m.erase(m.begin());
- EXPECT_TRUE(m.empty());
- EXPECT_EQ(m.end(), following_iter);
-}
-
-TEST(SmallMap, NonHashMap) {
- small_map<std::map<int, int>, 4, std::equal_to<int>> m;
- EXPECT_TRUE(m.empty());
-
- m[9] = 2;
- m[0] = 5;
-
- EXPECT_EQ(m[9], 2);
- EXPECT_EQ(m[0], 5);
- EXPECT_EQ(m.size(), 2u);
- EXPECT_FALSE(m.empty());
- EXPECT_FALSE(m.UsingFullMap());
-
- small_map<std::map<int, int>, 4, std::equal_to<int>>::iterator iter(
- m.begin());
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 9);
- EXPECT_EQ(iter->second, 2);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 0);
- EXPECT_EQ(iter->second, 5);
- ++iter;
- EXPECT_TRUE(iter == m.end());
- --iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 0);
- EXPECT_EQ(iter->second, 5);
-
- m[8] = 23;
- m[1234] = 90;
- m[-5] = 6;
-
- EXPECT_EQ(m[ 9], 2);
- EXPECT_EQ(m[ 0], 5);
- EXPECT_EQ(m[1234], 90);
- EXPECT_EQ(m[ 8], 23);
- EXPECT_EQ(m[ -5], 6);
- EXPECT_EQ(m.size(), 5u);
- EXPECT_FALSE(m.empty());
- EXPECT_TRUE(m.UsingFullMap());
-
- iter = m.begin();
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, -5);
- EXPECT_EQ(iter->second, 6);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 0);
- EXPECT_EQ(iter->second, 5);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 8);
- EXPECT_EQ(iter->second, 23);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 9);
- EXPECT_EQ(iter->second, 2);
- ++iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 1234);
- EXPECT_EQ(iter->second, 90);
- ++iter;
- EXPECT_TRUE(iter == m.end());
- --iter;
- ASSERT_TRUE(iter != m.end());
- EXPECT_EQ(iter->first, 1234);
- EXPECT_EQ(iter->second, 90);
-}
-
-TEST(SmallMap, DefaultEqualKeyWorks) {
- // If these tests compile, they pass. The EXPECT calls are only there to avoid
- // unused variable warnings.
- small_map<std::unordered_map<int, int>> hm;
- EXPECT_EQ(0u, hm.size());
- small_map<std::map<int, int>> m;
- EXPECT_EQ(0u, m.size());
-}
-
-namespace {
-
-class unordered_map_add_item : public std::unordered_map<int, int> {
- public:
- unordered_map_add_item() = default;
- explicit unordered_map_add_item(const std::pair<int, int>& item) {
- insert(item);
- }
-};
-
-void InitMap(unordered_map_add_item* map_ctor) {
- new (map_ctor) unordered_map_add_item(std::make_pair(0, 0));
-}
-
-class unordered_map_add_item_initializer {
- public:
- explicit unordered_map_add_item_initializer(int item_to_add)
- : item_(item_to_add) {}
- unordered_map_add_item_initializer() : item_(0) {}
- void operator()(unordered_map_add_item* map_ctor) const {
- new (map_ctor) unordered_map_add_item(std::make_pair(item_, item_));
- }
-
- int item_;
-};
-
-} // anonymous namespace
-
-TEST(SmallMap, SubclassInitializationWithFunctionPointer) {
- small_map<unordered_map_add_item, 4, std::equal_to<int>,
- void (&)(unordered_map_add_item*)>
- m(InitMap);
-
- EXPECT_TRUE(m.empty());
-
- m[1] = 1;
- m[2] = 2;
- m[3] = 3;
- m[4] = 4;
-
- EXPECT_EQ(4u, m.size());
- EXPECT_EQ(0u, m.count(0));
-
- m[5] = 5;
- EXPECT_EQ(6u, m.size());
- // Our function adds an extra item when we convert to a map.
- EXPECT_EQ(1u, m.count(0));
-}
-
-TEST(SmallMap, SubclassInitializationWithFunctionObject) {
- small_map<unordered_map_add_item, 4, std::equal_to<int>,
- unordered_map_add_item_initializer>
- m(unordered_map_add_item_initializer(-1));
-
- EXPECT_TRUE(m.empty());
-
- m[1] = 1;
- m[2] = 2;
- m[3] = 3;
- m[4] = 4;
-
- EXPECT_EQ(4u, m.size());
- EXPECT_EQ(0u, m.count(-1));
-
- m[5] = 5;
- EXPECT_EQ(6u, m.size());
- // Our functor adds an extra item when we convert to a map.
- EXPECT_EQ(1u, m.count(-1));
-}
-
-namespace {
-
-// This class acts as a basic implementation of a move-only type. The canonical
-// example of such a type is scoped_ptr/unique_ptr.
-template <typename V>
-class MoveOnlyType {
- public:
- MoveOnlyType() : value_(0) {}
- explicit MoveOnlyType(V value) : value_(value) {}
-
- MoveOnlyType(MoveOnlyType&& other) {
- *this = std::move(other);
- }
-
- MoveOnlyType& operator=(MoveOnlyType&& other) {
- value_ = other.value_;
- other.value_ = 0;
- return *this;
- }
-
- MoveOnlyType(const MoveOnlyType&) = delete;
- MoveOnlyType& operator=(const MoveOnlyType&) = delete;
-
- V value() const { return value_; }
-
- private:
- V value_;
-};
-
-} // namespace
-
-TEST(SmallMap, MoveOnlyValueType) {
- small_map<std::map<int, MoveOnlyType<int>>, 2> m;
-
- m[0] = MoveOnlyType<int>(1);
- m[1] = MoveOnlyType<int>(2);
- m.erase(m.begin());
-
- // small_map will move m[1] to an earlier index in the internal array.
- EXPECT_EQ(m.size(), 1u);
- EXPECT_EQ(m[1].value(), 2);
-
- m[0] = MoveOnlyType<int>(1);
- // small_map must move the values from the array into the internal std::map.
- m[2] = MoveOnlyType<int>(3);
-
- EXPECT_EQ(m.size(), 3u);
- EXPECT_EQ(m[0].value(), 1);
- EXPECT_EQ(m[1].value(), 2);
- EXPECT_EQ(m[2].value(), 3);
-
- m.erase(m.begin());
-
- // small_map should also let internal std::map erase with a move-only type.
- EXPECT_EQ(m.size(), 2u);
- EXPECT_EQ(m[1].value(), 2);
- EXPECT_EQ(m[2].value(), 3);
-}
-
-TEST(SmallMap, Emplace) {
- small_map<std::map<size_t, MoveOnlyType<size_t>>> sm;
-
- // loop through the transition from small map to map.
- for (size_t i = 1; i <= 10; ++i) {
- // insert an element
- auto ret = sm.emplace(i, MoveOnlyType<size_t>(100 * i));
- EXPECT_TRUE(ret.second);
- EXPECT_TRUE(ret.first == sm.find(i));
- EXPECT_EQ(ret.first->first, i);
- EXPECT_EQ(ret.first->second.value(), 100 * i);
-
- // try to insert it again with different value, fails, but we still get an
- // iterator back with the original value.
- ret = sm.emplace(i, MoveOnlyType<size_t>(i));
- EXPECT_FALSE(ret.second);
- EXPECT_TRUE(ret.first == sm.find(i));
- EXPECT_EQ(ret.first->first, i);
- EXPECT_EQ(ret.first->second.value(), 100 * i);
-
- // check the state of the map.
- for (size_t j = 1; j <= i; ++j) {
- const auto it = sm.find(j);
- EXPECT_TRUE(it != sm.end());
- EXPECT_EQ(it->first, j);
- EXPECT_EQ(it->second.value(), j * 100);
- }
- EXPECT_EQ(sm.size(), i);
- EXPECT_FALSE(sm.empty());
- }
-}
-
-} // namespace base
diff --git a/base/containers/stack_container_unittest.cc b/base/containers/stack_container_unittest.cc
deleted file mode 100644
index b6bb9b6352..0000000000
--- a/base/containers/stack_container_unittest.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/containers/stack_container.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/memory/ref_counted.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class Dummy : public base::RefCounted<Dummy> {
- public:
- explicit Dummy(int* alive) : alive_(alive) {
- ++*alive_;
- }
-
- private:
- friend class base::RefCounted<Dummy>;
-
- ~Dummy() {
- --*alive_;
- }
-
- int* const alive_;
-};
-
-} // namespace
-
-TEST(StackContainer, Vector) {
- const int stack_size = 3;
- StackVector<int, stack_size> vect;
- const int* stack_buffer = &vect.stack_data().stack_buffer()[0];
-
- // The initial |stack_size| elements should appear in the stack buffer.
- EXPECT_EQ(static_cast<size_t>(stack_size), vect.container().capacity());
- for (int i = 0; i < stack_size; i++) {
- vect.container().push_back(i);
- EXPECT_EQ(stack_buffer, &vect.container()[0]);
- EXPECT_TRUE(vect.stack_data().used_stack_buffer_);
- }
-
- // Adding more elements should push the array onto the heap.
- for (int i = 0; i < stack_size; i++) {
- vect.container().push_back(i + stack_size);
- EXPECT_NE(stack_buffer, &vect.container()[0]);
- EXPECT_FALSE(vect.stack_data().used_stack_buffer_);
- }
-
- // The array should still be in order.
- for (int i = 0; i < stack_size * 2; i++)
- EXPECT_EQ(i, vect.container()[i]);
-
- // Resize to smaller. Our STL implementation won't reallocate in this case,
- // otherwise it might use our stack buffer. We reserve right after the resize
- // to guarantee it isn't using the stack buffer, even though it doesn't have
- // much data.
- vect.container().resize(stack_size);
- vect.container().reserve(stack_size * 2);
- EXPECT_FALSE(vect.stack_data().used_stack_buffer_);
-
- // Copying the small vector to another should use the same allocator and use
- // the now-unused stack buffer. GENERALLY CALLERS SHOULD NOT DO THIS since
- // they have to get the template types just right and it can cause errors.
- std::vector<int, StackAllocator<int, stack_size> > other(vect.container());
- EXPECT_EQ(stack_buffer, &other.front());
- EXPECT_TRUE(vect.stack_data().used_stack_buffer_);
- for (int i = 0; i < stack_size; i++)
- EXPECT_EQ(i, other[i]);
-}
-
-TEST(StackContainer, VectorDoubleDelete) {
- // Regression testing for double-delete.
- typedef StackVector<scoped_refptr<Dummy>, 2> Vector;
- typedef Vector::ContainerType Container;
- Vector vect;
-
- int alive = 0;
- scoped_refptr<Dummy> dummy(new Dummy(&alive));
- EXPECT_EQ(alive, 1);
-
- vect->push_back(dummy);
- EXPECT_EQ(alive, 1);
-
- Dummy* dummy_unref = dummy.get();
- dummy = nullptr;
- EXPECT_EQ(alive, 1);
-
- Container::iterator itr = std::find(vect->begin(), vect->end(), dummy_unref);
- EXPECT_EQ(itr->get(), dummy_unref);
- vect->erase(itr);
- EXPECT_EQ(alive, 0);
-
- // Shouldn't crash at exit.
-}
-
-namespace {
-
-template <size_t alignment>
-class AlignedData {
- public:
- AlignedData() { memset(data_, 0, alignment); }
- ~AlignedData() = default;
- alignas(alignment) char data_[alignment];
-};
-
-} // anonymous namespace
-
-#define EXPECT_ALIGNED(ptr, align) \
- EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
-
-TEST(StackContainer, BufferAlignment) {
- StackVector<wchar_t, 16> text;
- text->push_back(L'A');
- EXPECT_ALIGNED(&text[0], alignof(wchar_t));
-
- StackVector<double, 1> doubles;
- doubles->push_back(0.0);
- EXPECT_ALIGNED(&doubles[0], alignof(double));
-
- StackVector<AlignedData<16>, 1> aligned16;
- aligned16->push_back(AlignedData<16>());
- EXPECT_ALIGNED(&aligned16[0], 16);
-
-#if !defined(__GNUC__) || defined(ARCH_CPU_X86_FAMILY)
- // It seems that non-X86 gcc doesn't respect greater than 16 byte alignment.
- // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33721 for details.
- // TODO(sbc):re-enable this if GCC starts respecting higher alignments.
- StackVector<AlignedData<256>, 1> aligned256;
- aligned256->push_back(AlignedData<256>());
- EXPECT_ALIGNED(&aligned256[0], 256);
-#endif
-}
-
-template class StackVector<int, 2>;
-template class StackVector<scoped_refptr<Dummy>, 2>;
-
-} // namespace base
diff --git a/base/containers/unique_ptr_adapters.h b/base/containers/unique_ptr_adapters.h
deleted file mode 100644
index 42fab190ab..0000000000
--- a/base/containers/unique_ptr_adapters.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
-#define BASE_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
-
-#include <memory>
-
-namespace base {
-
-// This transparent comparator allows to lookup by raw pointer in
-// a container of unique pointers. This functionality is based on C++14
-// extensions to std::set/std::map interface, and can also be used
-// with base::flat_set/base::flat_map.
-//
-// Example usage:
-// Foo* foo = ...
-// std::set<std::unique_ptr<Foo>, base::UniquePtrComparator> set;
-// set.insert(std::unique_ptr<Foo>(foo));
-// ...
-// auto it = set.find(foo);
-// EXPECT_EQ(foo, it->get());
-//
-// You can find more information about transparent comparisons here:
-// http://en.cppreference.com/w/cpp/utility/functional/less_void
-struct UniquePtrComparator {
- using is_transparent = int;
-
- template <typename T>
- bool operator()(const std::unique_ptr<T>& lhs,
- const std::unique_ptr<T>& rhs) const {
- return lhs < rhs;
- }
-
- template <typename T>
- bool operator()(const T* lhs, const std::unique_ptr<T>& rhs) const {
- return lhs < rhs.get();
- }
-
- template <typename T>
- bool operator()(const std::unique_ptr<T>& lhs, const T* rhs) const {
- return lhs.get() < rhs;
- }
-};
-
-// UniquePtrMatcher is useful for finding an element in a container of
-// unique_ptrs when you have the raw pointer.
-//
-// Example usage:
-// std::vector<std::unique_ptr<Foo>> vector;
-// Foo* element = ...
-// auto iter = std::find_if(vector.begin(), vector.end(),
-// MatchesUniquePtr(element));
-//
-// Example of erasing from container:
-// EraseIf(v, MatchesUniquePtr(element));
-//
-template <class T, class Deleter = std::default_delete<T>>
-struct UniquePtrMatcher {
- explicit UniquePtrMatcher(T* t) : t_(t) {}
-
- bool operator()(const std::unique_ptr<T, Deleter>& o) {
- return o.get() == t_;
- }
-
- private:
- T* const t_;
-};
-
-template <class T, class Deleter = std::default_delete<T>>
-UniquePtrMatcher<T, Deleter> MatchesUniquePtr(T* t) {
- return UniquePtrMatcher<T, Deleter>(t);
-}
-
-} // namespace base
-
-#endif // BASE_CONTAINERS_UNIQUE_PTR_ADAPTERS_H_
diff --git a/base/containers/unique_ptr_adapters_unittest.cc b/base/containers/unique_ptr_adapters_unittest.cc
deleted file mode 100644
index 5b8f1fc024..0000000000
--- a/base/containers/unique_ptr_adapters_unittest.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2017 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/containers/unique_ptr_adapters.h"
-
-#include <memory>
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class Foo {
- public:
- Foo() { instance_count++; }
- ~Foo() { instance_count--; }
- static int instance_count;
-};
-
-int Foo::instance_count = 0;
-
-TEST(UniquePtrComparatorTest, Basic) {
- std::set<std::unique_ptr<Foo>, UniquePtrComparator> set;
- Foo* foo1 = new Foo();
- Foo* foo2 = new Foo();
- Foo* foo3 = new Foo();
- EXPECT_EQ(3, Foo::instance_count);
-
- set.emplace(foo1);
- set.emplace(foo2);
-
- auto it1 = set.find(foo1);
- EXPECT_TRUE(it1 != set.end());
- EXPECT_EQ(foo1, it1->get());
-
- {
- auto it2 = set.find(foo2);
- EXPECT_TRUE(it2 != set.end());
- EXPECT_EQ(foo2, it2->get());
- }
-
- EXPECT_TRUE(set.find(foo3) == set.end());
-
- set.erase(it1);
- EXPECT_EQ(2, Foo::instance_count);
-
- EXPECT_TRUE(set.find(foo1) == set.end());
-
- {
- auto it2 = set.find(foo2);
- EXPECT_TRUE(it2 != set.end());
- EXPECT_EQ(foo2, it2->get());
- }
-
- set.clear();
- EXPECT_EQ(1, Foo::instance_count);
-
- EXPECT_TRUE(set.find(foo1) == set.end());
- EXPECT_TRUE(set.find(foo2) == set.end());
- EXPECT_TRUE(set.find(foo3) == set.end());
-
- delete foo3;
- EXPECT_EQ(0, Foo::instance_count);
-}
-
-TEST(UniquePtrMatcherTest, Basic) {
- std::vector<std::unique_ptr<Foo>> v;
- auto foo_ptr1 = std::make_unique<Foo>();
- Foo* foo1 = foo_ptr1.get();
- v.push_back(std::move(foo_ptr1));
- auto foo_ptr2 = std::make_unique<Foo>();
- Foo* foo2 = foo_ptr2.get();
- v.push_back(std::move(foo_ptr2));
-
- {
- auto iter = std::find_if(v.begin(), v.end(), UniquePtrMatcher<Foo>(foo1));
- ASSERT_TRUE(iter != v.end());
- EXPECT_EQ(foo1, iter->get());
- }
-
- {
- auto iter = std::find_if(v.begin(), v.end(), UniquePtrMatcher<Foo>(foo2));
- ASSERT_TRUE(iter != v.end());
- EXPECT_EQ(foo2, iter->get());
- }
-
- {
- auto iter = std::find_if(v.begin(), v.end(), MatchesUniquePtr(foo2));
- ASSERT_TRUE(iter != v.end());
- EXPECT_EQ(foo2, iter->get());
- }
-}
-
-class TestDeleter {
- public:
- void operator()(Foo* foo) { delete foo; }
-};
-
-TEST(UniquePtrMatcherTest, Deleter) {
- using UniqueFoo = std::unique_ptr<Foo, TestDeleter>;
- std::vector<UniqueFoo> v;
- UniqueFoo foo_ptr1(new Foo);
- Foo* foo1 = foo_ptr1.get();
- v.push_back(std::move(foo_ptr1));
- UniqueFoo foo_ptr2(new Foo);
- Foo* foo2 = foo_ptr2.get();
- v.push_back(std::move(foo_ptr2));
-
- {
- auto iter = std::find_if(v.begin(), v.end(),
- UniquePtrMatcher<Foo, TestDeleter>(foo1));
- ASSERT_TRUE(iter != v.end());
- EXPECT_EQ(foo1, iter->get());
- }
-
- {
- auto iter = std::find_if(v.begin(), v.end(),
- UniquePtrMatcher<Foo, TestDeleter>(foo2));
- ASSERT_TRUE(iter != v.end());
- EXPECT_EQ(foo2, iter->get());
- }
-
- {
- auto iter = std::find_if(v.begin(), v.end(),
- MatchesUniquePtr<Foo, TestDeleter>(foo2));
- ASSERT_TRUE(iter != v.end());
- EXPECT_EQ(foo2, iter->get());
- }
-}
-
-} // namespace
-} // namespace base
diff --git a/base/debug/activity_analyzer.cc b/base/debug/activity_analyzer.cc
deleted file mode 100644
index d787829579..0000000000
--- a/base/debug/activity_analyzer.cc
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2016 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/debug/activity_analyzer.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-
-namespace base {
-namespace debug {
-
-namespace {
-// An empty snapshot that can be returned when there otherwise is none.
-LazyInstance<ActivityUserData::Snapshot>::Leaky g_empty_user_data_snapshot;
-
-// DO NOT CHANGE VALUES. This is logged persistently in a histogram.
-enum AnalyzerCreationError {
- kInvalidMemoryMappedFile,
- kPmaBadFile,
- kPmaUninitialized,
- kPmaDeleted,
- kPmaCorrupt,
- kAnalyzerCreationErrorMax // Keep this last.
-};
-
-void LogAnalyzerCreationError(AnalyzerCreationError error) {
- UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.AnalyzerCreationError",
- error, kAnalyzerCreationErrorMax);
-}
-
-} // namespace
-
-ThreadActivityAnalyzer::Snapshot::Snapshot() = default;
-ThreadActivityAnalyzer::Snapshot::~Snapshot() = default;
-
-ThreadActivityAnalyzer::ThreadActivityAnalyzer(
- const ThreadActivityTracker& tracker)
- : activity_snapshot_valid_(tracker.CreateSnapshot(&activity_snapshot_)) {}
-
-ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size)
- : ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {}
-
-ThreadActivityAnalyzer::ThreadActivityAnalyzer(
- PersistentMemoryAllocator* allocator,
- PersistentMemoryAllocator::Reference reference)
- : ThreadActivityAnalyzer(allocator->GetAsArray<char>(
- reference,
- GlobalActivityTracker::kTypeIdActivityTracker,
- PersistentMemoryAllocator::kSizeAny),
- allocator->GetAllocSize(reference)) {}
-
-ThreadActivityAnalyzer::~ThreadActivityAnalyzer() = default;
-
-void ThreadActivityAnalyzer::AddGlobalInformation(
- GlobalActivityAnalyzer* global) {
- if (!IsValid())
- return;
-
- // User-data is held at the global scope even though it's referenced at the
- // thread scope.
- activity_snapshot_.user_data_stack.clear();
- for (auto& activity : activity_snapshot_.activity_stack) {
- // The global GetUserDataSnapshot will return an empty snapshot if the ref
- // or id is not valid.
- activity_snapshot_.user_data_stack.push_back(global->GetUserDataSnapshot(
- activity_snapshot_.process_id, activity.user_data_ref,
- activity.user_data_id));
- }
-}
-
-GlobalActivityAnalyzer::GlobalActivityAnalyzer(
- std::unique_ptr<PersistentMemoryAllocator> allocator)
- : allocator_(std::move(allocator)),
- analysis_stamp_(0LL),
- allocator_iterator_(allocator_.get()) {
- DCHECK(allocator_);
-}
-
-GlobalActivityAnalyzer::~GlobalActivityAnalyzer() = default;
-
-// static
-std::unique_ptr<GlobalActivityAnalyzer>
-GlobalActivityAnalyzer::CreateWithAllocator(
- std::unique_ptr<PersistentMemoryAllocator> allocator) {
- if (allocator->GetMemoryState() ==
- PersistentMemoryAllocator::MEMORY_UNINITIALIZED) {
- LogAnalyzerCreationError(kPmaUninitialized);
- return nullptr;
- }
- if (allocator->GetMemoryState() ==
- PersistentMemoryAllocator::MEMORY_DELETED) {
- LogAnalyzerCreationError(kPmaDeleted);
- return nullptr;
- }
- if (allocator->IsCorrupt()) {
- LogAnalyzerCreationError(kPmaCorrupt);
- return nullptr;
- }
-
- return WrapUnique(new GlobalActivityAnalyzer(std::move(allocator)));
-}
-
-#if !defined(OS_NACL)
-// static
-std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile(
- const FilePath& file_path) {
- // Map the file read-write so it can guarantee consistency between
- // the analyzer and any trackers that my still be active.
- std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
- mmfile->Initialize(file_path, MemoryMappedFile::READ_WRITE);
- if (!mmfile->IsValid()) {
- LogAnalyzerCreationError(kInvalidMemoryMappedFile);
- return nullptr;
- }
-
- if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)) {
- LogAnalyzerCreationError(kPmaBadFile);
- return nullptr;
- }
-
- return CreateWithAllocator(std::make_unique<FilePersistentMemoryAllocator>(
- std::move(mmfile), 0, 0, StringPiece(), /*readonly=*/true));
-}
-#endif // !defined(OS_NACL)
-
-// static
-std::unique_ptr<GlobalActivityAnalyzer>
-GlobalActivityAnalyzer::CreateWithSharedMemory(
- std::unique_ptr<SharedMemory> shm) {
- if (shm->mapped_size() == 0 ||
- !SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(*shm)) {
- return nullptr;
- }
- return CreateWithAllocator(std::make_unique<SharedPersistentMemoryAllocator>(
- std::move(shm), 0, StringPiece(), /*readonly=*/true));
-}
-
-// static
-std::unique_ptr<GlobalActivityAnalyzer>
-GlobalActivityAnalyzer::CreateWithSharedMemoryHandle(
- const SharedMemoryHandle& handle,
- size_t size) {
- std::unique_ptr<SharedMemory> shm(
- new SharedMemory(handle, /*readonly=*/true));
- if (!shm->Map(size))
- return nullptr;
- return CreateWithSharedMemory(std::move(shm));
-}
-
-int64_t GlobalActivityAnalyzer::GetFirstProcess() {
- PrepareAllAnalyzers();
- return GetNextProcess();
-}
-
-int64_t GlobalActivityAnalyzer::GetNextProcess() {
- if (process_ids_.empty())
- return 0;
- int64_t pid = process_ids_.back();
- process_ids_.pop_back();
- return pid;
-}
-
-ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetFirstAnalyzer(int64_t pid) {
- analyzers_iterator_ = analyzers_.begin();
- analyzers_iterator_pid_ = pid;
- if (analyzers_iterator_ == analyzers_.end())
- return nullptr;
- int64_t create_stamp;
- if (analyzers_iterator_->second->GetProcessId(&create_stamp) == pid &&
- create_stamp <= analysis_stamp_) {
- return analyzers_iterator_->second.get();
- }
- return GetNextAnalyzer();
-}
-
-ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetNextAnalyzer() {
- DCHECK(analyzers_iterator_ != analyzers_.end());
- int64_t create_stamp;
- do {
- ++analyzers_iterator_;
- if (analyzers_iterator_ == analyzers_.end())
- return nullptr;
- } while (analyzers_iterator_->second->GetProcessId(&create_stamp) !=
- analyzers_iterator_pid_ ||
- create_stamp > analysis_stamp_);
- return analyzers_iterator_->second.get();
-}
-
-ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread(
- const ThreadKey& key) {
- auto found = analyzers_.find(key);
- if (found == analyzers_.end())
- return nullptr;
- return found->second.get();
-}
-
-ActivityUserData::Snapshot GlobalActivityAnalyzer::GetUserDataSnapshot(
- int64_t pid,
- uint32_t ref,
- uint32_t id) {
- ActivityUserData::Snapshot snapshot;
-
- void* memory = allocator_->GetAsArray<char>(
- ref, GlobalActivityTracker::kTypeIdUserDataRecord,
- PersistentMemoryAllocator::kSizeAny);
- if (memory) {
- size_t size = allocator_->GetAllocSize(ref);
- const ActivityUserData user_data(memory, size);
- user_data.CreateSnapshot(&snapshot);
- int64_t process_id;
- int64_t create_stamp;
- if (!ActivityUserData::GetOwningProcessId(memory, &process_id,
- &create_stamp) ||
- process_id != pid || user_data.id() != id) {
- // This allocation has been overwritten since it was created. Return an
- // empty snapshot because whatever was captured is incorrect.
- snapshot.clear();
- }
- }
-
- return snapshot;
-}
-
-const ActivityUserData::Snapshot&
-GlobalActivityAnalyzer::GetProcessDataSnapshot(int64_t pid) {
- auto iter = process_data_.find(pid);
- if (iter == process_data_.end())
- return g_empty_user_data_snapshot.Get();
- if (iter->second.create_stamp > analysis_stamp_)
- return g_empty_user_data_snapshot.Get();
- DCHECK_EQ(pid, iter->second.process_id);
- return iter->second.data;
-}
-
-std::vector<std::string> GlobalActivityAnalyzer::GetLogMessages() {
- std::vector<std::string> messages;
- PersistentMemoryAllocator::Reference ref;
-
- PersistentMemoryAllocator::Iterator iter(allocator_.get());
- while ((ref = iter.GetNextOfType(
- GlobalActivityTracker::kTypeIdGlobalLogMessage)) != 0) {
- const char* message = allocator_->GetAsArray<char>(
- ref, GlobalActivityTracker::kTypeIdGlobalLogMessage,
- PersistentMemoryAllocator::kSizeAny);
- if (message)
- messages.push_back(message);
- }
-
- return messages;
-}
-
-std::vector<GlobalActivityTracker::ModuleInfo>
-GlobalActivityAnalyzer::GetModules(int64_t pid) {
- std::vector<GlobalActivityTracker::ModuleInfo> modules;
-
- PersistentMemoryAllocator::Iterator iter(allocator_.get());
- const GlobalActivityTracker::ModuleInfoRecord* record;
- while (
- (record =
- iter.GetNextOfObject<GlobalActivityTracker::ModuleInfoRecord>()) !=
- nullptr) {
- int64_t process_id;
- int64_t create_stamp;
- if (!OwningProcess::GetOwningProcessId(&record->owner, &process_id,
- &create_stamp) ||
- pid != process_id || create_stamp > analysis_stamp_) {
- continue;
- }
- GlobalActivityTracker::ModuleInfo info;
- if (record->DecodeTo(&info, allocator_->GetAllocSize(
- allocator_->GetAsReference(record)))) {
- modules.push_back(std::move(info));
- }
- }
-
- return modules;
-}
-
-GlobalActivityAnalyzer::ProgramLocation
-GlobalActivityAnalyzer::GetProgramLocationFromAddress(uint64_t address) {
- // TODO(bcwhite): Implement this.
- return { 0, 0 };
-}
-
-bool GlobalActivityAnalyzer::IsDataComplete() const {
- DCHECK(allocator_);
- return !allocator_->IsFull();
-}
-
-GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot() = default;
-GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
- const UserDataSnapshot& rhs) = default;
-GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
- UserDataSnapshot&& rhs) = default;
-GlobalActivityAnalyzer::UserDataSnapshot::~UserDataSnapshot() = default;
-
-void GlobalActivityAnalyzer::PrepareAllAnalyzers() {
- // Record the time when analysis started.
- analysis_stamp_ = base::Time::Now().ToInternalValue();
-
- // Fetch all the records. This will retrieve only ones created since the
- // last run since the PMA iterator will continue from where it left off.
- uint32_t type;
- PersistentMemoryAllocator::Reference ref;
- while ((ref = allocator_iterator_.GetNext(&type)) != 0) {
- switch (type) {
- case GlobalActivityTracker::kTypeIdActivityTracker:
- case GlobalActivityTracker::kTypeIdActivityTrackerFree:
- case GlobalActivityTracker::kTypeIdProcessDataRecord:
- case GlobalActivityTracker::kTypeIdProcessDataRecordFree:
- case PersistentMemoryAllocator::kTypeIdTransitioning:
- // Active, free, or transitioning: add it to the list of references
- // for later analysis.
- memory_references_.insert(ref);
- break;
- }
- }
-
- // Clear out any old information.
- analyzers_.clear();
- process_data_.clear();
- process_ids_.clear();
- std::set<int64_t> seen_pids;
-
- // Go through all the known references and create objects for them with
- // snapshots of the current state.
- for (PersistentMemoryAllocator::Reference memory_ref : memory_references_) {
- // Get the actual data segment for the tracker. Any type will do since it
- // is checked below.
- void* const base = allocator_->GetAsArray<char>(
- memory_ref, PersistentMemoryAllocator::kTypeIdAny,
- PersistentMemoryAllocator::kSizeAny);
- const size_t size = allocator_->GetAllocSize(memory_ref);
- if (!base)
- continue;
-
- switch (allocator_->GetType(memory_ref)) {
- case GlobalActivityTracker::kTypeIdActivityTracker: {
- // Create the analyzer on the data. This will capture a snapshot of the
- // tracker state. This can fail if the tracker is somehow corrupted or
- // is in the process of shutting down.
- std::unique_ptr<ThreadActivityAnalyzer> analyzer(
- new ThreadActivityAnalyzer(base, size));
- if (!analyzer->IsValid())
- continue;
- analyzer->AddGlobalInformation(this);
-
- // Track PIDs.
- int64_t pid = analyzer->GetProcessId();
- if (seen_pids.find(pid) == seen_pids.end()) {
- process_ids_.push_back(pid);
- seen_pids.insert(pid);
- }
-
- // Add this analyzer to the map of known ones, indexed by a unique
- // thread
- // identifier.
- DCHECK(!base::ContainsKey(analyzers_, analyzer->GetThreadKey()));
- analyzer->allocator_reference_ = ref;
- analyzers_[analyzer->GetThreadKey()] = std::move(analyzer);
- } break;
-
- case GlobalActivityTracker::kTypeIdProcessDataRecord: {
- // Get the PID associated with this data record.
- int64_t process_id;
- int64_t create_stamp;
- ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
- DCHECK(!base::ContainsKey(process_data_, process_id));
-
- // Create a snapshot of the data. This can fail if the data is somehow
- // corrupted or the process shutdown and the memory being released.
- UserDataSnapshot& snapshot = process_data_[process_id];
- snapshot.process_id = process_id;
- snapshot.create_stamp = create_stamp;
- const ActivityUserData process_data(base, size);
- if (!process_data.CreateSnapshot(&snapshot.data))
- break;
-
- // Check that nothing changed. If it did, forget what was recorded.
- ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
- if (process_id != snapshot.process_id ||
- create_stamp != snapshot.create_stamp) {
- process_data_.erase(process_id);
- break;
- }
-
- // Track PIDs.
- if (seen_pids.find(process_id) == seen_pids.end()) {
- process_ids_.push_back(process_id);
- seen_pids.insert(process_id);
- }
- } break;
- }
- }
-
- // Reverse the list of PIDs so that they get popped in the order found.
- std::reverse(process_ids_.begin(), process_ids_.end());
-}
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/activity_analyzer.h b/base/debug/activity_analyzer.h
deleted file mode 100644
index 9add85a9e0..0000000000
--- a/base/debug/activity_analyzer.h
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_DEBUG_ACTIVITY_ANALYZER_H_
-#define BASE_DEBUG_ACTIVITY_ANALYZER_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/debug/activity_tracker.h"
-
-namespace base {
-namespace debug {
-
-class GlobalActivityAnalyzer;
-
-// This class provides analysis of data captured from a ThreadActivityTracker.
-// When created, it takes a snapshot of the data held by the tracker and
-// makes that information available to other code.
-class BASE_EXPORT ThreadActivityAnalyzer {
- public:
- struct BASE_EXPORT Snapshot : ThreadActivityTracker::Snapshot {
- Snapshot();
- ~Snapshot();
-
- // The user-data snapshot for an activity, matching the |activity_stack|
- // of ThreadActivityTracker::Snapshot, if any.
- std::vector<ActivityUserData::Snapshot> user_data_stack;
- };
-
- // This class provides keys that uniquely identify a thread, even across
- // multiple processes.
- class ThreadKey {
- public:
- ThreadKey(int64_t pid, int64_t tid) : pid_(pid), tid_(tid) {}
-
- bool operator<(const ThreadKey& rhs) const {
- if (pid_ != rhs.pid_)
- return pid_ < rhs.pid_;
- return tid_ < rhs.tid_;
- }
-
- bool operator==(const ThreadKey& rhs) const {
- return (pid_ == rhs.pid_ && tid_ == rhs.tid_);
- }
-
- private:
- int64_t pid_;
- int64_t tid_;
- };
-
- // Creates an analyzer for an existing activity |tracker|. A snapshot is taken
- // immediately and the tracker is not referenced again.
- explicit ThreadActivityAnalyzer(const ThreadActivityTracker& tracker);
-
- // Creates an analyzer for a block of memory currently or previously in-use
- // by an activity-tracker. A snapshot is taken immediately and the memory
- // is not referenced again.
- ThreadActivityAnalyzer(void* base, size_t size);
-
- // Creates an analyzer for a block of memory held within a persistent-memory
- // |allocator| at the given |reference|. A snapshot is taken immediately and
- // the memory is not referenced again.
- ThreadActivityAnalyzer(PersistentMemoryAllocator* allocator,
- PersistentMemoryAllocator::Reference reference);
-
- ~ThreadActivityAnalyzer();
-
- // Adds information from the global analyzer.
- void AddGlobalInformation(GlobalActivityAnalyzer* global);
-
- // Returns true iff the contained data is valid. Results from all other
- // methods are undefined if this returns false.
- bool IsValid() { return activity_snapshot_valid_; }
-
- // Gets the process id and its creation stamp.
- int64_t GetProcessId(int64_t* out_stamp = nullptr) {
- if (out_stamp)
- *out_stamp = activity_snapshot_.create_stamp;
- return activity_snapshot_.process_id;
- }
-
- // Gets the name of the thread.
- const std::string& GetThreadName() {
- return activity_snapshot_.thread_name;
- }
-
- // Gets the TheadKey for this thread.
- ThreadKey GetThreadKey() {
- return ThreadKey(activity_snapshot_.process_id,
- activity_snapshot_.thread_id);
- }
-
- const Snapshot& activity_snapshot() { return activity_snapshot_; }
-
- private:
- friend class GlobalActivityAnalyzer;
-
- // The snapshot of the activity tracker taken at the moment of construction.
- Snapshot activity_snapshot_;
-
- // Flag indicating if the snapshot data is valid.
- bool activity_snapshot_valid_;
-
- // A reference into a persistent memory allocator, used by the global
- // analyzer to know where this tracker came from.
- PersistentMemoryAllocator::Reference allocator_reference_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadActivityAnalyzer);
-};
-
-
-// This class manages analyzers for all known processes and threads as stored
-// in a persistent memory allocator. It supports retrieval of them through
-// iteration and directly using a ThreadKey, which allows for cross-references
-// to be resolved.
-// Note that though atomic snapshots are used and everything has its snapshot
-// taken at the same time, the multi-snapshot itself is not atomic and thus may
-// show small inconsistencies between threads if attempted on a live system.
-class BASE_EXPORT GlobalActivityAnalyzer {
- public:
- struct ProgramLocation {
- int module;
- uintptr_t offset;
- };
-
- using ThreadKey = ThreadActivityAnalyzer::ThreadKey;
-
- // Creates a global analyzer from a persistent memory allocator.
- explicit GlobalActivityAnalyzer(
- std::unique_ptr<PersistentMemoryAllocator> allocator);
-
- ~GlobalActivityAnalyzer();
-
- // Creates a global analyzer using a given persistent-memory |allocator|.
- static std::unique_ptr<GlobalActivityAnalyzer> CreateWithAllocator(
- std::unique_ptr<PersistentMemoryAllocator> allocator);
-
-#if !defined(OS_NACL)
- // Creates a global analyzer using the contents of a file given in
- // |file_path|.
- static std::unique_ptr<GlobalActivityAnalyzer> CreateWithFile(
- const FilePath& file_path);
-#endif // !defined(OS_NACL)
-
- // Like above but accesses an allocator in a mapped shared-memory segment.
- static std::unique_ptr<GlobalActivityAnalyzer> CreateWithSharedMemory(
- std::unique_ptr<SharedMemory> shm);
-
- // Like above but takes a handle to an existing shared memory segment and
- // maps it before creating the tracker.
- static std::unique_ptr<GlobalActivityAnalyzer> CreateWithSharedMemoryHandle(
- const SharedMemoryHandle& handle,
- size_t size);
-
- // Iterates over all known valid processes and returns their PIDs or zero
- // if there are no more. Calls to GetFirstProcess() will perform a global
- // snapshot in order to provide a relatively consistent state across the
- // future calls to GetNextProcess() and GetFirst/NextAnalyzer(). PIDs are
- // returned in the order they're found meaning that a first-launched
- // controlling process will be found first. Note, however, that space
- // freed by an exiting process may be re-used by a later process.
- int64_t GetFirstProcess();
- int64_t GetNextProcess();
-
- // Iterates over all known valid analyzers for the a given process or returns
- // null if there are no more.
- //
- // GetFirstProcess() must be called first in order to capture a global
- // snapshot! Ownership stays with the global analyzer object and all existing
- // analyzer pointers are invalidated when GetFirstProcess() is called.
- ThreadActivityAnalyzer* GetFirstAnalyzer(int64_t pid);
- ThreadActivityAnalyzer* GetNextAnalyzer();
-
- // Gets the analyzer for a specific thread or null if there is none.
- // Ownership stays with the global analyzer object.
- ThreadActivityAnalyzer* GetAnalyzerForThread(const ThreadKey& key);
-
- // Extract user data based on a reference and its identifier.
- ActivityUserData::Snapshot GetUserDataSnapshot(int64_t pid,
- uint32_t ref,
- uint32_t id);
-
- // Extract the data for a specific process. An empty snapshot will be
- // returned if the process is not known.
- const ActivityUserData::Snapshot& GetProcessDataSnapshot(int64_t pid);
-
- // Gets all log messages stored within.
- std::vector<std::string> GetLogMessages();
-
- // Gets modules corresponding to a pid. This pid must come from a call to
- // GetFirst/NextProcess. Only modules that were first registered prior to
- // GetFirstProcess's snapshot are returned.
- std::vector<GlobalActivityTracker::ModuleInfo> GetModules(int64_t pid);
-
- // Gets the corresponding "program location" for a given "program counter".
- // This will return {0,0} if no mapping could be found.
- ProgramLocation GetProgramLocationFromAddress(uint64_t address);
-
- // Returns whether the data is complete. Data can be incomplete if the
- // recording size quota is hit.
- bool IsDataComplete() const;
-
- private:
- using AnalyzerMap =
- std::map<ThreadKey, std::unique_ptr<ThreadActivityAnalyzer>>;
-
- struct UserDataSnapshot {
- // Complex class needs out-of-line ctor/dtor.
- UserDataSnapshot();
- UserDataSnapshot(const UserDataSnapshot& rhs);
- UserDataSnapshot(UserDataSnapshot&& rhs);
- ~UserDataSnapshot();
-
- int64_t process_id;
- int64_t create_stamp;
- ActivityUserData::Snapshot data;
- };
-
- // Finds, creates, and indexes analyzers for all known processes and threads.
- void PrepareAllAnalyzers();
-
- // The persistent memory allocator holding all tracking data.
- std::unique_ptr<PersistentMemoryAllocator> allocator_;
-
- // The time stamp when analysis began. This is used to prevent looking into
- // process IDs that get reused when analyzing a live system.
- int64_t analysis_stamp_;
-
- // The iterator for finding tracking information in the allocator.
- PersistentMemoryAllocator::Iterator allocator_iterator_;
-
- // A set of all interesting memory references found within the allocator.
- std::set<PersistentMemoryAllocator::Reference> memory_references_;
-
- // A set of all process-data memory references found within the allocator.
- std::map<int64_t, UserDataSnapshot> process_data_;
-
- // A set of all process IDs collected during PrepareAllAnalyzers. These are
- // popped and returned one-by-one with calls to GetFirst/NextProcess().
- std::vector<int64_t> process_ids_;
-
- // A map, keyed by ThreadKey, of all valid activity analyzers.
- AnalyzerMap analyzers_;
-
- // The iterator within the analyzers_ map for returning analyzers through
- // first/next iteration.
- AnalyzerMap::iterator analyzers_iterator_;
- int64_t analyzers_iterator_pid_;
-
- DISALLOW_COPY_AND_ASSIGN(GlobalActivityAnalyzer);
-};
-
-} // namespace debug
-} // namespace base
-
-#endif // BASE_DEBUG_ACTIVITY_ANALYZER_H_
diff --git a/base/debug/activity_analyzer_unittest.cc b/base/debug/activity_analyzer_unittest.cc
deleted file mode 100644
index e08b43aff3..0000000000
--- a/base/debug/activity_analyzer_unittest.cc
+++ /dev/null
@@ -1,546 +0,0 @@
-// Copyright 2016 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/debug/activity_analyzer.h"
-
-#include <atomic>
-#include <memory>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/debug/activity_tracker.h"
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/memory/ptr_util.h"
-#include "base/pending_task.h"
-#include "base/process/process.h"
-#include "base/stl_util.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/spin_wait.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace debug {
-
-namespace {
-
-class TestActivityTracker : public ThreadActivityTracker {
- public:
- TestActivityTracker(std::unique_ptr<char[]> memory, size_t mem_size)
- : ThreadActivityTracker(memset(memory.get(), 0, mem_size), mem_size),
- mem_segment_(std::move(memory)) {}
-
- ~TestActivityTracker() override = default;
-
- private:
- std::unique_ptr<char[]> mem_segment_;
-};
-
-} // namespace
-
-
-class ActivityAnalyzerTest : public testing::Test {
- public:
- const int kMemorySize = 1 << 20; // 1MiB
- const int kStackSize = 1 << 10; // 1KiB
-
- ActivityAnalyzerTest() = default;
-
- ~ActivityAnalyzerTest() override {
- GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
- if (global_tracker) {
- global_tracker->ReleaseTrackerForCurrentThreadForTesting();
- delete global_tracker;
- }
- }
-
- std::unique_ptr<ThreadActivityTracker> CreateActivityTracker() {
- std::unique_ptr<char[]> memory(new char[kStackSize]);
- return std::make_unique<TestActivityTracker>(std::move(memory), kStackSize);
- }
-
- template <typename Function>
- void AsOtherProcess(int64_t pid, Function function) {
- std::unique_ptr<GlobalActivityTracker> old_global =
- GlobalActivityTracker::ReleaseForTesting();
- ASSERT_TRUE(old_global);
-
- PersistentMemoryAllocator* old_allocator = old_global->allocator();
- std::unique_ptr<PersistentMemoryAllocator> new_allocator(
- std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(old_allocator->data()), old_allocator->size(), 0,
- 0, "", false));
- GlobalActivityTracker::CreateWithAllocator(std::move(new_allocator), 3,
- pid);
-
- function();
-
- GlobalActivityTracker::ReleaseForTesting();
- GlobalActivityTracker::SetForTesting(std::move(old_global));
- }
-
- static void DoNothing() {}
-};
-
-TEST_F(ActivityAnalyzerTest, ThreadAnalyzerConstruction) {
- std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
- {
- ThreadActivityAnalyzer analyzer(*tracker);
- EXPECT_TRUE(analyzer.IsValid());
- EXPECT_EQ(PlatformThread::GetName(), analyzer.GetThreadName());
- }
-
- // TODO(bcwhite): More tests once Analyzer does more.
-}
-
-
-// GlobalActivityAnalyzer tests below.
-
-namespace {
-
-class SimpleActivityThread : public SimpleThread {
- public:
- SimpleActivityThread(const std::string& name,
- const void* source,
- Activity::Type activity,
- const ActivityData& data)
- : SimpleThread(name, Options()),
- source_(source),
- activity_(activity),
- data_(data),
- ready_(false),
- exit_(false),
- exit_condition_(&lock_) {}
-
- ~SimpleActivityThread() override = default;
-
- void Run() override {
- ThreadActivityTracker::ActivityId id =
- GlobalActivityTracker::Get()
- ->GetOrCreateTrackerForCurrentThread()
- ->PushActivity(source_, activity_, data_);
-
- {
- AutoLock auto_lock(lock_);
- ready_.store(true, std::memory_order_release);
- while (!exit_.load(std::memory_order_relaxed))
- exit_condition_.Wait();
- }
-
- GlobalActivityTracker::Get()->GetTrackerForCurrentThread()->PopActivity(id);
- }
-
- void Exit() {
- AutoLock auto_lock(lock_);
- exit_.store(true, std::memory_order_relaxed);
- exit_condition_.Signal();
- }
-
- void WaitReady() {
- SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(ready_.load(std::memory_order_acquire));
- }
-
- private:
- const void* source_;
- Activity::Type activity_;
- ActivityData data_;
-
- std::atomic<bool> ready_;
- std::atomic<bool> exit_;
- Lock lock_;
- ConditionVariable exit_condition_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleActivityThread);
-};
-
-} // namespace
-
-TEST_F(ActivityAnalyzerTest, GlobalAnalyzerConstruction) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
- GlobalActivityTracker::Get()->process_data().SetString("foo", "bar");
-
- PersistentMemoryAllocator* allocator =
- GlobalActivityTracker::Get()->allocator();
- GlobalActivityAnalyzer analyzer(std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "", true));
-
- // The only thread at this point is the test thread of this process.
- const int64_t pid = analyzer.GetFirstProcess();
- ASSERT_NE(0, pid);
- ThreadActivityAnalyzer* ta1 = analyzer.GetFirstAnalyzer(pid);
- ASSERT_TRUE(ta1);
- EXPECT_FALSE(analyzer.GetNextAnalyzer());
- ThreadActivityAnalyzer::ThreadKey tk1 = ta1->GetThreadKey();
- EXPECT_EQ(ta1, analyzer.GetAnalyzerForThread(tk1));
- EXPECT_EQ(0, analyzer.GetNextProcess());
-
- // Create a second thread that will do something.
- SimpleActivityThread t2("t2", nullptr, Activity::ACT_TASK,
- ActivityData::ForTask(11));
- t2.Start();
- t2.WaitReady();
-
- // Now there should be two. Calling GetFirstProcess invalidates any
- // previously returned analyzer pointers.
- ASSERT_EQ(pid, analyzer.GetFirstProcess());
- EXPECT_TRUE(analyzer.GetFirstAnalyzer(pid));
- EXPECT_TRUE(analyzer.GetNextAnalyzer());
- EXPECT_FALSE(analyzer.GetNextAnalyzer());
- EXPECT_EQ(0, analyzer.GetNextProcess());
-
- // Let thread exit.
- t2.Exit();
- t2.Join();
-
- // Now there should be only one again.
- ASSERT_EQ(pid, analyzer.GetFirstProcess());
- ThreadActivityAnalyzer* ta2 = analyzer.GetFirstAnalyzer(pid);
- ASSERT_TRUE(ta2);
- EXPECT_FALSE(analyzer.GetNextAnalyzer());
- ThreadActivityAnalyzer::ThreadKey tk2 = ta2->GetThreadKey();
- EXPECT_EQ(ta2, analyzer.GetAnalyzerForThread(tk2));
- EXPECT_EQ(tk1, tk2);
- EXPECT_EQ(0, analyzer.GetNextProcess());
-
- // Verify that there is process data.
- const ActivityUserData::Snapshot& data_snapshot =
- analyzer.GetProcessDataSnapshot(pid);
- ASSERT_LE(1U, data_snapshot.size());
- EXPECT_EQ("bar", data_snapshot.at("foo").GetString());
-}
-
-TEST_F(ActivityAnalyzerTest, GlobalAnalyzerFromSharedMemory) {
- SharedMemoryHandle handle1;
- SharedMemoryHandle handle2;
-
- {
- std::unique_ptr<SharedMemory> shmem(new SharedMemory());
- ASSERT_TRUE(shmem->CreateAndMapAnonymous(kMemorySize));
- handle1 = shmem->handle().Duplicate();
- ASSERT_TRUE(handle1.IsValid());
- handle2 = shmem->handle().Duplicate();
- ASSERT_TRUE(handle2.IsValid());
- }
-
- GlobalActivityTracker::CreateWithSharedMemoryHandle(handle1, kMemorySize, 0,
- "", 3);
- GlobalActivityTracker::Get()->process_data().SetString("foo", "bar");
-
- std::unique_ptr<GlobalActivityAnalyzer> analyzer =
- GlobalActivityAnalyzer::CreateWithSharedMemoryHandle(handle2,
- kMemorySize);
-
- const int64_t pid = analyzer->GetFirstProcess();
- ASSERT_NE(0, pid);
- const ActivityUserData::Snapshot& data_snapshot =
- analyzer->GetProcessDataSnapshot(pid);
- ASSERT_LE(1U, data_snapshot.size());
- EXPECT_EQ("bar", data_snapshot.at("foo").GetString());
-}
-
-TEST_F(ActivityAnalyzerTest, UserDataSnapshotTest) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
- ThreadActivityAnalyzer::Snapshot tracker_snapshot;
-
- const char string1a[] = "string1a";
- const char string1b[] = "string1b";
- const char string2a[] = "string2a";
- const char string2b[] = "string2b";
-
- PersistentMemoryAllocator* allocator =
- GlobalActivityTracker::Get()->allocator();
- GlobalActivityAnalyzer global_analyzer(
- std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "",
- true));
-
- ThreadActivityTracker* tracker =
- GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
-
- {
- ScopedActivity activity1(1, 11, 111);
- ActivityUserData& user_data1 = activity1.user_data();
- user_data1.Set("raw1", "foo1", 4);
- user_data1.SetString("string1", "bar1");
- user_data1.SetChar("char1", '1');
- user_data1.SetInt("int1", -1111);
- user_data1.SetUint("uint1", 1111);
- user_data1.SetBool("bool1", true);
- user_data1.SetReference("ref1", string1a, sizeof(string1a));
- user_data1.SetStringReference("sref1", string1b);
-
- {
- ScopedActivity activity2(2, 22, 222);
- ActivityUserData& user_data2 = activity2.user_data();
- user_data2.Set("raw2", "foo2", 4);
- user_data2.SetString("string2", "bar2");
- user_data2.SetChar("char2", '2');
- user_data2.SetInt("int2", -2222);
- user_data2.SetUint("uint2", 2222);
- user_data2.SetBool("bool2", false);
- user_data2.SetReference("ref2", string2a, sizeof(string2a));
- user_data2.SetStringReference("sref2", string2b);
-
- ASSERT_TRUE(tracker->CreateSnapshot(&tracker_snapshot));
- ASSERT_EQ(2U, tracker_snapshot.activity_stack.size());
-
- ThreadActivityAnalyzer analyzer(*tracker);
- analyzer.AddGlobalInformation(&global_analyzer);
- const ThreadActivityAnalyzer::Snapshot& analyzer_snapshot =
- analyzer.activity_snapshot();
- ASSERT_EQ(2U, analyzer_snapshot.user_data_stack.size());
- const ActivityUserData::Snapshot& user_data =
- analyzer_snapshot.user_data_stack.at(1);
- EXPECT_EQ(8U, user_data.size());
- ASSERT_TRUE(ContainsKey(user_data, "raw2"));
- EXPECT_EQ("foo2", user_data.at("raw2").Get().as_string());
- ASSERT_TRUE(ContainsKey(user_data, "string2"));
- EXPECT_EQ("bar2", user_data.at("string2").GetString().as_string());
- ASSERT_TRUE(ContainsKey(user_data, "char2"));
- EXPECT_EQ('2', user_data.at("char2").GetChar());
- ASSERT_TRUE(ContainsKey(user_data, "int2"));
- EXPECT_EQ(-2222, user_data.at("int2").GetInt());
- ASSERT_TRUE(ContainsKey(user_data, "uint2"));
- EXPECT_EQ(2222U, user_data.at("uint2").GetUint());
- ASSERT_TRUE(ContainsKey(user_data, "bool2"));
- EXPECT_FALSE(user_data.at("bool2").GetBool());
- ASSERT_TRUE(ContainsKey(user_data, "ref2"));
- EXPECT_EQ(string2a, user_data.at("ref2").GetReference().data());
- EXPECT_EQ(sizeof(string2a), user_data.at("ref2").GetReference().size());
- ASSERT_TRUE(ContainsKey(user_data, "sref2"));
- EXPECT_EQ(string2b, user_data.at("sref2").GetStringReference().data());
- EXPECT_EQ(strlen(string2b),
- user_data.at("sref2").GetStringReference().size());
- }
-
- ASSERT_TRUE(tracker->CreateSnapshot(&tracker_snapshot));
- ASSERT_EQ(1U, tracker_snapshot.activity_stack.size());
-
- ThreadActivityAnalyzer analyzer(*tracker);
- analyzer.AddGlobalInformation(&global_analyzer);
- const ThreadActivityAnalyzer::Snapshot& analyzer_snapshot =
- analyzer.activity_snapshot();
- ASSERT_EQ(1U, analyzer_snapshot.user_data_stack.size());
- const ActivityUserData::Snapshot& user_data =
- analyzer_snapshot.user_data_stack.at(0);
- EXPECT_EQ(8U, user_data.size());
- EXPECT_EQ("foo1", user_data.at("raw1").Get().as_string());
- EXPECT_EQ("bar1", user_data.at("string1").GetString().as_string());
- EXPECT_EQ('1', user_data.at("char1").GetChar());
- EXPECT_EQ(-1111, user_data.at("int1").GetInt());
- EXPECT_EQ(1111U, user_data.at("uint1").GetUint());
- EXPECT_TRUE(user_data.at("bool1").GetBool());
- EXPECT_EQ(string1a, user_data.at("ref1").GetReference().data());
- EXPECT_EQ(sizeof(string1a), user_data.at("ref1").GetReference().size());
- EXPECT_EQ(string1b, user_data.at("sref1").GetStringReference().data());
- EXPECT_EQ(strlen(string1b),
- user_data.at("sref1").GetStringReference().size());
- }
-
- ASSERT_TRUE(tracker->CreateSnapshot(&tracker_snapshot));
- ASSERT_EQ(0U, tracker_snapshot.activity_stack.size());
-}
-
-TEST_F(ActivityAnalyzerTest, GlobalUserDataTest) {
- const int64_t pid = GetCurrentProcId();
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
-
- const char string1[] = "foo";
- const char string2[] = "bar";
-
- PersistentMemoryAllocator* allocator =
- GlobalActivityTracker::Get()->allocator();
- GlobalActivityAnalyzer global_analyzer(
- std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "",
- true));
-
- ActivityUserData& process_data = GlobalActivityTracker::Get()->process_data();
- ASSERT_NE(0U, process_data.id());
- process_data.Set("raw", "foo", 3);
- process_data.SetString("string", "bar");
- process_data.SetChar("char", '9');
- process_data.SetInt("int", -9999);
- process_data.SetUint("uint", 9999);
- process_data.SetBool("bool", true);
- process_data.SetReference("ref", string1, sizeof(string1));
- process_data.SetStringReference("sref", string2);
-
- int64_t first_pid = global_analyzer.GetFirstProcess();
- DCHECK_EQ(pid, first_pid);
- const ActivityUserData::Snapshot& snapshot =
- global_analyzer.GetProcessDataSnapshot(pid);
- ASSERT_TRUE(ContainsKey(snapshot, "raw"));
- EXPECT_EQ("foo", snapshot.at("raw").Get().as_string());
- ASSERT_TRUE(ContainsKey(snapshot, "string"));
- EXPECT_EQ("bar", snapshot.at("string").GetString().as_string());
- ASSERT_TRUE(ContainsKey(snapshot, "char"));
- EXPECT_EQ('9', snapshot.at("char").GetChar());
- ASSERT_TRUE(ContainsKey(snapshot, "int"));
- EXPECT_EQ(-9999, snapshot.at("int").GetInt());
- ASSERT_TRUE(ContainsKey(snapshot, "uint"));
- EXPECT_EQ(9999U, snapshot.at("uint").GetUint());
- ASSERT_TRUE(ContainsKey(snapshot, "bool"));
- EXPECT_TRUE(snapshot.at("bool").GetBool());
- ASSERT_TRUE(ContainsKey(snapshot, "ref"));
- EXPECT_EQ(string1, snapshot.at("ref").GetReference().data());
- EXPECT_EQ(sizeof(string1), snapshot.at("ref").GetReference().size());
- ASSERT_TRUE(ContainsKey(snapshot, "sref"));
- EXPECT_EQ(string2, snapshot.at("sref").GetStringReference().data());
- EXPECT_EQ(strlen(string2), snapshot.at("sref").GetStringReference().size());
-}
-
-TEST_F(ActivityAnalyzerTest, GlobalModulesTest) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
- GlobalActivityTracker* global = GlobalActivityTracker::Get();
-
- PersistentMemoryAllocator* allocator = global->allocator();
- GlobalActivityAnalyzer global_analyzer(
- std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "",
- true));
-
- GlobalActivityTracker::ModuleInfo info1;
- info1.is_loaded = true;
- info1.address = 0x12345678;
- info1.load_time = 1111;
- info1.size = 0xABCDEF;
- info1.timestamp = 111;
- info1.age = 11;
- info1.identifier[0] = 1;
- info1.file = "anything";
- info1.debug_file = "elsewhere";
-
- global->RecordModuleInfo(info1);
- std::vector<GlobalActivityTracker::ModuleInfo> modules1;
- modules1 = global_analyzer.GetModules(global_analyzer.GetFirstProcess());
- ASSERT_EQ(1U, modules1.size());
- GlobalActivityTracker::ModuleInfo& stored1a = modules1[0];
- EXPECT_EQ(info1.is_loaded, stored1a.is_loaded);
- EXPECT_EQ(info1.address, stored1a.address);
- EXPECT_NE(info1.load_time, stored1a.load_time);
- EXPECT_EQ(info1.size, stored1a.size);
- EXPECT_EQ(info1.timestamp, stored1a.timestamp);
- EXPECT_EQ(info1.age, stored1a.age);
- EXPECT_EQ(info1.identifier[0], stored1a.identifier[0]);
- EXPECT_EQ(info1.file, stored1a.file);
- EXPECT_EQ(info1.debug_file, stored1a.debug_file);
-
- info1.is_loaded = false;
- global->RecordModuleInfo(info1);
- modules1 = global_analyzer.GetModules(global_analyzer.GetFirstProcess());
- ASSERT_EQ(1U, modules1.size());
- GlobalActivityTracker::ModuleInfo& stored1b = modules1[0];
- EXPECT_EQ(info1.is_loaded, stored1b.is_loaded);
- EXPECT_EQ(info1.address, stored1b.address);
- EXPECT_NE(info1.load_time, stored1b.load_time);
- EXPECT_EQ(info1.size, stored1b.size);
- EXPECT_EQ(info1.timestamp, stored1b.timestamp);
- EXPECT_EQ(info1.age, stored1b.age);
- EXPECT_EQ(info1.identifier[0], stored1b.identifier[0]);
- EXPECT_EQ(info1.file, stored1b.file);
- EXPECT_EQ(info1.debug_file, stored1b.debug_file);
-
- GlobalActivityTracker::ModuleInfo info2;
- info2.is_loaded = true;
- info2.address = 0x87654321;
- info2.load_time = 2222;
- info2.size = 0xFEDCBA;
- info2.timestamp = 222;
- info2.age = 22;
- info2.identifier[0] = 2;
- info2.file = "nothing";
- info2.debug_file = "farewell";
-
- global->RecordModuleInfo(info2);
- std::vector<GlobalActivityTracker::ModuleInfo> modules2;
- modules2 = global_analyzer.GetModules(global_analyzer.GetFirstProcess());
- ASSERT_EQ(2U, modules2.size());
- GlobalActivityTracker::ModuleInfo& stored2 = modules2[1];
- EXPECT_EQ(info2.is_loaded, stored2.is_loaded);
- EXPECT_EQ(info2.address, stored2.address);
- EXPECT_NE(info2.load_time, stored2.load_time);
- EXPECT_EQ(info2.size, stored2.size);
- EXPECT_EQ(info2.timestamp, stored2.timestamp);
- EXPECT_EQ(info2.age, stored2.age);
- EXPECT_EQ(info2.identifier[0], stored2.identifier[0]);
- EXPECT_EQ(info2.file, stored2.file);
- EXPECT_EQ(info2.debug_file, stored2.debug_file);
-}
-
-TEST_F(ActivityAnalyzerTest, GlobalLogMessages) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
-
- PersistentMemoryAllocator* allocator =
- GlobalActivityTracker::Get()->allocator();
- GlobalActivityAnalyzer analyzer(std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "", true));
-
- GlobalActivityTracker::Get()->RecordLogMessage("hello world");
- GlobalActivityTracker::Get()->RecordLogMessage("foo bar");
-
- std::vector<std::string> messages = analyzer.GetLogMessages();
- ASSERT_EQ(2U, messages.size());
- EXPECT_EQ("hello world", messages[0]);
- EXPECT_EQ("foo bar", messages[1]);
-}
-
-TEST_F(ActivityAnalyzerTest, GlobalMultiProcess) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 1001);
- GlobalActivityTracker* global = GlobalActivityTracker::Get();
- PersistentMemoryAllocator* allocator = global->allocator();
- EXPECT_EQ(1001, global->process_id());
-
- int64_t process_id;
- int64_t create_stamp;
- ActivityUserData::GetOwningProcessId(
- GlobalActivityTracker::Get()->process_data().GetBaseAddress(),
- &process_id, &create_stamp);
- ASSERT_EQ(1001, process_id);
-
- GlobalActivityTracker::Get()->process_data().SetInt("pid",
- global->process_id());
-
- GlobalActivityAnalyzer analyzer(std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(allocator->data()), allocator->size(), 0, 0, "", true));
-
- AsOtherProcess(2002, [&global]() {
- ASSERT_NE(global, GlobalActivityTracker::Get());
- EXPECT_EQ(2002, GlobalActivityTracker::Get()->process_id());
-
- int64_t process_id;
- int64_t create_stamp;
- ActivityUserData::GetOwningProcessId(
- GlobalActivityTracker::Get()->process_data().GetBaseAddress(),
- &process_id, &create_stamp);
- ASSERT_EQ(2002, process_id);
-
- GlobalActivityTracker::Get()->process_data().SetInt(
- "pid", GlobalActivityTracker::Get()->process_id());
- });
- ASSERT_EQ(global, GlobalActivityTracker::Get());
- EXPECT_EQ(1001, GlobalActivityTracker::Get()->process_id());
-
- const int64_t pid1 = analyzer.GetFirstProcess();
- ASSERT_EQ(1001, pid1);
- const int64_t pid2 = analyzer.GetNextProcess();
- ASSERT_EQ(2002, pid2);
- EXPECT_EQ(0, analyzer.GetNextProcess());
-
- const ActivityUserData::Snapshot& pdata1 =
- analyzer.GetProcessDataSnapshot(pid1);
- const ActivityUserData::Snapshot& pdata2 =
- analyzer.GetProcessDataSnapshot(pid2);
- EXPECT_EQ(1001, pdata1.at("pid").GetInt());
- EXPECT_EQ(2002, pdata2.at("pid").GetInt());
-}
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/asan_invalid_access.cc b/base/debug/asan_invalid_access.cc
deleted file mode 100644
index 07c19db9c5..0000000000
--- a/base/debug/asan_invalid_access.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// 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/debug/asan_invalid_access.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/debug/alias.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace base {
-namespace debug {
-
-namespace {
-
-#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
-// Corrupt a memory block and make sure that the corruption gets detected either
-// when we free it or when another crash happens (if |induce_crash| is set to
-// true).
-NOINLINE void CorruptMemoryBlock(bool induce_crash) {
- // NOTE(sebmarchand): We intentionally corrupt a memory block here in order to
- // trigger an Address Sanitizer (ASAN) error report.
- static const int kArraySize = 5;
- LONG* array = new LONG[kArraySize];
-
- // Explicitly call out to a kernel32 function to perform the memory access.
- // This way the underflow won't be detected but the corruption will (as the
- // allocator will still be hooked).
- auto InterlockedIncrementFn =
- reinterpret_cast<LONG (*)(LONG volatile * addend)>(
- GetProcAddress(GetModuleHandle(L"kernel32"), "InterlockedIncrement"));
- CHECK(InterlockedIncrementFn);
-
- LONG volatile dummy = InterlockedIncrementFn(array - 1);
- base::debug::Alias(const_cast<LONG*>(&dummy));
-
- if (induce_crash)
- CHECK(false);
- delete[] array;
-}
-#endif // OS_WIN && ADDRESS_SANITIZER
-
-} // namespace
-
-#if defined(ADDRESS_SANITIZER)
-// NOTE(sebmarchand): We intentionally perform some invalid heap access here in
-// order to trigger an AddressSanitizer (ASan) error report.
-
-static const size_t kArraySize = 5;
-
-void AsanHeapOverflow() {
- // Declares the array as volatile to make sure it doesn't get optimized away.
- std::unique_ptr<volatile int[]> array(
- const_cast<volatile int*>(new int[kArraySize]));
- int dummy = array[kArraySize];
- base::debug::Alias(&dummy);
-}
-
-void AsanHeapUnderflow() {
- // Declares the array as volatile to make sure it doesn't get optimized away.
- std::unique_ptr<volatile int[]> array(
- const_cast<volatile int*>(new int[kArraySize]));
- // We need to store the underflow address in a temporary variable as trying to
- // access array[-1] will trigger a warning C4245: "conversion from 'int' to
- // 'size_t', signed/unsigned mismatch".
- volatile int* underflow_address = &array[0] - 1;
- int dummy = *underflow_address;
- base::debug::Alias(&dummy);
-}
-
-void AsanHeapUseAfterFree() {
- // Declares the array as volatile to make sure it doesn't get optimized away.
- std::unique_ptr<volatile int[]> array(
- const_cast<volatile int*>(new int[kArraySize]));
- volatile int* dangling = array.get();
- array.reset();
- int dummy = dangling[kArraySize / 2];
- base::debug::Alias(&dummy);
-}
-
-#if defined(OS_WIN)
-void AsanCorruptHeapBlock() {
- CorruptMemoryBlock(false);
-}
-
-void AsanCorruptHeap() {
- CorruptMemoryBlock(true);
-}
-#endif // OS_WIN
-#endif // ADDRESS_SANITIZER
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/asan_invalid_access.h b/base/debug/asan_invalid_access.h
deleted file mode 100644
index dc9a7ee647..0000000000
--- a/base/debug/asan_invalid_access.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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.
-//
-// Defines some functions that intentionally do an invalid memory access in
-// order to trigger an AddressSanitizer (ASan) error report.
-
-#ifndef BASE_DEBUG_ASAN_INVALID_ACCESS_H_
-#define BASE_DEBUG_ASAN_INVALID_ACCESS_H_
-
-#include "base/base_export.h"
-#include "base/compiler_specific.h"
-#include "build/build_config.h"
-
-namespace base {
-namespace debug {
-
-#if defined(ADDRESS_SANITIZER)
-
-// Generates an heap buffer overflow.
-BASE_EXPORT NOINLINE void AsanHeapOverflow();
-
-// Generates an heap buffer underflow.
-BASE_EXPORT NOINLINE void AsanHeapUnderflow();
-
-// Generates an use after free.
-BASE_EXPORT NOINLINE void AsanHeapUseAfterFree();
-
-// The "corrupt-block" and "corrupt-heap" classes of bugs is specific to
-// Windows.
-#if defined(OS_WIN)
-// Corrupts a memory block and makes sure that the corruption gets detected when
-// we try to free this block.
-BASE_EXPORT NOINLINE void AsanCorruptHeapBlock();
-
-// Corrupts the heap and makes sure that the corruption gets detected when a
-// crash occur.
-BASE_EXPORT NOINLINE void AsanCorruptHeap();
-
-#endif // OS_WIN
-#endif // ADDRESS_SANITIZER
-
-} // namespace debug
-} // namespace base
-
-#endif // BASE_DEBUG_ASAN_INVALID_ACCESS_H_
diff --git a/base/debug/crash_logging_unittest.cc b/base/debug/crash_logging_unittest.cc
deleted file mode 100644
index c10d36e368..0000000000
--- a/base/debug/crash_logging_unittest.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2013 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/debug/crash_logging.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(CrashLoggingTest, UninitializedCrashKeyStringSupport) {
- auto* crash_key = base::debug::AllocateCrashKeyString(
- "test", base::debug::CrashKeySize::Size32);
- EXPECT_FALSE(crash_key);
-
- base::debug::SetCrashKeyString(crash_key, "value");
-
- base::debug::ClearCrashKeyString(crash_key);
-}
diff --git a/base/debug/proc_maps_linux_unittest.cc b/base/debug/proc_maps_linux_unittest.cc
deleted file mode 100644
index 7abf152b0e..0000000000
--- a/base/debug/proc_maps_linux_unittest.cc
+++ /dev/null
@@ -1,328 +0,0 @@
-// Copyright (c) 2013 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 <stddef.h>
-#include <stdint.h>
-
-#include "base/debug/proc_maps_linux.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/platform_thread.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace debug {
-
-TEST(ProcMapsTest, Empty) {
- std::vector<MappedMemoryRegion> regions;
- EXPECT_TRUE(ParseProcMaps("", &regions));
- EXPECT_EQ(0u, regions.size());
-}
-
-TEST(ProcMapsTest, NoSpaces) {
- static const char kNoSpaces[] =
- "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat\n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kNoSpaces, &regions));
- ASSERT_EQ(1u, regions.size());
-
- EXPECT_EQ(0x00400000u, regions[0].start);
- EXPECT_EQ(0x0040b000u, regions[0].end);
- EXPECT_EQ(0x00002200u, regions[0].offset);
- EXPECT_EQ("/bin/cat", regions[0].path);
-}
-
-TEST(ProcMapsTest, Spaces) {
- static const char kSpaces[] =
- "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/space cat\n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kSpaces, &regions));
- ASSERT_EQ(1u, regions.size());
-
- EXPECT_EQ(0x00400000u, regions[0].start);
- EXPECT_EQ(0x0040b000u, regions[0].end);
- EXPECT_EQ(0x00002200u, regions[0].offset);
- EXPECT_EQ("/bin/space cat", regions[0].path);
-}
-
-TEST(ProcMapsTest, NoNewline) {
- static const char kNoSpaces[] =
- "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_FALSE(ParseProcMaps(kNoSpaces, &regions));
-}
-
-TEST(ProcMapsTest, NoPath) {
- static const char kNoPath[] =
- "00400000-0040b000 rw-p 00000000 00:00 0 \n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kNoPath, &regions));
- ASSERT_EQ(1u, regions.size());
-
- EXPECT_EQ(0x00400000u, regions[0].start);
- EXPECT_EQ(0x0040b000u, regions[0].end);
- EXPECT_EQ(0x00000000u, regions[0].offset);
- EXPECT_EQ("", regions[0].path);
-}
-
-TEST(ProcMapsTest, Heap) {
- static const char kHeap[] =
- "022ac000-022cd000 rw-p 00000000 00:00 0 [heap]\n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kHeap, &regions));
- ASSERT_EQ(1u, regions.size());
-
- EXPECT_EQ(0x022ac000u, regions[0].start);
- EXPECT_EQ(0x022cd000u, regions[0].end);
- EXPECT_EQ(0x00000000u, regions[0].offset);
- EXPECT_EQ("[heap]", regions[0].path);
-}
-
-#if defined(ARCH_CPU_32_BITS)
-TEST(ProcMapsTest, Stack32) {
- static const char kStack[] =
- "beb04000-beb25000 rw-p 00000000 00:00 0 [stack]\n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kStack, &regions));
- ASSERT_EQ(1u, regions.size());
-
- EXPECT_EQ(0xbeb04000u, regions[0].start);
- EXPECT_EQ(0xbeb25000u, regions[0].end);
- EXPECT_EQ(0x00000000u, regions[0].offset);
- EXPECT_EQ("[stack]", regions[0].path);
-}
-#elif defined(ARCH_CPU_64_BITS)
-TEST(ProcMapsTest, Stack64) {
- static const char kStack[] =
- "7fff69c5b000-7fff69c7d000 rw-p 00000000 00:00 0 [stack]\n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kStack, &regions));
- ASSERT_EQ(1u, regions.size());
-
- EXPECT_EQ(0x7fff69c5b000u, regions[0].start);
- EXPECT_EQ(0x7fff69c7d000u, regions[0].end);
- EXPECT_EQ(0x00000000u, regions[0].offset);
- EXPECT_EQ("[stack]", regions[0].path);
-}
-#endif
-
-TEST(ProcMapsTest, Multiple) {
- static const char kMultiple[] =
- "00400000-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n"
- "0060a000-0060b000 r--p 0000a000 fc:00 794418 /bin/cat\n"
- "0060b000-0060c000 rw-p 0000b000 fc:00 794418 /bin/cat\n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kMultiple, &regions));
- ASSERT_EQ(3u, regions.size());
-
- EXPECT_EQ(0x00400000u, regions[0].start);
- EXPECT_EQ(0x0040b000u, regions[0].end);
- EXPECT_EQ(0x00000000u, regions[0].offset);
- EXPECT_EQ("/bin/cat", regions[0].path);
-
- EXPECT_EQ(0x0060a000u, regions[1].start);
- EXPECT_EQ(0x0060b000u, regions[1].end);
- EXPECT_EQ(0x0000a000u, regions[1].offset);
- EXPECT_EQ("/bin/cat", regions[1].path);
-
- EXPECT_EQ(0x0060b000u, regions[2].start);
- EXPECT_EQ(0x0060c000u, regions[2].end);
- EXPECT_EQ(0x0000b000u, regions[2].offset);
- EXPECT_EQ("/bin/cat", regions[2].path);
-}
-
-TEST(ProcMapsTest, Permissions) {
- static struct {
- const char* input;
- uint8_t permissions;
- } kTestCases[] = {
- {"00400000-0040b000 ---s 00000000 fc:00 794418 /bin/cat\n", 0},
- {"00400000-0040b000 ---S 00000000 fc:00 794418 /bin/cat\n", 0},
- {"00400000-0040b000 r--s 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::READ},
- {"00400000-0040b000 -w-s 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::WRITE},
- {"00400000-0040b000 --xs 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::EXECUTE},
- {"00400000-0040b000 rwxs 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::READ | MappedMemoryRegion::WRITE |
- MappedMemoryRegion::EXECUTE},
- {"00400000-0040b000 ---p 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::PRIVATE},
- {"00400000-0040b000 r--p 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::READ | MappedMemoryRegion::PRIVATE},
- {"00400000-0040b000 -w-p 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::WRITE | MappedMemoryRegion::PRIVATE},
- {"00400000-0040b000 --xp 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::EXECUTE | MappedMemoryRegion::PRIVATE},
- {"00400000-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n",
- MappedMemoryRegion::READ | MappedMemoryRegion::WRITE |
- MappedMemoryRegion::EXECUTE | MappedMemoryRegion::PRIVATE},
- };
-
- for (size_t i = 0; i < arraysize(kTestCases); ++i) {
- SCOPED_TRACE(
- base::StringPrintf("kTestCases[%zu] = %s", i, kTestCases[i].input));
-
- std::vector<MappedMemoryRegion> regions;
- EXPECT_TRUE(ParseProcMaps(kTestCases[i].input, &regions));
- EXPECT_EQ(1u, regions.size());
- if (regions.empty())
- continue;
- EXPECT_EQ(kTestCases[i].permissions, regions[0].permissions);
- }
-}
-
-#if defined(ADDRESS_SANITIZER)
-// AddressSanitizer may move local variables to a dedicated "fake stack" which
-// is outside the stack region listed in /proc/self/maps. We disable ASan
-// instrumentation for this function to force the variable to be local.
-__attribute__((no_sanitize_address))
-#endif
-void CheckProcMapsRegions(const std::vector<MappedMemoryRegion> &regions) {
- // We should be able to find both the current executable as well as the stack
- // mapped into memory. Use the address of |exe_path| as a way of finding the
- // stack.
- FilePath exe_path;
- EXPECT_TRUE(PathService::Get(FILE_EXE, &exe_path));
- uintptr_t address = reinterpret_cast<uintptr_t>(&exe_path);
- bool found_exe = false;
- bool found_stack = false;
- bool found_address = false;
-
- for (size_t i = 0; i < regions.size(); ++i) {
- if (regions[i].path == exe_path.value()) {
- // It's OK to find the executable mapped multiple times as there'll be
- // multiple sections (e.g., text, data).
- found_exe = true;
- }
-
- if (regions[i].path == "[stack]") {
-// On Android the test is run on a background thread, since [stack] is for
-// the main thread, we cannot test this.
-#if !defined(OS_ANDROID)
- EXPECT_GE(address, regions[i].start);
- EXPECT_LT(address, regions[i].end);
-#endif
- EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::READ);
- EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::WRITE);
- EXPECT_FALSE(regions[i].permissions & MappedMemoryRegion::EXECUTE);
- EXPECT_TRUE(regions[i].permissions & MappedMemoryRegion::PRIVATE);
- EXPECT_FALSE(found_stack) << "Found duplicate stacks";
- found_stack = true;
- }
-
- if (address >= regions[i].start && address < regions[i].end) {
- EXPECT_FALSE(found_address) << "Found same address in multiple regions";
- found_address = true;
- }
- }
-
- EXPECT_TRUE(found_exe);
- EXPECT_TRUE(found_stack);
- EXPECT_TRUE(found_address);
-}
-
-TEST(ProcMapsTest, ReadProcMaps) {
- std::string proc_maps;
- ASSERT_TRUE(ReadProcMaps(&proc_maps));
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(proc_maps, &regions));
- ASSERT_FALSE(regions.empty());
-
- CheckProcMapsRegions(regions);
-}
-
-TEST(ProcMapsTest, ReadProcMapsNonEmptyString) {
- std::string old_string("I forgot to clear the string");
- std::string proc_maps(old_string);
- ASSERT_TRUE(ReadProcMaps(&proc_maps));
- EXPECT_EQ(std::string::npos, proc_maps.find(old_string));
-}
-
-TEST(ProcMapsTest, MissingFields) {
- static const char* const kTestCases[] = {
- "00400000\n", // Missing end + beyond.
- "00400000-0040b000\n", // Missing perms + beyond.
- "00400000-0040b000 r-xp\n", // Missing offset + beyond.
- "00400000-0040b000 r-xp 00000000\n", // Missing device + beyond.
- "00400000-0040b000 r-xp 00000000 fc:00\n", // Missing inode + beyond.
- "00400000-0040b000 00000000 fc:00 794418 /bin/cat\n", // Missing perms.
- "00400000-0040b000 r-xp fc:00 794418 /bin/cat\n", // Missing offset.
- "00400000-0040b000 r-xp 00000000 fc:00 /bin/cat\n", // Missing inode.
- "00400000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing end.
- "-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing start.
- "00400000-0040b000 r-xp 00000000 794418 /bin/cat\n", // Missing device.
- };
-
- for (size_t i = 0; i < arraysize(kTestCases); ++i) {
- SCOPED_TRACE(base::StringPrintf("kTestCases[%zu] = %s", i, kTestCases[i]));
- std::vector<MappedMemoryRegion> regions;
- EXPECT_FALSE(ParseProcMaps(kTestCases[i], &regions));
- }
-}
-
-TEST(ProcMapsTest, InvalidInput) {
- static const char* const kTestCases[] = {
- "thisisal-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n",
- "0040000d-linvalid rwxp 00000000 fc:00 794418 /bin/cat\n",
- "00400000-0040b000 inpu 00000000 fc:00 794418 /bin/cat\n",
- "00400000-0040b000 rwxp tforproc fc:00 794418 /bin/cat\n",
- "00400000-0040b000 rwxp 00000000 ma:ps 794418 /bin/cat\n",
- "00400000-0040b000 rwxp 00000000 fc:00 parse! /bin/cat\n",
- };
-
- for (size_t i = 0; i < arraysize(kTestCases); ++i) {
- SCOPED_TRACE(base::StringPrintf("kTestCases[%zu] = %s", i, kTestCases[i]));
- std::vector<MappedMemoryRegion> regions;
- EXPECT_FALSE(ParseProcMaps(kTestCases[i], &regions));
- }
-}
-
-TEST(ProcMapsTest, ParseProcMapsEmptyString) {
- std::vector<MappedMemoryRegion> regions;
- EXPECT_TRUE(ParseProcMaps("", &regions));
- EXPECT_EQ(0ULL, regions.size());
-}
-
-// Testing a couple of remotely possible weird things in the input:
-// - Line ending with \r\n or \n\r.
-// - File name contains quotes.
-// - File name has whitespaces.
-TEST(ProcMapsTest, ParseProcMapsWeirdCorrectInput) {
- std::vector<MappedMemoryRegion> regions;
- const std::string kContents =
- "00400000-0040b000 r-xp 00000000 fc:00 2106562 "
- " /bin/cat\r\n"
- "7f53b7dad000-7f53b7f62000 r-xp 00000000 fc:00 263011 "
- " /lib/x86_64-linux-gnu/libc-2.15.so\n\r"
- "7f53b816d000-7f53b818f000 r-xp 00000000 fc:00 264284 "
- " /lib/x86_64-linux-gnu/ld-2.15.so\n"
- "7fff9c7ff000-7fff9c800000 r-xp 00000000 00:00 0 "
- " \"vd so\"\n"
- "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 "
- " [vsys call]\n";
- EXPECT_TRUE(ParseProcMaps(kContents, &regions));
- EXPECT_EQ(5ULL, regions.size());
- EXPECT_EQ("/bin/cat", regions[0].path);
- EXPECT_EQ("/lib/x86_64-linux-gnu/libc-2.15.so", regions[1].path);
- EXPECT_EQ("/lib/x86_64-linux-gnu/ld-2.15.so", regions[2].path);
- EXPECT_EQ("\"vd so\"", regions[3].path);
- EXPECT_EQ("[vsys call]", regions[4].path);
-}
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/stack_trace_unittest.cc b/base/debug/stack_trace_unittest.cc
deleted file mode 100644
index 02f076a2ae..0000000000
--- a/base/debug/stack_trace_unittest.cc
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright (c) 2011 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 <stddef.h>
-
-#include <limits>
-#include <sstream>
-#include <string>
-
-#include "base/debug/debugging_buildflags.h"
-#include "base/debug/stack_trace.h"
-#include "base/logging.h"
-#include "base/process/kill.h"
-#include "base/process/process_handle.h"
-#include "base/test/test_timeouts.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS)
-#include "base/test/multiprocess_test.h"
-#endif
-
-namespace base {
-namespace debug {
-
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS)
-typedef MultiProcessTest StackTraceTest;
-#else
-typedef testing::Test StackTraceTest;
-#endif
-
-// Note: On Linux, this test currently only fully works on Debug builds.
-// See comments in the #ifdef soup if you intend to change this.
-#if defined(OS_WIN)
-// Always fails on Windows: crbug.com/32070
-#define MAYBE_OutputToStream DISABLED_OutputToStream
-#else
-#define MAYBE_OutputToStream OutputToStream
-#endif
-#if !defined(__UCLIBC__) && !defined(_AIX)
-TEST_F(StackTraceTest, MAYBE_OutputToStream) {
- StackTrace trace;
-
- // Dump the trace into a string.
- std::ostringstream os;
- trace.OutputToStream(&os);
- std::string backtrace_message = os.str();
-
- // ToString() should produce the same output.
- EXPECT_EQ(backtrace_message, trace.ToString());
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && NDEBUG
- // Stack traces require an extra data table that bloats our binaries,
- // so they're turned off for release builds. We stop the test here,
- // at least letting us verify that the calls don't crash.
- return;
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && NDEBUG
-
- size_t frames_found = 0;
- trace.Addresses(&frames_found);
- ASSERT_GE(frames_found, 5u) <<
- "No stack frames found. Skipping rest of test.";
-
- // Check if the output has symbol initialization warning. If it does, fail.
- ASSERT_EQ(backtrace_message.find("Dumping unresolved backtrace"),
- std::string::npos) <<
- "Unable to resolve symbols. Skipping rest of test.";
-
-#if defined(OS_MACOSX)
-#if 0
- // Disabled due to -fvisibility=hidden in build config.
-
- // Symbol resolution via the backtrace_symbol function does not work well
- // in OS X.
- // See this thread:
- //
- // http://lists.apple.com/archives/darwin-dev/2009/Mar/msg00111.html
- //
- // Just check instead that we find our way back to the "start" symbol
- // which should be the first symbol in the trace.
- //
- // TODO(port): Find a more reliable way to resolve symbols.
-
- // Expect to at least find main.
- EXPECT_TRUE(backtrace_message.find("start") != std::string::npos)
- << "Expected to find start in backtrace:\n"
- << backtrace_message;
-
-#endif
-#elif defined(USE_SYMBOLIZE)
- // This branch is for gcc-compiled code, but not Mac due to the
- // above #if.
- // Expect a demangled symbol.
- EXPECT_TRUE(backtrace_message.find("testing::Test::Run()") !=
- std::string::npos)
- << "Expected a demangled symbol in backtrace:\n"
- << backtrace_message;
-
-#elif 0
- // This is the fall-through case; it used to cover Windows.
- // But it's disabled because of varying buildbot configs;
- // some lack symbols.
-
- // Expect to at least find main.
- EXPECT_TRUE(backtrace_message.find("main") != std::string::npos)
- << "Expected to find main in backtrace:\n"
- << backtrace_message;
-
-#if defined(OS_WIN)
-// MSVC doesn't allow the use of C99's __func__ within C++, so we fake it with
-// MSVC's __FUNCTION__ macro.
-#define __func__ __FUNCTION__
-#endif
-
- // Expect to find this function as well.
- // Note: This will fail if not linked with -rdynamic (aka -export_dynamic)
- EXPECT_TRUE(backtrace_message.find(__func__) != std::string::npos)
- << "Expected to find " << __func__ << " in backtrace:\n"
- << backtrace_message;
-
-#endif // define(OS_MACOSX)
-}
-
-#if !defined(OFFICIAL_BUILD) && !defined(NO_UNWIND_TABLES)
-// Disabled in Official builds, where Link-Time Optimization can result in two
-// or fewer stack frames being available, causing the test to fail.
-TEST_F(StackTraceTest, TruncatedTrace) {
- StackTrace trace;
-
- size_t count = 0;
- trace.Addresses(&count);
- ASSERT_LT(2u, count);
-
- StackTrace truncated(2);
- truncated.Addresses(&count);
- EXPECT_EQ(2u, count);
-}
-#endif // !defined(OFFICIAL_BUILD)
-
-// The test is used for manual testing, e.g., to see the raw output.
-TEST_F(StackTraceTest, DebugOutputToStream) {
- StackTrace trace;
- std::ostringstream os;
- trace.OutputToStream(&os);
- VLOG(1) << os.str();
-}
-
-// The test is used for manual testing, e.g., to see the raw output.
-TEST_F(StackTraceTest, DebugPrintBacktrace) {
- StackTrace().Print();
-}
-#endif // !defined(__UCLIBC__)
-
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
-#if !defined(OS_IOS)
-static char* newArray() {
- // Clang warns about the mismatched new[]/delete if they occur in the same
- // function.
- return new char[10];
-}
-
-MULTIPROCESS_TEST_MAIN(MismatchedMallocChildProcess) {
- char* pointer = newArray();
- delete pointer;
- return 2;
-}
-
-// Regression test for StackDumpingSignalHandler async-signal unsafety.
-// Combined with tcmalloc's debugallocation, that signal handler
-// and e.g. mismatched new[]/delete would cause a hang because
-// of re-entering malloc.
-TEST_F(StackTraceTest, AsyncSignalUnsafeSignalHandlerHang) {
- Process child = SpawnChild("MismatchedMallocChildProcess");
- ASSERT_TRUE(child.IsValid());
- int exit_code;
- ASSERT_TRUE(
- child.WaitForExitWithTimeout(TestTimeouts::action_timeout(), &exit_code));
-}
-#endif // !defined(OS_IOS)
-
-namespace {
-
-std::string itoa_r_wrapper(intptr_t i, size_t sz, int base, size_t padding) {
- char buffer[1024];
- CHECK_LE(sz, sizeof(buffer));
-
- char* result = internal::itoa_r(i, buffer, sz, base, padding);
- EXPECT_TRUE(result);
- return std::string(buffer);
-}
-
-} // namespace
-
-TEST_F(StackTraceTest, itoa_r) {
- EXPECT_EQ("0", itoa_r_wrapper(0, 128, 10, 0));
- EXPECT_EQ("-1", itoa_r_wrapper(-1, 128, 10, 0));
-
- // Test edge cases.
- if (sizeof(intptr_t) == 4) {
- EXPECT_EQ("ffffffff", itoa_r_wrapper(-1, 128, 16, 0));
- EXPECT_EQ("-2147483648",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10, 0));
- EXPECT_EQ("2147483647",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10, 0));
-
- EXPECT_EQ("80000000",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16, 0));
- EXPECT_EQ("7fffffff",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16, 0));
- } else if (sizeof(intptr_t) == 8) {
- EXPECT_EQ("ffffffffffffffff", itoa_r_wrapper(-1, 128, 16, 0));
- EXPECT_EQ("-9223372036854775808",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 10, 0));
- EXPECT_EQ("9223372036854775807",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 10, 0));
-
- EXPECT_EQ("8000000000000000",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::min(), 128, 16, 0));
- EXPECT_EQ("7fffffffffffffff",
- itoa_r_wrapper(std::numeric_limits<intptr_t>::max(), 128, 16, 0));
- } else {
- ADD_FAILURE() << "Missing test case for your size of intptr_t ("
- << sizeof(intptr_t) << ")";
- }
-
- // Test hex output.
- EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 0));
- EXPECT_EQ("deadbeef", itoa_r_wrapper(0xdeadbeef, 128, 16, 0));
-
- // Check that itoa_r respects passed buffer size limit.
- char buffer[1024];
- EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 10, 16, 0));
- EXPECT_TRUE(internal::itoa_r(0xdeadbeef, buffer, 9, 16, 0));
- EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 8, 16, 0));
- EXPECT_FALSE(internal::itoa_r(0xdeadbeef, buffer, 7, 16, 0));
- EXPECT_TRUE(internal::itoa_r(0xbeef, buffer, 5, 16, 4));
- EXPECT_FALSE(internal::itoa_r(0xbeef, buffer, 5, 16, 5));
- EXPECT_FALSE(internal::itoa_r(0xbeef, buffer, 5, 16, 6));
-
- // Test padding.
- EXPECT_EQ("1", itoa_r_wrapper(1, 128, 10, 0));
- EXPECT_EQ("1", itoa_r_wrapper(1, 128, 10, 1));
- EXPECT_EQ("01", itoa_r_wrapper(1, 128, 10, 2));
- EXPECT_EQ("001", itoa_r_wrapper(1, 128, 10, 3));
- EXPECT_EQ("0001", itoa_r_wrapper(1, 128, 10, 4));
- EXPECT_EQ("00001", itoa_r_wrapper(1, 128, 10, 5));
- EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 0));
- EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 1));
- EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 2));
- EXPECT_EQ("688", itoa_r_wrapper(0x688, 128, 16, 3));
- EXPECT_EQ("0688", itoa_r_wrapper(0x688, 128, 16, 4));
- EXPECT_EQ("00688", itoa_r_wrapper(0x688, 128, 16, 5));
-}
-#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
-
-#if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
-
-template <size_t Depth>
-void NOINLINE ExpectStackFramePointers(const void** frames,
- size_t max_depth) {
- code_start:
- // Calling __builtin_frame_address() forces compiler to emit
- // frame pointers, even if they are not enabled.
- EXPECT_NE(nullptr, __builtin_frame_address(0));
- ExpectStackFramePointers<Depth - 1>(frames, max_depth);
-
- constexpr size_t frame_index = Depth - 1;
- const void* frame = frames[frame_index];
- EXPECT_GE(frame, &&code_start) << "For frame at index " << frame_index;
- EXPECT_LE(frame, &&code_end) << "For frame at index " << frame_index;
- code_end: return;
-}
-
-template <>
-void NOINLINE ExpectStackFramePointers<1>(const void** frames,
- size_t max_depth) {
- code_start:
- // Calling __builtin_frame_address() forces compiler to emit
- // frame pointers, even if they are not enabled.
- EXPECT_NE(nullptr, __builtin_frame_address(0));
- size_t count = TraceStackFramePointers(frames, max_depth, 0);
- ASSERT_EQ(max_depth, count);
-
- const void* frame = frames[0];
- EXPECT_GE(frame, &&code_start) << "For the top frame";
- EXPECT_LE(frame, &&code_end) << "For the top frame";
- code_end: return;
-}
-
-#if defined(MEMORY_SANITIZER)
-// The test triggers use-of-uninitialized-value errors on MSan bots.
-// This is expected because we're walking and reading the stack, and
-// sometimes we read fp / pc from the place that previously held
-// uninitialized value.
-#define MAYBE_TraceStackFramePointers DISABLED_TraceStackFramePointers
-#else
-#define MAYBE_TraceStackFramePointers TraceStackFramePointers
-#endif
-TEST_F(StackTraceTest, MAYBE_TraceStackFramePointers) {
- constexpr size_t kDepth = 5;
- const void* frames[kDepth];
- ExpectStackFramePointers<kDepth>(frames, kDepth);
-}
-
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
-#define MAYBE_StackEnd StackEnd
-#else
-#define MAYBE_StackEnd DISABLED_StackEnd
-#endif
-
-TEST_F(StackTraceTest, MAYBE_StackEnd) {
- EXPECT_NE(0u, GetStackEnd());
-}
-
-#endif // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/thread_heap_usage_tracker.cc b/base/debug/thread_heap_usage_tracker.cc
deleted file mode 100644
index 6d00b1ccbb..0000000000
--- a/base/debug/thread_heap_usage_tracker.cc
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright 2016 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/debug/thread_heap_usage_tracker.h"
-
-#include <stdint.h>
-#include <algorithm>
-#include <limits>
-#include <new>
-#include <type_traits>
-
-#include "base/allocator/allocator_shim.h"
-#include "base/allocator/buildflags.h"
-#include "base/logging.h"
-#include "base/no_destructor.h"
-#include "base/threading/thread_local_storage.h"
-#include "build/build_config.h"
-
-#if defined(OS_MACOSX) || defined(OS_IOS)
-#include <malloc/malloc.h>
-#else
-#include <malloc.h>
-#endif
-
-namespace base {
-namespace debug {
-
-namespace {
-
-using base::allocator::AllocatorDispatch;
-
-const uintptr_t kSentinelMask = std::numeric_limits<uintptr_t>::max() - 1;
-ThreadHeapUsage* const kInitializationSentinel =
- reinterpret_cast<ThreadHeapUsage*>(kSentinelMask);
-ThreadHeapUsage* const kTeardownSentinel =
- reinterpret_cast<ThreadHeapUsage*>(kSentinelMask | 1);
-
-ThreadLocalStorage::Slot& ThreadAllocationUsage() {
- static NoDestructor<ThreadLocalStorage::Slot> thread_allocator_usage(
- [](void* thread_heap_usage) {
- // This destructor will be called twice. Once to destroy the actual
- // ThreadHeapUsage instance and a second time, immediately after, for
- // the sentinel. Re-setting the TLS slow (below) does re-initialize the
- // TLS slot. The ThreadLocalStorage code is designed to deal with this
- // use case and will re-call the destructor with the kTeardownSentinel
- // as arg.
- if (thread_heap_usage == kTeardownSentinel)
- return;
- DCHECK_NE(thread_heap_usage, kInitializationSentinel);
-
- // Deleting the ThreadHeapUsage TLS object will re-enter the shim and
- // hit RecordFree() (see below). The sentinel prevents RecordFree() from
- // re-creating another ThreadHeapUsage object.
- ThreadAllocationUsage().Set(kTeardownSentinel);
- delete static_cast<ThreadHeapUsage*>(thread_heap_usage);
- });
- return *thread_allocator_usage;
-}
-
-bool g_heap_tracking_enabled = false;
-
-// Forward declared as it needs to delegate memory allocation to the next
-// lower shim.
-ThreadHeapUsage* GetOrCreateThreadUsage();
-
-size_t GetAllocSizeEstimate(const AllocatorDispatch* next,
- void* ptr,
- void* context) {
- if (ptr == nullptr)
- return 0U;
-
- return next->get_size_estimate_function(next, ptr, context);
-}
-
-void RecordAlloc(const AllocatorDispatch* next,
- void* ptr,
- size_t size,
- void* context) {
- ThreadHeapUsage* usage = GetOrCreateThreadUsage();
- if (usage == nullptr)
- return;
-
- usage->alloc_ops++;
- size_t estimate = GetAllocSizeEstimate(next, ptr, context);
- if (size && estimate) {
- // Only keep track of the net number of bytes allocated in the scope if the
- // size estimate function returns sane values, e.g. non-zero.
- usage->alloc_bytes += estimate;
- usage->alloc_overhead_bytes += estimate - size;
-
- // Record the max outstanding number of bytes, but only if the difference
- // is net positive (e.g. more bytes allocated than freed in the scope).
- if (usage->alloc_bytes > usage->free_bytes) {
- uint64_t allocated_bytes = usage->alloc_bytes - usage->free_bytes;
- if (allocated_bytes > usage->max_allocated_bytes)
- usage->max_allocated_bytes = allocated_bytes;
- }
- } else {
- usage->alloc_bytes += size;
- }
-}
-
-void RecordFree(const AllocatorDispatch* next, void* ptr, void* context) {
- ThreadHeapUsage* usage = GetOrCreateThreadUsage();
- if (usage == nullptr)
- return;
-
- size_t estimate = GetAllocSizeEstimate(next, ptr, context);
- usage->free_ops++;
- usage->free_bytes += estimate;
-}
-
-void* AllocFn(const AllocatorDispatch* self, size_t size, void* context) {
- void* ret = self->next->alloc_function(self->next, size, context);
- if (ret != nullptr)
- RecordAlloc(self->next, ret, size, context);
-
- return ret;
-}
-
-void* AllocZeroInitializedFn(const AllocatorDispatch* self,
- size_t n,
- size_t size,
- void* context) {
- void* ret =
- self->next->alloc_zero_initialized_function(self->next, n, size, context);
- if (ret != nullptr)
- RecordAlloc(self->next, ret, size, context);
-
- return ret;
-}
-
-void* AllocAlignedFn(const AllocatorDispatch* self,
- size_t alignment,
- size_t size,
- void* context) {
- void* ret =
- self->next->alloc_aligned_function(self->next, alignment, size, context);
- if (ret != nullptr)
- RecordAlloc(self->next, ret, size, context);
-
- return ret;
-}
-
-void* ReallocFn(const AllocatorDispatch* self,
- void* address,
- size_t size,
- void* context) {
- if (address != nullptr)
- RecordFree(self->next, address, context);
-
- void* ret = self->next->realloc_function(self->next, address, size, context);
- if (ret != nullptr && size != 0)
- RecordAlloc(self->next, ret, size, context);
-
- return ret;
-}
-
-void FreeFn(const AllocatorDispatch* self, void* address, void* context) {
- if (address != nullptr)
- RecordFree(self->next, address, context);
- self->next->free_function(self->next, address, context);
-}
-
-size_t GetSizeEstimateFn(const AllocatorDispatch* self,
- void* address,
- void* context) {
- return self->next->get_size_estimate_function(self->next, address, context);
-}
-
-unsigned BatchMallocFn(const AllocatorDispatch* self,
- size_t size,
- void** results,
- unsigned num_requested,
- void* context) {
- unsigned count = self->next->batch_malloc_function(self->next, size, results,
- num_requested, context);
- for (unsigned i = 0; i < count; ++i) {
- RecordAlloc(self->next, results[i], size, context);
- }
- return count;
-}
-
-void BatchFreeFn(const AllocatorDispatch* self,
- void** to_be_freed,
- unsigned num_to_be_freed,
- void* context) {
- for (unsigned i = 0; i < num_to_be_freed; ++i) {
- if (to_be_freed[i] != nullptr) {
- RecordFree(self->next, to_be_freed[i], context);
- }
- }
- self->next->batch_free_function(self->next, to_be_freed, num_to_be_freed,
- context);
-}
-
-void FreeDefiniteSizeFn(const AllocatorDispatch* self,
- void* ptr,
- size_t size,
- void* context) {
- if (ptr != nullptr)
- RecordFree(self->next, ptr, context);
- self->next->free_definite_size_function(self->next, ptr, size, context);
-}
-
-// The allocator dispatch used to intercept heap operations.
-AllocatorDispatch allocator_dispatch = {&AllocFn,
- &AllocZeroInitializedFn,
- &AllocAlignedFn,
- &ReallocFn,
- &FreeFn,
- &GetSizeEstimateFn,
- &BatchMallocFn,
- &BatchFreeFn,
- &FreeDefiniteSizeFn,
- nullptr};
-
-ThreadHeapUsage* GetOrCreateThreadUsage() {
- auto tls_ptr = reinterpret_cast<uintptr_t>(ThreadAllocationUsage().Get());
- if ((tls_ptr & kSentinelMask) == kSentinelMask)
- return nullptr; // Re-entrancy case.
-
- auto* allocator_usage = reinterpret_cast<ThreadHeapUsage*>(tls_ptr);
- if (allocator_usage == nullptr) {
- // Prevent reentrancy due to the allocation below.
- ThreadAllocationUsage().Set(kInitializationSentinel);
-
- allocator_usage = new ThreadHeapUsage();
- static_assert(std::is_pod<ThreadHeapUsage>::value,
- "AllocatorDispatch must be POD");
- memset(allocator_usage, 0, sizeof(*allocator_usage));
- ThreadAllocationUsage().Set(allocator_usage);
- }
-
- return allocator_usage;
-}
-
-} // namespace
-
-ThreadHeapUsageTracker::ThreadHeapUsageTracker() : thread_usage_(nullptr) {
- static_assert(std::is_pod<ThreadHeapUsage>::value, "Must be POD.");
-}
-
-ThreadHeapUsageTracker::~ThreadHeapUsageTracker() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (thread_usage_ != nullptr) {
- // If this tracker wasn't stopped, make it inclusive so that the
- // usage isn't lost.
- Stop(false);
- }
-}
-
-void ThreadHeapUsageTracker::Start() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- thread_usage_ = GetOrCreateThreadUsage();
- usage_ = *thread_usage_;
-
- // Reset the stats for our current scope.
- // The per-thread usage instance now tracks this scope's usage, while this
- // instance persists the outer scope's usage stats. On destruction, this
- // instance will restore the outer scope's usage stats with this scope's
- // usage added.
- memset(thread_usage_, 0, sizeof(*thread_usage_));
-}
-
-void ThreadHeapUsageTracker::Stop(bool usage_is_exclusive) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK_NE(nullptr, thread_usage_);
-
- ThreadHeapUsage current = *thread_usage_;
- if (usage_is_exclusive) {
- // Restore the outer scope.
- *thread_usage_ = usage_;
- } else {
- // Update the outer scope with the accrued inner usage.
- if (thread_usage_->max_allocated_bytes) {
- uint64_t outer_net_alloc_bytes = usage_.alloc_bytes - usage_.free_bytes;
-
- thread_usage_->max_allocated_bytes =
- std::max(usage_.max_allocated_bytes,
- outer_net_alloc_bytes + thread_usage_->max_allocated_bytes);
- }
-
- thread_usage_->alloc_ops += usage_.alloc_ops;
- thread_usage_->alloc_bytes += usage_.alloc_bytes;
- thread_usage_->alloc_overhead_bytes += usage_.alloc_overhead_bytes;
- thread_usage_->free_ops += usage_.free_ops;
- thread_usage_->free_bytes += usage_.free_bytes;
- }
-
- thread_usage_ = nullptr;
- usage_ = current;
-}
-
-ThreadHeapUsage ThreadHeapUsageTracker::GetUsageSnapshot() {
- ThreadHeapUsage* usage = GetOrCreateThreadUsage();
- DCHECK_NE(nullptr, usage);
- return *usage;
-}
-
-void ThreadHeapUsageTracker::EnableHeapTracking() {
- EnsureTLSInitialized();
-
- CHECK_EQ(false, g_heap_tracking_enabled) << "No double-enabling.";
- g_heap_tracking_enabled = true;
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
- base::allocator::InsertAllocatorDispatch(&allocator_dispatch);
-#else
- CHECK(false) << "Can't enable heap tracking without the shim.";
-#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
-}
-
-bool ThreadHeapUsageTracker::IsHeapTrackingEnabled() {
- return g_heap_tracking_enabled;
-}
-
-void ThreadHeapUsageTracker::DisableHeapTrackingForTesting() {
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
- base::allocator::RemoveAllocatorDispatchForTesting(&allocator_dispatch);
-#else
- CHECK(false) << "Can't disable heap tracking without the shim.";
-#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
- DCHECK_EQ(true, g_heap_tracking_enabled) << "Heap tracking not enabled.";
- g_heap_tracking_enabled = false;
-}
-
-base::allocator::AllocatorDispatch*
-ThreadHeapUsageTracker::GetDispatchForTesting() {
- return &allocator_dispatch;
-}
-
-void ThreadHeapUsageTracker::EnsureTLSInitialized() {
- ignore_result(ThreadAllocationUsage());
-}
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/thread_heap_usage_tracker_unittest.cc b/base/debug/thread_heap_usage_tracker_unittest.cc
deleted file mode 100644
index b99576cbad..0000000000
--- a/base/debug/thread_heap_usage_tracker_unittest.cc
+++ /dev/null
@@ -1,607 +0,0 @@
-// Copyright 2016 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/debug/thread_heap_usage_tracker.h"
-
-#include <map>
-
-#include "base/allocator/allocator_shim.h"
-#include "base/allocator/buildflags.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_MACOSX)
-#include "base/allocator/allocator_interception_mac.h"
-#endif
-
-namespace base {
-namespace debug {
-
-namespace {
-
-class TestingThreadHeapUsageTracker : public ThreadHeapUsageTracker {
- public:
- using ThreadHeapUsageTracker::DisableHeapTrackingForTesting;
- using ThreadHeapUsageTracker::EnsureTLSInitialized;
- using ThreadHeapUsageTracker::GetDispatchForTesting;
-};
-
-// A fixture class that allows testing the AllocatorDispatch associated with
-// the ThreadHeapUsageTracker class in isolation against a mocked
-// underlying
-// heap implementation.
-class ThreadHeapUsageTrackerTest : public testing::Test {
- public:
- using AllocatorDispatch = base::allocator::AllocatorDispatch;
-
- static const size_t kAllocationPadding;
- enum SizeFunctionKind {
- EXACT_SIZE_FUNCTION,
- PADDING_SIZE_FUNCTION,
- ZERO_SIZE_FUNCTION,
- };
-
- ThreadHeapUsageTrackerTest() : size_function_kind_(EXACT_SIZE_FUNCTION) {
- EXPECT_EQ(nullptr, g_self);
- g_self = this;
- }
-
- ~ThreadHeapUsageTrackerTest() override {
- EXPECT_EQ(this, g_self);
- g_self = nullptr;
- }
-
- void set_size_function_kind(SizeFunctionKind kind) {
- size_function_kind_ = kind;
- }
-
- void SetUp() override {
- TestingThreadHeapUsageTracker::EnsureTLSInitialized();
-
- dispatch_under_test_ =
- TestingThreadHeapUsageTracker::GetDispatchForTesting();
- ASSERT_EQ(nullptr, dispatch_under_test_->next);
-
- dispatch_under_test_->next = &g_mock_dispatch;
- }
-
- void TearDown() override {
- ASSERT_EQ(&g_mock_dispatch, dispatch_under_test_->next);
-
- dispatch_under_test_->next = nullptr;
- }
-
- void* MockMalloc(size_t size) {
- return dispatch_under_test_->alloc_function(dispatch_under_test_, size,
- nullptr);
- }
-
- void* MockCalloc(size_t n, size_t size) {
- return dispatch_under_test_->alloc_zero_initialized_function(
- dispatch_under_test_, n, size, nullptr);
- }
-
- void* MockAllocAligned(size_t alignment, size_t size) {
- return dispatch_under_test_->alloc_aligned_function(
- dispatch_under_test_, alignment, size, nullptr);
- }
-
- void* MockRealloc(void* address, size_t size) {
- return dispatch_under_test_->realloc_function(dispatch_under_test_, address,
- size, nullptr);
- }
-
- void MockFree(void* address) {
- dispatch_under_test_->free_function(dispatch_under_test_, address, nullptr);
- }
-
- size_t MockGetSizeEstimate(void* address) {
- return dispatch_under_test_->get_size_estimate_function(
- dispatch_under_test_, address, nullptr);
- }
-
- private:
- void RecordAlloc(void* address, size_t size) {
- if (address != nullptr)
- allocation_size_map_[address] = size;
- }
-
- void DeleteAlloc(void* address) {
- if (address != nullptr)
- EXPECT_EQ(1U, allocation_size_map_.erase(address));
- }
-
- size_t GetSizeEstimate(void* address) {
- auto it = allocation_size_map_.find(address);
- if (it == allocation_size_map_.end())
- return 0;
-
- size_t ret = it->second;
- switch (size_function_kind_) {
- case EXACT_SIZE_FUNCTION:
- break;
- case PADDING_SIZE_FUNCTION:
- ret += kAllocationPadding;
- break;
- case ZERO_SIZE_FUNCTION:
- ret = 0;
- break;
- }
-
- return ret;
- }
-
- static void* OnAllocFn(const AllocatorDispatch* self,
- size_t size,
- void* context) {
- EXPECT_EQ(&g_mock_dispatch, self);
-
- void* ret = malloc(size);
- g_self->RecordAlloc(ret, size);
- return ret;
- }
-
- static void* OnAllocZeroInitializedFn(const AllocatorDispatch* self,
- size_t n,
- size_t size,
- void* context) {
- EXPECT_EQ(&g_mock_dispatch, self);
-
- void* ret = calloc(n, size);
- g_self->RecordAlloc(ret, n * size);
- return ret;
- }
-
- static void* OnAllocAlignedFn(const AllocatorDispatch* self,
- size_t alignment,
- size_t size,
- void* context) {
- EXPECT_EQ(&g_mock_dispatch, self);
-
- // This is a cheat as it doesn't return aligned allocations. This has the
- // advantage of working for all platforms for this test.
- void* ret = malloc(size);
- g_self->RecordAlloc(ret, size);
- return ret;
- }
-
- static void* OnReallocFn(const AllocatorDispatch* self,
- void* address,
- size_t size,
- void* context) {
- EXPECT_EQ(&g_mock_dispatch, self);
-
- g_self->DeleteAlloc(address);
- void* ret = realloc(address, size);
- g_self->RecordAlloc(ret, size);
- return ret;
- }
-
- static void OnFreeFn(const AllocatorDispatch* self,
- void* address,
- void* context) {
- EXPECT_EQ(&g_mock_dispatch, self);
-
- g_self->DeleteAlloc(address);
- free(address);
- }
-
- static size_t OnGetSizeEstimateFn(const AllocatorDispatch* self,
- void* address,
- void* context) {
- EXPECT_EQ(&g_mock_dispatch, self);
-
- return g_self->GetSizeEstimate(address);
- }
-
- using AllocationSizeMap = std::map<void*, size_t>;
-
- SizeFunctionKind size_function_kind_;
- AllocationSizeMap allocation_size_map_;
- AllocatorDispatch* dispatch_under_test_;
-
- static base::allocator::AllocatorDispatch g_mock_dispatch;
- static ThreadHeapUsageTrackerTest* g_self;
-};
-
-const size_t ThreadHeapUsageTrackerTest::kAllocationPadding = 23;
-
-ThreadHeapUsageTrackerTest* ThreadHeapUsageTrackerTest::g_self = nullptr;
-
-base::allocator::AllocatorDispatch ThreadHeapUsageTrackerTest::g_mock_dispatch =
- {
- &ThreadHeapUsageTrackerTest::OnAllocFn, // alloc_function
- &ThreadHeapUsageTrackerTest::
- OnAllocZeroInitializedFn, // alloc_zero_initialized_function
- &ThreadHeapUsageTrackerTest::
- OnAllocAlignedFn, // alloc_aligned_function
- &ThreadHeapUsageTrackerTest::OnReallocFn, // realloc_function
- &ThreadHeapUsageTrackerTest::OnFreeFn, // free_function
- &ThreadHeapUsageTrackerTest::
- OnGetSizeEstimateFn, // get_size_estimate_function
- nullptr, // batch_malloc
- nullptr, // batch_free
- nullptr, // free_definite_size_function
- nullptr, // next
-};
-
-} // namespace
-
-TEST_F(ThreadHeapUsageTrackerTest, SimpleUsageWithExactSizeFunction) {
- set_size_function_kind(EXACT_SIZE_FUNCTION);
-
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- ThreadHeapUsage u1 = ThreadHeapUsageTracker::GetUsageSnapshot();
-
- EXPECT_EQ(0U, u1.alloc_ops);
- EXPECT_EQ(0U, u1.alloc_bytes);
- EXPECT_EQ(0U, u1.alloc_overhead_bytes);
- EXPECT_EQ(0U, u1.free_ops);
- EXPECT_EQ(0U, u1.free_bytes);
- EXPECT_EQ(0U, u1.max_allocated_bytes);
-
- const size_t kAllocSize = 1029U;
- void* ptr = MockMalloc(kAllocSize);
- MockFree(ptr);
-
- usage_tracker.Stop(false);
- ThreadHeapUsage u2 = usage_tracker.usage();
-
- EXPECT_EQ(1U, u2.alloc_ops);
- EXPECT_EQ(kAllocSize, u2.alloc_bytes);
- EXPECT_EQ(0U, u2.alloc_overhead_bytes);
- EXPECT_EQ(1U, u2.free_ops);
- EXPECT_EQ(kAllocSize, u2.free_bytes);
- EXPECT_EQ(kAllocSize, u2.max_allocated_bytes);
-}
-
-TEST_F(ThreadHeapUsageTrackerTest, SimpleUsageWithPaddingSizeFunction) {
- set_size_function_kind(PADDING_SIZE_FUNCTION);
-
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- ThreadHeapUsage u1 = ThreadHeapUsageTracker::GetUsageSnapshot();
-
- EXPECT_EQ(0U, u1.alloc_ops);
- EXPECT_EQ(0U, u1.alloc_bytes);
- EXPECT_EQ(0U, u1.alloc_overhead_bytes);
- EXPECT_EQ(0U, u1.free_ops);
- EXPECT_EQ(0U, u1.free_bytes);
- EXPECT_EQ(0U, u1.max_allocated_bytes);
-
- const size_t kAllocSize = 1029U;
- void* ptr = MockMalloc(kAllocSize);
- MockFree(ptr);
-
- usage_tracker.Stop(false);
- ThreadHeapUsage u2 = usage_tracker.usage();
-
- EXPECT_EQ(1U, u2.alloc_ops);
- EXPECT_EQ(kAllocSize + kAllocationPadding, u2.alloc_bytes);
- EXPECT_EQ(kAllocationPadding, u2.alloc_overhead_bytes);
- EXPECT_EQ(1U, u2.free_ops);
- EXPECT_EQ(kAllocSize + kAllocationPadding, u2.free_bytes);
- EXPECT_EQ(kAllocSize + kAllocationPadding, u2.max_allocated_bytes);
-}
-
-TEST_F(ThreadHeapUsageTrackerTest, SimpleUsageWithZeroSizeFunction) {
- set_size_function_kind(ZERO_SIZE_FUNCTION);
-
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- ThreadHeapUsage u1 = ThreadHeapUsageTracker::GetUsageSnapshot();
- EXPECT_EQ(0U, u1.alloc_ops);
- EXPECT_EQ(0U, u1.alloc_bytes);
- EXPECT_EQ(0U, u1.alloc_overhead_bytes);
- EXPECT_EQ(0U, u1.free_ops);
- EXPECT_EQ(0U, u1.free_bytes);
- EXPECT_EQ(0U, u1.max_allocated_bytes);
-
- const size_t kAllocSize = 1029U;
- void* ptr = MockMalloc(kAllocSize);
- MockFree(ptr);
-
- usage_tracker.Stop(false);
- ThreadHeapUsage u2 = usage_tracker.usage();
-
- // With a get-size function that returns zero, there's no way to get the size
- // of an allocation that's being freed, hence the shim can't tally freed bytes
- // nor the high-watermark allocated bytes.
- EXPECT_EQ(1U, u2.alloc_ops);
- EXPECT_EQ(kAllocSize, u2.alloc_bytes);
- EXPECT_EQ(0U, u2.alloc_overhead_bytes);
- EXPECT_EQ(1U, u2.free_ops);
- EXPECT_EQ(0U, u2.free_bytes);
- EXPECT_EQ(0U, u2.max_allocated_bytes);
-}
-
-TEST_F(ThreadHeapUsageTrackerTest, ReallocCorrectlyTallied) {
- const size_t kAllocSize = 237U;
-
- {
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- // Reallocating nullptr should count as a single alloc.
- void* ptr = MockRealloc(nullptr, kAllocSize);
- ThreadHeapUsage usage = ThreadHeapUsageTracker::GetUsageSnapshot();
- EXPECT_EQ(1U, usage.alloc_ops);
- EXPECT_EQ(kAllocSize, usage.alloc_bytes);
- EXPECT_EQ(0U, usage.alloc_overhead_bytes);
- EXPECT_EQ(0U, usage.free_ops);
- EXPECT_EQ(0U, usage.free_bytes);
- EXPECT_EQ(kAllocSize, usage.max_allocated_bytes);
-
- // Reallocating a valid pointer to a zero size should count as a single
- // free.
- ptr = MockRealloc(ptr, 0U);
-
- usage_tracker.Stop(false);
- EXPECT_EQ(1U, usage_tracker.usage().alloc_ops);
- EXPECT_EQ(kAllocSize, usage_tracker.usage().alloc_bytes);
- EXPECT_EQ(0U, usage_tracker.usage().alloc_overhead_bytes);
- EXPECT_EQ(1U, usage_tracker.usage().free_ops);
- EXPECT_EQ(kAllocSize, usage_tracker.usage().free_bytes);
- EXPECT_EQ(kAllocSize, usage_tracker.usage().max_allocated_bytes);
-
- // Realloc to zero size may or may not return a nullptr - make sure to
- // free the zero-size alloc in the latter case.
- if (ptr != nullptr)
- MockFree(ptr);
- }
-
- {
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- void* ptr = MockMalloc(kAllocSize);
- ThreadHeapUsage usage = ThreadHeapUsageTracker::GetUsageSnapshot();
- EXPECT_EQ(1U, usage.alloc_ops);
-
- // Now try reallocating a valid pointer to a larger size, this should count
- // as one free and one alloc.
- const size_t kLargerAllocSize = kAllocSize + 928U;
- ptr = MockRealloc(ptr, kLargerAllocSize);
-
- usage_tracker.Stop(false);
- EXPECT_EQ(2U, usage_tracker.usage().alloc_ops);
- EXPECT_EQ(kAllocSize + kLargerAllocSize, usage_tracker.usage().alloc_bytes);
- EXPECT_EQ(0U, usage_tracker.usage().alloc_overhead_bytes);
- EXPECT_EQ(1U, usage_tracker.usage().free_ops);
- EXPECT_EQ(kAllocSize, usage_tracker.usage().free_bytes);
- EXPECT_EQ(kLargerAllocSize, usage_tracker.usage().max_allocated_bytes);
-
- MockFree(ptr);
- }
-}
-
-TEST_F(ThreadHeapUsageTrackerTest, NestedMaxWorks) {
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- const size_t kOuterAllocSize = 1029U;
- void* ptr = MockMalloc(kOuterAllocSize);
- MockFree(ptr);
-
- EXPECT_EQ(kOuterAllocSize,
- ThreadHeapUsageTracker::GetUsageSnapshot().max_allocated_bytes);
-
- {
- ThreadHeapUsageTracker inner_usage_tracker;
- inner_usage_tracker.Start();
-
- const size_t kInnerAllocSize = 673U;
- ptr = MockMalloc(kInnerAllocSize);
- MockFree(ptr);
-
- inner_usage_tracker.Stop(false);
-
- EXPECT_EQ(kInnerAllocSize, inner_usage_tracker.usage().max_allocated_bytes);
- }
-
- // The greater, outer allocation size should have been restored.
- EXPECT_EQ(kOuterAllocSize,
- ThreadHeapUsageTracker::GetUsageSnapshot().max_allocated_bytes);
-
- const size_t kLargerInnerAllocSize = kOuterAllocSize + 673U;
- {
- ThreadHeapUsageTracker inner_usage_tracker;
- inner_usage_tracker.Start();
-
- ptr = MockMalloc(kLargerInnerAllocSize);
- MockFree(ptr);
-
- inner_usage_tracker.Stop(false);
- EXPECT_EQ(kLargerInnerAllocSize,
- inner_usage_tracker.usage().max_allocated_bytes);
- }
-
- // The greater, inner allocation size should have been preserved.
- EXPECT_EQ(kLargerInnerAllocSize,
- ThreadHeapUsageTracker::GetUsageSnapshot().max_allocated_bytes);
-
- // Now try the case with an outstanding net alloc size when entering the
- // inner scope.
- void* outer_ptr = MockMalloc(kOuterAllocSize);
- EXPECT_EQ(kLargerInnerAllocSize,
- ThreadHeapUsageTracker::GetUsageSnapshot().max_allocated_bytes);
- {
- ThreadHeapUsageTracker inner_usage_tracker;
- inner_usage_tracker.Start();
-
- ptr = MockMalloc(kLargerInnerAllocSize);
- MockFree(ptr);
-
- inner_usage_tracker.Stop(false);
- EXPECT_EQ(kLargerInnerAllocSize,
- inner_usage_tracker.usage().max_allocated_bytes);
- }
-
- // While the inner scope saw only the inner net outstanding allocation size,
- // the outer scope saw both outstanding at the same time.
- EXPECT_EQ(kOuterAllocSize + kLargerInnerAllocSize,
- ThreadHeapUsageTracker::GetUsageSnapshot().max_allocated_bytes);
-
- MockFree(outer_ptr);
-
- // Test a net-negative scope.
- ptr = MockMalloc(kLargerInnerAllocSize);
- {
- ThreadHeapUsageTracker inner_usage_tracker;
- inner_usage_tracker.Start();
-
- MockFree(ptr);
-
- const size_t kInnerAllocSize = 1;
- ptr = MockMalloc(kInnerAllocSize);
-
- inner_usage_tracker.Stop(false);
- // Since the scope is still net-negative, the max is clamped at zero.
- EXPECT_EQ(0U, inner_usage_tracker.usage().max_allocated_bytes);
- }
-
- MockFree(ptr);
-}
-
-TEST_F(ThreadHeapUsageTrackerTest, NoStopImpliesInclusive) {
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- const size_t kOuterAllocSize = 1029U;
- void* ptr = MockMalloc(kOuterAllocSize);
- MockFree(ptr);
-
- ThreadHeapUsage usage = ThreadHeapUsageTracker::GetUsageSnapshot();
- EXPECT_EQ(kOuterAllocSize, usage.max_allocated_bytes);
-
- const size_t kInnerLargerAllocSize = kOuterAllocSize + 673U;
-
- {
- ThreadHeapUsageTracker inner_usage_tracker;
- inner_usage_tracker.Start();
-
- // Make a larger allocation than the outer scope.
- ptr = MockMalloc(kInnerLargerAllocSize);
- MockFree(ptr);
-
- // inner_usage_tracker goes out of scope without a Stop().
- }
-
- ThreadHeapUsage current = ThreadHeapUsageTracker::GetUsageSnapshot();
- EXPECT_EQ(usage.alloc_ops + 1, current.alloc_ops);
- EXPECT_EQ(usage.alloc_bytes + kInnerLargerAllocSize, current.alloc_bytes);
- EXPECT_EQ(usage.free_ops + 1, current.free_ops);
- EXPECT_EQ(usage.free_bytes + kInnerLargerAllocSize, current.free_bytes);
- EXPECT_EQ(kInnerLargerAllocSize, current.max_allocated_bytes);
-}
-
-TEST_F(ThreadHeapUsageTrackerTest, ExclusiveScopesWork) {
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- const size_t kOuterAllocSize = 1029U;
- void* ptr = MockMalloc(kOuterAllocSize);
- MockFree(ptr);
-
- ThreadHeapUsage usage = ThreadHeapUsageTracker::GetUsageSnapshot();
- EXPECT_EQ(kOuterAllocSize, usage.max_allocated_bytes);
-
- {
- ThreadHeapUsageTracker inner_usage_tracker;
- inner_usage_tracker.Start();
-
- // Make a larger allocation than the outer scope.
- ptr = MockMalloc(kOuterAllocSize + 673U);
- MockFree(ptr);
-
- // This tracker is exlusive, all activity should be private to this scope.
- inner_usage_tracker.Stop(true);
- }
-
- ThreadHeapUsage current = ThreadHeapUsageTracker::GetUsageSnapshot();
- EXPECT_EQ(usage.alloc_ops, current.alloc_ops);
- EXPECT_EQ(usage.alloc_bytes, current.alloc_bytes);
- EXPECT_EQ(usage.alloc_overhead_bytes, current.alloc_overhead_bytes);
- EXPECT_EQ(usage.free_ops, current.free_ops);
- EXPECT_EQ(usage.free_bytes, current.free_bytes);
- EXPECT_EQ(usage.max_allocated_bytes, current.max_allocated_bytes);
-}
-
-TEST_F(ThreadHeapUsageTrackerTest, AllShimFunctionsAreProvided) {
- const size_t kAllocSize = 100;
- void* alloc = MockMalloc(kAllocSize);
- size_t estimate = MockGetSizeEstimate(alloc);
- ASSERT_TRUE(estimate == 0 || estimate >= kAllocSize);
- MockFree(alloc);
-
- alloc = MockCalloc(kAllocSize, 1);
- estimate = MockGetSizeEstimate(alloc);
- ASSERT_TRUE(estimate == 0 || estimate >= kAllocSize);
- MockFree(alloc);
-
- alloc = MockAllocAligned(1, kAllocSize);
- estimate = MockGetSizeEstimate(alloc);
- ASSERT_TRUE(estimate == 0 || estimate >= kAllocSize);
-
- alloc = MockRealloc(alloc, kAllocSize);
- estimate = MockGetSizeEstimate(alloc);
- ASSERT_TRUE(estimate == 0 || estimate >= kAllocSize);
- MockFree(alloc);
-}
-
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
-class ThreadHeapUsageShimTest : public testing::Test {
-#if defined(OS_MACOSX)
- void SetUp() override { allocator::InitializeAllocatorShim(); }
- void TearDown() override { allocator::UninterceptMallocZonesForTesting(); }
-#endif
-};
-
-TEST_F(ThreadHeapUsageShimTest, HooksIntoMallocWhenShimAvailable) {
- ASSERT_FALSE(ThreadHeapUsageTracker::IsHeapTrackingEnabled());
-
- ThreadHeapUsageTracker::EnableHeapTracking();
-
- ASSERT_TRUE(ThreadHeapUsageTracker::IsHeapTrackingEnabled());
-
- const size_t kAllocSize = 9993;
- // This test verifies that the scoped heap data is affected by malloc &
- // free only when the shim is available.
- ThreadHeapUsageTracker usage_tracker;
- usage_tracker.Start();
-
- ThreadHeapUsage u1 = ThreadHeapUsageTracker::GetUsageSnapshot();
- void* ptr = malloc(kAllocSize);
- // Prevent the compiler from optimizing out the malloc/free pair.
- ASSERT_NE(nullptr, ptr);
-
- ThreadHeapUsage u2 = ThreadHeapUsageTracker::GetUsageSnapshot();
- free(ptr);
-
- usage_tracker.Stop(false);
- ThreadHeapUsage u3 = usage_tracker.usage();
-
- // Verify that at least one allocation operation was recorded, and that free
- // operations are at least monotonically growing.
- EXPECT_LE(0U, u1.alloc_ops);
- EXPECT_LE(u1.alloc_ops + 1, u2.alloc_ops);
- EXPECT_LE(u1.alloc_ops + 1, u3.alloc_ops);
-
- // Verify that at least the bytes above were recorded.
- EXPECT_LE(u1.alloc_bytes + kAllocSize, u2.alloc_bytes);
-
- // Verify that at least the one free operation above was recorded.
- EXPECT_LE(u2.free_ops + 1, u3.free_ops);
-
- TestingThreadHeapUsageTracker::DisableHeapTrackingForTesting();
-
- ASSERT_FALSE(ThreadHeapUsageTracker::IsHeapTrackingEnabled());
-}
-#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
-
-} // namespace debug
-} // namespace base
diff --git a/base/deferred_sequenced_task_runner.cc b/base/deferred_sequenced_task_runner.cc
deleted file mode 100644
index f88170c3db..0000000000
--- a/base/deferred_sequenced_task_runner.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2013 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/deferred_sequenced_task_runner.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-
-namespace base {
-
-DeferredSequencedTaskRunner::DeferredTask::DeferredTask()
- : is_non_nestable(false) {
-}
-
-DeferredSequencedTaskRunner::DeferredTask::DeferredTask(DeferredTask&& other) =
- default;
-
-DeferredSequencedTaskRunner::DeferredTask::~DeferredTask() = default;
-
-DeferredSequencedTaskRunner::DeferredTask&
-DeferredSequencedTaskRunner::DeferredTask::operator=(DeferredTask&& other) =
- default;
-
-DeferredSequencedTaskRunner::DeferredSequencedTaskRunner(
- scoped_refptr<SequencedTaskRunner> target_task_runner)
- : DeferredSequencedTaskRunner() {
- DCHECK(target_task_runner);
- target_task_runner_ = std::move(target_task_runner);
-}
-
-DeferredSequencedTaskRunner::DeferredSequencedTaskRunner()
- : created_thread_id_(PlatformThread::CurrentId()) {}
-
-bool DeferredSequencedTaskRunner::PostDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) {
- AutoLock lock(lock_);
- if (started_) {
- DCHECK(deferred_tasks_queue_.empty());
- return target_task_runner_->PostDelayedTask(from_here, std::move(task),
- delay);
- }
-
- QueueDeferredTask(from_here, std::move(task), delay,
- false /* is_non_nestable */);
- return true;
-}
-
-bool DeferredSequencedTaskRunner::RunsTasksInCurrentSequence() const {
- AutoLock lock(lock_);
- if (target_task_runner_)
- return target_task_runner_->RunsTasksInCurrentSequence();
-
- return created_thread_id_ == PlatformThread::CurrentId();
-}
-
-bool DeferredSequencedTaskRunner::PostNonNestableDelayedTask(
- const Location& from_here,
- OnceClosure task,
- TimeDelta delay) {
- AutoLock lock(lock_);
- if (started_) {
- DCHECK(deferred_tasks_queue_.empty());
- return target_task_runner_->PostNonNestableDelayedTask(
- from_here, std::move(task), delay);
- }
- QueueDeferredTask(from_here, std::move(task), delay,
- true /* is_non_nestable */);
- return true;
-}
-
-void DeferredSequencedTaskRunner::Start() {
- AutoLock lock(lock_);
- StartImpl();
-}
-
-void DeferredSequencedTaskRunner::StartWithTaskRunner(
- scoped_refptr<SequencedTaskRunner> target_task_runner) {
- AutoLock lock(lock_);
- DCHECK(!target_task_runner_);
- DCHECK(target_task_runner);
- target_task_runner_ = std::move(target_task_runner);
- StartImpl();
-}
-
-DeferredSequencedTaskRunner::~DeferredSequencedTaskRunner() = default;
-
-void DeferredSequencedTaskRunner::QueueDeferredTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay,
- bool is_non_nestable) {
- lock_.AssertAcquired();
-
- // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
- // for details.
- CHECK(task);
-
- DeferredTask deferred_task;
- deferred_task.posted_from = from_here;
- deferred_task.task = std::move(task);
- deferred_task.delay = delay;
- deferred_task.is_non_nestable = is_non_nestable;
- deferred_tasks_queue_.push_back(std::move(deferred_task));
-}
-
-void DeferredSequencedTaskRunner::StartImpl() {
- lock_.AssertAcquired(); // Callers should have grabbed the lock.
- DCHECK(!started_);
- started_ = true;
- DCHECK(target_task_runner_);
- for (std::vector<DeferredTask>::iterator i = deferred_tasks_queue_.begin();
- i != deferred_tasks_queue_.end();
- ++i) {
- DeferredTask& task = *i;
- if (task.is_non_nestable) {
- target_task_runner_->PostNonNestableDelayedTask(
- task.posted_from, std::move(task.task), task.delay);
- } else {
- target_task_runner_->PostDelayedTask(task.posted_from,
- std::move(task.task), task.delay);
- }
- }
- deferred_tasks_queue_.clear();
-}
-
-} // namespace base
diff --git a/base/deferred_sequenced_task_runner.h b/base/deferred_sequenced_task_runner.h
deleted file mode 100644
index 2805f479e6..0000000000
--- a/base/deferred_sequenced_task_runner.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_
-#define BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_
-
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-
-namespace base {
-
-// A DeferredSequencedTaskRunner is a subclass of SequencedTaskRunner that
-// queues up all requests until the first call to Start() is issued.
-// DeferredSequencedTaskRunner may be created in two ways:
-// . with an explicit SequencedTaskRunner that the events are flushed to
-// . without a SequencedTaskRunner. In this configuration the
-// SequencedTaskRunner is supplied in StartWithTaskRunner().
-class BASE_EXPORT DeferredSequencedTaskRunner : public SequencedTaskRunner {
- public:
- explicit DeferredSequencedTaskRunner(
- scoped_refptr<SequencedTaskRunner> target_runner);
-
- // Use this constructor when you don't have the target SequencedTaskRunner.
- // When using this call StartWithTaskRunner().
- DeferredSequencedTaskRunner();
-
- // TaskRunner implementation
- bool PostDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override;
- bool RunsTasksInCurrentSequence() const override;
-
- // SequencedTaskRunner implementation
- bool PostNonNestableDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override;
-
- // Start the execution - posts all queued tasks to the target executor. The
- // deferred tasks are posted with their initial delay, meaning that the task
- // execution delay is actually measured from Start.
- // Fails when called a second time.
- void Start();
-
- // Same as Start(), but must be used with the no-arg constructor.
- void StartWithTaskRunner(
- scoped_refptr<SequencedTaskRunner> target_task_runner);
-
- private:
- struct DeferredTask {
- DeferredTask();
- DeferredTask(DeferredTask&& other);
- ~DeferredTask();
- DeferredTask& operator=(DeferredTask&& other);
-
- Location posted_from;
- OnceClosure task;
- // The delay this task was initially posted with.
- TimeDelta delay;
- bool is_non_nestable;
- };
-
- ~DeferredSequencedTaskRunner() override;
-
- // Both variants of Start() call into this.
- void StartImpl();
-
- // Creates a |Task| object and adds it to |deferred_tasks_queue_|.
- void QueueDeferredTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay,
- bool is_non_nestable);
-
- // // Protects |started_| and |deferred_tasks_queue_|.
- mutable Lock lock_;
-
- const PlatformThreadId created_thread_id_;
-
- bool started_ = false;
- scoped_refptr<SequencedTaskRunner> target_task_runner_;
- std::vector<DeferredTask> deferred_tasks_queue_;
-
- DISALLOW_COPY_AND_ASSIGN(DeferredSequencedTaskRunner);
-};
-
-} // namespace base
-
-#endif // BASE_DEFERRED_SEQUENCED_TASK_RUNNER_H_
diff --git a/base/deferred_sequenced_task_runner_unittest.cc b/base/deferred_sequenced_task_runner_unittest.cc
deleted file mode 100644
index 5cb220fdf9..0000000000
--- a/base/deferred_sequenced_task_runner_unittest.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2013 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/deferred_sequenced_task_runner.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback_forward.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class DeferredSequencedTaskRunnerTest : public testing::Test {
- public:
- class ExecuteTaskOnDestructor : public RefCounted<ExecuteTaskOnDestructor> {
- public:
- ExecuteTaskOnDestructor(
- DeferredSequencedTaskRunnerTest* executor,
- int task_id)
- : executor_(executor),
- task_id_(task_id) {
- }
- private:
- friend class RefCounted<ExecuteTaskOnDestructor>;
- virtual ~ExecuteTaskOnDestructor() { executor_->ExecuteTask(task_id_); }
- DeferredSequencedTaskRunnerTest* executor_;
- int task_id_;
- };
-
- void ExecuteTask(int task_id) {
- AutoLock lock(lock_);
- executed_task_ids_.push_back(task_id);
- }
-
- void PostExecuteTask(int task_id) {
- runner_->PostTask(FROM_HERE,
- BindOnce(&DeferredSequencedTaskRunnerTest::ExecuteTask,
- Unretained(this), task_id));
- }
-
- void StartRunner() {
- runner_->Start();
- }
-
- void DoNothing(ExecuteTaskOnDestructor* object) {
- }
-
- protected:
- DeferredSequencedTaskRunnerTest()
- : loop_(),
- runner_(new DeferredSequencedTaskRunner(loop_.task_runner())) {}
-
- MessageLoop loop_;
- scoped_refptr<DeferredSequencedTaskRunner> runner_;
- mutable Lock lock_;
- std::vector<int> executed_task_ids_;
-};
-
-TEST_F(DeferredSequencedTaskRunnerTest, Stopped) {
- PostExecuteTask(1);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, Start) {
- StartRunner();
- PostExecuteTask(1);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, StartWithMultipleElements) {
- StartRunner();
- for (int i = 1; i < 5; ++i)
- PostExecuteTask(i);
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4));
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, DeferredStart) {
- PostExecuteTask(1);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
-
- StartRunner();
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1));
-
- PostExecuteTask(2);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2));
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleElements) {
- for (int i = 1; i < 5; ++i)
- PostExecuteTask(i);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre());
-
- StartRunner();
- for (int i = 5; i < 9; ++i)
- PostExecuteTask(i);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleThreads) {
- {
- Thread thread1("DeferredSequencedTaskRunnerTestThread1");
- Thread thread2("DeferredSequencedTaskRunnerTestThread2");
- thread1.Start();
- thread2.Start();
- for (int i = 0; i < 5; ++i) {
- thread1.task_runner()->PostTask(
- FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
- Unretained(this), 2 * i));
- thread2.task_runner()->PostTask(
- FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::PostExecuteTask,
- Unretained(this), 2 * i + 1));
- if (i == 2) {
- thread1.task_runner()->PostTask(
- FROM_HERE, BindOnce(&DeferredSequencedTaskRunnerTest::StartRunner,
- Unretained(this)));
- }
- }
- }
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(executed_task_ids_,
- testing::WhenSorted(testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)));
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, ObjectDestructionOrder) {
- {
- Thread thread("DeferredSequencedTaskRunnerTestThread");
- thread.Start();
- runner_ = new DeferredSequencedTaskRunner(thread.task_runner());
- for (int i = 0; i < 5; ++i) {
- {
- // Use a block to ensure that no reference to |short_lived_object|
- // is kept on the main thread after it is posted to |runner_|.
- scoped_refptr<ExecuteTaskOnDestructor> short_lived_object =
- new ExecuteTaskOnDestructor(this, 2 * i);
- runner_->PostTask(
- FROM_HERE,
- BindOnce(&DeferredSequencedTaskRunnerTest::DoNothing,
- Unretained(this), RetainedRef(short_lived_object)));
- }
- // |short_lived_object| with id |2 * i| should be destroyed before the
- // task |2 * i + 1| is executed.
- PostExecuteTask(2 * i + 1);
- }
- StartRunner();
- }
-
- // All |short_lived_object| with id |2 * i| are destroyed before the task
- // |2 * i + 1| is executed.
- EXPECT_THAT(executed_task_ids_,
- testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
-}
-
-void GetRunsTasksInCurrentSequence(bool* result,
- scoped_refptr<SequencedTaskRunner> runner,
- OnceClosure quit) {
- *result = runner->RunsTasksInCurrentSequence();
- std::move(quit).Run();
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, RunsTasksInCurrentSequence) {
- scoped_refptr<DeferredSequencedTaskRunner> runner =
- MakeRefCounted<DeferredSequencedTaskRunner>();
- EXPECT_TRUE(runner->RunsTasksInCurrentSequence());
-
- Thread thread1("DeferredSequencedTaskRunnerTestThread1");
- thread1.Start();
- bool runs_task_in_current_thread = true;
- base::RunLoop run_loop;
- thread1.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&GetRunsTasksInCurrentSequence, &runs_task_in_current_thread,
- runner, run_loop.QuitClosure()));
- run_loop.Run();
- EXPECT_FALSE(runs_task_in_current_thread);
-}
-
-TEST_F(DeferredSequencedTaskRunnerTest, StartWithTaskRunner) {
- scoped_refptr<DeferredSequencedTaskRunner> runner =
- MakeRefCounted<DeferredSequencedTaskRunner>();
- bool run_called = false;
- base::RunLoop run_loop;
- runner->PostTask(FROM_HERE,
- BindOnce(
- [](bool* run_called, base::Closure quit_closure) {
- *run_called = true;
- std::move(quit_closure).Run();
- },
- &run_called, run_loop.QuitClosure()));
- runner->StartWithTaskRunner(loop_.task_runner());
- run_loop.Run();
- EXPECT_TRUE(run_called);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/file_descriptor_store.cc b/base/file_descriptor_store.cc
deleted file mode 100644
index 71cf2b3f51..0000000000
--- a/base/file_descriptor_store.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 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/file_descriptor_store.h"
-
-#include <utility>
-
-#include "base/logging.h"
-
-namespace base {
-
-FileDescriptorStore::Descriptor::Descriptor(const std::string& key,
- base::ScopedFD fd)
- : key(key),
- fd(std::move(fd)),
- region(base::MemoryMappedFile::Region::kWholeFile) {}
-
-FileDescriptorStore::Descriptor::Descriptor(
- const std::string& key,
- base::ScopedFD fd,
- base::MemoryMappedFile::Region region)
- : key(key), fd(std::move(fd)), region(region) {}
-
-FileDescriptorStore::Descriptor::Descriptor(
- FileDescriptorStore::Descriptor&& other)
- : key(other.key), fd(std::move(other.fd)), region(other.region) {}
-
-FileDescriptorStore::Descriptor::~Descriptor() = default;
-
-// static
-FileDescriptorStore& FileDescriptorStore::GetInstance() {
- static FileDescriptorStore* store = new FileDescriptorStore;
- return *store;
-}
-
-base::ScopedFD FileDescriptorStore::TakeFD(
- const std::string& key,
- base::MemoryMappedFile::Region* region) {
- base::ScopedFD fd = MaybeTakeFD(key, region);
- if (!fd.is_valid())
- DLOG(DCHECK) << "Unknown global descriptor: " << key;
- return fd;
-}
-
-base::ScopedFD FileDescriptorStore::MaybeTakeFD(
- const std::string& key,
- base::MemoryMappedFile::Region* region) {
- auto iter = descriptors_.find(key);
- if (iter == descriptors_.end())
- return base::ScopedFD();
- *region = iter->second.region;
- base::ScopedFD result = std::move(iter->second.fd);
- descriptors_.erase(iter);
- return result;
-}
-
-void FileDescriptorStore::Set(const std::string& key, base::ScopedFD fd) {
- Set(key, std::move(fd), base::MemoryMappedFile::Region::kWholeFile);
-}
-
-void FileDescriptorStore::Set(const std::string& key,
- base::ScopedFD fd,
- base::MemoryMappedFile::Region region) {
- Descriptor descriptor(key, std::move(fd), region);
- descriptors_.insert(std::make_pair(key, std::move(descriptor)));
-}
-
-FileDescriptorStore::FileDescriptorStore() = default;
-
-FileDescriptorStore::~FileDescriptorStore() = default;
-
-} // namespace base
diff --git a/base/file_descriptor_store.h b/base/file_descriptor_store.h
deleted file mode 100644
index b6bd079916..0000000000
--- a/base/file_descriptor_store.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_FILE_DESCRIPTOR_STORE_H_
-#define BASE_FILE_DESCRIPTOR_STORE_H_
-
-#include <map>
-#include <string>
-
-#include "base/files/memory_mapped_file.h"
-#include "base/files/scoped_file.h"
-#include "base/macros.h"
-
-namespace base {
-
-// The file descriptor store is used to associate file descriptors with keys
-// that must be unique.
-// It is used to share file descriptors from a process to its child.
-class BASE_EXPORT FileDescriptorStore {
- public:
- struct Descriptor {
- Descriptor(const std::string& key, base::ScopedFD fd);
- Descriptor(const std::string& key,
- base::ScopedFD fd,
- base::MemoryMappedFile::Region region);
- Descriptor(Descriptor&& other);
- ~Descriptor();
-
- Descriptor& operator=(Descriptor&& other) = default;
-
- // Globally unique key.
- std::string key;
- // Actual FD.
- base::ScopedFD fd;
- // Optional region, defaults to kWholeFile.
- base::MemoryMappedFile::Region region;
- };
- using Mapping = std::map<std::string, Descriptor>;
-
- // Returns the singleton instance of FileDescriptorStore.
- static FileDescriptorStore& GetInstance();
-
- // Gets a descriptor given a key and also populates |region|.
- // It is a fatal error if the key is not known.
- base::ScopedFD TakeFD(const std::string& key,
- base::MemoryMappedFile::Region* region);
-
- // Gets a descriptor given a key. Returns an empty ScopedFD on error.
- base::ScopedFD MaybeTakeFD(const std::string& key,
- base::MemoryMappedFile::Region* region);
-
- // Sets the descriptor for the given |key|. This sets the region associated
- // with |key| to kWholeFile.
- void Set(const std::string& key, base::ScopedFD fd);
-
- // Sets the descriptor and |region| for the given |key|.
- void Set(const std::string& key,
- base::ScopedFD fd,
- base::MemoryMappedFile::Region region);
-
- private:
- FileDescriptorStore();
- ~FileDescriptorStore();
-
- Mapping descriptors_;
-
- DISALLOW_COPY_AND_ASSIGN(FileDescriptorStore);
-};
-
-} // namespace base
-
-#endif // BASE_FILE_DESCRIPTOR_STORE_H_
diff --git a/base/files/file_locking_unittest.cc b/base/files/file_locking_unittest.cc
deleted file mode 100644
index e158b7d06a..0000000000
--- a/base/files/file_locking_unittest.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2015 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/command_line.h"
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-using base::File;
-using base::FilePath;
-
-namespace {
-
-// Flag for the parent to share a temp dir to the child.
-const char kTempDirFlag[] = "temp-dir";
-
-// Flags to control how the subprocess unlocks the file.
-const char kFileUnlock[] = "file-unlock";
-const char kCloseUnlock[] = "close-unlock";
-const char kExitUnlock[] = "exit-unlock";
-
-// File to lock in temp dir.
-const char kLockFile[] = "lockfile";
-
-// Constants for various requests and responses, used as |signal_file| parameter
-// to signal/wait helpers.
-const char kSignalLockFileLocked[] = "locked.signal";
-const char kSignalLockFileClose[] = "close.signal";
-const char kSignalLockFileClosed[] = "closed.signal";
-const char kSignalLockFileUnlock[] = "unlock.signal";
-const char kSignalLockFileUnlocked[] = "unlocked.signal";
-const char kSignalExit[] = "exit.signal";
-
-// Signal an event by creating a file which didn't previously exist.
-bool SignalEvent(const FilePath& signal_dir, const char* signal_file) {
- File file(signal_dir.AppendASCII(signal_file),
- File::FLAG_CREATE | File::FLAG_WRITE);
- return file.IsValid();
-}
-
-// Check whether an event was signaled.
-bool CheckEvent(const FilePath& signal_dir, const char* signal_file) {
- File file(signal_dir.AppendASCII(signal_file),
- File::FLAG_OPEN | File::FLAG_READ);
- return file.IsValid();
-}
-
-// Busy-wait for an event to be signaled, returning false for timeout.
-bool WaitForEventWithTimeout(const FilePath& signal_dir,
- const char* signal_file,
- const base::TimeDelta& timeout) {
- const base::Time finish_by = base::Time::Now() + timeout;
- while (!CheckEvent(signal_dir, signal_file)) {
- if (base::Time::Now() > finish_by)
- return false;
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
- }
- return true;
-}
-
-// Wait forever for the event to be signaled (should never return false).
-bool WaitForEvent(const FilePath& signal_dir, const char* signal_file) {
- return WaitForEventWithTimeout(signal_dir, signal_file,
- base::TimeDelta::Max());
-}
-
-// Keep these in sync so StartChild*() can refer to correct test main.
-#define ChildMain ChildLockUnlock
-#define ChildMainString "ChildLockUnlock"
-
-// Subprocess to test getting a file lock then releasing it. |kTempDirFlag|
-// must pass in an existing temporary directory for the lockfile and signal
-// files. One of the following flags must be passed to determine how to unlock
-// the lock file:
-// - |kFileUnlock| calls Unlock() to unlock.
-// - |kCloseUnlock| calls Close() while the lock is held.
-// - |kExitUnlock| exits while the lock is held.
-MULTIPROCESS_TEST_MAIN(ChildMain) {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- const FilePath temp_path = command_line->GetSwitchValuePath(kTempDirFlag);
- CHECK(base::DirectoryExists(temp_path));
-
- // Immediately lock the file.
- File file(temp_path.AppendASCII(kLockFile),
- File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE);
- CHECK(file.IsValid());
- CHECK_EQ(File::FILE_OK, file.Lock());
- CHECK(SignalEvent(temp_path, kSignalLockFileLocked));
-
- if (command_line->HasSwitch(kFileUnlock)) {
- // Wait for signal to unlock, then unlock the file.
- CHECK(WaitForEvent(temp_path, kSignalLockFileUnlock));
- CHECK_EQ(File::FILE_OK, file.Unlock());
- CHECK(SignalEvent(temp_path, kSignalLockFileUnlocked));
- } else if (command_line->HasSwitch(kCloseUnlock)) {
- // Wait for the signal to close, then close the file.
- CHECK(WaitForEvent(temp_path, kSignalLockFileClose));
- file.Close();
- CHECK(!file.IsValid());
- CHECK(SignalEvent(temp_path, kSignalLockFileClosed));
- } else {
- CHECK(command_line->HasSwitch(kExitUnlock));
- }
-
- // Wait for signal to exit, so that unlock or close can be distinguished from
- // exit.
- CHECK(WaitForEvent(temp_path, kSignalExit));
- return 0;
-}
-
-} // namespace
-
-class FileLockingTest : public testing::Test {
- public:
- FileLockingTest() = default;
-
- protected:
- void SetUp() override {
- testing::Test::SetUp();
-
- // Setup the temp dir and the lock file.
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- lock_file_.Initialize(
- temp_dir_.GetPath().AppendASCII(kLockFile),
- File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
- ASSERT_TRUE(lock_file_.IsValid());
- }
-
- bool SignalEvent(const char* signal_file) {
- return ::SignalEvent(temp_dir_.GetPath(), signal_file);
- }
-
- bool WaitForEventOrTimeout(const char* signal_file) {
- return ::WaitForEventWithTimeout(temp_dir_.GetPath(), signal_file,
- TestTimeouts::action_timeout());
- }
-
- // Start a child process set to use the specified unlock action, and wait for
- // it to lock the file.
- void StartChildAndSignalLock(const char* unlock_action) {
- // Create a temporary dir and spin up a ChildLockExit subprocess against it.
- const FilePath temp_path = temp_dir_.GetPath();
- base::CommandLine child_command_line(
- base::GetMultiProcessTestChildBaseCommandLine());
- child_command_line.AppendSwitchPath(kTempDirFlag, temp_path);
- child_command_line.AppendSwitch(unlock_action);
- lock_child_ = base::SpawnMultiProcessTestChild(
- ChildMainString, child_command_line, base::LaunchOptions());
- ASSERT_TRUE(lock_child_.IsValid());
-
- // Wait for the child to lock the file.
- ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileLocked));
- }
-
- // Signal the child to exit cleanly.
- void ExitChildCleanly() {
- ASSERT_TRUE(SignalEvent(kSignalExit));
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- lock_child_, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
-
- base::ScopedTempDir temp_dir_;
- base::File lock_file_;
- base::Process lock_child_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FileLockingTest);
-};
-
-// Test that locks are released by Unlock().
-TEST_F(FileLockingTest, LockAndUnlock) {
- StartChildAndSignalLock(kFileUnlock);
-
- ASSERT_NE(File::FILE_OK, lock_file_.Lock());
- ASSERT_TRUE(SignalEvent(kSignalLockFileUnlock));
- ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileUnlocked));
- ASSERT_EQ(File::FILE_OK, lock_file_.Lock());
- ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
-
- ExitChildCleanly();
-}
-
-// Test that locks are released on Close().
-TEST_F(FileLockingTest, UnlockOnClose) {
- StartChildAndSignalLock(kCloseUnlock);
-
- ASSERT_NE(File::FILE_OK, lock_file_.Lock());
- ASSERT_TRUE(SignalEvent(kSignalLockFileClose));
- ASSERT_TRUE(WaitForEventOrTimeout(kSignalLockFileClosed));
- ASSERT_EQ(File::FILE_OK, lock_file_.Lock());
- ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
-
- ExitChildCleanly();
-}
-
-// Test that locks are released on exit.
-TEST_F(FileLockingTest, UnlockOnExit) {
- StartChildAndSignalLock(kExitUnlock);
-
- ASSERT_NE(File::FILE_OK, lock_file_.Lock());
- ExitChildCleanly();
- ASSERT_EQ(File::FILE_OK, lock_file_.Lock());
- ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
-}
-
-// Test that killing the process releases the lock. This should cover crashing.
-// Flaky on Android (http://crbug.com/747518)
-#if defined(OS_ANDROID)
-#define MAYBE_UnlockOnTerminate DISABLED_UnlockOnTerminate
-#else
-#define MAYBE_UnlockOnTerminate UnlockOnTerminate
-#endif
-TEST_F(FileLockingTest, MAYBE_UnlockOnTerminate) {
- // The child will wait for an exit which never arrives.
- StartChildAndSignalLock(kExitUnlock);
-
- ASSERT_NE(File::FILE_OK, lock_file_.Lock());
- ASSERT_TRUE(TerminateMultiProcessTestChild(lock_child_, 0, true));
- ASSERT_EQ(File::FILE_OK, lock_file_.Lock());
- ASSERT_EQ(File::FILE_OK, lock_file_.Unlock());
-}
diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc
deleted file mode 100644
index 49ed36ba44..0000000000
--- a/base/files/file_path_watcher_fsevents.cc
+++ /dev/null
@@ -1,282 +0,0 @@
-// 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/files/file_path_watcher_fsevents.h"
-
-#include <dispatch/dispatch.h>
-
-#include <list>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-
-namespace base {
-
-namespace {
-
-// The latency parameter passed to FSEventsStreamCreate().
-const CFAbsoluteTime kEventLatencySeconds = 0.3;
-
-// Resolve any symlinks in the path.
-FilePath ResolvePath(const FilePath& path) {
- const unsigned kMaxLinksToResolve = 255;
-
- std::vector<FilePath::StringType> component_vector;
- path.GetComponents(&component_vector);
- std::list<FilePath::StringType>
- components(component_vector.begin(), component_vector.end());
-
- FilePath result;
- unsigned resolve_count = 0;
- while (resolve_count < kMaxLinksToResolve && !components.empty()) {
- FilePath component(*components.begin());
- components.pop_front();
-
- FilePath current;
- if (component.IsAbsolute()) {
- current = component;
- } else {
- current = result.Append(component);
- }
-
- FilePath target;
- if (ReadSymbolicLink(current, &target)) {
- if (target.IsAbsolute())
- result.clear();
- std::vector<FilePath::StringType> target_components;
- target.GetComponents(&target_components);
- components.insert(components.begin(), target_components.begin(),
- target_components.end());
- resolve_count++;
- } else {
- result = current;
- }
- }
-
- if (resolve_count >= kMaxLinksToResolve)
- result.clear();
- return result;
-}
-
-} // namespace
-
-FilePathWatcherFSEvents::FilePathWatcherFSEvents()
- : queue_(dispatch_queue_create(
- base::StringPrintf("org.chromium.base.FilePathWatcher.%p", this)
- .c_str(),
- DISPATCH_QUEUE_SERIAL)),
- fsevent_stream_(nullptr),
- weak_factory_(this) {}
-
-FilePathWatcherFSEvents::~FilePathWatcherFSEvents() {
- DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
- DCHECK(callback_.is_null())
- << "Cancel() must be called before FilePathWatcher is destroyed.";
-}
-
-bool FilePathWatcherFSEvents::Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) {
- DCHECK(!callback.is_null());
- DCHECK(callback_.is_null());
-
- // This class could support non-recursive watches, but that is currently
- // left to FilePathWatcherKQueue.
- if (!recursive)
- return false;
-
- set_task_runner(SequencedTaskRunnerHandle::Get());
- callback_ = callback;
-
- FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
- // The block runtime would implicitly capture the reference, not the object
- // it's referencing. Copy the path into a local, so that the value is
- // captured by the block's scope.
- const FilePath path_copy(path);
-
- dispatch_async(queue_, ^{
- StartEventStream(start_event, path_copy);
- });
- return true;
-}
-
-void FilePathWatcherFSEvents::Cancel() {
- set_cancelled();
- callback_.Reset();
-
- // Switch to the dispatch queue to tear down the event stream. As the queue is
- // owned by |this|, and this method is called from the destructor, execute the
- // block synchronously.
- dispatch_sync(queue_, ^{
- if (fsevent_stream_) {
- DestroyEventStream();
- target_.clear();
- resolved_target_.clear();
- }
- });
-}
-
-// static
-void FilePathWatcherFSEvents::FSEventsCallback(
- ConstFSEventStreamRef stream,
- void* event_watcher,
- size_t num_events,
- void* event_paths,
- const FSEventStreamEventFlags flags[],
- const FSEventStreamEventId event_ids[]) {
- FilePathWatcherFSEvents* watcher =
- reinterpret_cast<FilePathWatcherFSEvents*>(event_watcher);
- bool root_changed = watcher->ResolveTargetPath();
- std::vector<FilePath> paths;
- FSEventStreamEventId root_change_at = FSEventStreamGetLatestEventId(stream);
- for (size_t i = 0; i < num_events; i++) {
- if (flags[i] & kFSEventStreamEventFlagRootChanged)
- root_changed = true;
- if (event_ids[i])
- root_change_at = std::min(root_change_at, event_ids[i]);
- paths.push_back(FilePath(
- reinterpret_cast<char**>(event_paths)[i]).StripTrailingSeparators());
- }
-
- // Reinitialize the event stream if we find changes to the root. This is
- // necessary since FSEvents doesn't report any events for the subtree after
- // the directory to be watched gets created.
- if (root_changed) {
- // Resetting the event stream from within the callback fails (FSEvents spews
- // bad file descriptor errors), so do the reset asynchronously.
- //
- // We can't dispatch_async a call to UpdateEventStream() directly because
- // there would be no guarantee that |watcher| still exists when it runs.
- //
- // Instead, bounce on task_runner() and use a WeakPtr to verify that
- // |watcher| still exists. If it does, dispatch_async a call to
- // UpdateEventStream(). Because the destructor of |watcher| runs on
- // task_runner() and calls dispatch_sync, it is guaranteed that |watcher|
- // still exists when UpdateEventStream() runs.
- watcher->task_runner()->PostTask(
- FROM_HERE, Bind(
- [](WeakPtr<FilePathWatcherFSEvents> weak_watcher,
- FSEventStreamEventId root_change_at) {
- if (!weak_watcher)
- return;
- FilePathWatcherFSEvents* watcher = weak_watcher.get();
- dispatch_async(watcher->queue_, ^{
- watcher->UpdateEventStream(root_change_at);
- });
- },
- watcher->weak_factory_.GetWeakPtr(), root_change_at));
- }
-
- watcher->OnFilePathsChanged(paths);
-}
-
-void FilePathWatcherFSEvents::OnFilePathsChanged(
- const std::vector<FilePath>& paths) {
- DCHECK(!resolved_target_.empty());
- task_runner()->PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::DispatchEvents, weak_factory_.GetWeakPtr(),
- paths, target_, resolved_target_));
-}
-
-void FilePathWatcherFSEvents::DispatchEvents(const std::vector<FilePath>& paths,
- const FilePath& target,
- const FilePath& resolved_target) {
- DCHECK(task_runner()->RunsTasksInCurrentSequence());
-
- // Don't issue callbacks after Cancel() has been called.
- if (is_cancelled() || callback_.is_null()) {
- return;
- }
-
- for (const FilePath& path : paths) {
- if (resolved_target.IsParent(path) || resolved_target == path) {
- callback_.Run(target, false);
- return;
- }
- }
-}
-
-void FilePathWatcherFSEvents::UpdateEventStream(
- FSEventStreamEventId start_event) {
- // It can happen that the watcher gets canceled while tasks that call this
- // function are still in flight, so abort if this situation is detected.
- if (resolved_target_.empty())
- return;
-
- if (fsevent_stream_)
- DestroyEventStream();
-
- ScopedCFTypeRef<CFStringRef> cf_path(CFStringCreateWithCString(
- NULL, resolved_target_.value().c_str(), kCFStringEncodingMacHFS));
- ScopedCFTypeRef<CFStringRef> cf_dir_path(CFStringCreateWithCString(
- NULL, resolved_target_.DirName().value().c_str(),
- kCFStringEncodingMacHFS));
- CFStringRef paths_array[] = { cf_path.get(), cf_dir_path.get() };
- ScopedCFTypeRef<CFArrayRef> watched_paths(CFArrayCreate(
- NULL, reinterpret_cast<const void**>(paths_array), arraysize(paths_array),
- &kCFTypeArrayCallBacks));
-
- FSEventStreamContext context;
- context.version = 0;
- context.info = this;
- context.retain = NULL;
- context.release = NULL;
- context.copyDescription = NULL;
-
- fsevent_stream_ = FSEventStreamCreate(NULL, &FSEventsCallback, &context,
- watched_paths,
- start_event,
- kEventLatencySeconds,
- kFSEventStreamCreateFlagWatchRoot);
- FSEventStreamSetDispatchQueue(fsevent_stream_, queue_);
-
- if (!FSEventStreamStart(fsevent_stream_)) {
- task_runner()->PostTask(FROM_HERE,
- Bind(&FilePathWatcherFSEvents::ReportError,
- weak_factory_.GetWeakPtr(), target_));
- }
-}
-
-bool FilePathWatcherFSEvents::ResolveTargetPath() {
- FilePath resolved = ResolvePath(target_).StripTrailingSeparators();
- bool changed = resolved != resolved_target_;
- resolved_target_ = resolved;
- if (resolved_target_.empty()) {
- task_runner()->PostTask(FROM_HERE,
- Bind(&FilePathWatcherFSEvents::ReportError,
- weak_factory_.GetWeakPtr(), target_));
- }
- return changed;
-}
-
-void FilePathWatcherFSEvents::ReportError(const FilePath& target) {
- DCHECK(task_runner()->RunsTasksInCurrentSequence());
- if (!callback_.is_null()) {
- callback_.Run(target, true);
- }
-}
-
-void FilePathWatcherFSEvents::DestroyEventStream() {
- FSEventStreamStop(fsevent_stream_);
- FSEventStreamInvalidate(fsevent_stream_);
- FSEventStreamRelease(fsevent_stream_);
- fsevent_stream_ = NULL;
-}
-
-void FilePathWatcherFSEvents::StartEventStream(FSEventStreamEventId start_event,
- const FilePath& path) {
- DCHECK(resolved_target_.empty());
-
- target_ = path;
- ResolveTargetPath();
- UpdateEventStream(start_event);
-}
-
-} // namespace base
diff --git a/base/files/file_path_watcher_fsevents.h b/base/files/file_path_watcher_fsevents.h
deleted file mode 100644
index dcdf2fbf9d..0000000000
--- a/base/files/file_path_watcher_fsevents.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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.
-
-#ifndef BASE_FILES_FILE_PATH_WATCHER_FSEVENTS_H_
-#define BASE_FILES_FILE_PATH_WATCHER_FSEVENTS_H_
-
-#include <CoreServices/CoreServices.h>
-#include <stddef.h>
-
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/files/file_path_watcher.h"
-#include "base/mac/scoped_dispatch_object.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-
-namespace base {
-
-// Mac-specific file watcher implementation based on FSEvents.
-// There are trade-offs between the FSEvents implementation and a kqueue
-// implementation. The biggest issues are that FSEvents on 10.6 sometimes drops
-// events and kqueue does not trigger for modifications to a file in a watched
-// directory. See file_path_watcher_mac.cc for the code that decides when to
-// use which one.
-class FilePathWatcherFSEvents : public FilePathWatcher::PlatformDelegate {
- public:
- FilePathWatcherFSEvents();
- ~FilePathWatcherFSEvents() override;
-
- // FilePathWatcher::PlatformDelegate overrides.
- bool Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) override;
- void Cancel() override;
-
- private:
- static void FSEventsCallback(ConstFSEventStreamRef stream,
- void* event_watcher,
- size_t num_events,
- void* event_paths,
- const FSEventStreamEventFlags flags[],
- const FSEventStreamEventId event_ids[]);
-
- // Called from FSEventsCallback whenever there is a change to the paths.
- void OnFilePathsChanged(const std::vector<FilePath>& paths);
-
- // Called on the message_loop() thread to dispatch path events. Can't access
- // target_ and resolved_target_ directly as those are modified on the
- // libdispatch thread.
- void DispatchEvents(const std::vector<FilePath>& paths,
- const FilePath& target,
- const FilePath& resolved_target);
-
- // (Re-)Initialize the event stream to start reporting events from
- // |start_event|.
- void UpdateEventStream(FSEventStreamEventId start_event);
-
- // Returns true if resolving the target path got a different result than
- // last time it was done.
- bool ResolveTargetPath();
-
- // Report an error watching the given target.
- void ReportError(const FilePath& target);
-
- // Destroy the event stream.
- void DestroyEventStream();
-
- // Start watching the FSEventStream.
- void StartEventStream(FSEventStreamEventId start_event, const FilePath& path);
-
- // Callback to notify upon changes.
- // (Only accessed from the message_loop() thread.)
- FilePathWatcher::Callback callback_;
-
- // The dispatch queue on which the the event stream is scheduled.
- ScopedDispatchObject<dispatch_queue_t> queue_;
-
- // Target path to watch (passed to callback).
- // (Only accessed from the libdispatch queue.)
- FilePath target_;
-
- // Target path with all symbolic links resolved.
- // (Only accessed from the libdispatch queue.)
- FilePath resolved_target_;
-
- // Backend stream we receive event callbacks from (strong reference).
- // (Only accessed from the libdispatch queue.)
- FSEventStreamRef fsevent_stream_;
-
- WeakPtrFactory<FilePathWatcherFSEvents> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(FilePathWatcherFSEvents);
-};
-
-} // namespace base
-
-#endif // BASE_FILES_FILE_PATH_WATCHER_FSEVENTS_H_
diff --git a/base/files/file_path_watcher_kqueue.cc b/base/files/file_path_watcher_kqueue.cc
deleted file mode 100644
index 036809d6cf..0000000000
--- a/base/files/file_path_watcher_kqueue.cc
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/files/file_path_watcher_kqueue.h"
-
-#include <fcntl.h>
-#include <stddef.h>
-#include <sys/param.h>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-
-// On some platforms these are not defined.
-#if !defined(EV_RECEIPT)
-#define EV_RECEIPT 0
-#endif
-#if !defined(O_EVTONLY)
-#define O_EVTONLY O_RDONLY
-#endif
-
-namespace base {
-
-FilePathWatcherKQueue::FilePathWatcherKQueue() : kqueue_(-1) {}
-
-FilePathWatcherKQueue::~FilePathWatcherKQueue() {
- DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
-}
-
-void FilePathWatcherKQueue::ReleaseEvent(struct kevent& event) {
- CloseFileDescriptor(&event.ident);
- EventData* entry = EventDataForKevent(event);
- delete entry;
- event.udata = NULL;
-}
-
-int FilePathWatcherKQueue::EventsForPath(FilePath path, EventVector* events) {
- // Make sure that we are working with a clean slate.
- DCHECK(events->empty());
-
- std::vector<FilePath::StringType> components;
- path.GetComponents(&components);
-
- if (components.size() < 1) {
- return -1;
- }
-
- int last_existing_entry = 0;
- FilePath built_path;
- bool path_still_exists = true;
- for (std::vector<FilePath::StringType>::iterator i = components.begin();
- i != components.end(); ++i) {
- if (i == components.begin()) {
- built_path = FilePath(*i);
- } else {
- built_path = built_path.Append(*i);
- }
- uintptr_t fd = kNoFileDescriptor;
- if (path_still_exists) {
- fd = FileDescriptorForPath(built_path);
- if (fd == kNoFileDescriptor) {
- path_still_exists = false;
- } else {
- ++last_existing_entry;
- }
- }
- FilePath::StringType subdir = (i != (components.end() - 1)) ? *(i + 1) : "";
- EventData* data = new EventData(built_path, subdir);
- struct kevent event;
- EV_SET(&event, fd, EVFILT_VNODE, (EV_ADD | EV_CLEAR | EV_RECEIPT),
- (NOTE_DELETE | NOTE_WRITE | NOTE_ATTRIB |
- NOTE_RENAME | NOTE_REVOKE | NOTE_EXTEND), 0, data);
- events->push_back(event);
- }
- return last_existing_entry;
-}
-
-uintptr_t FilePathWatcherKQueue::FileDescriptorForPath(const FilePath& path) {
- int fd = HANDLE_EINTR(open(path.value().c_str(), O_EVTONLY));
- if (fd == -1)
- return kNoFileDescriptor;
- return fd;
-}
-
-void FilePathWatcherKQueue::CloseFileDescriptor(uintptr_t* fd) {
- if (*fd == kNoFileDescriptor) {
- return;
- }
-
- if (IGNORE_EINTR(close(*fd)) != 0) {
- DPLOG(ERROR) << "close";
- }
- *fd = kNoFileDescriptor;
-}
-
-bool FilePathWatcherKQueue::AreKeventValuesValid(struct kevent* kevents,
- int count) {
- if (count < 0) {
- DPLOG(ERROR) << "kevent";
- return false;
- }
- bool valid = true;
- for (int i = 0; i < count; ++i) {
- if (kevents[i].flags & EV_ERROR && kevents[i].data) {
- // Find the kevent in |events_| that matches the kevent with the error.
- EventVector::iterator event = events_.begin();
- for (; event != events_.end(); ++event) {
- if (event->ident == kevents[i].ident) {
- break;
- }
- }
- std::string path_name;
- if (event != events_.end()) {
- EventData* event_data = EventDataForKevent(*event);
- if (event_data != NULL) {
- path_name = event_data->path_.value();
- }
- }
- if (path_name.empty()) {
- path_name = base::StringPrintf(
- "fd %ld", reinterpret_cast<long>(&kevents[i].ident));
- }
- DLOG(ERROR) << "Error: " << kevents[i].data << " for " << path_name;
- valid = false;
- }
- }
- return valid;
-}
-
-void FilePathWatcherKQueue::HandleAttributesChange(
- const EventVector::iterator& event,
- bool* target_file_affected,
- bool* update_watches) {
- EventVector::iterator next_event = event + 1;
- EventData* next_event_data = EventDataForKevent(*next_event);
- // Check to see if the next item in path is still accessible.
- uintptr_t have_access = FileDescriptorForPath(next_event_data->path_);
- if (have_access == kNoFileDescriptor) {
- *target_file_affected = true;
- *update_watches = true;
- EventVector::iterator local_event(event);
- for (; local_event != events_.end(); ++local_event) {
- // Close all nodes from the event down. This has the side effect of
- // potentially rendering other events in |updates| invalid.
- // There is no need to remove the events from |kqueue_| because this
- // happens as a side effect of closing the file descriptor.
- CloseFileDescriptor(&local_event->ident);
- }
- } else {
- CloseFileDescriptor(&have_access);
- }
-}
-
-void FilePathWatcherKQueue::HandleDeleteOrMoveChange(
- const EventVector::iterator& event,
- bool* target_file_affected,
- bool* update_watches) {
- *target_file_affected = true;
- *update_watches = true;
- EventVector::iterator local_event(event);
- for (; local_event != events_.end(); ++local_event) {
- // Close all nodes from the event down. This has the side effect of
- // potentially rendering other events in |updates| invalid.
- // There is no need to remove the events from |kqueue_| because this
- // happens as a side effect of closing the file descriptor.
- CloseFileDescriptor(&local_event->ident);
- }
-}
-
-void FilePathWatcherKQueue::HandleCreateItemChange(
- const EventVector::iterator& event,
- bool* target_file_affected,
- bool* update_watches) {
- // Get the next item in the path.
- EventVector::iterator next_event = event + 1;
- // Check to see if it already has a valid file descriptor.
- if (!IsKeventFileDescriptorOpen(*next_event)) {
- EventData* next_event_data = EventDataForKevent(*next_event);
- // If not, attempt to open a file descriptor for it.
- next_event->ident = FileDescriptorForPath(next_event_data->path_);
- if (IsKeventFileDescriptorOpen(*next_event)) {
- *update_watches = true;
- if (next_event_data->subdir_.empty()) {
- *target_file_affected = true;
- }
- }
- }
-}
-
-bool FilePathWatcherKQueue::UpdateWatches(bool* target_file_affected) {
- // Iterate over events adding kevents for items that exist to the kqueue.
- // Then check to see if new components in the path have been created.
- // Repeat until no new components in the path are detected.
- // This is to get around races in directory creation in a watched path.
- bool update_watches = true;
- while (update_watches) {
- size_t valid;
- for (valid = 0; valid < events_.size(); ++valid) {
- if (!IsKeventFileDescriptorOpen(events_[valid])) {
- break;
- }
- }
- if (valid == 0) {
- // The root of the file path is inaccessible?
- return false;
- }
-
- EventVector updates(valid);
- int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], valid, &updates[0],
- valid, NULL));
- if (!AreKeventValuesValid(&updates[0], count)) {
- return false;
- }
- update_watches = false;
- for (; valid < events_.size(); ++valid) {
- EventData* event_data = EventDataForKevent(events_[valid]);
- events_[valid].ident = FileDescriptorForPath(event_data->path_);
- if (IsKeventFileDescriptorOpen(events_[valid])) {
- update_watches = true;
- if (event_data->subdir_.empty()) {
- *target_file_affected = true;
- }
- } else {
- break;
- }
- }
- }
- return true;
-}
-
-bool FilePathWatcherKQueue::Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) {
- DCHECK(target_.value().empty()); // Can only watch one path.
- DCHECK(!callback.is_null());
- DCHECK_EQ(kqueue_, -1);
- // Recursive watch is not supported using kqueue.
- DCHECK(!recursive);
-
- callback_ = callback;
- target_ = path;
-
- set_task_runner(SequencedTaskRunnerHandle::Get());
-
- kqueue_ = kqueue();
- if (kqueue_ == -1) {
- DPLOG(ERROR) << "kqueue";
- return false;
- }
-
- int last_entry = EventsForPath(target_, &events_);
- DCHECK_NE(last_entry, 0);
-
- EventVector responses(last_entry);
-
- int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry,
- &responses[0], last_entry, NULL));
- if (!AreKeventValuesValid(&responses[0], count)) {
- // Calling Cancel() here to close any file descriptors that were opened.
- // This would happen in the destructor anyways, but FilePathWatchers tend to
- // be long lived, and if an error has occurred, there is no reason to waste
- // the file descriptors.
- Cancel();
- return false;
- }
-
- // It's safe to use Unretained() because the watch is cancelled and the
- // callback cannot be invoked after |kqueue_watch_controller_| (which is a
- // member of |this|) has been deleted.
- kqueue_watch_controller_ = FileDescriptorWatcher::WatchReadable(
- kqueue_,
- Bind(&FilePathWatcherKQueue::OnKQueueReadable, Unretained(this)));
-
- return true;
-}
-
-void FilePathWatcherKQueue::Cancel() {
- if (!task_runner()) {
- set_cancelled();
- return;
- }
-
- DCHECK(task_runner()->RunsTasksInCurrentSequence());
- if (!is_cancelled()) {
- set_cancelled();
- kqueue_watch_controller_.reset();
- if (IGNORE_EINTR(close(kqueue_)) != 0) {
- DPLOG(ERROR) << "close kqueue";
- }
- kqueue_ = -1;
- std::for_each(events_.begin(), events_.end(), ReleaseEvent);
- events_.clear();
- callback_.Reset();
- }
-}
-
-void FilePathWatcherKQueue::OnKQueueReadable() {
- DCHECK(task_runner()->RunsTasksInCurrentSequence());
- DCHECK(events_.size());
-
- // Request the file system update notifications that have occurred and return
- // them in |updates|. |count| will contain the number of updates that have
- // occurred.
- EventVector updates(events_.size());
- struct timespec timeout = {0, 0};
- int count = HANDLE_EINTR(kevent(kqueue_, NULL, 0, &updates[0], updates.size(),
- &timeout));
-
- // Error values are stored within updates, so check to make sure that no
- // errors occurred.
- if (!AreKeventValuesValid(&updates[0], count)) {
- callback_.Run(target_, true /* error */);
- Cancel();
- return;
- }
-
- bool update_watches = false;
- bool send_notification = false;
-
- // Iterate through each of the updates and react to them.
- for (int i = 0; i < count; ++i) {
- // Find our kevent record that matches the update notification.
- EventVector::iterator event = events_.begin();
- for (; event != events_.end(); ++event) {
- if (!IsKeventFileDescriptorOpen(*event) ||
- event->ident == updates[i].ident) {
- break;
- }
- }
- if (event == events_.end() || !IsKeventFileDescriptorOpen(*event)) {
- // The event may no longer exist in |events_| because another event
- // modified |events_| in such a way to make it invalid. For example if
- // the path is /foo/bar/bam and foo is deleted, NOTE_DELETE events for
- // foo, bar and bam will be sent. If foo is processed first, then
- // the file descriptors for bar and bam will already be closed and set
- // to -1 before they get a chance to be processed.
- continue;
- }
-
- EventData* event_data = EventDataForKevent(*event);
-
- // If the subdir is empty, this is the last item on the path and is the
- // target file.
- bool target_file_affected = event_data->subdir_.empty();
- if ((updates[i].fflags & NOTE_ATTRIB) && !target_file_affected) {
- HandleAttributesChange(event, &target_file_affected, &update_watches);
- }
- if (updates[i].fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) {
- HandleDeleteOrMoveChange(event, &target_file_affected, &update_watches);
- }
- if ((updates[i].fflags & NOTE_WRITE) && !target_file_affected) {
- HandleCreateItemChange(event, &target_file_affected, &update_watches);
- }
- send_notification |= target_file_affected;
- }
-
- if (update_watches) {
- if (!UpdateWatches(&send_notification)) {
- callback_.Run(target_, true /* error */);
- Cancel();
- }
- }
-
- if (send_notification) {
- callback_.Run(target_, false);
- }
-}
-
-} // namespace base
diff --git a/base/files/file_path_watcher_kqueue.h b/base/files/file_path_watcher_kqueue.h
deleted file mode 100644
index ef79be5596..0000000000
--- a/base/files/file_path_watcher_kqueue.h
+++ /dev/null
@@ -1,125 +0,0 @@
-// 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.
-
-#ifndef BASE_FILES_FILE_PATH_WATCHER_KQUEUE_H_
-#define BASE_FILES_FILE_PATH_WATCHER_KQUEUE_H_
-
-#include <sys/event.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/files/file_path.h"
-#include "base/files/file_path_watcher.h"
-#include "base/macros.h"
-
-namespace base {
-
-// Mac-specific file watcher implementation based on kqueue.
-// The Linux and Windows versions are able to detect:
-// - file creation/deletion/modification in a watched directory
-// - file creation/deletion/modification for a watched file
-// - modifications to the paths to a watched object that would affect the
-// object such as renaming/attibute changes etc.
-// The kqueue implementation will handle all of the items in the list above
-// except for detecting modifications to files in a watched directory. It will
-// detect the creation and deletion of files, just not the modification of
-// files. It does however detect the attribute changes that the FSEvents impl
-// would miss.
-class FilePathWatcherKQueue : public FilePathWatcher::PlatformDelegate {
- public:
- FilePathWatcherKQueue();
- ~FilePathWatcherKQueue() override;
-
- // FilePathWatcher::PlatformDelegate overrides.
- bool Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) override;
- void Cancel() override;
-
- private:
- class EventData {
- public:
- EventData(const FilePath& path, const FilePath::StringType& subdir)
- : path_(path), subdir_(subdir) { }
- FilePath path_; // Full path to this item.
- FilePath::StringType subdir_; // Path to any sub item.
- };
-
- typedef std::vector<struct kevent> EventVector;
-
- // Called when data is available in |kqueue_|.
- void OnKQueueReadable();
-
- // Returns true if the kevent values are error free.
- bool AreKeventValuesValid(struct kevent* kevents, int count);
-
- // Respond to a change of attributes of the path component represented by
- // |event|. Sets |target_file_affected| to true if |target_| is affected.
- // Sets |update_watches| to true if |events_| need to be updated.
- void HandleAttributesChange(const EventVector::iterator& event,
- bool* target_file_affected,
- bool* update_watches);
-
- // Respond to a move or deletion of the path component represented by
- // |event|. Sets |target_file_affected| to true if |target_| is affected.
- // Sets |update_watches| to true if |events_| need to be updated.
- void HandleDeleteOrMoveChange(const EventVector::iterator& event,
- bool* target_file_affected,
- bool* update_watches);
-
- // Respond to a creation of an item in the path component represented by
- // |event|. Sets |target_file_affected| to true if |target_| is affected.
- // Sets |update_watches| to true if |events_| need to be updated.
- void HandleCreateItemChange(const EventVector::iterator& event,
- bool* target_file_affected,
- bool* update_watches);
-
- // Update |events_| with the current status of the system.
- // Sets |target_file_affected| to true if |target_| is affected.
- // Returns false if an error occurs.
- bool UpdateWatches(bool* target_file_affected);
-
- // Fills |events| with one kevent per component in |path|.
- // Returns the number of valid events created where a valid event is
- // defined as one that has a ident (file descriptor) field != -1.
- static int EventsForPath(FilePath path, EventVector *events);
-
- // Release a kevent generated by EventsForPath.
- static void ReleaseEvent(struct kevent& event);
-
- // Returns a file descriptor that will not block the system from deleting
- // the file it references.
- static uintptr_t FileDescriptorForPath(const FilePath& path);
-
- static const uintptr_t kNoFileDescriptor = static_cast<uintptr_t>(-1);
-
- // Closes |*fd| and sets |*fd| to -1.
- static void CloseFileDescriptor(uintptr_t* fd);
-
- // Returns true if kevent has open file descriptor.
- static bool IsKeventFileDescriptorOpen(const struct kevent& event) {
- return event.ident != kNoFileDescriptor;
- }
-
- static EventData* EventDataForKevent(const struct kevent& event) {
- return reinterpret_cast<EventData*>(event.udata);
- }
-
- EventVector events_;
- FilePathWatcher::Callback callback_;
- FilePath target_;
- int kqueue_;
-
- // Throughout the lifetime of this, OnKQueueReadable() will be called when
- // data is available in |kqueue_|.
- std::unique_ptr<FileDescriptorWatcher::Controller> kqueue_watch_controller_;
-
- DISALLOW_COPY_AND_ASSIGN(FilePathWatcherKQueue);
-};
-
-} // namespace base
-
-#endif // BASE_FILES_FILE_PATH_WATCHER_KQUEUE_H_
diff --git a/base/files/file_path_watcher_stub.cc b/base/files/file_path_watcher_stub.cc
deleted file mode 100644
index 93a5babe9b..0000000000
--- a/base/files/file_path_watcher_stub.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 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.
-
-// This file exists for Unix systems which don't have the inotify headers, and
-// thus cannot build file_watcher_inotify.cc
-
-#include "base/files/file_path_watcher.h"
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-
-namespace base {
-
-namespace {
-
-class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
- public:
- FilePathWatcherImpl() = default;
- ~FilePathWatcherImpl() override = default;
-
- bool Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) override {
- return false;
- }
-
- void Cancel() override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FilePathWatcherImpl);
-};
-
-} // namespace
-
-FilePathWatcher::FilePathWatcher() {
- sequence_checker_.DetachFromSequence();
- impl_ = std::make_unique<FilePathWatcherImpl>();
-}
-
-} // namespace base
diff --git a/base/files/file_proxy.cc b/base/files/file_proxy.cc
deleted file mode 100644
index f16e5940b5..0000000000
--- a/base/files/file_proxy.cc
+++ /dev/null
@@ -1,358 +0,0 @@
-// 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/files/file_proxy.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/task_runner.h"
-#include "base/task_runner_util.h"
-
-namespace {
-
-void FileDeleter(base::File file) {
-}
-
-} // namespace
-
-namespace base {
-
-class FileHelper {
- public:
- FileHelper(FileProxy* proxy, File file)
- : file_(std::move(file)),
- error_(File::FILE_ERROR_FAILED),
- task_runner_(proxy->task_runner()),
- proxy_(AsWeakPtr(proxy)) {
- }
-
- void PassFile() {
- if (proxy_)
- proxy_->SetFile(std::move(file_));
- else if (file_.IsValid())
- task_runner_->PostTask(FROM_HERE,
- BindOnce(&FileDeleter, std::move(file_)));
- }
-
- protected:
- File file_;
- File::Error error_;
-
- private:
- scoped_refptr<TaskRunner> task_runner_;
- WeakPtr<FileProxy> proxy_;
- DISALLOW_COPY_AND_ASSIGN(FileHelper);
-};
-
-namespace {
-
-class GenericFileHelper : public FileHelper {
- public:
- GenericFileHelper(FileProxy* proxy, File file)
- : FileHelper(proxy, std::move(file)) {
- }
-
- void Close() {
- file_.Close();
- error_ = File::FILE_OK;
- }
-
- void SetTimes(Time last_access_time, Time last_modified_time) {
- bool rv = file_.SetTimes(last_access_time, last_modified_time);
- error_ = rv ? File::FILE_OK : File::FILE_ERROR_FAILED;
- }
-
- void SetLength(int64_t length) {
- if (file_.SetLength(length))
- error_ = File::FILE_OK;
- }
-
- void Flush() {
- if (file_.Flush())
- error_ = File::FILE_OK;
- }
-
- void Reply(FileProxy::StatusCallback callback) {
- PassFile();
- if (!callback.is_null())
- std::move(callback).Run(error_);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GenericFileHelper);
-};
-
-class CreateOrOpenHelper : public FileHelper {
- public:
- CreateOrOpenHelper(FileProxy* proxy, File file)
- : FileHelper(proxy, std::move(file)) {
- }
-
- void RunWork(const FilePath& file_path, int file_flags) {
- file_.Initialize(file_path, file_flags);
- error_ = file_.IsValid() ? File::FILE_OK : file_.error_details();
- }
-
- void Reply(FileProxy::StatusCallback callback) {
- DCHECK(!callback.is_null());
- PassFile();
- std::move(callback).Run(error_);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CreateOrOpenHelper);
-};
-
-class CreateTemporaryHelper : public FileHelper {
- public:
- CreateTemporaryHelper(FileProxy* proxy, File file)
- : FileHelper(proxy, std::move(file)) {
- }
-
- void RunWork(uint32_t additional_file_flags) {
- // TODO(darin): file_util should have a variant of CreateTemporaryFile
- // that returns a FilePath and a File.
- if (!CreateTemporaryFile(&file_path_)) {
- // TODO(davidben): base::CreateTemporaryFile should preserve the error
- // code.
- error_ = File::FILE_ERROR_FAILED;
- return;
- }
-
- uint32_t file_flags = File::FLAG_WRITE | File::FLAG_TEMPORARY |
- File::FLAG_CREATE_ALWAYS | additional_file_flags;
-
- file_.Initialize(file_path_, file_flags);
- if (file_.IsValid()) {
- error_ = File::FILE_OK;
- } else {
- error_ = file_.error_details();
- DeleteFile(file_path_, false);
- file_path_.clear();
- }
- }
-
- void Reply(FileProxy::CreateTemporaryCallback callback) {
- DCHECK(!callback.is_null());
- PassFile();
- std::move(callback).Run(error_, file_path_);
- }
-
- private:
- FilePath file_path_;
- DISALLOW_COPY_AND_ASSIGN(CreateTemporaryHelper);
-};
-
-class GetInfoHelper : public FileHelper {
- public:
- GetInfoHelper(FileProxy* proxy, File file)
- : FileHelper(proxy, std::move(file)) {
- }
-
- void RunWork() {
- if (file_.GetInfo(&file_info_))
- error_ = File::FILE_OK;
- }
-
- void Reply(FileProxy::GetFileInfoCallback callback) {
- PassFile();
- DCHECK(!callback.is_null());
- std::move(callback).Run(error_, file_info_);
- }
-
- private:
- File::Info file_info_;
- DISALLOW_COPY_AND_ASSIGN(GetInfoHelper);
-};
-
-class ReadHelper : public FileHelper {
- public:
- ReadHelper(FileProxy* proxy, File file, int bytes_to_read)
- : FileHelper(proxy, std::move(file)),
- buffer_(new char[bytes_to_read]),
- bytes_to_read_(bytes_to_read),
- bytes_read_(0) {
- }
-
- void RunWork(int64_t offset) {
- bytes_read_ = file_.Read(offset, buffer_.get(), bytes_to_read_);
- error_ = (bytes_read_ < 0) ? File::FILE_ERROR_FAILED : File::FILE_OK;
- }
-
- void Reply(FileProxy::ReadCallback callback) {
- PassFile();
- DCHECK(!callback.is_null());
- std::move(callback).Run(error_, buffer_.get(), bytes_read_);
- }
-
- private:
- std::unique_ptr<char[]> buffer_;
- int bytes_to_read_;
- int bytes_read_;
- DISALLOW_COPY_AND_ASSIGN(ReadHelper);
-};
-
-class WriteHelper : public FileHelper {
- public:
- WriteHelper(FileProxy* proxy,
- File file,
- const char* buffer, int bytes_to_write)
- : FileHelper(proxy, std::move(file)),
- buffer_(new char[bytes_to_write]),
- bytes_to_write_(bytes_to_write),
- bytes_written_(0) {
- memcpy(buffer_.get(), buffer, bytes_to_write);
- }
-
- void RunWork(int64_t offset) {
- bytes_written_ = file_.Write(offset, buffer_.get(), bytes_to_write_);
- error_ = (bytes_written_ < 0) ? File::FILE_ERROR_FAILED : File::FILE_OK;
- }
-
- void Reply(FileProxy::WriteCallback callback) {
- PassFile();
- if (!callback.is_null())
- std::move(callback).Run(error_, bytes_written_);
- }
-
- private:
- std::unique_ptr<char[]> buffer_;
- int bytes_to_write_;
- int bytes_written_;
- DISALLOW_COPY_AND_ASSIGN(WriteHelper);
-};
-
-} // namespace
-
-FileProxy::FileProxy(TaskRunner* task_runner) : task_runner_(task_runner) {
-}
-
-FileProxy::~FileProxy() {
- if (file_.IsValid())
- task_runner_->PostTask(FROM_HERE, BindOnce(&FileDeleter, std::move(file_)));
-}
-
-bool FileProxy::CreateOrOpen(const FilePath& file_path,
- uint32_t file_flags,
- StatusCallback callback) {
- DCHECK(!file_.IsValid());
- CreateOrOpenHelper* helper = new CreateOrOpenHelper(this, File());
- return task_runner_->PostTaskAndReply(
- FROM_HERE,
- BindOnce(&CreateOrOpenHelper::RunWork, Unretained(helper), file_path,
- file_flags),
- BindOnce(&CreateOrOpenHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-bool FileProxy::CreateTemporary(uint32_t additional_file_flags,
- CreateTemporaryCallback callback) {
- DCHECK(!file_.IsValid());
- CreateTemporaryHelper* helper = new CreateTemporaryHelper(this, File());
- return task_runner_->PostTaskAndReply(
- FROM_HERE,
- BindOnce(&CreateTemporaryHelper::RunWork, Unretained(helper),
- additional_file_flags),
- BindOnce(&CreateTemporaryHelper::Reply, Owned(helper),
- std::move(callback)));
-}
-
-bool FileProxy::IsValid() const {
- return file_.IsValid();
-}
-
-void FileProxy::SetFile(File file) {
- DCHECK(!file_.IsValid());
- file_ = std::move(file);
-}
-
-File FileProxy::TakeFile() {
- return std::move(file_);
-}
-
-File FileProxy::DuplicateFile() {
- return file_.Duplicate();
-}
-
-PlatformFile FileProxy::GetPlatformFile() const {
- return file_.GetPlatformFile();
-}
-
-bool FileProxy::Close(StatusCallback callback) {
- DCHECK(file_.IsValid());
- GenericFileHelper* helper = new GenericFileHelper(this, std::move(file_));
- return task_runner_->PostTaskAndReply(
- FROM_HERE, BindOnce(&GenericFileHelper::Close, Unretained(helper)),
- BindOnce(&GenericFileHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-bool FileProxy::GetInfo(GetFileInfoCallback callback) {
- DCHECK(file_.IsValid());
- GetInfoHelper* helper = new GetInfoHelper(this, std::move(file_));
- return task_runner_->PostTaskAndReply(
- FROM_HERE, BindOnce(&GetInfoHelper::RunWork, Unretained(helper)),
- BindOnce(&GetInfoHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-bool FileProxy::Read(int64_t offset, int bytes_to_read, ReadCallback callback) {
- DCHECK(file_.IsValid());
- if (bytes_to_read < 0)
- return false;
-
- ReadHelper* helper = new ReadHelper(this, std::move(file_), bytes_to_read);
- return task_runner_->PostTaskAndReply(
- FROM_HERE, BindOnce(&ReadHelper::RunWork, Unretained(helper), offset),
- BindOnce(&ReadHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-bool FileProxy::Write(int64_t offset,
- const char* buffer,
- int bytes_to_write,
- WriteCallback callback) {
- DCHECK(file_.IsValid());
- if (bytes_to_write <= 0 || buffer == nullptr)
- return false;
-
- WriteHelper* helper =
- new WriteHelper(this, std::move(file_), buffer, bytes_to_write);
- return task_runner_->PostTaskAndReply(
- FROM_HERE, BindOnce(&WriteHelper::RunWork, Unretained(helper), offset),
- BindOnce(&WriteHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-bool FileProxy::SetTimes(Time last_access_time,
- Time last_modified_time,
- StatusCallback callback) {
- DCHECK(file_.IsValid());
- GenericFileHelper* helper = new GenericFileHelper(this, std::move(file_));
- return task_runner_->PostTaskAndReply(
- FROM_HERE,
- BindOnce(&GenericFileHelper::SetTimes, Unretained(helper),
- last_access_time, last_modified_time),
- BindOnce(&GenericFileHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-bool FileProxy::SetLength(int64_t length, StatusCallback callback) {
- DCHECK(file_.IsValid());
- GenericFileHelper* helper = new GenericFileHelper(this, std::move(file_));
- return task_runner_->PostTaskAndReply(
- FROM_HERE,
- BindOnce(&GenericFileHelper::SetLength, Unretained(helper), length),
- BindOnce(&GenericFileHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-bool FileProxy::Flush(StatusCallback callback) {
- DCHECK(file_.IsValid());
- GenericFileHelper* helper = new GenericFileHelper(this, std::move(file_));
- return task_runner_->PostTaskAndReply(
- FROM_HERE, BindOnce(&GenericFileHelper::Flush, Unretained(helper)),
- BindOnce(&GenericFileHelper::Reply, Owned(helper), std::move(callback)));
-}
-
-} // namespace base
diff --git a/base/files/file_proxy.h b/base/files/file_proxy.h
deleted file mode 100644
index d17e4d3b09..0000000000
--- a/base/files/file_proxy.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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.
-
-#ifndef BASE_FILES_FILE_PROXY_H_
-#define BASE_FILES_FILE_PROXY_H_
-
-#include <stdint.h>
-
-#include "base/base_export.h"
-#include "base/callback_forward.h"
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-
-namespace base {
-
-class TaskRunner;
-class Time;
-
-// This class provides asynchronous access to a File. All methods follow the
-// same rules of the equivalent File method, as they are implemented by bouncing
-// the operation to File using a TaskRunner.
-//
-// This class performs automatic proxying to close the underlying file at
-// destruction.
-//
-// The TaskRunner is in charge of any sequencing of the operations, but a single
-// operation can be proxied at a time, regardless of the use of a callback.
-// In other words, having a sequence like
-//
-// proxy.Write(...);
-// proxy.Write(...);
-//
-// means the second Write will always fail.
-class BASE_EXPORT FileProxy : public SupportsWeakPtr<FileProxy> {
- public:
- // This callback is used by methods that report only an error code. It is
- // valid to pass a null callback to some functions that takes a
- // StatusCallback, in which case the operation will complete silently.
- using StatusCallback = OnceCallback<void(File::Error)>;
- using CreateTemporaryCallback =
- OnceCallback<void(File::Error, const FilePath&)>;
- using GetFileInfoCallback =
- OnceCallback<void(File::Error, const File::Info&)>;
- using ReadCallback =
- OnceCallback<void(File::Error, const char* data, int bytes_read)>;
- using WriteCallback = OnceCallback<void(File::Error, int bytes_written)>;
-
- FileProxy();
- explicit FileProxy(TaskRunner* task_runner);
- ~FileProxy();
-
- // Creates or opens a file with the given flags. It is invalid to pass a null
- // callback. If File::FLAG_CREATE is set in |file_flags| it always tries to
- // create a new file at the given |file_path| and fails if the file already
- // exists.
- //
- // This returns false if task posting to |task_runner| has failed.
- bool CreateOrOpen(const FilePath& file_path,
- uint32_t file_flags,
- StatusCallback callback);
-
- // Creates a temporary file for writing. The path and an open file are
- // returned. It is invalid to pass a null callback. The additional file flags
- // will be added on top of the default file flags which are:
- // File::FLAG_CREATE_ALWAYS
- // File::FLAG_WRITE
- // File::FLAG_TEMPORARY.
- //
- // This returns false if task posting to |task_runner| has failed.
- bool CreateTemporary(uint32_t additional_file_flags,
- CreateTemporaryCallback callback);
-
- // Returns true if the underlying |file_| is valid.
- bool IsValid() const;
-
- // Returns true if a new file was created (or an old one truncated to zero
- // length to simulate a new file), and false otherwise.
- bool created() const { return file_.created(); }
-
- // Claims ownership of |file|. It is an error to call this method when
- // IsValid() returns true.
- void SetFile(File file);
-
- File TakeFile();
-
- // Returns a new File object that is a duplicate of the underlying |file_|.
- // See the comment at File::Duplicate for caveats.
- File DuplicateFile();
-
- PlatformFile GetPlatformFile() const;
-
- // Proxies File::Close. The callback can be null.
- // This returns false if task posting to |task_runner| has failed.
- bool Close(StatusCallback callback);
-
- // Proxies File::GetInfo. The callback can't be null.
- // This returns false if task posting to |task_runner| has failed.
- bool GetInfo(GetFileInfoCallback callback);
-
- // Proxies File::Read. The callback can't be null.
- // This returns false if |bytes_to_read| is less than zero, or
- // if task posting to |task_runner| has failed.
- bool Read(int64_t offset, int bytes_to_read, ReadCallback callback);
-
- // Proxies File::Write. The callback can be null.
- // This returns false if |bytes_to_write| is less than or equal to zero,
- // if |buffer| is NULL, or if task posting to |task_runner| has failed.
- bool Write(int64_t offset,
- const char* buffer,
- int bytes_to_write,
- WriteCallback callback);
-
- // Proxies File::SetTimes. The callback can be null.
- // This returns false if task posting to |task_runner| has failed.
- bool SetTimes(Time last_access_time,
- Time last_modified_time,
- StatusCallback callback);
-
- // Proxies File::SetLength. The callback can be null.
- // This returns false if task posting to |task_runner| has failed.
- bool SetLength(int64_t length, StatusCallback callback);
-
- // Proxies File::Flush. The callback can be null.
- // This returns false if task posting to |task_runner| has failed.
- bool Flush(StatusCallback callback);
-
- private:
- friend class FileHelper;
- TaskRunner* task_runner() { return task_runner_.get(); }
-
- scoped_refptr<TaskRunner> task_runner_;
- File file_;
- DISALLOW_COPY_AND_ASSIGN(FileProxy);
-};
-
-} // namespace base
-
-#endif // BASE_FILES_FILE_PROXY_H_
diff --git a/base/files/file_proxy_unittest.cc b/base/files/file_proxy_unittest.cc
deleted file mode 100644
index cb689db2f6..0000000000
--- a/base/files/file_proxy_unittest.cc
+++ /dev/null
@@ -1,401 +0,0 @@
-// 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/files/file_proxy.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class FileProxyTest : public testing::Test {
- public:
- FileProxyTest()
- : file_thread_("FileProxyTestFileThread"),
- error_(File::FILE_OK),
- bytes_written_(-1),
- weak_factory_(this) {}
-
- void SetUp() override {
- ASSERT_TRUE(dir_.CreateUniqueTempDir());
- ASSERT_TRUE(file_thread_.Start());
- }
-
- void DidFinish(File::Error error) {
- error_ = error;
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- void DidCreateOrOpen(File::Error error) {
- error_ = error;
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- void DidCreateTemporary(File::Error error,
- const FilePath& path) {
- error_ = error;
- path_ = path;
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- void DidGetFileInfo(File::Error error,
- const File::Info& file_info) {
- error_ = error;
- file_info_ = file_info;
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- void DidRead(File::Error error,
- const char* data,
- int bytes_read) {
- error_ = error;
- buffer_.resize(bytes_read);
- memcpy(&buffer_[0], data, bytes_read);
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- void DidWrite(File::Error error,
- int bytes_written) {
- error_ = error;
- bytes_written_ = bytes_written;
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- protected:
- void CreateProxy(uint32_t flags, FileProxy* proxy) {
- proxy->CreateOrOpen(
- TestPath(), flags,
- BindOnce(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
- EXPECT_TRUE(proxy->IsValid());
- }
-
- TaskRunner* file_task_runner() const {
- return file_thread_.task_runner().get();
- }
- const FilePath& TestDirPath() const { return dir_.GetPath(); }
- const FilePath TestPath() const { return dir_.GetPath().AppendASCII("test"); }
-
- ScopedTempDir dir_;
- MessageLoopForIO message_loop_;
- Thread file_thread_;
-
- File::Error error_;
- FilePath path_;
- File::Info file_info_;
- std::vector<char> buffer_;
- int bytes_written_;
- WeakPtrFactory<FileProxyTest> weak_factory_;
-};
-
-TEST_F(FileProxyTest, CreateOrOpen_Create) {
- FileProxy proxy(file_task_runner());
- proxy.CreateOrOpen(
- TestPath(), File::FLAG_CREATE | File::FLAG_READ,
- BindOnce(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
-
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_TRUE(proxy.IsValid());
- EXPECT_TRUE(proxy.created());
- EXPECT_TRUE(PathExists(TestPath()));
-}
-
-TEST_F(FileProxyTest, CreateOrOpen_Open) {
- // Creates a file.
- base::WriteFile(TestPath(), nullptr, 0);
- ASSERT_TRUE(PathExists(TestPath()));
-
- // Opens the created file.
- FileProxy proxy(file_task_runner());
- proxy.CreateOrOpen(
- TestPath(), File::FLAG_OPEN | File::FLAG_READ,
- BindOnce(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
-
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_TRUE(proxy.IsValid());
- EXPECT_FALSE(proxy.created());
-}
-
-TEST_F(FileProxyTest, CreateOrOpen_OpenNonExistent) {
- FileProxy proxy(file_task_runner());
- proxy.CreateOrOpen(
- TestPath(), File::FLAG_OPEN | File::FLAG_READ,
- BindOnce(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
- EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, error_);
- EXPECT_FALSE(proxy.IsValid());
- EXPECT_FALSE(proxy.created());
- EXPECT_FALSE(PathExists(TestPath()));
-}
-
-TEST_F(FileProxyTest, CreateOrOpen_AbandonedCreate) {
- bool prev = ThreadRestrictions::SetIOAllowed(false);
- {
- FileProxy proxy(file_task_runner());
- proxy.CreateOrOpen(
- TestPath(), File::FLAG_CREATE | File::FLAG_READ,
- BindOnce(&FileProxyTest::DidCreateOrOpen, weak_factory_.GetWeakPtr()));
- }
- RunLoop().Run();
- ThreadRestrictions::SetIOAllowed(prev);
-
- EXPECT_TRUE(PathExists(TestPath()));
-}
-
-TEST_F(FileProxyTest, Close) {
- // Creates a file.
- FileProxy proxy(file_task_runner());
- CreateProxy(File::FLAG_CREATE | File::FLAG_WRITE, &proxy);
-
-#if defined(OS_WIN)
- // This fails on Windows if the file is not closed.
- EXPECT_FALSE(base::Move(TestPath(), TestDirPath().AppendASCII("new")));
-#endif
-
- proxy.Close(BindOnce(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_FALSE(proxy.IsValid());
-
- // Now it should pass on all platforms.
- EXPECT_TRUE(base::Move(TestPath(), TestDirPath().AppendASCII("new")));
-}
-
-TEST_F(FileProxyTest, CreateTemporary) {
- {
- FileProxy proxy(file_task_runner());
- proxy.CreateTemporary(0 /* additional_file_flags */,
- BindOnce(&FileProxyTest::DidCreateTemporary,
- weak_factory_.GetWeakPtr()));
- RunLoop().Run();
-
- EXPECT_TRUE(proxy.IsValid());
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_TRUE(PathExists(path_));
-
- // The file should be writable.
- proxy.Write(0, "test", 4,
- BindOnce(&FileProxyTest::DidWrite, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_EQ(4, bytes_written_);
- }
-
- // Make sure the written data can be read from the returned path.
- std::string data;
- EXPECT_TRUE(ReadFileToString(path_, &data));
- EXPECT_EQ("test", data);
-
- // Make sure we can & do delete the created file to prevent leaks on the bots.
- EXPECT_TRUE(base::DeleteFile(path_, false));
-}
-
-TEST_F(FileProxyTest, SetAndTake) {
- File file(TestPath(), File::FLAG_CREATE | File::FLAG_READ);
- ASSERT_TRUE(file.IsValid());
- FileProxy proxy(file_task_runner());
- EXPECT_FALSE(proxy.IsValid());
- proxy.SetFile(std::move(file));
- EXPECT_TRUE(proxy.IsValid());
- EXPECT_FALSE(file.IsValid());
-
- file = proxy.TakeFile();
- EXPECT_FALSE(proxy.IsValid());
- EXPECT_TRUE(file.IsValid());
-}
-
-TEST_F(FileProxyTest, DuplicateFile) {
- FileProxy proxy(file_task_runner());
- CreateProxy(File::FLAG_CREATE | File::FLAG_WRITE, &proxy);
- ASSERT_TRUE(proxy.IsValid());
-
- base::File duplicate = proxy.DuplicateFile();
- EXPECT_TRUE(proxy.IsValid());
- EXPECT_TRUE(duplicate.IsValid());
-
- FileProxy invalid_proxy(file_task_runner());
- ASSERT_FALSE(invalid_proxy.IsValid());
-
- base::File invalid_duplicate = invalid_proxy.DuplicateFile();
- EXPECT_FALSE(invalid_proxy.IsValid());
- EXPECT_FALSE(invalid_duplicate.IsValid());
-}
-
-TEST_F(FileProxyTest, GetInfo) {
- // Setup.
- ASSERT_EQ(4, base::WriteFile(TestPath(), "test", 4));
- File::Info expected_info;
- GetFileInfo(TestPath(), &expected_info);
-
- // Run.
- FileProxy proxy(file_task_runner());
- CreateProxy(File::FLAG_OPEN | File::FLAG_READ, &proxy);
- proxy.GetInfo(
- BindOnce(&FileProxyTest::DidGetFileInfo, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
-
- // Verify.
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_EQ(expected_info.size, file_info_.size);
- EXPECT_EQ(expected_info.is_directory, file_info_.is_directory);
- EXPECT_EQ(expected_info.is_symbolic_link, file_info_.is_symbolic_link);
- EXPECT_EQ(expected_info.last_modified, file_info_.last_modified);
- EXPECT_EQ(expected_info.creation_time, file_info_.creation_time);
-}
-
-TEST_F(FileProxyTest, Read) {
- // Setup.
- const char expected_data[] = "bleh";
- int expected_bytes = arraysize(expected_data);
- ASSERT_EQ(expected_bytes,
- base::WriteFile(TestPath(), expected_data, expected_bytes));
-
- // Run.
- FileProxy proxy(file_task_runner());
- CreateProxy(File::FLAG_OPEN | File::FLAG_READ, &proxy);
-
- proxy.Read(0, 128,
- BindOnce(&FileProxyTest::DidRead, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
-
- // Verify.
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_EQ(expected_bytes, static_cast<int>(buffer_.size()));
- for (size_t i = 0; i < buffer_.size(); ++i) {
- EXPECT_EQ(expected_data[i], buffer_[i]);
- }
-}
-
-TEST_F(FileProxyTest, WriteAndFlush) {
- FileProxy proxy(file_task_runner());
- CreateProxy(File::FLAG_CREATE | File::FLAG_WRITE, &proxy);
-
- const char data[] = "foo!";
- int data_bytes = arraysize(data);
- proxy.Write(0, data, data_bytes,
- BindOnce(&FileProxyTest::DidWrite, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
- EXPECT_EQ(File::FILE_OK, error_);
- EXPECT_EQ(data_bytes, bytes_written_);
-
- // Flush the written data. (So that the following read should always
- // succeed. On some platforms it may work with or without this flush.)
- proxy.Flush(BindOnce(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
- EXPECT_EQ(File::FILE_OK, error_);
-
- // Verify the written data.
- char buffer[10];
- EXPECT_EQ(data_bytes, base::ReadFile(TestPath(), buffer, data_bytes));
- for (int i = 0; i < data_bytes; ++i) {
- EXPECT_EQ(data[i], buffer[i]);
- }
-}
-
-#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
-// Flaky on Android, see http://crbug.com/489602
-// TODO(crbug.com/851734): Implementation depends on stat, which is not
-// implemented on Fuchsia
-#define MAYBE_SetTimes DISABLED_SetTimes
-#else
-#define MAYBE_SetTimes SetTimes
-#endif
-TEST_F(FileProxyTest, MAYBE_SetTimes) {
- FileProxy proxy(file_task_runner());
- CreateProxy(
- File::FLAG_CREATE | File::FLAG_WRITE | File::FLAG_WRITE_ATTRIBUTES,
- &proxy);
-
- Time last_accessed_time = Time::Now() - TimeDelta::FromDays(12345);
- Time last_modified_time = Time::Now() - TimeDelta::FromHours(98765);
-
- proxy.SetTimes(
- last_accessed_time, last_modified_time,
- BindOnce(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
- EXPECT_EQ(File::FILE_OK, error_);
-
- File::Info info;
- GetFileInfo(TestPath(), &info);
-
- // The returned values may only have the seconds precision, so we cast
- // the double values to int here.
- EXPECT_EQ(static_cast<int>(last_modified_time.ToDoubleT()),
- static_cast<int>(info.last_modified.ToDoubleT()));
- EXPECT_EQ(static_cast<int>(last_accessed_time.ToDoubleT()),
- static_cast<int>(info.last_accessed.ToDoubleT()));
-}
-
-TEST_F(FileProxyTest, SetLength_Shrink) {
- // Setup.
- const char kTestData[] = "0123456789";
- ASSERT_EQ(10, base::WriteFile(TestPath(), kTestData, 10));
- File::Info info;
- GetFileInfo(TestPath(), &info);
- ASSERT_EQ(10, info.size);
-
- // Run.
- FileProxy proxy(file_task_runner());
- CreateProxy(File::FLAG_OPEN | File::FLAG_WRITE, &proxy);
- proxy.SetLength(
- 7, BindOnce(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
-
- // Verify.
- GetFileInfo(TestPath(), &info);
- ASSERT_EQ(7, info.size);
-
- char buffer[7];
- EXPECT_EQ(7, base::ReadFile(TestPath(), buffer, 7));
- int i = 0;
- for (; i < 7; ++i)
- EXPECT_EQ(kTestData[i], buffer[i]);
-}
-
-TEST_F(FileProxyTest, SetLength_Expand) {
- // Setup.
- const char kTestData[] = "9876543210";
- ASSERT_EQ(10, base::WriteFile(TestPath(), kTestData, 10));
- File::Info info;
- GetFileInfo(TestPath(), &info);
- ASSERT_EQ(10, info.size);
-
- // Run.
- FileProxy proxy(file_task_runner());
- CreateProxy(File::FLAG_OPEN | File::FLAG_WRITE, &proxy);
- proxy.SetLength(
- 53, BindOnce(&FileProxyTest::DidFinish, weak_factory_.GetWeakPtr()));
- RunLoop().Run();
-
- // Verify.
- GetFileInfo(TestPath(), &info);
- ASSERT_EQ(53, info.size);
-
- char buffer[53];
- EXPECT_EQ(53, base::ReadFile(TestPath(), buffer, 53));
- int i = 0;
- for (; i < 10; ++i)
- EXPECT_EQ(kTestData[i], buffer[i]);
- for (; i < 53; ++i)
- EXPECT_EQ(0, buffer[i]);
-}
-
-} // namespace base
diff --git a/base/files/file_util_android.cc b/base/files/file_util_android.cc
deleted file mode 100644
index b8b3b3720f..0000000000
--- a/base/files/file_util_android.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/files/file_util.h"
-
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-
-namespace base {
-
-bool GetShmemTempDir(bool executable, base::FilePath* path) {
- return PathService::Get(base::DIR_CACHE, path);
-}
-
-} // namespace base
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index f5f32674e0..066a1d1d5a 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -593,9 +593,8 @@ bool GetTempDir(FilePath* path) {
}
#if defined(OS_ANDROID)
-#if 0 // This is for building Chromium browser on Android.
return PathService::Get(DIR_CACHE, path);
-#endif
+#elif defined(__ANDROID__)
*path = FilePath("/data/local/tmp");
return true;
#else
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
deleted file mode 100644
index 68abc7c52d..0000000000
--- a/base/files/file_util_unittest.cc
+++ /dev/null
@@ -1,3749 +0,0 @@
-// Copyright (c) 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.
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <algorithm>
-#include <fstream>
-#include <initializer_list>
-#include <memory>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/base_paths.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/files/file.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/guid.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/scoped_environment_variable_override.h"
-#include "base/test/test_file_util.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-#include "testing/platform_test.h"
-
-#if defined(OS_WIN)
-#include <shellapi.h>
-#include <shlobj.h>
-#include <tchar.h>
-#include <windows.h>
-#include <winioctl.h>
-#include "base/strings/string_number_conversions.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/win_util.h"
-#endif
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-#if defined(OS_LINUX)
-#include <linux/fs.h>
-#endif
-
-#if defined(OS_ANDROID)
-#include "base/android/content_uri_utils.h"
-#endif
-
-// This macro helps avoid wrapped lines in the test structs.
-#define FPL(x) FILE_PATH_LITERAL(x)
-
-namespace base {
-
-namespace {
-
-const size_t kLargeFileSize = (1 << 16) + 3;
-
-// To test that NormalizeFilePath() deals with NTFS reparse points correctly,
-// we need functions to create and delete reparse points.
-#if defined(OS_WIN)
-typedef struct _REPARSE_DATA_BUFFER {
- ULONG ReparseTag;
- USHORT ReparseDataLength;
- USHORT Reserved;
- union {
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- ULONG Flags;
- WCHAR PathBuffer[1];
- } SymbolicLinkReparseBuffer;
- struct {
- USHORT SubstituteNameOffset;
- USHORT SubstituteNameLength;
- USHORT PrintNameOffset;
- USHORT PrintNameLength;
- WCHAR PathBuffer[1];
- } MountPointReparseBuffer;
- struct {
- UCHAR DataBuffer[1];
- } GenericReparseBuffer;
- };
-} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
-
-// Sets a reparse point. |source| will now point to |target|. Returns true if
-// the call succeeds, false otherwise.
-bool SetReparsePoint(HANDLE source, const FilePath& target_path) {
- std::wstring kPathPrefix = L"\\??\\";
- std::wstring target_str;
- // The juction will not work if the target path does not start with \??\ .
- if (kPathPrefix != target_path.value().substr(0, kPathPrefix.size()))
- target_str += kPathPrefix;
- target_str += target_path.value();
- const wchar_t* target = target_str.c_str();
- USHORT size_target = static_cast<USHORT>(wcslen(target)) * sizeof(target[0]);
- char buffer[2000] = {0};
- DWORD returned;
-
- REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
-
- data->ReparseTag = 0xa0000003;
- memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
-
- data->MountPointReparseBuffer.SubstituteNameLength = size_target;
- data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
- data->ReparseDataLength = size_target + 4 + 8;
-
- int data_size = data->ReparseDataLength + 8;
-
- if (!DeviceIoControl(source, FSCTL_SET_REPARSE_POINT, &buffer, data_size,
- NULL, 0, &returned, NULL)) {
- return false;
- }
- return true;
-}
-
-// Delete the reparse point referenced by |source|. Returns true if the call
-// succeeds, false otherwise.
-bool DeleteReparsePoint(HANDLE source) {
- DWORD returned;
- REPARSE_DATA_BUFFER data = {0};
- data.ReparseTag = 0xa0000003;
- if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
- &returned, NULL)) {
- return false;
- }
- return true;
-}
-
-// Manages a reparse point for a test.
-class ReparsePoint {
- public:
- // Creates a reparse point from |source| (an empty directory) to |target|.
- ReparsePoint(const FilePath& source, const FilePath& target) {
- dir_.Set(
- ::CreateFile(source.value().c_str(),
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, // Needed to open a directory.
- NULL));
- created_ = dir_.IsValid() && SetReparsePoint(dir_.Get(), target);
- }
-
- ~ReparsePoint() {
- if (created_)
- DeleteReparsePoint(dir_.Get());
- }
-
- bool IsValid() { return created_; }
-
- private:
- win::ScopedHandle dir_;
- bool created_;
- DISALLOW_COPY_AND_ASSIGN(ReparsePoint);
-};
-
-#endif
-
-// Fuchsia doesn't support file permissions.
-#if !defined(OS_FUCHSIA)
-#if defined(OS_POSIX)
-// Provide a simple way to change the permissions bits on |path| in tests.
-// ASSERT failures will return, but not stop the test. Caller should wrap
-// calls to this function in ASSERT_NO_FATAL_FAILURE().
-void ChangePosixFilePermissions(const FilePath& path,
- int mode_bits_to_set,
- int mode_bits_to_clear) {
- ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear)
- << "Can't set and clear the same bits.";
-
- int mode = 0;
- ASSERT_TRUE(GetPosixFilePermissions(path, &mode));
- mode |= mode_bits_to_set;
- mode &= ~mode_bits_to_clear;
- ASSERT_TRUE(SetPosixFilePermissions(path, mode));
-}
-#endif // defined(OS_POSIX)
-
-// Sets the source file to read-only.
-void SetReadOnly(const FilePath& path, bool read_only) {
-#if defined(OS_WIN)
- // On Windows, it involves setting/removing the 'readonly' bit.
- DWORD attrs = GetFileAttributes(path.value().c_str());
- ASSERT_NE(INVALID_FILE_ATTRIBUTES, attrs);
- ASSERT_TRUE(SetFileAttributes(
- path.value().c_str(), read_only ? (attrs | FILE_ATTRIBUTE_READONLY)
- : (attrs & ~FILE_ATTRIBUTE_READONLY)));
-
- DWORD expected =
- read_only
- ? ((attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY)) |
- FILE_ATTRIBUTE_READONLY)
- : (attrs & (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DIRECTORY));
-
- // Ignore FILE_ATTRIBUTE_NOT_CONTENT_INDEXED if present.
- attrs = GetFileAttributes(path.value().c_str()) &
- ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
- ASSERT_EQ(expected, attrs);
-#else
- // On all other platforms, it involves removing/setting the write bit.
- mode_t mode = read_only ? S_IRUSR : (S_IRUSR | S_IWUSR);
- EXPECT_TRUE(SetPosixFilePermissions(
- path, DirectoryExists(path) ? (mode | S_IXUSR) : mode));
-#endif // defined(OS_WIN)
-}
-
-bool IsReadOnly(const FilePath& path) {
-#if defined(OS_WIN)
- DWORD attrs = GetFileAttributes(path.value().c_str());
- EXPECT_NE(INVALID_FILE_ATTRIBUTES, attrs);
- return attrs & FILE_ATTRIBUTE_READONLY;
-#else
- int mode = 0;
- EXPECT_TRUE(GetPosixFilePermissions(path, &mode));
- return !(mode & S_IWUSR);
-#endif // defined(OS_WIN)
-}
-
-#endif // defined(OS_FUCHSIA)
-
-const wchar_t bogus_content[] = L"I'm cannon fodder.";
-
-const int FILES_AND_DIRECTORIES =
- FileEnumerator::FILES | FileEnumerator::DIRECTORIES;
-
-// file_util winds up using autoreleased objects on the Mac, so this needs
-// to be a PlatformTest
-class FileUtilTest : public PlatformTest {
- protected:
- void SetUp() override {
- PlatformTest::SetUp();
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- }
-
- ScopedTempDir temp_dir_;
-};
-
-// Collects all the results from the given file enumerator, and provides an
-// interface to query whether a given file is present.
-class FindResultCollector {
- public:
- explicit FindResultCollector(FileEnumerator* enumerator) {
- FilePath cur_file;
- while (!(cur_file = enumerator->Next()).value().empty()) {
- FilePath::StringType path = cur_file.value();
- // The file should not be returned twice.
- EXPECT_TRUE(files_.end() == files_.find(path))
- << "Same file returned twice";
-
- // Save for later.
- files_.insert(path);
- }
- }
-
- // Returns true if the enumerator found the file.
- bool HasFile(const FilePath& file) const {
- return files_.find(file.value()) != files_.end();
- }
-
- int size() {
- return static_cast<int>(files_.size());
- }
-
- private:
- std::set<FilePath::StringType> files_;
-};
-
-// Simple function to dump some text into a new file.
-void CreateTextFile(const FilePath& filename,
- const std::wstring& contents) {
- std::wofstream file;
- file.open(filename.value().c_str());
- ASSERT_TRUE(file.is_open());
- file << contents;
- file.close();
-}
-
-// Simple function to take out some text from a file.
-std::wstring ReadTextFile(const FilePath& filename) {
- wchar_t contents[64];
- std::wifstream file;
- file.open(filename.value().c_str());
- EXPECT_TRUE(file.is_open());
- file.getline(contents, arraysize(contents));
- file.close();
- return std::wstring(contents);
-}
-
-// Sets |is_inheritable| to indicate whether or not |stream| is set up to be
-// inerhited into child processes (i.e., HANDLE_FLAG_INHERIT is set on the
-// underlying handle on Windows, or FD_CLOEXEC is not set on the underlying file
-// descriptor on POSIX). Calls to this function must be wrapped with
-// ASSERT_NO_FATAL_FAILURE to properly abort tests in case of fatal failure.
-void GetIsInheritable(FILE* stream, bool* is_inheritable) {
-#if defined(OS_WIN)
- HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stream)));
- ASSERT_NE(INVALID_HANDLE_VALUE, handle);
-
- DWORD info = 0;
- ASSERT_EQ(TRUE, ::GetHandleInformation(handle, &info));
- *is_inheritable = ((info & HANDLE_FLAG_INHERIT) != 0);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- int fd = fileno(stream);
- ASSERT_NE(-1, fd);
- int flags = fcntl(fd, F_GETFD, 0);
- ASSERT_NE(-1, flags);
- *is_inheritable = ((flags & FD_CLOEXEC) == 0);
-#else
-#error Not implemented
-#endif
-}
-
-TEST_F(FileUtilTest, FileAndDirectorySize) {
- // Create three files of 20, 30 and 3 chars (utf8). ComputeDirectorySize
- // should return 53 bytes.
- FilePath file_01 = temp_dir_.GetPath().Append(FPL("The file 01.txt"));
- CreateTextFile(file_01, L"12345678901234567890");
- int64_t size_f1 = 0;
- ASSERT_TRUE(GetFileSize(file_01, &size_f1));
- EXPECT_EQ(20ll, size_f1);
-
- FilePath subdir_path = temp_dir_.GetPath().Append(FPL("Level2"));
- CreateDirectory(subdir_path);
-
- FilePath file_02 = subdir_path.Append(FPL("The file 02.txt"));
- CreateTextFile(file_02, L"123456789012345678901234567890");
- int64_t size_f2 = 0;
- ASSERT_TRUE(GetFileSize(file_02, &size_f2));
- EXPECT_EQ(30ll, size_f2);
-
- FilePath subsubdir_path = subdir_path.Append(FPL("Level3"));
- CreateDirectory(subsubdir_path);
-
- FilePath file_03 = subsubdir_path.Append(FPL("The file 03.txt"));
- CreateTextFile(file_03, L"123");
-
- int64_t computed_size = ComputeDirectorySize(temp_dir_.GetPath());
- EXPECT_EQ(size_f1 + size_f2 + 3, computed_size);
-}
-
-TEST_F(FileUtilTest, NormalizeFilePathBasic) {
- // Create a directory under the test dir. Because we create it,
- // we know it is not a link.
- FilePath file_a_path = temp_dir_.GetPath().Append(FPL("file_a"));
- FilePath dir_path = temp_dir_.GetPath().Append(FPL("dir"));
- FilePath file_b_path = dir_path.Append(FPL("file_b"));
- CreateDirectory(dir_path);
-
- FilePath normalized_file_a_path, normalized_file_b_path;
- ASSERT_FALSE(PathExists(file_a_path));
- ASSERT_FALSE(NormalizeFilePath(file_a_path, &normalized_file_a_path))
- << "NormalizeFilePath() should fail on nonexistent paths.";
-
- CreateTextFile(file_a_path, bogus_content);
- ASSERT_TRUE(PathExists(file_a_path));
- ASSERT_TRUE(NormalizeFilePath(file_a_path, &normalized_file_a_path));
-
- CreateTextFile(file_b_path, bogus_content);
- ASSERT_TRUE(PathExists(file_b_path));
- ASSERT_TRUE(NormalizeFilePath(file_b_path, &normalized_file_b_path));
-
- // Beacuse this test created |dir_path|, we know it is not a link
- // or junction. So, the real path of the directory holding file a
- // must be the parent of the path holding file b.
- ASSERT_TRUE(normalized_file_a_path.DirName()
- .IsParent(normalized_file_b_path.DirName()));
-}
-
-#if defined(OS_WIN)
-
-TEST_F(FileUtilTest, NormalizeFilePathReparsePoints) {
- // Build the following directory structure:
- //
- // temp_dir
- // |-> base_a
- // | |-> sub_a
- // | |-> file.txt
- // | |-> long_name___... (Very long name.)
- // | |-> sub_long
- // | |-> deep.txt
- // |-> base_b
- // |-> to_sub_a (reparse point to temp_dir\base_a\sub_a)
- // |-> to_base_b (reparse point to temp_dir\base_b)
- // |-> to_sub_long (reparse point to temp_dir\sub_a\long_name_\sub_long)
-
- FilePath base_a = temp_dir_.GetPath().Append(FPL("base_a"));
-#if defined(OS_WIN)
- // TEMP can have a lower case drive letter.
- string16 temp_base_a = base_a.value();
- ASSERT_FALSE(temp_base_a.empty());
- *temp_base_a.begin() = ToUpperASCII(*temp_base_a.begin());
- base_a = FilePath(temp_base_a);
-#endif
- ASSERT_TRUE(CreateDirectory(base_a));
-
- FilePath sub_a = base_a.Append(FPL("sub_a"));
- ASSERT_TRUE(CreateDirectory(sub_a));
-
- FilePath file_txt = sub_a.Append(FPL("file.txt"));
- CreateTextFile(file_txt, bogus_content);
-
- // Want a directory whose name is long enough to make the path to the file
- // inside just under MAX_PATH chars. This will be used to test that when
- // a junction expands to a path over MAX_PATH chars in length,
- // NormalizeFilePath() fails without crashing.
- FilePath sub_long_rel(FPL("sub_long"));
- FilePath deep_txt(FPL("deep.txt"));
-
- int target_length = MAX_PATH;
- target_length -= (sub_a.value().length() + 1); // +1 for the sepperator '\'.
- target_length -= (sub_long_rel.Append(deep_txt).value().length() + 1);
- // Without making the path a bit shorter, CreateDirectory() fails.
- // the resulting path is still long enough to hit the failing case in
- // NormalizePath().
- const int kCreateDirLimit = 4;
- target_length -= kCreateDirLimit;
- FilePath::StringType long_name_str = FPL("long_name_");
- long_name_str.resize(target_length, '_');
-
- FilePath long_name = sub_a.Append(FilePath(long_name_str));
- FilePath deep_file = long_name.Append(sub_long_rel).Append(deep_txt);
- ASSERT_EQ(static_cast<size_t>(MAX_PATH - kCreateDirLimit),
- deep_file.value().length());
-
- FilePath sub_long = deep_file.DirName();
- ASSERT_TRUE(CreateDirectory(sub_long));
- CreateTextFile(deep_file, bogus_content);
-
- FilePath base_b = temp_dir_.GetPath().Append(FPL("base_b"));
- ASSERT_TRUE(CreateDirectory(base_b));
-
- FilePath to_sub_a = base_b.Append(FPL("to_sub_a"));
- ASSERT_TRUE(CreateDirectory(to_sub_a));
- FilePath normalized_path;
- {
- ReparsePoint reparse_to_sub_a(to_sub_a, sub_a);
- ASSERT_TRUE(reparse_to_sub_a.IsValid());
-
- FilePath to_base_b = base_b.Append(FPL("to_base_b"));
- ASSERT_TRUE(CreateDirectory(to_base_b));
- ReparsePoint reparse_to_base_b(to_base_b, base_b);
- ASSERT_TRUE(reparse_to_base_b.IsValid());
-
- FilePath to_sub_long = base_b.Append(FPL("to_sub_long"));
- ASSERT_TRUE(CreateDirectory(to_sub_long));
- ReparsePoint reparse_to_sub_long(to_sub_long, sub_long);
- ASSERT_TRUE(reparse_to_sub_long.IsValid());
-
- // Normalize a junction free path: base_a\sub_a\file.txt .
- ASSERT_TRUE(NormalizeFilePath(file_txt, &normalized_path));
- ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
-
- // Check that the path base_b\to_sub_a\file.txt can be normalized to exclude
- // the junction to_sub_a.
- ASSERT_TRUE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
- &normalized_path));
- ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
-
- // Check that the path base_b\to_base_b\to_base_b\to_sub_a\file.txt can be
- // normalized to exclude junctions to_base_b and to_sub_a .
- ASSERT_TRUE(NormalizeFilePath(base_b.Append(FPL("to_base_b"))
- .Append(FPL("to_base_b"))
- .Append(FPL("to_sub_a"))
- .Append(FPL("file.txt")),
- &normalized_path));
- ASSERT_STREQ(file_txt.value().c_str(), normalized_path.value().c_str());
-
- // A long enough path will cause NormalizeFilePath() to fail. Make a long
- // path using to_base_b many times, and check that paths long enough to fail
- // do not cause a crash.
- FilePath long_path = base_b;
- const int kLengthLimit = MAX_PATH + 200;
- while (long_path.value().length() <= kLengthLimit) {
- long_path = long_path.Append(FPL("to_base_b"));
- }
- long_path = long_path.Append(FPL("to_sub_a"))
- .Append(FPL("file.txt"));
-
- ASSERT_FALSE(NormalizeFilePath(long_path, &normalized_path));
-
- // Normalizing the junction to deep.txt should fail, because the expanded
- // path to deep.txt is longer than MAX_PATH.
- ASSERT_FALSE(NormalizeFilePath(to_sub_long.Append(deep_txt),
- &normalized_path));
-
- // Delete the reparse points, and see that NormalizeFilePath() fails
- // to traverse them.
- }
-
- ASSERT_FALSE(NormalizeFilePath(to_sub_a.Append(FPL("file.txt")),
- &normalized_path));
-}
-
-TEST_F(FileUtilTest, DevicePathToDriveLetter) {
- // Get a drive letter.
- string16 real_drive_letter =
- ToUpperASCII(temp_dir_.GetPath().value().substr(0, 2));
- if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
- LOG(ERROR) << "Can't get a drive letter to test with.";
- return;
- }
-
- // Get the NT style path to that drive.
- wchar_t device_path[MAX_PATH] = {'\0'};
- ASSERT_TRUE(
- ::QueryDosDevice(real_drive_letter.c_str(), device_path, MAX_PATH));
- FilePath actual_device_path(device_path);
- FilePath win32_path;
-
- // Run DevicePathToDriveLetterPath() on the NT style path we got from
- // QueryDosDevice(). Expect the drive letter we started with.
- ASSERT_TRUE(DevicePathToDriveLetterPath(actual_device_path, &win32_path));
- ASSERT_EQ(real_drive_letter, win32_path.value());
-
- // Add some directories to the path. Expect those extra path componenets
- // to be preserved.
- FilePath kRelativePath(FPL("dir1\\dir2\\file.txt"));
- ASSERT_TRUE(DevicePathToDriveLetterPath(
- actual_device_path.Append(kRelativePath),
- &win32_path));
- EXPECT_EQ(FilePath(real_drive_letter + L"\\").Append(kRelativePath).value(),
- win32_path.value());
-
- // Deform the real path so that it is invalid by removing the last four
- // characters. The way windows names devices that are hard disks
- // (\Device\HardDiskVolume${NUMBER}) guarantees that the string is longer
- // than three characters. The only way the truncated string could be a
- // real drive is if more than 10^3 disks are mounted:
- // \Device\HardDiskVolume10000 would be truncated to \Device\HardDiskVolume1
- // Check that DevicePathToDriveLetterPath fails.
- int path_length = actual_device_path.value().length();
- int new_length = path_length - 4;
- ASSERT_LT(0, new_length);
- FilePath prefix_of_real_device_path(
- actual_device_path.value().substr(0, new_length));
- ASSERT_FALSE(DevicePathToDriveLetterPath(prefix_of_real_device_path,
- &win32_path));
-
- ASSERT_FALSE(DevicePathToDriveLetterPath(
- prefix_of_real_device_path.Append(kRelativePath),
- &win32_path));
-
- // Deform the real path so that it is invalid by adding some characters. For
- // example, if C: maps to \Device\HardDiskVolume8, then we simulate a
- // request for the drive letter whose native path is
- // \Device\HardDiskVolume812345 . We assume such a device does not exist,
- // because drives are numbered in order and mounting 112345 hard disks will
- // never happen.
- const FilePath::StringType kExtraChars = FPL("12345");
-
- FilePath real_device_path_plus_numbers(
- actual_device_path.value() + kExtraChars);
-
- ASSERT_FALSE(DevicePathToDriveLetterPath(
- real_device_path_plus_numbers,
- &win32_path));
-
- ASSERT_FALSE(DevicePathToDriveLetterPath(
- real_device_path_plus_numbers.Append(kRelativePath),
- &win32_path));
-}
-
-TEST_F(FileUtilTest, CreateTemporaryFileInDirLongPathTest) {
- // Test that CreateTemporaryFileInDir() creates a path and returns a long path
- // if it is available. This test requires that:
- // - the filesystem at |temp_dir_| supports long filenames.
- // - the account has FILE_LIST_DIRECTORY permission for all ancestor
- // directories of |temp_dir_|.
- const FilePath::CharType kLongDirName[] = FPL("A long path");
- const FilePath::CharType kTestSubDirName[] = FPL("test");
- FilePath long_test_dir = temp_dir_.GetPath().Append(kLongDirName);
- ASSERT_TRUE(CreateDirectory(long_test_dir));
-
- // kLongDirName is not a 8.3 component. So GetShortName() should give us a
- // different short name.
- WCHAR path_buffer[MAX_PATH];
- DWORD path_buffer_length = GetShortPathName(long_test_dir.value().c_str(),
- path_buffer, MAX_PATH);
- ASSERT_LT(path_buffer_length, DWORD(MAX_PATH));
- ASSERT_NE(DWORD(0), path_buffer_length);
- FilePath short_test_dir(path_buffer);
- ASSERT_STRNE(kLongDirName, short_test_dir.BaseName().value().c_str());
-
- FilePath temp_file;
- ASSERT_TRUE(CreateTemporaryFileInDir(short_test_dir, &temp_file));
- EXPECT_STREQ(kLongDirName, temp_file.DirName().BaseName().value().c_str());
- EXPECT_TRUE(PathExists(temp_file));
-
- // Create a subdirectory of |long_test_dir| and make |long_test_dir|
- // unreadable. We should still be able to create a temp file in the
- // subdirectory, but we won't be able to determine the long path for it. This
- // mimics the environment that some users run where their user profiles reside
- // in a location where the don't have full access to the higher level
- // directories. (Note that this assumption is true for NTFS, but not for some
- // network file systems. E.g. AFS).
- FilePath access_test_dir = long_test_dir.Append(kTestSubDirName);
- ASSERT_TRUE(CreateDirectory(access_test_dir));
- FilePermissionRestorer long_test_dir_restorer(long_test_dir);
- ASSERT_TRUE(MakeFileUnreadable(long_test_dir));
-
- // Use the short form of the directory to create a temporary filename.
- ASSERT_TRUE(CreateTemporaryFileInDir(
- short_test_dir.Append(kTestSubDirName), &temp_file));
- EXPECT_TRUE(PathExists(temp_file));
- EXPECT_TRUE(short_test_dir.IsParent(temp_file.DirName()));
-
- // Check that the long path can't be determined for |temp_file|.
- path_buffer_length = GetLongPathName(temp_file.value().c_str(),
- path_buffer, MAX_PATH);
- EXPECT_EQ(DWORD(0), path_buffer_length);
-}
-
-#endif // defined(OS_WIN)
-
-#if defined(OS_POSIX)
-
-TEST_F(FileUtilTest, CreateAndReadSymlinks) {
- FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
- FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
- CreateTextFile(link_to, bogus_content);
-
- ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
- << "Failed to create file symlink.";
-
- // If we created the link properly, we should be able to read the contents
- // through it.
- EXPECT_EQ(bogus_content, ReadTextFile(link_from));
-
- FilePath result;
- ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
- EXPECT_EQ(link_to.value(), result.value());
-
- // Link to a directory.
- link_from = temp_dir_.GetPath().Append(FPL("from_dir"));
- link_to = temp_dir_.GetPath().Append(FPL("to_dir"));
- ASSERT_TRUE(CreateDirectory(link_to));
- ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
- << "Failed to create directory symlink.";
-
- // Test failures.
- EXPECT_FALSE(CreateSymbolicLink(link_to, link_to));
- EXPECT_FALSE(ReadSymbolicLink(link_to, &result));
- FilePath missing = temp_dir_.GetPath().Append(FPL("missing"));
- EXPECT_FALSE(ReadSymbolicLink(missing, &result));
-}
-
-// The following test of NormalizeFilePath() require that we create a symlink.
-// This can not be done on Windows before Vista. On Vista, creating a symlink
-// requires privilege "SeCreateSymbolicLinkPrivilege".
-// TODO(skerner): Investigate the possibility of giving base_unittests the
-// privileges required to create a symlink.
-TEST_F(FileUtilTest, NormalizeFilePathSymlinks) {
- // Link one file to another.
- FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
- FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
- CreateTextFile(link_to, bogus_content);
-
- ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
- << "Failed to create file symlink.";
-
- // Check that NormalizeFilePath sees the link.
- FilePath normalized_path;
- ASSERT_TRUE(NormalizeFilePath(link_from, &normalized_path));
- EXPECT_NE(link_from, link_to);
- EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
- EXPECT_EQ(link_to.BaseName().value(), normalized_path.BaseName().value());
-
- // Link to a directory.
- link_from = temp_dir_.GetPath().Append(FPL("from_dir"));
- link_to = temp_dir_.GetPath().Append(FPL("to_dir"));
- ASSERT_TRUE(CreateDirectory(link_to));
- ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
- << "Failed to create directory symlink.";
-
- EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path))
- << "Links to directories should return false.";
-
- // Test that a loop in the links causes NormalizeFilePath() to return false.
- link_from = temp_dir_.GetPath().Append(FPL("link_a"));
- link_to = temp_dir_.GetPath().Append(FPL("link_b"));
- ASSERT_TRUE(CreateSymbolicLink(link_to, link_from))
- << "Failed to create loop symlink a.";
- ASSERT_TRUE(CreateSymbolicLink(link_from, link_to))
- << "Failed to create loop symlink b.";
-
- // Infinite loop!
- EXPECT_FALSE(NormalizeFilePath(link_from, &normalized_path));
-}
-
-TEST_F(FileUtilTest, DeleteSymlinkToExistentFile) {
- // Create a file.
- FilePath file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 2.txt"));
- CreateTextFile(file_name, bogus_content);
- ASSERT_TRUE(PathExists(file_name));
-
- // Create a symlink to the file.
- FilePath file_link = temp_dir_.GetPath().Append("file_link_2");
- ASSERT_TRUE(CreateSymbolicLink(file_name, file_link))
- << "Failed to create symlink.";
-
- // Delete the symbolic link.
- EXPECT_TRUE(DeleteFile(file_link, false));
-
- // Make sure original file is not deleted.
- EXPECT_FALSE(PathExists(file_link));
- EXPECT_TRUE(PathExists(file_name));
-}
-
-TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) {
- // Create a non-existent file path.
- FilePath non_existent =
- temp_dir_.GetPath().Append(FPL("Test DeleteFile 3.txt"));
- EXPECT_FALSE(PathExists(non_existent));
-
- // Create a symlink to the non-existent file.
- FilePath file_link = temp_dir_.GetPath().Append("file_link_3");
- ASSERT_TRUE(CreateSymbolicLink(non_existent, file_link))
- << "Failed to create symlink.";
-
- // Make sure the symbolic link is exist.
- EXPECT_TRUE(IsLink(file_link));
- EXPECT_FALSE(PathExists(file_link));
-
- // Delete the symbolic link.
- EXPECT_TRUE(DeleteFile(file_link, false));
-
- // Make sure the symbolic link is deleted.
- EXPECT_FALSE(IsLink(file_link));
-}
-
-TEST_F(FileUtilTest, CopyFileFollowsSymlinks) {
- FilePath link_from = temp_dir_.GetPath().Append(FPL("from_file"));
- FilePath link_to = temp_dir_.GetPath().Append(FPL("to_file"));
- CreateTextFile(link_to, bogus_content);
-
- ASSERT_TRUE(CreateSymbolicLink(link_to, link_from));
-
- // If we created the link properly, we should be able to read the contents
- // through it.
- EXPECT_EQ(bogus_content, ReadTextFile(link_from));
-
- FilePath result;
- ASSERT_TRUE(ReadSymbolicLink(link_from, &result));
- EXPECT_EQ(link_to.value(), result.value());
-
- // Create another file and copy it to |link_from|.
- FilePath src_file = temp_dir_.GetPath().Append(FPL("src.txt"));
- const std::wstring file_contents(L"Gooooooooooooooooooooogle");
- CreateTextFile(src_file, file_contents);
- ASSERT_TRUE(CopyFile(src_file, link_from));
-
- // Make sure |link_from| is still a symlink, and |link_to| has been written to
- // by CopyFile().
- EXPECT_TRUE(IsLink(link_from));
- EXPECT_EQ(file_contents, ReadTextFile(link_from));
- EXPECT_EQ(file_contents, ReadTextFile(link_to));
-}
-
-TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) {
- // Create a file path.
- FilePath file_name =
- temp_dir_.GetPath().Append(FPL("Test Readable File.txt"));
- EXPECT_FALSE(PathExists(file_name));
-
- static constexpr char kData[] = "hello";
- static constexpr int kDataSize = sizeof(kData) - 1;
- char buffer[kDataSize];
-
- // Write file.
- EXPECT_EQ(kDataSize, WriteFile(file_name, kData, kDataSize));
- EXPECT_TRUE(PathExists(file_name));
-
- // Make sure the file is readable.
- int32_t mode = 0;
- EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
- EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
-
- // Get rid of the read permission.
- EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
- EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
- EXPECT_FALSE(mode & FILE_PERMISSION_READ_BY_USER);
- // Make sure the file can't be read.
- EXPECT_EQ(-1, ReadFile(file_name, buffer, kDataSize));
-
- // Give the read permission.
- EXPECT_TRUE(SetPosixFilePermissions(file_name, FILE_PERMISSION_READ_BY_USER));
- EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
- EXPECT_TRUE(mode & FILE_PERMISSION_READ_BY_USER);
- // Make sure the file can be read.
- EXPECT_EQ(kDataSize, ReadFile(file_name, buffer, kDataSize));
-
- // Delete the file.
- EXPECT_TRUE(DeleteFile(file_name, false));
- EXPECT_FALSE(PathExists(file_name));
-}
-
-TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) {
- // Create a file path.
- FilePath file_name =
- temp_dir_.GetPath().Append(FPL("Test Readable File.txt"));
- EXPECT_FALSE(PathExists(file_name));
-
- const std::string kData("hello");
-
- // Write file.
- EXPECT_EQ(static_cast<int>(kData.length()),
- WriteFile(file_name, kData.data(), kData.length()));
- EXPECT_TRUE(PathExists(file_name));
-
- // Make sure the file is writable.
- int mode = 0;
- EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
- EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
- EXPECT_TRUE(PathIsWritable(file_name));
-
- // Get rid of the write permission.
- EXPECT_TRUE(SetPosixFilePermissions(file_name, 0u));
- EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
- EXPECT_FALSE(mode & FILE_PERMISSION_WRITE_BY_USER);
- // Make sure the file can't be write.
- EXPECT_EQ(-1, WriteFile(file_name, kData.data(), kData.length()));
- EXPECT_FALSE(PathIsWritable(file_name));
-
- // Give read permission.
- EXPECT_TRUE(SetPosixFilePermissions(file_name,
- FILE_PERMISSION_WRITE_BY_USER));
- EXPECT_TRUE(GetPosixFilePermissions(file_name, &mode));
- EXPECT_TRUE(mode & FILE_PERMISSION_WRITE_BY_USER);
- // Make sure the file can be write.
- EXPECT_EQ(static_cast<int>(kData.length()),
- WriteFile(file_name, kData.data(), kData.length()));
- EXPECT_TRUE(PathIsWritable(file_name));
-
- // Delete the file.
- EXPECT_TRUE(DeleteFile(file_name, false));
- EXPECT_FALSE(PathExists(file_name));
-}
-
-TEST_F(FileUtilTest, ChangeDirectoryPermissionsAndEnumerate) {
- // Create a directory path.
- FilePath subdir_path = temp_dir_.GetPath().Append(FPL("PermissionTest1"));
- CreateDirectory(subdir_path);
- ASSERT_TRUE(PathExists(subdir_path));
-
- // Create a dummy file to enumerate.
- FilePath file_name = subdir_path.Append(FPL("Test Readable File.txt"));
- EXPECT_FALSE(PathExists(file_name));
- const std::string kData("hello");
- EXPECT_EQ(static_cast<int>(kData.length()),
- WriteFile(file_name, kData.data(), kData.length()));
- EXPECT_TRUE(PathExists(file_name));
-
- // Make sure the directory has the all permissions.
- int mode = 0;
- EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
- EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
-
- // Get rid of the permissions from the directory.
- EXPECT_TRUE(SetPosixFilePermissions(subdir_path, 0u));
- EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
- EXPECT_FALSE(mode & FILE_PERMISSION_USER_MASK);
-
- // Make sure the file in the directory can't be enumerated.
- FileEnumerator f1(subdir_path, true, FileEnumerator::FILES);
- EXPECT_TRUE(PathExists(subdir_path));
- FindResultCollector c1(&f1);
- EXPECT_EQ(0, c1.size());
- EXPECT_FALSE(GetPosixFilePermissions(file_name, &mode));
-
- // Give the permissions to the directory.
- EXPECT_TRUE(SetPosixFilePermissions(subdir_path, FILE_PERMISSION_USER_MASK));
- EXPECT_TRUE(GetPosixFilePermissions(subdir_path, &mode));
- EXPECT_EQ(FILE_PERMISSION_USER_MASK, mode & FILE_PERMISSION_USER_MASK);
-
- // Make sure the file in the directory can be enumerated.
- FileEnumerator f2(subdir_path, true, FileEnumerator::FILES);
- FindResultCollector c2(&f2);
- EXPECT_TRUE(c2.HasFile(file_name));
- EXPECT_EQ(1, c2.size());
-
- // Delete the file.
- EXPECT_TRUE(DeleteFile(subdir_path, true));
- EXPECT_FALSE(PathExists(subdir_path));
-}
-
-TEST_F(FileUtilTest, ExecutableExistsInPath) {
- // Create two directories that we will put in our PATH
- const FilePath::CharType kDir1[] = FPL("dir1");
- const FilePath::CharType kDir2[] = FPL("dir2");
-
- FilePath dir1 = temp_dir_.GetPath().Append(kDir1);
- FilePath dir2 = temp_dir_.GetPath().Append(kDir2);
- ASSERT_TRUE(CreateDirectory(dir1));
- ASSERT_TRUE(CreateDirectory(dir2));
-
- test::ScopedEnvironmentVariableOverride scoped_env(
- "PATH", dir1.value() + ":" + dir2.value());
- ASSERT_TRUE(scoped_env.IsOverridden());
-
- const FilePath::CharType kRegularFileName[] = FPL("regular_file");
- const FilePath::CharType kExeFileName[] = FPL("exe");
- const FilePath::CharType kDneFileName[] = FPL("does_not_exist");
-
- const FilePath kExePath = dir1.Append(kExeFileName);
- const FilePath kRegularFilePath = dir2.Append(kRegularFileName);
-
- // Write file.
- const std::string kData("hello");
- ASSERT_EQ(static_cast<int>(kData.length()),
- WriteFile(kExePath, kData.data(), kData.length()));
- ASSERT_TRUE(PathExists(kExePath));
- ASSERT_EQ(static_cast<int>(kData.length()),
- WriteFile(kRegularFilePath, kData.data(), kData.length()));
- ASSERT_TRUE(PathExists(kRegularFilePath));
-
- ASSERT_TRUE(SetPosixFilePermissions(dir1.Append(kExeFileName),
- FILE_PERMISSION_EXECUTE_BY_USER));
-
- EXPECT_TRUE(ExecutableExistsInPath(scoped_env.GetEnv(), kExeFileName));
- EXPECT_FALSE(ExecutableExistsInPath(scoped_env.GetEnv(), kRegularFileName));
- EXPECT_FALSE(ExecutableExistsInPath(scoped_env.GetEnv(), kDneFileName));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryPermissions) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create some regular files under the directory with various permissions.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
- CreateTextFile(file_name_from, L"Mordecai");
- ASSERT_TRUE(PathExists(file_name_from));
- ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0755));
-
- FilePath file2_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
- CreateTextFile(file2_name_from, L"Rigby");
- ASSERT_TRUE(PathExists(file2_name_from));
- ASSERT_TRUE(SetPosixFilePermissions(file2_name_from, 0777));
-
- FilePath file3_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
- CreateTextFile(file3_name_from, L"Benson");
- ASSERT_TRUE(PathExists(file3_name_from));
- ASSERT_TRUE(SetPosixFilePermissions(file3_name_from, 0400));
-
- // Copy the directory recursively.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
- FilePath file2_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Reggy-2.txt"));
- FilePath file3_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Reggy-3.txt"));
-
- ASSERT_FALSE(PathExists(dir_name_to));
-
- EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
- ASSERT_TRUE(PathExists(file_name_to));
- ASSERT_TRUE(PathExists(file2_name_to));
- ASSERT_TRUE(PathExists(file3_name_to));
-
- int mode = 0;
- int expected_mode;
- ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
-#if defined(OS_MACOSX)
- expected_mode = 0755;
-#elif defined(OS_CHROMEOS)
- expected_mode = 0644;
-#else
- expected_mode = 0600;
-#endif
- EXPECT_EQ(expected_mode, mode);
-
- ASSERT_TRUE(GetPosixFilePermissions(file2_name_to, &mode));
-#if defined(OS_MACOSX)
- expected_mode = 0755;
-#elif defined(OS_CHROMEOS)
- expected_mode = 0644;
-#else
- expected_mode = 0600;
-#endif
- EXPECT_EQ(expected_mode, mode);
-
- ASSERT_TRUE(GetPosixFilePermissions(file3_name_to, &mode));
-#if defined(OS_MACOSX)
- expected_mode = 0600;
-#elif defined(OS_CHROMEOS)
- expected_mode = 0644;
-#else
- expected_mode = 0600;
-#endif
- EXPECT_EQ(expected_mode, mode);
-}
-
-TEST_F(FileUtilTest, CopyDirectoryPermissionsOverExistingFile) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
- CreateTextFile(file_name_from, L"Mordecai");
- ASSERT_TRUE(PathExists(file_name_from));
- ASSERT_TRUE(SetPosixFilePermissions(file_name_from, 0644));
-
- // Create a directory.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- CreateDirectory(dir_name_to);
- ASSERT_TRUE(PathExists(dir_name_to));
-
- // Create a file under the directory with wider permissions.
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
- CreateTextFile(file_name_to, L"Rigby");
- ASSERT_TRUE(PathExists(file_name_to));
- ASSERT_TRUE(SetPosixFilePermissions(file_name_to, 0777));
-
- // Ensure that when we copy the directory, the file contents are copied
- // but the permissions on the destination are left alone.
- EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
- ASSERT_TRUE(PathExists(file_name_to));
- ASSERT_EQ(L"Mordecai", ReadTextFile(file_name_to));
-
- int mode = 0;
- ASSERT_TRUE(GetPosixFilePermissions(file_name_to, &mode));
- EXPECT_EQ(0777, mode);
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclDoesNotOverwrite) {
- // Create source directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
- CreateTextFile(file_name_from, L"Mordecai");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create destination directory.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- CreateDirectory(dir_name_to);
- ASSERT_TRUE(PathExists(dir_name_to));
-
- // Create a file under the directory with the same name.
- FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt"));
- CreateTextFile(file_name_to, L"Rigby");
- ASSERT_TRUE(PathExists(file_name_to));
-
- // Ensure that copying failed and the file was not overwritten.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
- ASSERT_TRUE(PathExists(file_name_to));
- ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingFile) {
- // Create source directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create destination directory.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- CreateDirectory(dir_name_to);
- ASSERT_TRUE(PathExists(dir_name_to));
-
- // Create a regular file under the directory with the same name.
- FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
- CreateTextFile(file_name_to, L"Rigby");
- ASSERT_TRUE(PathExists(file_name_to));
-
- // Ensure that copying failed and the file was not overwritten.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
- ASSERT_TRUE(PathExists(file_name_to));
- ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingDirectory) {
- // Create source directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create destination directory.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- CreateDirectory(dir_name_to);
- ASSERT_TRUE(PathExists(dir_name_to));
-
- // Create a subdirectory under the directory with the same name.
- FilePath subdir_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
- CreateDirectory(subdir_name_to);
- ASSERT_TRUE(PathExists(subdir_name_to));
-
- // Ensure that copying failed and the file was not overwritten.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
-}
-
-TEST_F(FileUtilTest, CopyFileExecutablePermission) {
- FilePath src = temp_dir_.GetPath().Append(FPL("src.txt"));
- const std::wstring file_contents(L"Gooooooooooooooooooooogle");
- CreateTextFile(src, file_contents);
-
- ASSERT_TRUE(SetPosixFilePermissions(src, 0755));
- int mode = 0;
- ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
- EXPECT_EQ(0755, mode);
-
- FilePath dst = temp_dir_.GetPath().Append(FPL("dst.txt"));
- ASSERT_TRUE(CopyFile(src, dst));
- EXPECT_EQ(file_contents, ReadTextFile(dst));
-
- ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
- int expected_mode;
-#if defined(OS_MACOSX)
- expected_mode = 0755;
-#elif defined(OS_CHROMEOS)
- expected_mode = 0644;
-#else
- expected_mode = 0600;
-#endif
- EXPECT_EQ(expected_mode, mode);
- ASSERT_TRUE(DeleteFile(dst, false));
-
- ASSERT_TRUE(SetPosixFilePermissions(src, 0777));
- ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
- EXPECT_EQ(0777, mode);
-
- ASSERT_TRUE(CopyFile(src, dst));
- EXPECT_EQ(file_contents, ReadTextFile(dst));
-
- ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
-#if defined(OS_MACOSX)
- expected_mode = 0755;
-#elif defined(OS_CHROMEOS)
- expected_mode = 0644;
-#else
- expected_mode = 0600;
-#endif
- EXPECT_EQ(expected_mode, mode);
- ASSERT_TRUE(DeleteFile(dst, false));
-
- ASSERT_TRUE(SetPosixFilePermissions(src, 0400));
- ASSERT_TRUE(GetPosixFilePermissions(src, &mode));
- EXPECT_EQ(0400, mode);
-
- ASSERT_TRUE(CopyFile(src, dst));
- EXPECT_EQ(file_contents, ReadTextFile(dst));
-
- ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
-#if defined(OS_MACOSX)
- expected_mode = 0600;
-#elif defined(OS_CHROMEOS)
- expected_mode = 0644;
-#else
- expected_mode = 0600;
-#endif
- EXPECT_EQ(expected_mode, mode);
-
- // This time, do not delete |dst|. Instead set its permissions to 0777.
- ASSERT_TRUE(SetPosixFilePermissions(dst, 0777));
- ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
- EXPECT_EQ(0777, mode);
-
- // Overwrite it and check the permissions again.
- ASSERT_TRUE(CopyFile(src, dst));
- EXPECT_EQ(file_contents, ReadTextFile(dst));
- ASSERT_TRUE(GetPosixFilePermissions(dst, &mode));
- EXPECT_EQ(0777, mode);
-}
-
-#endif // defined(OS_POSIX)
-
-#if !defined(OS_FUCHSIA)
-
-TEST_F(FileUtilTest, CopyFileACL) {
- // While FileUtilTest.CopyFile asserts the content is correctly copied over,
- // this test case asserts the access control bits are meeting expectations in
- // CopyFile().
- FilePath src = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("src.txt"));
- const std::wstring file_contents(L"Gooooooooooooooooooooogle");
- CreateTextFile(src, file_contents);
-
- // Set the source file to read-only.
- ASSERT_FALSE(IsReadOnly(src));
- SetReadOnly(src, true);
- ASSERT_TRUE(IsReadOnly(src));
-
- // Copy the file.
- FilePath dst = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("dst.txt"));
- ASSERT_TRUE(CopyFile(src, dst));
- EXPECT_EQ(file_contents, ReadTextFile(dst));
-
- ASSERT_FALSE(IsReadOnly(dst));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryACL) {
- // Create source directories.
- FilePath src = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("src"));
- FilePath src_subdir = src.Append(FILE_PATH_LITERAL("subdir"));
- CreateDirectory(src_subdir);
- ASSERT_TRUE(PathExists(src_subdir));
-
- // Create a file under the directory.
- FilePath src_file = src.Append(FILE_PATH_LITERAL("src.txt"));
- CreateTextFile(src_file, L"Gooooooooooooooooooooogle");
- SetReadOnly(src_file, true);
- ASSERT_TRUE(IsReadOnly(src_file));
-
- // Make directory read-only.
- SetReadOnly(src_subdir, true);
- ASSERT_TRUE(IsReadOnly(src_subdir));
-
- // Copy the directory recursively.
- FilePath dst = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("dst"));
- FilePath dst_file = dst.Append(FILE_PATH_LITERAL("src.txt"));
- EXPECT_TRUE(CopyDirectory(src, dst, true));
-
- FilePath dst_subdir = dst.Append(FILE_PATH_LITERAL("subdir"));
- ASSERT_FALSE(IsReadOnly(dst_subdir));
- ASSERT_FALSE(IsReadOnly(dst_file));
-
- // Give write permissions to allow deletion.
- SetReadOnly(src_subdir, false);
- ASSERT_FALSE(IsReadOnly(src_subdir));
-}
-
-#endif // !defined(OS_FUCHSIA)
-
-TEST_F(FileUtilTest, DeleteNonExistent) {
- FilePath non_existent =
- temp_dir_.GetPath().AppendASCII("bogus_file_dne.foobar");
- ASSERT_FALSE(PathExists(non_existent));
-
- EXPECT_TRUE(DeleteFile(non_existent, false));
- ASSERT_FALSE(PathExists(non_existent));
- EXPECT_TRUE(DeleteFile(non_existent, true));
- ASSERT_FALSE(PathExists(non_existent));
-}
-
-TEST_F(FileUtilTest, DeleteNonExistentWithNonExistentParent) {
- FilePath non_existent = temp_dir_.GetPath().AppendASCII("bogus_topdir");
- non_existent = non_existent.AppendASCII("bogus_subdir");
- ASSERT_FALSE(PathExists(non_existent));
-
- EXPECT_TRUE(DeleteFile(non_existent, false));
- ASSERT_FALSE(PathExists(non_existent));
- EXPECT_TRUE(DeleteFile(non_existent, true));
- ASSERT_FALSE(PathExists(non_existent));
-}
-
-TEST_F(FileUtilTest, DeleteFile) {
- // Create a file
- FilePath file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 1.txt"));
- CreateTextFile(file_name, bogus_content);
- ASSERT_TRUE(PathExists(file_name));
-
- // Make sure it's deleted
- EXPECT_TRUE(DeleteFile(file_name, false));
- EXPECT_FALSE(PathExists(file_name));
-
- // Test recursive case, create a new file
- file_name = temp_dir_.GetPath().Append(FPL("Test DeleteFile 2.txt"));
- CreateTextFile(file_name, bogus_content);
- ASSERT_TRUE(PathExists(file_name));
-
- // Make sure it's deleted
- EXPECT_TRUE(DeleteFile(file_name, true));
- EXPECT_FALSE(PathExists(file_name));
-}
-
-#if defined(OS_WIN)
-// Tests that the Delete function works for wild cards, especially
-// with the recursion flag. Also coincidentally tests PathExists.
-// TODO(erikkay): see if anyone's actually using this feature of the API
-TEST_F(FileUtilTest, DeleteWildCard) {
- // Create a file and a directory
- FilePath file_name =
- temp_dir_.GetPath().Append(FPL("Test DeleteWildCard.txt"));
- CreateTextFile(file_name, bogus_content);
- ASSERT_TRUE(PathExists(file_name));
-
- FilePath subdir_path = temp_dir_.GetPath().Append(FPL("DeleteWildCardDir"));
- CreateDirectory(subdir_path);
- ASSERT_TRUE(PathExists(subdir_path));
-
- // Create the wildcard path
- FilePath directory_contents = temp_dir_.GetPath();
- directory_contents = directory_contents.Append(FPL("*"));
-
- // Delete non-recursively and check that only the file is deleted
- EXPECT_TRUE(DeleteFile(directory_contents, false));
- EXPECT_FALSE(PathExists(file_name));
- EXPECT_TRUE(PathExists(subdir_path));
-
- // Delete recursively and make sure all contents are deleted
- EXPECT_TRUE(DeleteFile(directory_contents, true));
- EXPECT_FALSE(PathExists(file_name));
- EXPECT_FALSE(PathExists(subdir_path));
-}
-
-// TODO(erikkay): see if anyone's actually using this feature of the API
-TEST_F(FileUtilTest, DeleteNonExistantWildCard) {
- // Create a file and a directory
- FilePath subdir_path =
- temp_dir_.GetPath().Append(FPL("DeleteNonExistantWildCard"));
- CreateDirectory(subdir_path);
- ASSERT_TRUE(PathExists(subdir_path));
-
- // Create the wildcard path
- FilePath directory_contents = subdir_path;
- directory_contents = directory_contents.Append(FPL("*"));
-
- // Delete non-recursively and check nothing got deleted
- EXPECT_TRUE(DeleteFile(directory_contents, false));
- EXPECT_TRUE(PathExists(subdir_path));
-
- // Delete recursively and check nothing got deleted
- EXPECT_TRUE(DeleteFile(directory_contents, true));
- EXPECT_TRUE(PathExists(subdir_path));
-}
-#endif
-
-// Tests non-recursive Delete() for a directory.
-TEST_F(FileUtilTest, DeleteDirNonRecursive) {
- // Create a subdirectory and put a file and two directories inside.
- FilePath test_subdir =
- temp_dir_.GetPath().Append(FPL("DeleteDirNonRecursive"));
- CreateDirectory(test_subdir);
- ASSERT_TRUE(PathExists(test_subdir));
-
- FilePath file_name = test_subdir.Append(FPL("Test DeleteDir.txt"));
- CreateTextFile(file_name, bogus_content);
- ASSERT_TRUE(PathExists(file_name));
-
- FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
- CreateDirectory(subdir_path1);
- ASSERT_TRUE(PathExists(subdir_path1));
-
- FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
- CreateDirectory(subdir_path2);
- ASSERT_TRUE(PathExists(subdir_path2));
-
- // Delete non-recursively and check that the empty dir got deleted
- EXPECT_TRUE(DeleteFile(subdir_path2, false));
- EXPECT_FALSE(PathExists(subdir_path2));
-
- // Delete non-recursively and check that nothing got deleted
- EXPECT_FALSE(DeleteFile(test_subdir, false));
- EXPECT_TRUE(PathExists(test_subdir));
- EXPECT_TRUE(PathExists(file_name));
- EXPECT_TRUE(PathExists(subdir_path1));
-}
-
-// Tests recursive Delete() for a directory.
-TEST_F(FileUtilTest, DeleteDirRecursive) {
- // Create a subdirectory and put a file and two directories inside.
- FilePath test_subdir = temp_dir_.GetPath().Append(FPL("DeleteDirRecursive"));
- CreateDirectory(test_subdir);
- ASSERT_TRUE(PathExists(test_subdir));
-
- FilePath file_name = test_subdir.Append(FPL("Test DeleteDirRecursive.txt"));
- CreateTextFile(file_name, bogus_content);
- ASSERT_TRUE(PathExists(file_name));
-
- FilePath subdir_path1 = test_subdir.Append(FPL("TestSubDir1"));
- CreateDirectory(subdir_path1);
- ASSERT_TRUE(PathExists(subdir_path1));
-
- FilePath subdir_path2 = test_subdir.Append(FPL("TestSubDir2"));
- CreateDirectory(subdir_path2);
- ASSERT_TRUE(PathExists(subdir_path2));
-
- // Delete recursively and check that the empty dir got deleted
- EXPECT_TRUE(DeleteFile(subdir_path2, true));
- EXPECT_FALSE(PathExists(subdir_path2));
-
- // Delete recursively and check that everything got deleted
- EXPECT_TRUE(DeleteFile(test_subdir, true));
- EXPECT_FALSE(PathExists(file_name));
- EXPECT_FALSE(PathExists(subdir_path1));
- EXPECT_FALSE(PathExists(test_subdir));
-}
-
-// Tests recursive Delete() for a directory.
-TEST_F(FileUtilTest, DeleteDirRecursiveWithOpenFile) {
- // Create a subdirectory and put a file and two directories inside.
- FilePath test_subdir = temp_dir_.GetPath().Append(FPL("DeleteWithOpenFile"));
- CreateDirectory(test_subdir);
- ASSERT_TRUE(PathExists(test_subdir));
-
- FilePath file_name1 = test_subdir.Append(FPL("Undeletebable File1.txt"));
- File file1(file_name1,
- File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
- ASSERT_TRUE(PathExists(file_name1));
-
- FilePath file_name2 = test_subdir.Append(FPL("Deleteable File2.txt"));
- CreateTextFile(file_name2, bogus_content);
- ASSERT_TRUE(PathExists(file_name2));
-
- FilePath file_name3 = test_subdir.Append(FPL("Undeletebable File3.txt"));
- File file3(file_name3,
- File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE);
- ASSERT_TRUE(PathExists(file_name3));
-
-#if defined(OS_LINUX)
- // On Windows, holding the file open in sufficient to make it un-deletable.
- // The POSIX code is verifiable on Linux by creating an "immutable" file but
- // this is best-effort because it's not supported by all file systems. Both
- // files will have the same flags so no need to get them individually.
- int flags;
- bool file_attrs_supported =
- ioctl(file1.GetPlatformFile(), FS_IOC_GETFLAGS, &flags) == 0;
- // Some filesystems (e.g. tmpfs) don't support file attributes.
- if (file_attrs_supported) {
- flags |= FS_IMMUTABLE_FL;
- ioctl(file1.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
- ioctl(file3.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
- }
-#endif
-
- // Delete recursively and check that at least the second file got deleted.
- // This ensures that un-deletable files don't impact those that can be.
- DeleteFile(test_subdir, true);
- EXPECT_FALSE(PathExists(file_name2));
-
-#if defined(OS_LINUX)
- // Make sure that the test can clean up after itself.
- if (file_attrs_supported) {
- flags &= ~FS_IMMUTABLE_FL;
- ioctl(file1.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
- ioctl(file3.GetPlatformFile(), FS_IOC_SETFLAGS, &flags);
- }
-#endif
-}
-
-TEST_F(FileUtilTest, MoveFileNew) {
- // Create a file
- FilePath file_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // The destination.
- FilePath file_name_to = temp_dir_.GetPath().Append(
- FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
- ASSERT_FALSE(PathExists(file_name_to));
-
- EXPECT_TRUE(Move(file_name_from, file_name_to));
-
- // Check everything has been moved.
- EXPECT_FALSE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(file_name_to));
-}
-
-TEST_F(FileUtilTest, MoveFileExists) {
- // Create a file
- FilePath file_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // The destination name.
- FilePath file_name_to = temp_dir_.GetPath().Append(
- FILE_PATH_LITERAL("Move_Test_File_Destination.txt"));
- CreateTextFile(file_name_to, L"Old file content");
- ASSERT_TRUE(PathExists(file_name_to));
-
- EXPECT_TRUE(Move(file_name_from, file_name_to));
-
- // Check everything has been moved.
- EXPECT_FALSE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(file_name_to));
- EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
-}
-
-TEST_F(FileUtilTest, MoveFileDirExists) {
- // Create a file
- FilePath file_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // The destination directory
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
- CreateDirectory(dir_name_to);
- ASSERT_TRUE(PathExists(dir_name_to));
-
- EXPECT_FALSE(Move(file_name_from, dir_name_to));
-}
-
-
-TEST_F(FileUtilTest, MoveNew) {
- // Create a directory
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory
- FilePath txt_file_name(FILE_PATH_LITERAL("Move_Test_File.txt"));
- FilePath file_name_from = dir_name_from.Append(txt_file_name);
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Move the directory.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
-
- ASSERT_FALSE(PathExists(dir_name_to));
-
- EXPECT_TRUE(Move(dir_name_from, dir_name_to));
-
- // Check everything has been moved.
- EXPECT_FALSE(PathExists(dir_name_from));
- EXPECT_FALSE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
-
- // Test path traversal.
- file_name_from = dir_name_to.Append(txt_file_name);
- file_name_to = dir_name_to.Append(FILE_PATH_LITERAL(".."));
- file_name_to = file_name_to.Append(txt_file_name);
- EXPECT_FALSE(Move(file_name_from, file_name_to));
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_FALSE(PathExists(file_name_to));
- EXPECT_TRUE(internal::MoveUnsafe(file_name_from, file_name_to));
- EXPECT_FALSE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(file_name_to));
-}
-
-TEST_F(FileUtilTest, MoveExist) {
- // Create a directory
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Move_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Move the directory
- FilePath dir_name_exists =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
-
- FilePath dir_name_to =
- dir_name_exists.Append(FILE_PATH_LITERAL("Move_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Move_Test_File.txt"));
-
- // Create the destination directory.
- CreateDirectory(dir_name_exists);
- ASSERT_TRUE(PathExists(dir_name_exists));
-
- EXPECT_TRUE(Move(dir_name_from, dir_name_to));
-
- // Check everything has been moved.
- EXPECT_FALSE(PathExists(dir_name_from));
- EXPECT_FALSE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryRecursivelyNew) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create a file under the subdirectory.
- FilePath file_name2_from =
- subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name2_from));
-
- // Copy the directory recursively.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- FilePath subdir_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
- FilePath file_name2_to =
- subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
-
- ASSERT_FALSE(PathExists(dir_name_to));
-
- EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, true));
-
- // Check everything has been copied.
- EXPECT_TRUE(PathExists(dir_name_from));
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(subdir_name_from));
- EXPECT_TRUE(PathExists(file_name2_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
- EXPECT_TRUE(PathExists(subdir_name_to));
- EXPECT_TRUE(PathExists(file_name2_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryRecursivelyExists) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create a file under the subdirectory.
- FilePath file_name2_from =
- subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name2_from));
-
- // Copy the directory recursively.
- FilePath dir_name_exists =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
-
- FilePath dir_name_to =
- dir_name_exists.Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- FilePath subdir_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
- FilePath file_name2_to =
- subdir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
-
- // Create the destination directory.
- CreateDirectory(dir_name_exists);
- ASSERT_TRUE(PathExists(dir_name_exists));
-
- EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_exists, true));
-
- // Check everything has been copied.
- EXPECT_TRUE(PathExists(dir_name_from));
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(subdir_name_from));
- EXPECT_TRUE(PathExists(file_name2_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
- EXPECT_TRUE(PathExists(subdir_name_to));
- EXPECT_TRUE(PathExists(file_name2_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryNew) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create a file under the subdirectory.
- FilePath file_name2_from =
- subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name2_from));
-
- // Copy the directory not recursively.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- FilePath subdir_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
-
- ASSERT_FALSE(PathExists(dir_name_to));
-
- EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
-
- // Check everything has been copied.
- EXPECT_TRUE(PathExists(dir_name_from));
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(subdir_name_from));
- EXPECT_TRUE(PathExists(file_name2_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
- EXPECT_FALSE(PathExists(subdir_name_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExists) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Subdir"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create a file under the subdirectory.
- FilePath file_name2_from =
- subdir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name2_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name2_from));
-
- // Copy the directory not recursively.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- FilePath subdir_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Subdir"));
-
- // Create the destination directory.
- CreateDirectory(dir_name_to);
- ASSERT_TRUE(PathExists(dir_name_to));
-
- EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
-
- // Check everything has been copied.
- EXPECT_TRUE(PathExists(dir_name_from));
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(subdir_name_from));
- EXPECT_TRUE(PathExists(file_name2_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
- EXPECT_FALSE(PathExists(subdir_name_to));
-}
-
-TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToNew) {
- // Create a file
- FilePath file_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // The destination name
- FilePath file_name_to = temp_dir_.GetPath().Append(
- FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
- ASSERT_FALSE(PathExists(file_name_to));
-
- EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
-
- // Check the has been copied
- EXPECT_TRUE(PathExists(file_name_to));
-}
-
-TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExisting) {
- // Create a file
- FilePath file_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // The destination name
- FilePath file_name_to = temp_dir_.GetPath().Append(
- FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
- CreateTextFile(file_name_to, L"Old file content");
- ASSERT_TRUE(PathExists(file_name_to));
-
- EXPECT_TRUE(CopyDirectory(file_name_from, file_name_to, true));
-
- // Check the has been copied
- EXPECT_TRUE(PathExists(file_name_to));
- EXPECT_TRUE(L"Gooooooooooooooooooooogle" == ReadTextFile(file_name_to));
-}
-
-TEST_F(FileUtilTest, CopyFileWithCopyDirectoryRecursiveToExistingDirectory) {
- // Create a file
- FilePath file_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // The destination
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Destination"));
- CreateDirectory(dir_name_to);
- ASSERT_TRUE(PathExists(dir_name_to));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
-
- EXPECT_TRUE(CopyDirectory(file_name_from, dir_name_to, true));
-
- // Check the has been copied
- EXPECT_TRUE(PathExists(file_name_to));
-}
-
-TEST_F(FileUtilTest, CopyFileFailureWithCopyDirectoryExcl) {
- // Create a file
- FilePath file_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Make a destination file.
- FilePath file_name_to = temp_dir_.GetPath().Append(
- FILE_PATH_LITERAL("Copy_Test_File_Destination.txt"));
- CreateTextFile(file_name_to, L"Old file content");
- ASSERT_TRUE(PathExists(file_name_to));
-
- // Overwriting the destination should fail.
- EXPECT_FALSE(CopyDirectoryExcl(file_name_from, file_name_to, true));
- EXPECT_EQ(L"Old file content", ReadTextFile(file_name_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryWithTrailingSeparators) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Copy the directory recursively.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
-
- // Create from path with trailing separators.
-#if defined(OS_WIN)
- FilePath from_path =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir\\\\\\"));
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- FilePath from_path =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir///"));
-#endif
-
- EXPECT_TRUE(CopyDirectory(from_path, dir_name_to, true));
-
- // Check everything has been copied.
- EXPECT_TRUE(PathExists(dir_name_from));
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
-}
-
-#if defined(OS_POSIX)
-TEST_F(FileUtilTest, CopyDirectoryWithNonRegularFiles) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_from));
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a symbolic link under the directory pointing to that file.
- FilePath symlink_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Symlink"));
- ASSERT_TRUE(CreateSymbolicLink(file_name_from, symlink_name_from));
- ASSERT_TRUE(PathExists(symlink_name_from));
-
- // Create a fifo under the directory.
- FilePath fifo_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Fifo"));
- ASSERT_EQ(0, mkfifo(fifo_name_from.value().c_str(), 0644));
- ASSERT_TRUE(PathExists(fifo_name_from));
-
- // Copy the directory.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- FilePath symlink_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Symlink"));
- FilePath fifo_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Fifo"));
-
- ASSERT_FALSE(PathExists(dir_name_to));
-
- EXPECT_TRUE(CopyDirectory(dir_name_from, dir_name_to, false));
-
- // Check that only directories and regular files are copied.
- EXPECT_TRUE(PathExists(dir_name_from));
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(symlink_name_from));
- EXPECT_TRUE(PathExists(fifo_name_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
- EXPECT_FALSE(PathExists(symlink_name_to));
- EXPECT_FALSE(PathExists(fifo_name_to));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclFileOverSymlink) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_from));
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a destination directory with a symlink of the same name.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_to));
- ASSERT_TRUE(PathExists(dir_name_to));
-
- FilePath symlink_target =
- dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
- CreateTextFile(symlink_target, L"asdf");
- ASSERT_TRUE(PathExists(symlink_target));
-
- FilePath symlink_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
- ASSERT_TRUE(PathExists(symlink_name_to));
-
- // Check that copying fails.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverSymlink) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_from));
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create a destination directory with a symlink of the same name.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_to));
- ASSERT_TRUE(PathExists(dir_name_to));
-
- FilePath symlink_target = dir_name_to.Append(FILE_PATH_LITERAL("Subsub"));
- CreateTextFile(symlink_target, L"asdf");
- ASSERT_TRUE(PathExists(symlink_target));
-
- FilePath symlink_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
- ASSERT_TRUE(PathExists(symlink_name_to));
-
- // Check that copying fails.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclFileOverDanglingSymlink) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_from));
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a destination directory with a dangling symlink of the same name.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_to));
- ASSERT_TRUE(PathExists(dir_name_to));
-
- FilePath symlink_target =
- dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
- CreateTextFile(symlink_target, L"asdf");
- ASSERT_TRUE(PathExists(symlink_target));
-
- FilePath symlink_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
- ASSERT_TRUE(PathExists(symlink_name_to));
- ASSERT_TRUE(DeleteFile(symlink_target, false));
-
- // Check that copying fails and that no file was created for the symlink's
- // referent.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
- EXPECT_FALSE(PathExists(symlink_target));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverDanglingSymlink) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_from));
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a subdirectory.
- FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub"));
- CreateDirectory(subdir_name_from);
- ASSERT_TRUE(PathExists(subdir_name_from));
-
- // Create a destination directory with a dangling symlink of the same name.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_to));
- ASSERT_TRUE(PathExists(dir_name_to));
-
- FilePath symlink_target =
- dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt"));
- CreateTextFile(symlink_target, L"asdf");
- ASSERT_TRUE(PathExists(symlink_target));
-
- FilePath symlink_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to));
- ASSERT_TRUE(PathExists(symlink_name_to));
- ASSERT_TRUE(DeleteFile(symlink_target, false));
-
- // Check that copying fails and that no directory was created for the
- // symlink's referent.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
- EXPECT_FALSE(PathExists(symlink_target));
-}
-
-TEST_F(FileUtilTest, CopyDirectoryExclFileOverFifo) {
- // Create a directory.
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_from));
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory.
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Create a destination directory with a fifo of the same name.
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_to));
- ASSERT_TRUE(PathExists(dir_name_to));
-
- FilePath fifo_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- ASSERT_EQ(0, mkfifo(fifo_name_to.value().c_str(), 0644));
- ASSERT_TRUE(PathExists(fifo_name_to));
-
- // Check that copying fails.
- EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false));
-}
-#endif // defined(OS_POSIX)
-
-TEST_F(FileUtilTest, CopyFile) {
- // Create a directory
- FilePath dir_name_from =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir"));
- ASSERT_TRUE(CreateDirectory(dir_name_from));
- ASSERT_TRUE(DirectoryExists(dir_name_from));
-
- // Create a file under the directory
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt"));
- const std::wstring file_contents(L"Gooooooooooooooooooooogle");
- CreateTextFile(file_name_from, file_contents);
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Copy the file.
- FilePath dest_file = dir_name_from.Append(FILE_PATH_LITERAL("DestFile.txt"));
- ASSERT_TRUE(CopyFile(file_name_from, dest_file));
-
- // Try to copy the file to another location using '..' in the path.
- FilePath dest_file2(dir_name_from);
- dest_file2 = dest_file2.AppendASCII("..");
- dest_file2 = dest_file2.AppendASCII("DestFile.txt");
- ASSERT_FALSE(CopyFile(file_name_from, dest_file2));
-
- FilePath dest_file2_test(dir_name_from);
- dest_file2_test = dest_file2_test.DirName();
- dest_file2_test = dest_file2_test.AppendASCII("DestFile.txt");
-
- // Check expected copy results.
- EXPECT_TRUE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(dest_file));
- EXPECT_EQ(file_contents, ReadTextFile(dest_file));
- EXPECT_FALSE(PathExists(dest_file2_test));
- EXPECT_FALSE(PathExists(dest_file2));
-
- // Change |file_name_from| contents.
- const std::wstring new_file_contents(L"Moogle");
- CreateTextFile(file_name_from, new_file_contents);
- ASSERT_TRUE(PathExists(file_name_from));
- EXPECT_EQ(new_file_contents, ReadTextFile(file_name_from));
-
- // Overwrite |dest_file|.
- ASSERT_TRUE(CopyFile(file_name_from, dest_file));
- EXPECT_TRUE(PathExists(dest_file));
- EXPECT_EQ(new_file_contents, ReadTextFile(dest_file));
-
- // Create another directory.
- FilePath dest_dir = temp_dir_.GetPath().Append(FPL("dest_dir"));
- ASSERT_TRUE(CreateDirectory(dest_dir));
- EXPECT_TRUE(DirectoryExists(dest_dir));
- EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
-
- // Make sure CopyFile() cannot overwrite a directory.
- ASSERT_FALSE(CopyFile(file_name_from, dest_dir));
- EXPECT_TRUE(DirectoryExists(dest_dir));
- EXPECT_TRUE(IsDirectoryEmpty(dest_dir));
-}
-
-// file_util winds up using autoreleased objects on the Mac, so this needs
-// to be a PlatformTest.
-typedef PlatformTest ReadOnlyFileUtilTest;
-
-TEST_F(ReadOnlyFileUtilTest, ContentsEqual) {
- FilePath data_dir;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
- data_dir = data_dir.AppendASCII("file_util");
- ASSERT_TRUE(PathExists(data_dir));
-
- FilePath original_file =
- data_dir.Append(FILE_PATH_LITERAL("original.txt"));
- FilePath same_file =
- data_dir.Append(FILE_PATH_LITERAL("same.txt"));
- FilePath same_length_file =
- data_dir.Append(FILE_PATH_LITERAL("same_length.txt"));
- FilePath different_file =
- data_dir.Append(FILE_PATH_LITERAL("different.txt"));
- FilePath different_first_file =
- data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
- FilePath different_last_file =
- data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
- FilePath empty1_file =
- data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
- FilePath empty2_file =
- data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
- FilePath shortened_file =
- data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
- FilePath binary_file =
- data_dir.Append(FILE_PATH_LITERAL("binary_file.bin"));
- FilePath binary_file_same =
- data_dir.Append(FILE_PATH_LITERAL("binary_file_same.bin"));
- FilePath binary_file_diff =
- data_dir.Append(FILE_PATH_LITERAL("binary_file_diff.bin"));
-
- EXPECT_TRUE(ContentsEqual(original_file, original_file));
- EXPECT_TRUE(ContentsEqual(original_file, same_file));
- EXPECT_FALSE(ContentsEqual(original_file, same_length_file));
- EXPECT_FALSE(ContentsEqual(original_file, different_file));
- EXPECT_FALSE(ContentsEqual(FilePath(FILE_PATH_LITERAL("bogusname")),
- FilePath(FILE_PATH_LITERAL("bogusname"))));
- EXPECT_FALSE(ContentsEqual(original_file, different_first_file));
- EXPECT_FALSE(ContentsEqual(original_file, different_last_file));
- EXPECT_TRUE(ContentsEqual(empty1_file, empty2_file));
- EXPECT_FALSE(ContentsEqual(original_file, shortened_file));
- EXPECT_FALSE(ContentsEqual(shortened_file, original_file));
- EXPECT_TRUE(ContentsEqual(binary_file, binary_file_same));
- EXPECT_FALSE(ContentsEqual(binary_file, binary_file_diff));
-}
-
-TEST_F(ReadOnlyFileUtilTest, TextContentsEqual) {
- FilePath data_dir;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
- data_dir = data_dir.AppendASCII("file_util");
- ASSERT_TRUE(PathExists(data_dir));
-
- FilePath original_file =
- data_dir.Append(FILE_PATH_LITERAL("original.txt"));
- FilePath same_file =
- data_dir.Append(FILE_PATH_LITERAL("same.txt"));
- FilePath crlf_file =
- data_dir.Append(FILE_PATH_LITERAL("crlf.txt"));
- FilePath shortened_file =
- data_dir.Append(FILE_PATH_LITERAL("shortened.txt"));
- FilePath different_file =
- data_dir.Append(FILE_PATH_LITERAL("different.txt"));
- FilePath different_first_file =
- data_dir.Append(FILE_PATH_LITERAL("different_first.txt"));
- FilePath different_last_file =
- data_dir.Append(FILE_PATH_LITERAL("different_last.txt"));
- FilePath first1_file =
- data_dir.Append(FILE_PATH_LITERAL("first1.txt"));
- FilePath first2_file =
- data_dir.Append(FILE_PATH_LITERAL("first2.txt"));
- FilePath empty1_file =
- data_dir.Append(FILE_PATH_LITERAL("empty1.txt"));
- FilePath empty2_file =
- data_dir.Append(FILE_PATH_LITERAL("empty2.txt"));
- FilePath blank_line_file =
- data_dir.Append(FILE_PATH_LITERAL("blank_line.txt"));
- FilePath blank_line_crlf_file =
- data_dir.Append(FILE_PATH_LITERAL("blank_line_crlf.txt"));
-
- EXPECT_TRUE(TextContentsEqual(original_file, same_file));
- EXPECT_TRUE(TextContentsEqual(original_file, crlf_file));
- EXPECT_FALSE(TextContentsEqual(original_file, shortened_file));
- EXPECT_FALSE(TextContentsEqual(original_file, different_file));
- EXPECT_FALSE(TextContentsEqual(original_file, different_first_file));
- EXPECT_FALSE(TextContentsEqual(original_file, different_last_file));
- EXPECT_FALSE(TextContentsEqual(first1_file, first2_file));
- EXPECT_TRUE(TextContentsEqual(empty1_file, empty2_file));
- EXPECT_FALSE(TextContentsEqual(original_file, empty1_file));
- EXPECT_TRUE(TextContentsEqual(blank_line_file, blank_line_crlf_file));
-}
-
-// We don't need equivalent functionality outside of Windows.
-#if defined(OS_WIN)
-TEST_F(FileUtilTest, CopyAndDeleteDirectoryTest) {
- // Create a directory
- FilePath dir_name_from = temp_dir_.GetPath().Append(
- FILE_PATH_LITERAL("CopyAndDelete_From_Subdir"));
- CreateDirectory(dir_name_from);
- ASSERT_TRUE(PathExists(dir_name_from));
-
- // Create a file under the directory
- FilePath file_name_from =
- dir_name_from.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
- CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle");
- ASSERT_TRUE(PathExists(file_name_from));
-
- // Move the directory by using CopyAndDeleteDirectory
- FilePath dir_name_to =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("CopyAndDelete_To_Subdir"));
- FilePath file_name_to =
- dir_name_to.Append(FILE_PATH_LITERAL("CopyAndDelete_Test_File.txt"));
-
- ASSERT_FALSE(PathExists(dir_name_to));
-
- EXPECT_TRUE(internal::CopyAndDeleteDirectory(dir_name_from,
- dir_name_to));
-
- // Check everything has been moved.
- EXPECT_FALSE(PathExists(dir_name_from));
- EXPECT_FALSE(PathExists(file_name_from));
- EXPECT_TRUE(PathExists(dir_name_to));
- EXPECT_TRUE(PathExists(file_name_to));
-}
-
-TEST_F(FileUtilTest, GetTempDirTest) {
- static const TCHAR* kTmpKey = _T("TMP");
- static const TCHAR* kTmpValues[] = {
- _T(""), _T("C:"), _T("C:\\"), _T("C:\\tmp"), _T("C:\\tmp\\")
- };
- // Save the original $TMP.
- size_t original_tmp_size;
- TCHAR* original_tmp;
- ASSERT_EQ(0, ::_tdupenv_s(&original_tmp, &original_tmp_size, kTmpKey));
- // original_tmp may be NULL.
-
- for (unsigned int i = 0; i < arraysize(kTmpValues); ++i) {
- FilePath path;
- ::_tputenv_s(kTmpKey, kTmpValues[i]);
- GetTempDir(&path);
- EXPECT_TRUE(path.IsAbsolute()) << "$TMP=" << kTmpValues[i] <<
- " result=" << path.value();
- }
-
- // Restore the original $TMP.
- if (original_tmp) {
- ::_tputenv_s(kTmpKey, original_tmp);
- free(original_tmp);
- } else {
- ::_tputenv_s(kTmpKey, _T(""));
- }
-}
-#endif // OS_WIN
-
-// Test that files opened by OpenFile are not set up for inheritance into child
-// procs.
-TEST_F(FileUtilTest, OpenFileNoInheritance) {
- FilePath file_path(temp_dir_.GetPath().Append(FPL("a_file")));
-
- for (const char* mode : {"wb", "r,ccs=UTF-8"}) {
- SCOPED_TRACE(mode);
- ASSERT_NO_FATAL_FAILURE(CreateTextFile(file_path, L"Geepers"));
- FILE* file = OpenFile(file_path, mode);
- ASSERT_NE(nullptr, file);
- {
- ScopedClosureRunner file_closer(Bind(IgnoreResult(&CloseFile), file));
- bool is_inheritable = true;
- ASSERT_NO_FATAL_FAILURE(GetIsInheritable(file, &is_inheritable));
- EXPECT_FALSE(is_inheritable);
- }
- ASSERT_TRUE(DeleteFile(file_path, false));
- }
-}
-
-TEST_F(FileUtilTest, CreateTemporaryFileTest) {
- FilePath temp_files[3];
- for (int i = 0; i < 3; i++) {
- ASSERT_TRUE(CreateTemporaryFile(&(temp_files[i])));
- EXPECT_TRUE(PathExists(temp_files[i]));
- EXPECT_FALSE(DirectoryExists(temp_files[i]));
- }
- for (int i = 0; i < 3; i++)
- EXPECT_FALSE(temp_files[i] == temp_files[(i+1)%3]);
- for (int i = 0; i < 3; i++)
- EXPECT_TRUE(DeleteFile(temp_files[i], false));
-}
-
-TEST_F(FileUtilTest, CreateAndOpenTemporaryFileTest) {
- FilePath names[3];
- FILE* fps[3];
- int i;
-
- // Create; make sure they are open and exist.
- for (i = 0; i < 3; ++i) {
- fps[i] = CreateAndOpenTemporaryFile(&(names[i]));
- ASSERT_TRUE(fps[i]);
- EXPECT_TRUE(PathExists(names[i]));
- }
-
- // Make sure all names are unique.
- for (i = 0; i < 3; ++i) {
- EXPECT_FALSE(names[i] == names[(i+1)%3]);
- }
-
- // Close and delete.
- for (i = 0; i < 3; ++i) {
- EXPECT_TRUE(CloseFile(fps[i]));
- EXPECT_TRUE(DeleteFile(names[i], false));
- }
-}
-
-#if defined(OS_FUCHSIA)
-// TODO(crbug.com/851747): Re-enable when the Fuchsia-side fix for fdopen has
-// been rolled into Chromium.
-#define MAYBE_FileToFILE DISABLED_FileToFILE
-#else
-#define MAYBE_FileToFILE FileToFILE
-#endif
-TEST_F(FileUtilTest, MAYBE_FileToFILE) {
- File file;
- FILE* stream = FileToFILE(std::move(file), "w");
- EXPECT_FALSE(stream);
-
- FilePath file_name = temp_dir_.GetPath().Append(FPL("The file.txt"));
- file = File(file_name, File::FLAG_CREATE | File::FLAG_WRITE);
- EXPECT_TRUE(file.IsValid());
-
- stream = FileToFILE(std::move(file), "w");
- EXPECT_TRUE(stream);
- EXPECT_FALSE(file.IsValid());
- EXPECT_TRUE(CloseFile(stream));
-}
-
-TEST_F(FileUtilTest, CreateNewTempDirectoryTest) {
- FilePath temp_dir;
- ASSERT_TRUE(CreateNewTempDirectory(FilePath::StringType(), &temp_dir));
- EXPECT_TRUE(PathExists(temp_dir));
- EXPECT_TRUE(DeleteFile(temp_dir, false));
-}
-
-TEST_F(FileUtilTest, CreateNewTemporaryDirInDirTest) {
- FilePath new_dir;
- ASSERT_TRUE(CreateTemporaryDirInDir(
- temp_dir_.GetPath(), FILE_PATH_LITERAL("CreateNewTemporaryDirInDirTest"),
- &new_dir));
- EXPECT_TRUE(PathExists(new_dir));
- EXPECT_TRUE(temp_dir_.GetPath().IsParent(new_dir));
- EXPECT_TRUE(DeleteFile(new_dir, false));
-}
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-TEST_F(FileUtilTest, GetShmemTempDirTest) {
- FilePath dir;
- EXPECT_TRUE(GetShmemTempDir(false, &dir));
- EXPECT_TRUE(DirectoryExists(dir));
-}
-#endif
-
-TEST_F(FileUtilTest, GetHomeDirTest) {
-#if !defined(OS_ANDROID) // Not implemented on Android.
- // We don't actually know what the home directory is supposed to be without
- // calling some OS functions which would just duplicate the implementation.
- // So here we just test that it returns something "reasonable".
- FilePath home = GetHomeDir();
- ASSERT_FALSE(home.empty());
- ASSERT_TRUE(home.IsAbsolute());
-#endif
-}
-
-TEST_F(FileUtilTest, CreateDirectoryTest) {
- FilePath test_root =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("create_directory_test"));
-#if defined(OS_WIN)
- FilePath test_path =
- test_root.Append(FILE_PATH_LITERAL("dir\\tree\\likely\\doesnt\\exist\\"));
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- FilePath test_path =
- test_root.Append(FILE_PATH_LITERAL("dir/tree/likely/doesnt/exist/"));
-#endif
-
- EXPECT_FALSE(PathExists(test_path));
- EXPECT_TRUE(CreateDirectory(test_path));
- EXPECT_TRUE(PathExists(test_path));
- // CreateDirectory returns true if the DirectoryExists returns true.
- EXPECT_TRUE(CreateDirectory(test_path));
-
- // Doesn't work to create it on top of a non-dir
- test_path = test_path.Append(FILE_PATH_LITERAL("foobar.txt"));
- EXPECT_FALSE(PathExists(test_path));
- CreateTextFile(test_path, L"test file");
- EXPECT_TRUE(PathExists(test_path));
- EXPECT_FALSE(CreateDirectory(test_path));
-
- EXPECT_TRUE(DeleteFile(test_root, true));
- EXPECT_FALSE(PathExists(test_root));
- EXPECT_FALSE(PathExists(test_path));
-
- // Verify assumptions made by the Windows implementation:
- // 1. The current directory always exists.
- // 2. The root directory always exists.
- ASSERT_TRUE(DirectoryExists(FilePath(FilePath::kCurrentDirectory)));
- FilePath top_level = test_root;
- while (top_level != top_level.DirName()) {
- top_level = top_level.DirName();
- }
- ASSERT_TRUE(DirectoryExists(top_level));
-
- // Given these assumptions hold, it should be safe to
- // test that "creating" these directories succeeds.
- EXPECT_TRUE(CreateDirectory(
- FilePath(FilePath::kCurrentDirectory)));
- EXPECT_TRUE(CreateDirectory(top_level));
-
-#if defined(OS_WIN)
- FilePath invalid_drive(FILE_PATH_LITERAL("o:\\"));
- FilePath invalid_path =
- invalid_drive.Append(FILE_PATH_LITERAL("some\\inaccessible\\dir"));
- if (!PathExists(invalid_drive)) {
- EXPECT_FALSE(CreateDirectory(invalid_path));
- }
-#endif
-}
-
-TEST_F(FileUtilTest, DetectDirectoryTest) {
- // Check a directory
- FilePath test_root =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("detect_directory_test"));
- EXPECT_FALSE(PathExists(test_root));
- EXPECT_TRUE(CreateDirectory(test_root));
- EXPECT_TRUE(PathExists(test_root));
- EXPECT_TRUE(DirectoryExists(test_root));
- // Check a file
- FilePath test_path =
- test_root.Append(FILE_PATH_LITERAL("foobar.txt"));
- EXPECT_FALSE(PathExists(test_path));
- CreateTextFile(test_path, L"test file");
- EXPECT_TRUE(PathExists(test_path));
- EXPECT_FALSE(DirectoryExists(test_path));
- EXPECT_TRUE(DeleteFile(test_path, false));
-
- EXPECT_TRUE(DeleteFile(test_root, true));
-}
-
-TEST_F(FileUtilTest, FileEnumeratorTest) {
- // Test an empty directory.
- FileEnumerator f0(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
- EXPECT_EQ(FPL(""), f0.Next().value());
- EXPECT_EQ(FPL(""), f0.Next().value());
-
- // Test an empty directory, non-recursively, including "..".
- FileEnumerator f0_dotdot(
- temp_dir_.GetPath(), false,
- FILES_AND_DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT);
- EXPECT_EQ(temp_dir_.GetPath().Append(FPL("..")).value(),
- f0_dotdot.Next().value());
- EXPECT_EQ(FPL(""), f0_dotdot.Next().value());
-
- // create the directories
- FilePath dir1 = temp_dir_.GetPath().Append(FPL("dir1"));
- EXPECT_TRUE(CreateDirectory(dir1));
- FilePath dir2 = temp_dir_.GetPath().Append(FPL("dir2"));
- EXPECT_TRUE(CreateDirectory(dir2));
- FilePath dir2inner = dir2.Append(FPL("inner"));
- EXPECT_TRUE(CreateDirectory(dir2inner));
-
- // create the files
- FilePath dir2file = dir2.Append(FPL("dir2file.txt"));
- CreateTextFile(dir2file, std::wstring());
- FilePath dir2innerfile = dir2inner.Append(FPL("innerfile.txt"));
- CreateTextFile(dir2innerfile, std::wstring());
- FilePath file1 = temp_dir_.GetPath().Append(FPL("file1.txt"));
- CreateTextFile(file1, std::wstring());
- FilePath file2_rel = dir2.Append(FilePath::kParentDirectory)
- .Append(FPL("file2.txt"));
- CreateTextFile(file2_rel, std::wstring());
- FilePath file2_abs = temp_dir_.GetPath().Append(FPL("file2.txt"));
-
- // Only enumerate files.
- FileEnumerator f1(temp_dir_.GetPath(), true, FileEnumerator::FILES);
- FindResultCollector c1(&f1);
- EXPECT_TRUE(c1.HasFile(file1));
- EXPECT_TRUE(c1.HasFile(file2_abs));
- EXPECT_TRUE(c1.HasFile(dir2file));
- EXPECT_TRUE(c1.HasFile(dir2innerfile));
- EXPECT_EQ(4, c1.size());
-
- // Only enumerate directories.
- FileEnumerator f2(temp_dir_.GetPath(), true, FileEnumerator::DIRECTORIES);
- FindResultCollector c2(&f2);
- EXPECT_TRUE(c2.HasFile(dir1));
- EXPECT_TRUE(c2.HasFile(dir2));
- EXPECT_TRUE(c2.HasFile(dir2inner));
- EXPECT_EQ(3, c2.size());
-
- // Only enumerate directories non-recursively.
- FileEnumerator f2_non_recursive(temp_dir_.GetPath(), false,
- FileEnumerator::DIRECTORIES);
- FindResultCollector c2_non_recursive(&f2_non_recursive);
- EXPECT_TRUE(c2_non_recursive.HasFile(dir1));
- EXPECT_TRUE(c2_non_recursive.HasFile(dir2));
- EXPECT_EQ(2, c2_non_recursive.size());
-
- // Only enumerate directories, non-recursively, including "..".
- FileEnumerator f2_dotdot(
- temp_dir_.GetPath(), false,
- FileEnumerator::DIRECTORIES | FileEnumerator::INCLUDE_DOT_DOT);
- FindResultCollector c2_dotdot(&f2_dotdot);
- EXPECT_TRUE(c2_dotdot.HasFile(dir1));
- EXPECT_TRUE(c2_dotdot.HasFile(dir2));
- EXPECT_TRUE(c2_dotdot.HasFile(temp_dir_.GetPath().Append(FPL(".."))));
- EXPECT_EQ(3, c2_dotdot.size());
-
- // Enumerate files and directories.
- FileEnumerator f3(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
- FindResultCollector c3(&f3);
- EXPECT_TRUE(c3.HasFile(dir1));
- EXPECT_TRUE(c3.HasFile(dir2));
- EXPECT_TRUE(c3.HasFile(file1));
- EXPECT_TRUE(c3.HasFile(file2_abs));
- EXPECT_TRUE(c3.HasFile(dir2file));
- EXPECT_TRUE(c3.HasFile(dir2inner));
- EXPECT_TRUE(c3.HasFile(dir2innerfile));
- EXPECT_EQ(7, c3.size());
-
- // Non-recursive operation.
- FileEnumerator f4(temp_dir_.GetPath(), false, FILES_AND_DIRECTORIES);
- FindResultCollector c4(&f4);
- EXPECT_TRUE(c4.HasFile(dir2));
- EXPECT_TRUE(c4.HasFile(dir2));
- EXPECT_TRUE(c4.HasFile(file1));
- EXPECT_TRUE(c4.HasFile(file2_abs));
- EXPECT_EQ(4, c4.size());
-
- // Enumerate with a pattern.
- FileEnumerator f5(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES,
- FPL("dir*"));
- FindResultCollector c5(&f5);
- EXPECT_TRUE(c5.HasFile(dir1));
- EXPECT_TRUE(c5.HasFile(dir2));
- EXPECT_TRUE(c5.HasFile(dir2file));
- EXPECT_TRUE(c5.HasFile(dir2inner));
- EXPECT_TRUE(c5.HasFile(dir2innerfile));
- EXPECT_EQ(5, c5.size());
-
-#if defined(OS_WIN)
- {
- // Make dir1 point to dir2.
- ReparsePoint reparse_point(dir1, dir2);
- EXPECT_TRUE(reparse_point.IsValid());
-
- // There can be a delay for the enumeration code to see the change on
- // the file system so skip this test for XP.
- // Enumerate the reparse point.
- FileEnumerator f6(dir1, true, FILES_AND_DIRECTORIES);
- FindResultCollector c6(&f6);
- FilePath inner2 = dir1.Append(FPL("inner"));
- EXPECT_TRUE(c6.HasFile(inner2));
- EXPECT_TRUE(c6.HasFile(inner2.Append(FPL("innerfile.txt"))));
- EXPECT_TRUE(c6.HasFile(dir1.Append(FPL("dir2file.txt"))));
- EXPECT_EQ(3, c6.size());
-
- // No changes for non recursive operation.
- FileEnumerator f7(temp_dir_.GetPath(), false, FILES_AND_DIRECTORIES);
- FindResultCollector c7(&f7);
- EXPECT_TRUE(c7.HasFile(dir2));
- EXPECT_TRUE(c7.HasFile(dir2));
- EXPECT_TRUE(c7.HasFile(file1));
- EXPECT_TRUE(c7.HasFile(file2_abs));
- EXPECT_EQ(4, c7.size());
-
- // Should not enumerate inside dir1 when using recursion.
- FileEnumerator f8(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
- FindResultCollector c8(&f8);
- EXPECT_TRUE(c8.HasFile(dir1));
- EXPECT_TRUE(c8.HasFile(dir2));
- EXPECT_TRUE(c8.HasFile(file1));
- EXPECT_TRUE(c8.HasFile(file2_abs));
- EXPECT_TRUE(c8.HasFile(dir2file));
- EXPECT_TRUE(c8.HasFile(dir2inner));
- EXPECT_TRUE(c8.HasFile(dir2innerfile));
- EXPECT_EQ(7, c8.size());
- }
-#endif
-
- // Make sure the destructor closes the find handle while in the middle of a
- // query to allow TearDown to delete the directory.
- FileEnumerator f9(temp_dir_.GetPath(), true, FILES_AND_DIRECTORIES);
- EXPECT_FALSE(f9.Next().value().empty()); // Should have found something
- // (we don't care what).
-}
-
-TEST_F(FileUtilTest, AppendToFile) {
- FilePath data_dir =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("FilePathTest"));
-
- // Create a fresh, empty copy of this directory.
- if (PathExists(data_dir)) {
- ASSERT_TRUE(DeleteFile(data_dir, true));
- }
- ASSERT_TRUE(CreateDirectory(data_dir));
-
- // Create a fresh, empty copy of this directory.
- if (PathExists(data_dir)) {
- ASSERT_TRUE(DeleteFile(data_dir, true));
- }
- ASSERT_TRUE(CreateDirectory(data_dir));
- FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
-
- std::string data("hello");
- EXPECT_FALSE(AppendToFile(foobar, data.c_str(), data.size()));
- EXPECT_EQ(static_cast<int>(data.length()),
- WriteFile(foobar, data.c_str(), data.length()));
- EXPECT_TRUE(AppendToFile(foobar, data.c_str(), data.size()));
-
- const std::wstring read_content = ReadTextFile(foobar);
- EXPECT_EQ(L"hellohello", read_content);
-}
-
-TEST_F(FileUtilTest, ReadFile) {
- // Create a test file to be read.
- const std::string kTestData("The quick brown fox jumps over the lazy dog.");
- FilePath file_path =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileTest"));
-
- ASSERT_EQ(static_cast<int>(kTestData.size()),
- WriteFile(file_path, kTestData.data(), kTestData.size()));
-
- // Make buffers with various size.
- std::vector<char> small_buffer(kTestData.size() / 2);
- std::vector<char> exact_buffer(kTestData.size());
- std::vector<char> large_buffer(kTestData.size() * 2);
-
- // Read the file with smaller buffer.
- int bytes_read_small = ReadFile(
- file_path, &small_buffer[0], static_cast<int>(small_buffer.size()));
- EXPECT_EQ(static_cast<int>(small_buffer.size()), bytes_read_small);
- EXPECT_EQ(
- std::string(kTestData.begin(), kTestData.begin() + small_buffer.size()),
- std::string(small_buffer.begin(), small_buffer.end()));
-
- // Read the file with buffer which have exactly same size.
- int bytes_read_exact = ReadFile(
- file_path, &exact_buffer[0], static_cast<int>(exact_buffer.size()));
- EXPECT_EQ(static_cast<int>(kTestData.size()), bytes_read_exact);
- EXPECT_EQ(kTestData, std::string(exact_buffer.begin(), exact_buffer.end()));
-
- // Read the file with larger buffer.
- int bytes_read_large = ReadFile(
- file_path, &large_buffer[0], static_cast<int>(large_buffer.size()));
- EXPECT_EQ(static_cast<int>(kTestData.size()), bytes_read_large);
- EXPECT_EQ(kTestData, std::string(large_buffer.begin(),
- large_buffer.begin() + kTestData.size()));
-
- // Make sure the return value is -1 if the file doesn't exist.
- FilePath file_path_not_exist =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileNotExistTest"));
- EXPECT_EQ(-1,
- ReadFile(file_path_not_exist,
- &exact_buffer[0],
- static_cast<int>(exact_buffer.size())));
-}
-
-TEST_F(FileUtilTest, ReadFileToString) {
- const char kTestData[] = "0123";
- std::string data;
-
- FilePath file_path =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
- FilePath file_path_dangerous =
- temp_dir_.GetPath()
- .Append(FILE_PATH_LITERAL(".."))
- .Append(temp_dir_.GetPath().BaseName())
- .Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
-
- // Create test file.
- ASSERT_EQ(static_cast<int>(strlen(kTestData)),
- WriteFile(file_path, kTestData, strlen(kTestData)));
-
- EXPECT_TRUE(ReadFileToString(file_path, &data));
- EXPECT_EQ(kTestData, data);
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
- EXPECT_EQ(0u, data.length());
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
- EXPECT_EQ("01", data);
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 3));
- EXPECT_EQ("012", data);
-
- data = "temp";
- EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, &data, 4));
- EXPECT_EQ("0123", data);
-
- data = "temp";
- EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, &data, 6));
- EXPECT_EQ("0123", data);
-
- EXPECT_TRUE(ReadFileToStringWithMaxSize(file_path, nullptr, 6));
-
- EXPECT_TRUE(ReadFileToString(file_path, nullptr));
-
- data = "temp";
- EXPECT_FALSE(ReadFileToString(file_path_dangerous, &data));
- EXPECT_EQ(0u, data.length());
-
- // Delete test file.
- EXPECT_TRUE(DeleteFile(file_path, false));
-
- data = "temp";
- EXPECT_FALSE(ReadFileToString(file_path, &data));
- EXPECT_EQ(0u, data.length());
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 6));
- EXPECT_EQ(0u, data.length());
-}
-
-#if !defined(OS_WIN)
-TEST_F(FileUtilTest, ReadFileToStringWithUnknownFileSize) {
- FilePath file_path("/dev/zero");
- std::string data = "temp";
-
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
- EXPECT_EQ(0u, data.length());
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
- EXPECT_EQ(std::string(2, '\0'), data);
-
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 6));
-
- // Read more than buffer size.
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, kLargeFileSize));
- EXPECT_EQ(kLargeFileSize, data.length());
- EXPECT_EQ(std::string(kLargeFileSize, '\0'), data);
-
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, kLargeFileSize));
-}
-#endif // !defined(OS_WIN)
-
-#if !defined(OS_WIN) && !defined(OS_NACL) && !defined(OS_FUCHSIA) && \
- !defined(OS_IOS)
-#define ChildMain WriteToPipeChildMain
-#define ChildMainString "WriteToPipeChildMain"
-
-MULTIPROCESS_TEST_MAIN(ChildMain) {
- const char kTestData[] = "0123";
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
-
- int fd = open(pipe_path.value().c_str(), O_WRONLY);
- CHECK_NE(-1, fd);
- size_t written = 0;
- while (written < strlen(kTestData)) {
- ssize_t res = write(fd, kTestData + written, strlen(kTestData) - written);
- if (res == -1)
- break;
- written += res;
- }
- CHECK_EQ(strlen(kTestData), written);
- CHECK_EQ(0, close(fd));
- return 0;
-}
-
-#define MoreThanBufferSizeChildMain WriteToPipeMoreThanBufferSizeChildMain
-#define MoreThanBufferSizeChildMainString \
- "WriteToPipeMoreThanBufferSizeChildMain"
-
-MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) {
- std::string data(kLargeFileSize, 'c');
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
-
- int fd = open(pipe_path.value().c_str(), O_WRONLY);
- CHECK_NE(-1, fd);
-
- size_t written = 0;
- while (written < data.size()) {
- ssize_t res = write(fd, data.c_str() + written, data.size() - written);
- if (res == -1) {
- // We are unable to write because reading process has already read
- // requested number of bytes and closed pipe.
- break;
- }
- written += res;
- }
- CHECK_EQ(0, close(fd));
- return 0;
-}
-
-TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
- FilePath pipe_path =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("test_pipe"));
- ASSERT_EQ(0, mkfifo(pipe_path.value().c_str(), 0600));
-
- base::CommandLine child_command_line(
- base::GetMultiProcessTestChildBaseCommandLine());
- child_command_line.AppendSwitchPath("pipe-path", pipe_path);
-
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- ChildMainString, child_command_line, base::LaunchOptions());
- ASSERT_TRUE(child_process.IsValid());
-
- std::string data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 2));
- EXPECT_EQ("01", data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- ChildMainString, child_command_line, base::LaunchOptions());
- ASSERT_TRUE(child_process.IsValid());
-
- std::string data = "temp";
- EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
- EXPECT_EQ("0123", data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line,
- base::LaunchOptions());
- ASSERT_TRUE(child_process.IsValid());
-
- std::string data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
- EXPECT_EQ("cccccc", data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line,
- base::LaunchOptions());
- ASSERT_TRUE(child_process.IsValid());
-
- std::string data = "temp";
- EXPECT_FALSE(
- ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize - 1));
- EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line,
- base::LaunchOptions());
- ASSERT_TRUE(child_process.IsValid());
-
- std::string data = "temp";
- EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize));
- EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line,
- base::LaunchOptions());
- ASSERT_TRUE(child_process.IsValid());
-
- std::string data = "temp";
- EXPECT_TRUE(
- ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize * 5));
- EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
-
- ASSERT_EQ(0, unlink(pipe_path.value().c_str()));
-}
-#endif // !defined(OS_WIN) && !defined(OS_NACL) && !defined(OS_FUCHSIA) &&
- // !defined(OS_IOS)
-
-#if defined(OS_WIN)
-#define ChildMain WriteToPipeChildMain
-#define ChildMainString "WriteToPipeChildMain"
-
-MULTIPROCESS_TEST_MAIN(ChildMain) {
- const char kTestData[] = "0123";
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
- std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
- EXPECT_FALSE(switch_string.empty());
- unsigned int switch_uint = 0;
- EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
- win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
-
- HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
- PIPE_WAIT, 1, 0, 0, 0, NULL);
- EXPECT_NE(ph, INVALID_HANDLE_VALUE);
- EXPECT_TRUE(SetEvent(sync_event.Get()));
- EXPECT_TRUE(ConnectNamedPipe(ph, NULL));
-
- DWORD written;
- EXPECT_TRUE(::WriteFile(ph, kTestData, strlen(kTestData), &written, NULL));
- EXPECT_EQ(strlen(kTestData), written);
- CloseHandle(ph);
- return 0;
-}
-
-#define MoreThanBufferSizeChildMain WriteToPipeMoreThanBufferSizeChildMain
-#define MoreThanBufferSizeChildMainString \
- "WriteToPipeMoreThanBufferSizeChildMain"
-
-MULTIPROCESS_TEST_MAIN(MoreThanBufferSizeChildMain) {
- std::string data(kLargeFileSize, 'c');
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- const FilePath pipe_path = command_line->GetSwitchValuePath("pipe-path");
- std::string switch_string = command_line->GetSwitchValueASCII("sync_event");
- EXPECT_FALSE(switch_string.empty());
- unsigned int switch_uint = 0;
- EXPECT_TRUE(StringToUint(switch_string, &switch_uint));
- win::ScopedHandle sync_event(win::Uint32ToHandle(switch_uint));
-
- HANDLE ph = CreateNamedPipe(pipe_path.value().c_str(), PIPE_ACCESS_OUTBOUND,
- PIPE_WAIT, 1, data.size(), data.size(), 0, NULL);
- EXPECT_NE(ph, INVALID_HANDLE_VALUE);
- EXPECT_TRUE(SetEvent(sync_event.Get()));
- EXPECT_TRUE(ConnectNamedPipe(ph, NULL));
-
- DWORD written;
- EXPECT_TRUE(::WriteFile(ph, data.c_str(), data.size(), &written, NULL));
- EXPECT_EQ(data.size(), written);
- CloseHandle(ph);
- return 0;
-}
-
-TEST_F(FileUtilTest, ReadFileToStringWithNamedPipe) {
- FilePath pipe_path(FILE_PATH_LITERAL("\\\\.\\pipe\\test_pipe"));
- win::ScopedHandle sync_event(CreateEvent(0, false, false, nullptr));
-
- base::CommandLine child_command_line(
- base::GetMultiProcessTestChildBaseCommandLine());
- child_command_line.AppendSwitchPath("pipe-path", pipe_path);
- child_command_line.AppendSwitchASCII(
- "sync_event", UintToString(win::HandleToUint32(sync_event.Get())));
-
- base::LaunchOptions options;
- options.handles_to_inherit.push_back(sync_event.Get());
-
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- ChildMainString, child_command_line, options);
- ASSERT_TRUE(child_process.IsValid());
- // Wait for pipe creation in child process.
- EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
-
- std::string data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 2));
- EXPECT_EQ("01", data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- ChildMainString, child_command_line, options);
- ASSERT_TRUE(child_process.IsValid());
- // Wait for pipe creation in child process.
- EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
-
- std::string data = "temp";
- EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
- EXPECT_EQ("0123", data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line, options);
- ASSERT_TRUE(child_process.IsValid());
- // Wait for pipe creation in child process.
- EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
-
- std::string data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(pipe_path, &data, 6));
- EXPECT_EQ("cccccc", data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line, options);
- ASSERT_TRUE(child_process.IsValid());
- // Wait for pipe creation in child process.
- EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
-
- std::string data = "temp";
- EXPECT_FALSE(
- ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize - 1));
- EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line, options);
- ASSERT_TRUE(child_process.IsValid());
- // Wait for pipe creation in child process.
- EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
-
- std::string data = "temp";
- EXPECT_TRUE(ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize));
- EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
- {
- base::Process child_process = base::SpawnMultiProcessTestChild(
- MoreThanBufferSizeChildMainString, child_command_line, options);
- ASSERT_TRUE(child_process.IsValid());
- // Wait for pipe creation in child process.
- EXPECT_EQ(WAIT_OBJECT_0, WaitForSingleObject(sync_event.Get(), INFINITE));
-
- std::string data = "temp";
- EXPECT_TRUE(
- ReadFileToStringWithMaxSize(pipe_path, &data, kLargeFileSize * 5));
- EXPECT_EQ(std::string(kLargeFileSize, 'c'), data);
-
- int rv = -1;
- ASSERT_TRUE(WaitForMultiprocessTestChildExit(
- child_process, TestTimeouts::action_timeout(), &rv));
- ASSERT_EQ(0, rv);
- }
-}
-#endif // defined(OS_WIN)
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-TEST_F(FileUtilTest, ReadFileToStringWithProcFileSystem) {
- FilePath file_path("/proc/cpuinfo");
- std::string data = "temp";
-
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 0));
- EXPECT_EQ(0u, data.length());
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 2));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("pr", data));
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 4));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("proc", data));
-
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 4));
-}
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
-
-TEST_F(FileUtilTest, ReadFileToStringWithLargeFile) {
- std::string data(kLargeFileSize, 'c');
-
- FilePath file_path =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
-
- // Create test file.
- ASSERT_EQ(static_cast<int>(kLargeFileSize),
- WriteFile(file_path, data.c_str(), kLargeFileSize));
-
- std::string actual_data = "temp";
- EXPECT_TRUE(ReadFileToString(file_path, &actual_data));
- EXPECT_EQ(data, actual_data);
-
- actual_data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &actual_data, 0));
- EXPECT_EQ(0u, actual_data.length());
-
- // Read more than buffer size.
- actual_data = "temp";
- EXPECT_FALSE(
- ReadFileToStringWithMaxSize(file_path, &actual_data, kLargeFileSize - 1));
- EXPECT_EQ(std::string(kLargeFileSize - 1, 'c'), actual_data);
-}
-
-TEST_F(FileUtilTest, TouchFile) {
- FilePath data_dir =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("FilePathTest"));
-
- // Create a fresh, empty copy of this directory.
- if (PathExists(data_dir)) {
- ASSERT_TRUE(DeleteFile(data_dir, true));
- }
- ASSERT_TRUE(CreateDirectory(data_dir));
-
- FilePath foobar(data_dir.Append(FILE_PATH_LITERAL("foobar.txt")));
- std::string data("hello");
- ASSERT_EQ(static_cast<int>(data.length()),
- WriteFile(foobar, data.c_str(), data.length()));
-
- Time access_time;
- // This timestamp is divisible by one day (in local timezone),
- // to make it work on FAT too.
- ASSERT_TRUE(Time::FromString("Wed, 16 Nov 1994, 00:00:00",
- &access_time));
-
- Time modification_time;
- // Note that this timestamp is divisible by two (seconds) - FAT stores
- // modification times with 2s resolution.
- ASSERT_TRUE(Time::FromString("Tue, 15 Nov 1994, 12:45:26 GMT",
- &modification_time));
-
- ASSERT_TRUE(TouchFile(foobar, access_time, modification_time));
- File::Info file_info;
- ASSERT_TRUE(GetFileInfo(foobar, &file_info));
-#if !defined(OS_FUCHSIA)
- // Access time is not supported on Fuchsia, see https://crbug.com/735233.
- EXPECT_EQ(access_time.ToInternalValue(),
- file_info.last_accessed.ToInternalValue());
-#endif
- EXPECT_EQ(modification_time.ToInternalValue(),
- file_info.last_modified.ToInternalValue());
-}
-
-TEST_F(FileUtilTest, IsDirectoryEmpty) {
- FilePath empty_dir =
- temp_dir_.GetPath().Append(FILE_PATH_LITERAL("EmptyDir"));
-
- ASSERT_FALSE(PathExists(empty_dir));
-
- ASSERT_TRUE(CreateDirectory(empty_dir));
-
- EXPECT_TRUE(IsDirectoryEmpty(empty_dir));
-
- FilePath foo(empty_dir.Append(FILE_PATH_LITERAL("foo.txt")));
- std::string bar("baz");
- ASSERT_EQ(static_cast<int>(bar.length()),
- WriteFile(foo, bar.c_str(), bar.length()));
-
- EXPECT_FALSE(IsDirectoryEmpty(empty_dir));
-}
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-TEST_F(FileUtilTest, SetNonBlocking) {
- const int kInvalidFd = 99999;
- EXPECT_FALSE(SetNonBlocking(kInvalidFd));
-
- base::FilePath path;
- ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path));
- path = path.Append(FPL("file_util")).Append(FPL("original.txt"));
- ScopedFD fd(open(path.value().c_str(), O_RDONLY));
- ASSERT_GE(fd.get(), 0);
- EXPECT_TRUE(SetNonBlocking(fd.get()));
-}
-
-TEST_F(FileUtilTest, SetCloseOnExec) {
- const int kInvalidFd = 99999;
- EXPECT_FALSE(SetCloseOnExec(kInvalidFd));
-
- base::FilePath path;
- ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path));
- path = path.Append(FPL("file_util")).Append(FPL("original.txt"));
- ScopedFD fd(open(path.value().c_str(), O_RDONLY));
- ASSERT_GE(fd.get(), 0);
- EXPECT_TRUE(SetCloseOnExec(fd.get()));
-}
-
-#endif
-
-#if defined(OS_POSIX)
-
-// Testing VerifyPathControlledByAdmin() is hard, because there is no
-// way a test can make a file owned by root, or change file paths
-// at the root of the file system. VerifyPathControlledByAdmin()
-// is implemented as a call to VerifyPathControlledByUser, which gives
-// us the ability to test with paths under the test's temp directory,
-// using a user id we control.
-// Pull tests of VerifyPathControlledByUserTest() into a separate test class
-// with a common SetUp() method.
-class VerifyPathControlledByUserTest : public FileUtilTest {
- protected:
- void SetUp() override {
- FileUtilTest::SetUp();
-
- // Create a basic structure used by each test.
- // base_dir_
- // |-> sub_dir_
- // |-> text_file_
-
- base_dir_ = temp_dir_.GetPath().AppendASCII("base_dir");
- ASSERT_TRUE(CreateDirectory(base_dir_));
-
- sub_dir_ = base_dir_.AppendASCII("sub_dir");
- ASSERT_TRUE(CreateDirectory(sub_dir_));
-
- text_file_ = sub_dir_.AppendASCII("file.txt");
- CreateTextFile(text_file_, L"This text file has some text in it.");
-
- // Get the user and group files are created with from |base_dir_|.
- struct stat stat_buf;
- ASSERT_EQ(0, stat(base_dir_.value().c_str(), &stat_buf));
- uid_ = stat_buf.st_uid;
- ok_gids_.insert(stat_buf.st_gid);
- bad_gids_.insert(stat_buf.st_gid + 1);
-
- ASSERT_EQ(uid_, getuid()); // This process should be the owner.
-
- // To ensure that umask settings do not cause the initial state
- // of permissions to be different from what we expect, explicitly
- // set permissions on the directories we create.
- // Make all files and directories non-world-writable.
-
- // Users and group can read, write, traverse
- int enabled_permissions =
- FILE_PERMISSION_USER_MASK | FILE_PERMISSION_GROUP_MASK;
- // Other users can't read, write, traverse
- int disabled_permissions = FILE_PERMISSION_OTHERS_MASK;
-
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(
- base_dir_, enabled_permissions, disabled_permissions));
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(
- sub_dir_, enabled_permissions, disabled_permissions));
- }
-
- FilePath base_dir_;
- FilePath sub_dir_;
- FilePath text_file_;
- uid_t uid_;
-
- std::set<gid_t> ok_gids_;
- std::set<gid_t> bad_gids_;
-};
-
-TEST_F(VerifyPathControlledByUserTest, BadPaths) {
- // File does not exist.
- FilePath does_not_exist = base_dir_.AppendASCII("does")
- .AppendASCII("not")
- .AppendASCII("exist");
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, does_not_exist, uid_, ok_gids_));
-
- // |base| not a subpath of |path|.
- EXPECT_FALSE(VerifyPathControlledByUser(sub_dir_, base_dir_, uid_, ok_gids_));
-
- // An empty base path will fail to be a prefix for any path.
- FilePath empty;
- EXPECT_FALSE(VerifyPathControlledByUser(empty, base_dir_, uid_, ok_gids_));
-
- // Finding that a bad call fails proves nothing unless a good call succeeds.
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
-}
-
-TEST_F(VerifyPathControlledByUserTest, Symlinks) {
- // Symlinks in the path should cause failure.
-
- // Symlink to the file at the end of the path.
- FilePath file_link = base_dir_.AppendASCII("file_link");
- ASSERT_TRUE(CreateSymbolicLink(text_file_, file_link))
- << "Failed to create symlink.";
-
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, file_link, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(file_link, file_link, uid_, ok_gids_));
-
- // Symlink from one directory to another within the path.
- FilePath link_to_sub_dir = base_dir_.AppendASCII("link_to_sub_dir");
- ASSERT_TRUE(CreateSymbolicLink(sub_dir_, link_to_sub_dir))
- << "Failed to create symlink.";
-
- FilePath file_path_with_link = link_to_sub_dir.AppendASCII("file.txt");
- ASSERT_TRUE(PathExists(file_path_with_link));
-
- EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, file_path_with_link, uid_,
- ok_gids_));
-
- EXPECT_FALSE(VerifyPathControlledByUser(link_to_sub_dir, file_path_with_link,
- uid_, ok_gids_));
-
- // Symlinks in parents of base path are allowed.
- EXPECT_TRUE(VerifyPathControlledByUser(file_path_with_link,
- file_path_with_link, uid_, ok_gids_));
-}
-
-TEST_F(VerifyPathControlledByUserTest, OwnershipChecks) {
- // Get a uid that is not the uid of files we create.
- uid_t bad_uid = uid_ + 1;
-
- // Make all files and directories non-world-writable.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
-
- // We control these paths.
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- // Another user does not control these paths.
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, sub_dir_, bad_uid, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, bad_uid, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(sub_dir_, text_file_, bad_uid, ok_gids_));
-
- // Another group does not control the paths.
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
-}
-
-TEST_F(VerifyPathControlledByUserTest, GroupWriteTest) {
- // Make all files and directories writable only by their owner.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH|S_IWGRP));
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH|S_IWGRP));
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(text_file_, 0u, S_IWOTH|S_IWGRP));
-
- // Any group is okay because the path is not group-writable.
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
- EXPECT_TRUE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
-
- // No group is okay, because we don't check the group
- // if no group can write.
- std::set<gid_t> no_gids; // Empty set of gids.
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, no_gids));
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, text_file_, uid_, no_gids));
- EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, no_gids));
-
- // Make all files and directories writable by their group.
- ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(base_dir_, S_IWGRP, 0u));
- ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(sub_dir_, S_IWGRP, 0u));
- ASSERT_NO_FATAL_FAILURE(ChangePosixFilePermissions(text_file_, S_IWGRP, 0u));
-
- // Now |ok_gids_| works, but |bad_gids_| fails.
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, bad_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, bad_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, bad_gids_));
-
- // Because any group in the group set is allowed,
- // the union of good and bad gids passes.
-
- std::set<gid_t> multiple_gids;
- std::set_union(
- ok_gids_.begin(), ok_gids_.end(),
- bad_gids_.begin(), bad_gids_.end(),
- std::inserter(multiple_gids, multiple_gids.begin()));
-
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, multiple_gids));
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, multiple_gids));
- EXPECT_TRUE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, multiple_gids));
-}
-
-TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
- // Make all files and directories non-world-writable.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
-
- // Initialy, we control all parts of the path.
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- // Make base_dir_ world-writable.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(base_dir_, S_IWOTH, 0u));
- EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- // Make sub_dir_ world writable.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(sub_dir_, S_IWOTH, 0u));
- EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- // Make text_file_ world writable.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(text_file_, S_IWOTH, 0u));
- EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- // Make sub_dir_ non-world writable.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(sub_dir_, 0u, S_IWOTH));
- EXPECT_FALSE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- // Make base_dir_ non-world-writable.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(base_dir_, 0u, S_IWOTH));
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_FALSE(
- VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-
- // Back to the initial state: Nothing is writable, so every path
- // should pass.
- ASSERT_NO_FATAL_FAILURE(
- ChangePosixFilePermissions(text_file_, 0u, S_IWOTH));
- EXPECT_TRUE(VerifyPathControlledByUser(base_dir_, sub_dir_, uid_, ok_gids_));
- EXPECT_TRUE(
- VerifyPathControlledByUser(base_dir_, text_file_, uid_, ok_gids_));
- EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
-}
-
-#endif // defined(OS_POSIX)
-
-#if defined(OS_ANDROID)
-TEST_F(FileUtilTest, ValidContentUriTest) {
- // Get the test image path.
- FilePath data_dir;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &data_dir));
- data_dir = data_dir.AppendASCII("file_util");
- ASSERT_TRUE(PathExists(data_dir));
- FilePath image_file = data_dir.Append(FILE_PATH_LITERAL("red.png"));
- int64_t image_size;
- GetFileSize(image_file, &image_size);
- ASSERT_GT(image_size, 0);
-
- // Insert the image into MediaStore. MediaStore will do some conversions, and
- // return the content URI.
- FilePath path = InsertImageIntoMediaStore(image_file);
- EXPECT_TRUE(path.IsContentUri());
- EXPECT_TRUE(PathExists(path));
- // The file size may not equal to the input image as MediaStore may convert
- // the image.
- int64_t content_uri_size;
- GetFileSize(path, &content_uri_size);
- EXPECT_EQ(image_size, content_uri_size);
-
- // We should be able to read the file.
- File file = OpenContentUriForRead(path);
- EXPECT_TRUE(file.IsValid());
- auto buffer = std::make_unique<char[]>(image_size);
- EXPECT_TRUE(file.ReadAtCurrentPos(buffer.get(), image_size));
-}
-
-TEST_F(FileUtilTest, NonExistentContentUriTest) {
- FilePath path("content://foo.bar");
- EXPECT_TRUE(path.IsContentUri());
- EXPECT_FALSE(PathExists(path));
- // Size should be smaller than 0.
- int64_t size;
- EXPECT_FALSE(GetFileSize(path, &size));
-
- // We should not be able to read the file.
- File file = OpenContentUriForRead(path);
- EXPECT_FALSE(file.IsValid());
-}
-#endif
-
-// Test that temp files obtained racily are all unique (no interference between
-// threads). Mimics file operations in DoLaunchChildTestProcess() to rule out
-// thread-safety issues @ https://crbug.com/826408#c17.
-#if defined(OS_FUCHSIA)
-// TODO(crbug.com/844416): Too slow to run on infra due to QEMU overloads.
-#define MAYBE_MultiThreadedTempFiles DISABLED_MultiThreadedTempFiles
-#else
-#define MAYBE_MultiThreadedTempFiles MultiThreadedTempFiles
-#endif
-TEST(FileUtilMultiThreadedTest, MAYBE_MultiThreadedTempFiles) {
- constexpr int kNumThreads = 64;
- constexpr int kNumWritesPerThread = 32;
-
- std::unique_ptr<Thread> threads[kNumThreads];
- for (auto& thread : threads) {
- thread = std::make_unique<Thread>("test worker");
- thread->Start();
- }
-
- // Wait until all threads are started for max parallelism.
- for (auto& thread : threads)
- thread->WaitUntilThreadStarted();
-
- const RepeatingClosure open_write_close_read = BindRepeating([]() {
- FilePath output_filename;
- ScopedFILE output_file(CreateAndOpenTemporaryFile(&output_filename));
- EXPECT_TRUE(output_file);
-
- const std::string content = GenerateGUID();
-#if defined(OS_WIN)
- HANDLE handle =
- reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(output_file.get())));
- DWORD bytes_written = 0;
- ::WriteFile(handle, content.c_str(), content.length(), &bytes_written,
- NULL);
-#else
- size_t bytes_written =
- ::write(::fileno(output_file.get()), content.c_str(), content.length());
-#endif
- EXPECT_EQ(content.length(), bytes_written);
- ::fflush(output_file.get());
- output_file.reset();
-
- std::string output_file_contents;
- EXPECT_TRUE(ReadFileToString(output_filename, &output_file_contents))
- << output_filename;
-
- EXPECT_EQ(content, output_file_contents);
-
- DeleteFile(output_filename, false);
- });
-
- // Post tasks to each thread in a round-robin fashion to ensure as much
- // parallelism as possible.
- for (int i = 0; i < kNumWritesPerThread; ++i) {
- for (auto& thread : threads) {
- thread->task_runner()->PostTask(FROM_HERE, open_write_close_read);
- }
- }
-
- for (auto& thread : threads)
- thread->Stop();
-}
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-TEST(ScopedFD, ScopedFDDoesClose) {
- int fds[2];
- char c = 0;
- ASSERT_EQ(0, pipe(fds));
- const int write_end = fds[1];
- ScopedFD read_end_closer(fds[0]);
- {
- ScopedFD write_end_closer(fds[1]);
- }
- // This is the only thread. This file descriptor should no longer be valid.
- int ret = close(write_end);
- EXPECT_EQ(-1, ret);
- EXPECT_EQ(EBADF, errno);
- // Make sure read(2) won't block.
- ASSERT_EQ(0, fcntl(fds[0], F_SETFL, O_NONBLOCK));
- // Reading the pipe should EOF.
- EXPECT_EQ(0, read(fds[0], &c, 1));
-}
-
-#if defined(GTEST_HAS_DEATH_TEST)
-void CloseWithScopedFD(int fd) {
- ScopedFD fd_closer(fd);
-}
-#endif
-
-TEST(ScopedFD, ScopedFDCrashesOnCloseFailure) {
- int fds[2];
- ASSERT_EQ(0, pipe(fds));
- ScopedFD read_end_closer(fds[0]);
- EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
-#if defined(GTEST_HAS_DEATH_TEST)
- // This is the only thread. This file descriptor should no longer be valid.
- // Trying to close it should crash. This is important for security.
- EXPECT_DEATH(CloseWithScopedFD(fds[1]), "");
-#endif
-}
-
-#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-} // namespace
-
-} // namespace base
diff --git a/base/files/memory_mapped_file_unittest.cc b/base/files/memory_mapped_file_unittest.cc
deleted file mode 100644
index b7acc61887..0000000000
--- a/base/files/memory_mapped_file_unittest.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-// 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/files/memory_mapped_file.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace base {
-
-namespace {
-
-// Create a temporary buffer and fill it with a watermark sequence.
-std::unique_ptr<uint8_t[]> CreateTestBuffer(size_t size, size_t offset) {
- std::unique_ptr<uint8_t[]> buf(new uint8_t[size]);
- for (size_t i = 0; i < size; ++i)
- buf.get()[i] = static_cast<uint8_t>((offset + i) % 253);
- return buf;
-}
-
-// Check that the watermark sequence is consistent with the |offset| provided.
-bool CheckBufferContents(const uint8_t* data, size_t size, size_t offset) {
- std::unique_ptr<uint8_t[]> test_data(CreateTestBuffer(size, offset));
- return memcmp(test_data.get(), data, size) == 0;
-}
-
-class MemoryMappedFileTest : public PlatformTest {
- protected:
- void SetUp() override {
- PlatformTest::SetUp();
- CreateTemporaryFile(&temp_file_path_);
- }
-
- void TearDown() override { EXPECT_TRUE(DeleteFile(temp_file_path_, false)); }
-
- void CreateTemporaryTestFile(size_t size) {
- File file(temp_file_path_,
- File::FLAG_CREATE_ALWAYS | File::FLAG_READ | File::FLAG_WRITE);
- EXPECT_TRUE(file.IsValid());
-
- std::unique_ptr<uint8_t[]> test_data(CreateTestBuffer(size, 0));
- size_t bytes_written =
- file.Write(0, reinterpret_cast<char*>(test_data.get()), size);
- EXPECT_EQ(size, bytes_written);
- file.Close();
- }
-
- const FilePath temp_file_path() const { return temp_file_path_; }
-
- private:
- FilePath temp_file_path_;
-};
-
-TEST_F(MemoryMappedFileTest, MapWholeFileByPath) {
- const size_t kFileSize = 68 * 1024;
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
- map.Initialize(temp_file_path());
- ASSERT_EQ(kFileSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
-}
-
-TEST_F(MemoryMappedFileTest, MapWholeFileByFD) {
- const size_t kFileSize = 68 * 1024;
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
- map.Initialize(File(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ));
- ASSERT_EQ(kFileSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
-}
-
-TEST_F(MemoryMappedFileTest, MapSmallFile) {
- const size_t kFileSize = 127;
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
- map.Initialize(temp_file_path());
- ASSERT_EQ(kFileSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
-}
-
-TEST_F(MemoryMappedFileTest, MapWholeFileUsingRegion) {
- const size_t kFileSize = 157 * 1024;
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
-
- File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
- map.Initialize(std::move(file), MemoryMappedFile::Region::kWholeFile);
- ASSERT_EQ(kFileSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
-}
-
-TEST_F(MemoryMappedFileTest, MapPartialRegionAtBeginning) {
- const size_t kFileSize = 157 * 1024;
- const size_t kPartialSize = 4 * 1024 + 32;
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
-
- File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
- MemoryMappedFile::Region region = {0, kPartialSize};
- map.Initialize(std::move(file), region);
- ASSERT_EQ(kPartialSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, 0));
-}
-
-TEST_F(MemoryMappedFileTest, MapPartialRegionAtEnd) {
- const size_t kFileSize = 157 * 1024;
- const size_t kPartialSize = 5 * 1024 - 32;
- const size_t kOffset = kFileSize - kPartialSize;
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
-
- File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
- MemoryMappedFile::Region region = {kOffset, kPartialSize};
- map.Initialize(std::move(file), region);
- ASSERT_EQ(kPartialSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
-}
-
-TEST_F(MemoryMappedFileTest, MapSmallPartialRegionInTheMiddle) {
- const size_t kFileSize = 157 * 1024;
- const size_t kOffset = 1024 * 5 + 32;
- const size_t kPartialSize = 8;
-
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
-
- File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
- MemoryMappedFile::Region region = {kOffset, kPartialSize};
- map.Initialize(std::move(file), region);
- ASSERT_EQ(kPartialSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
-}
-
-TEST_F(MemoryMappedFileTest, MapLargePartialRegionInTheMiddle) {
- const size_t kFileSize = 157 * 1024;
- const size_t kOffset = 1024 * 5 + 32;
- const size_t kPartialSize = 16 * 1024 - 32;
-
- CreateTemporaryTestFile(kFileSize);
- MemoryMappedFile map;
-
- File file(temp_file_path(), File::FLAG_OPEN | File::FLAG_READ);
- MemoryMappedFile::Region region = {kOffset, kPartialSize};
- map.Initialize(std::move(file), region);
- ASSERT_EQ(kPartialSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kPartialSize, kOffset));
-}
-
-TEST_F(MemoryMappedFileTest, WriteableFile) {
- const size_t kFileSize = 127;
- CreateTemporaryTestFile(kFileSize);
-
- {
- MemoryMappedFile map;
- map.Initialize(temp_file_path(), MemoryMappedFile::READ_WRITE);
- ASSERT_EQ(kFileSize, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
-
- uint8_t* bytes = map.data();
- bytes[0] = 'B';
- bytes[1] = 'a';
- bytes[2] = 'r';
- bytes[kFileSize - 1] = '!';
- EXPECT_FALSE(CheckBufferContents(map.data(), kFileSize, 0));
- EXPECT_TRUE(CheckBufferContents(map.data() + 3, kFileSize - 4, 3));
- }
-
- int64_t file_size;
- ASSERT_TRUE(GetFileSize(temp_file_path(), &file_size));
- EXPECT_EQ(static_cast<int64_t>(kFileSize), file_size);
-
- std::string contents;
- ASSERT_TRUE(ReadFileToString(temp_file_path(), &contents));
- EXPECT_EQ("Bar", contents.substr(0, 3));
- EXPECT_EQ("!", contents.substr(kFileSize - 1, 1));
-}
-
-TEST_F(MemoryMappedFileTest, ExtendableFile) {
- const size_t kFileSize = 127;
- const size_t kFileExtend = 100;
- CreateTemporaryTestFile(kFileSize);
-
- {
- File file(temp_file_path(),
- File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE);
- MemoryMappedFile::Region region = {0, kFileSize + kFileExtend};
- MemoryMappedFile map;
- map.Initialize(std::move(file), region,
- MemoryMappedFile::READ_WRITE_EXTEND);
- EXPECT_EQ(kFileSize + kFileExtend, map.length());
- ASSERT_TRUE(map.data() != nullptr);
- EXPECT_TRUE(map.IsValid());
- ASSERT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
-
- uint8_t* bytes = map.data();
- EXPECT_EQ(0, bytes[kFileSize + 0]);
- EXPECT_EQ(0, bytes[kFileSize + 1]);
- EXPECT_EQ(0, bytes[kFileSize + 2]);
- bytes[kFileSize + 0] = 'B';
- bytes[kFileSize + 1] = 'A';
- bytes[kFileSize + 2] = 'Z';
- EXPECT_TRUE(CheckBufferContents(map.data(), kFileSize, 0));
- }
-
- int64_t file_size;
- ASSERT_TRUE(GetFileSize(temp_file_path(), &file_size));
- EXPECT_LE(static_cast<int64_t>(kFileSize + 3), file_size);
- EXPECT_GE(static_cast<int64_t>(kFileSize + kFileExtend), file_size);
-
- std::string contents;
- ASSERT_TRUE(ReadFileToString(temp_file_path(), &contents));
- EXPECT_EQ("BAZ", contents.substr(kFileSize, 3));
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/hash_unittest.cc b/base/hash_unittest.cc
deleted file mode 100644
index fc8a7519ee..0000000000
--- a/base/hash_unittest.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// 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/hash.h"
-
-#include <string>
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(HashTest, String) {
- std::string str;
- // Empty string (should hash to 0).
- str = "";
- EXPECT_EQ(0u, Hash(str));
-
- // Simple test.
- str = "hello world";
- EXPECT_EQ(2794219650u, Hash(str));
-
- // Change one bit.
- str = "helmo world";
- EXPECT_EQ(1006697176u, Hash(str));
-
- // Insert a null byte.
- str = "hello world";
- str[5] = '\0';
- EXPECT_EQ(2319902537u, Hash(str));
-
- // Test that the bytes after the null contribute to the hash.
- str = "hello worle";
- str[5] = '\0';
- EXPECT_EQ(553904462u, Hash(str));
-
- // Extremely long string.
- // Also tests strings with high bit set, and null byte.
- std::vector<char> long_string_buffer;
- for (int i = 0; i < 4096; ++i)
- long_string_buffer.push_back((i % 256) - 128);
- str.assign(&long_string_buffer.front(), long_string_buffer.size());
- EXPECT_EQ(2797962408u, Hash(str));
-
- // All possible lengths (mod 4). Tests separate code paths. Also test with
- // final byte high bit set (regression test for http://crbug.com/90659).
- // Note that the 1 and 3 cases have a weird bug where the final byte is
- // treated as a signed char. It was decided on the above bug discussion to
- // enshrine that behaviour as "correct" to avoid invalidating existing hashes.
-
- // Length mod 4 == 0.
- str = "hello w\xab";
- EXPECT_EQ(615571198u, Hash(str));
- // Length mod 4 == 1.
- str = "hello wo\xab";
- EXPECT_EQ(623474296u, Hash(str));
- // Length mod 4 == 2.
- str = "hello wor\xab";
- EXPECT_EQ(4278562408u, Hash(str));
- // Length mod 4 == 3.
- str = "hello worl\xab";
- EXPECT_EQ(3224633008u, Hash(str));
-}
-
-TEST(HashTest, CString) {
- const char* str;
- // Empty string (should hash to 0).
- str = "";
- EXPECT_EQ(0u, Hash(str, strlen(str)));
-
- // Simple test.
- str = "hello world";
- EXPECT_EQ(2794219650u, Hash(str, strlen(str)));
-
- // Ensure that it stops reading after the given length, and does not expect a
- // null byte.
- str = "hello world; don't read this part";
- EXPECT_EQ(2794219650u, Hash(str, strlen("hello world")));
-}
-
-} // namespace base
diff --git a/base/i18n/base_i18n_switches.cc b/base/i18n/base_i18n_switches.cc
deleted file mode 100644
index 103d6653d3..0000000000
--- a/base/i18n/base_i18n_switches.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 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/i18n/base_i18n_switches.h"
-
-namespace switches {
-
-// Force the UI to a specific direction. Valid values are "ltr" (left-to-right)
-// and "rtl" (right-to-left).
-const char kForceUIDirection[] = "force-ui-direction";
-
-// Force the text rendering to a specific direction. Valid values are "ltr"
-// (left-to-right) and "rtl" (right-to-left). Only tested meaningfully with
-// RTL.
-const char kForceTextDirection[] = "force-text-direction";
-
-const char kForceDirectionLTR[] = "ltr";
-const char kForceDirectionRTL[] = "rtl";
-
-} // namespace switches
diff --git a/base/i18n/base_i18n_switches.h b/base/i18n/base_i18n_switches.h
deleted file mode 100644
index d1ba690642..0000000000
--- a/base/i18n/base_i18n_switches.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_I18N_BASE_I18N_SWITCHES_H_
-#define BASE_I18N_BASE_I18N_SWITCHES_H_
-
-#include "base/i18n/base_i18n_export.h"
-
-namespace switches {
-
-BASE_I18N_EXPORT extern const char kForceUIDirection[];
-BASE_I18N_EXPORT extern const char kForceTextDirection[];
-
-// kForce*Direction choices for the switches above.
-BASE_I18N_EXPORT extern const char kForceDirectionLTR[];
-BASE_I18N_EXPORT extern const char kForceDirectionRTL[];
-
-} // namespace switches
-
-#endif // BASE_I18N_BASE_I18N_SWITCHES_H_
diff --git a/base/i18n/bidi_line_iterator.cc b/base/i18n/bidi_line_iterator.cc
deleted file mode 100644
index 3f7f868661..0000000000
--- a/base/i18n/bidi_line_iterator.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2011 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/i18n/bidi_line_iterator.h"
-
-#include "base/logging.h"
-
-namespace base {
-namespace i18n {
-
-namespace {
-
-UBiDiLevel GetParagraphLevelForDirection(TextDirection direction) {
- switch (direction) {
- case UNKNOWN_DIRECTION:
- return UBIDI_DEFAULT_LTR;
- break;
- case RIGHT_TO_LEFT:
- return 1; // Highest RTL level.
- break;
- case LEFT_TO_RIGHT:
- return 0; // Highest LTR level.
- break;
- default:
- NOTREACHED();
- return 0;
- }
-}
-
-// Overrides the default bidi class for a given character, for the custom
-// "AS_URL" behavior. Returns U_BIDI_CLASS_DEFAULT to defer to the default ICU
-// behavior.
-//
-// Matches the C callback interface of ICU's UBiDiClassCallback type (which is
-// why there is an unused argument).
-UCharDirection GetURLBiDiClassCallback(const void* /*unused*/, UChar32 c) {
- // Note: Use a switch statement instead of strchr() to avoid iterating over a
- // string for each character (the switch allows for much better compiler
- // optimization).
- switch (c) {
- // The set of characters that delimit URL components (separating the scheme,
- // username, password, domain labels, host, path segments, query
- // names/values and fragment).
- case '#':
- case '&':
- case '.':
- case '/':
- case ':':
- case '=':
- case '?':
- case '@':
- // Treat all of these characters as strong LTR, which effectively
- // surrounds all of the text components of a URL (e.g., the domain labels
- // and path segments) in a left-to-right embedding. This ensures that the
- // URL components read from left to right, regardless of any RTL
- // characters. (Within each component, RTL sequences are rendered from
- // right to left as expected.)
- return U_LEFT_TO_RIGHT;
- default:
- return U_BIDI_CLASS_DEFAULT;
- }
-}
-
-} // namespace
-
-BiDiLineIterator::BiDiLineIterator() : bidi_(nullptr) {}
-
-BiDiLineIterator::~BiDiLineIterator() {
- if (bidi_) {
- ubidi_close(bidi_);
- bidi_ = nullptr;
- }
-}
-
-bool BiDiLineIterator::Open(const string16& text,
- TextDirection direction,
- CustomBehavior behavior) {
- DCHECK(!bidi_);
- UErrorCode error = U_ZERO_ERROR;
- bidi_ = ubidi_openSized(static_cast<int>(text.length()), 0, &error);
- if (U_FAILURE(error))
- return false;
-
- if (behavior == CustomBehavior::AS_URL) {
- ubidi_setClassCallback(bidi_, GetURLBiDiClassCallback, nullptr, nullptr,
- nullptr, &error);
- if (U_FAILURE(error))
- return false;
- }
-
- ubidi_setPara(bidi_, text.data(), static_cast<int>(text.length()),
- GetParagraphLevelForDirection(direction), nullptr, &error);
- return (U_SUCCESS(error));
-}
-
-int BiDiLineIterator::CountRuns() const {
- DCHECK(bidi_ != nullptr);
- UErrorCode error = U_ZERO_ERROR;
- const int runs = ubidi_countRuns(bidi_, &error);
- return U_SUCCESS(error) ? runs : 0;
-}
-
-UBiDiDirection BiDiLineIterator::GetVisualRun(int index,
- int* start,
- int* length) const {
- DCHECK(bidi_ != nullptr);
- return ubidi_getVisualRun(bidi_, index, start, length);
-}
-
-void BiDiLineIterator::GetLogicalRun(int start,
- int* end,
- UBiDiLevel* level) const {
- DCHECK(bidi_ != nullptr);
- ubidi_getLogicalRun(bidi_, start, end, level);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/bidi_line_iterator.h b/base/i18n/bidi_line_iterator.h
deleted file mode 100644
index d840f6197b..0000000000
--- a/base/i18n/bidi_line_iterator.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_BIDI_LINE_ITERATOR_H_
-#define BASE_I18N_BIDI_LINE_ITERATOR_H_
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/i18n/rtl.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "third_party/icu/source/common/unicode/ubidi.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
-
-namespace base {
-namespace i18n {
-
-// A simple wrapper class for the bidirectional iterator of ICU.
-// This class uses the bidirectional iterator of ICU to split a line of
-// bidirectional texts into visual runs in its display order.
-class BASE_I18N_EXPORT BiDiLineIterator {
- public:
- // Specifies some alternative iteration behavior.
- enum class CustomBehavior {
- // No special behavior.
- NONE,
- // Treat URL delimiter characters as strong LTR. This is a special treatment
- // for URLs that purposefully violates the URL Standard, as an experiment.
- // It should only be used behind a flag.
- AS_URL
- };
-
- BiDiLineIterator();
- ~BiDiLineIterator();
-
- // Initializes the bidirectional iterator with the specified text. Returns
- // whether initialization succeeded.
- bool Open(const string16& text,
- TextDirection direction,
- CustomBehavior behavior);
-
- // Returns the number of visual runs in the text, or zero on error.
- int CountRuns() const;
-
- // Gets the logical offset, length, and direction of the specified visual run.
- UBiDiDirection GetVisualRun(int index, int* start, int* length) const;
-
- // Given a start position, figure out where the run ends (and the BiDiLevel).
- void GetLogicalRun(int start, int* end, UBiDiLevel* level) const;
-
- private:
- UBiDi* bidi_;
-
- DISALLOW_COPY_AND_ASSIGN(BiDiLineIterator);
-};
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_BIDI_LINE_ITERATOR_H_
diff --git a/base/i18n/bidi_line_iterator_unittest.cc b/base/i18n/bidi_line_iterator_unittest.cc
deleted file mode 100644
index d531313bf1..0000000000
--- a/base/i18n/bidi_line_iterator_unittest.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2017 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/i18n/bidi_line_iterator.h"
-
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace i18n {
-namespace {
-
-class BiDiLineIteratorTest : public testing::TestWithParam<TextDirection> {
- public:
- BiDiLineIteratorTest() = default;
-
- BiDiLineIterator* iterator() { return &iterator_; }
-
- private:
- BiDiLineIterator iterator_;
-
- DISALLOW_COPY_AND_ASSIGN(BiDiLineIteratorTest);
-};
-
-TEST_P(BiDiLineIteratorTest, OnlyLTR) {
- iterator()->Open(UTF8ToUTF16("abc 😁 测试"), GetParam(),
- BiDiLineIterator::CustomBehavior::NONE);
- ASSERT_EQ(1, iterator()->CountRuns());
-
- int start, length;
- EXPECT_EQ(UBIDI_LTR, iterator()->GetVisualRun(0, &start, &length));
- EXPECT_EQ(0, start);
- EXPECT_EQ(9, length);
-
- int end;
- UBiDiLevel level;
- iterator()->GetLogicalRun(0, &end, &level);
- EXPECT_EQ(9, end);
- if (GetParam() == TextDirection::RIGHT_TO_LEFT)
- EXPECT_EQ(2, level);
- else
- EXPECT_EQ(0, level);
-}
-
-TEST_P(BiDiLineIteratorTest, OnlyRTL) {
- iterator()->Open(UTF8ToUTF16("מה השעה"), GetParam(),
- BiDiLineIterator::CustomBehavior::NONE);
- ASSERT_EQ(1, iterator()->CountRuns());
-
- int start, length;
- EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length));
- EXPECT_EQ(0, start);
- EXPECT_EQ(7, length);
-
- int end;
- UBiDiLevel level;
- iterator()->GetLogicalRun(0, &end, &level);
- EXPECT_EQ(7, end);
- EXPECT_EQ(1, level);
-}
-
-TEST_P(BiDiLineIteratorTest, Mixed) {
- iterator()->Open(UTF8ToUTF16("אני משתמש ב- Chrome כדפדפן האינטרנט שלי"),
- GetParam(), BiDiLineIterator::CustomBehavior::NONE);
- ASSERT_EQ(3, iterator()->CountRuns());
-
- // We'll get completely different results depending on the top-level paragraph
- // direction.
- if (GetParam() == TextDirection::RIGHT_TO_LEFT) {
- // If para direction is RTL, expect the LTR substring "Chrome" to be nested
- // within the surrounding RTL text.
- int start, length;
- EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length));
- EXPECT_EQ(19, start);
- EXPECT_EQ(20, length);
- EXPECT_EQ(UBIDI_LTR, iterator()->GetVisualRun(1, &start, &length));
- EXPECT_EQ(13, start);
- EXPECT_EQ(6, length);
- EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(2, &start, &length));
- EXPECT_EQ(0, start);
- EXPECT_EQ(13, length);
-
- int end;
- UBiDiLevel level;
- iterator()->GetLogicalRun(0, &end, &level);
- EXPECT_EQ(13, end);
- EXPECT_EQ(1, level);
- iterator()->GetLogicalRun(13, &end, &level);
- EXPECT_EQ(19, end);
- EXPECT_EQ(2, level);
- iterator()->GetLogicalRun(19, &end, &level);
- EXPECT_EQ(39, end);
- EXPECT_EQ(1, level);
- } else {
- // If the para direction is LTR, expect the LTR substring "- Chrome " to be
- // at the top level, with two nested RTL runs on either side.
- int start, length;
- EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length));
- EXPECT_EQ(0, start);
- EXPECT_EQ(11, length);
- EXPECT_EQ(UBIDI_LTR, iterator()->GetVisualRun(1, &start, &length));
- EXPECT_EQ(11, start);
- EXPECT_EQ(9, length);
- EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(2, &start, &length));
- EXPECT_EQ(20, start);
- EXPECT_EQ(19, length);
-
- int end;
- UBiDiLevel level;
- iterator()->GetLogicalRun(0, &end, &level);
- EXPECT_EQ(11, end);
- EXPECT_EQ(1, level);
- iterator()->GetLogicalRun(11, &end, &level);
- EXPECT_EQ(20, end);
- EXPECT_EQ(0, level);
- iterator()->GetLogicalRun(20, &end, &level);
- EXPECT_EQ(39, end);
- EXPECT_EQ(1, level);
- }
-}
-
-TEST_P(BiDiLineIteratorTest, RTLPunctuationNoCustomBehavior) {
- // This string features Hebrew characters interleaved with ASCII punctuation.
- iterator()->Open(UTF8ToUTF16("א!ב\"ג#ד$ה%ו&ז'ח(ט)י*ך+כ,ל-ם.מ/"
- "ן:נ;ס<ע=ף>פ?ץ@צ[ק\\ר]ש^ת_א`ב{ג|ד}ה~ו"),
- GetParam(), BiDiLineIterator::CustomBehavior::NONE);
-
- // Expect a single RTL run.
- ASSERT_EQ(1, iterator()->CountRuns());
-
- int start, length;
- EXPECT_EQ(UBIDI_RTL, iterator()->GetVisualRun(0, &start, &length));
- EXPECT_EQ(0, start);
- EXPECT_EQ(65, length);
-
- int end;
- UBiDiLevel level;
- iterator()->GetLogicalRun(0, &end, &level);
- EXPECT_EQ(65, end);
- EXPECT_EQ(1, level);
-}
-
-TEST_P(BiDiLineIteratorTest, RTLPunctuationAsURL) {
- // This string features Hebrew characters interleaved with ASCII punctuation.
- iterator()->Open(UTF8ToUTF16("א!ב\"ג#ד$ה%ו&ז'ח(ט)י*ך+כ,ל-ם.מ/"
- "ן:נ;ס<ע=ף>פ?ץ@צ[ק\\ר]ש^ת_א`ב{ג|ד}ה~ו"),
- GetParam(), BiDiLineIterator::CustomBehavior::AS_URL);
-
- const int kStringSize = 65;
-
- // Expect a primary RTL run, broken up by each of the 8 punctuation marks that
- // are considered strong LTR (17 runs total).
- struct {
- int start;
- UBiDiDirection dir;
- } expected_runs[] = {
- {0, UBIDI_RTL}, {5, UBIDI_LTR}, // '#'
- {6, UBIDI_RTL}, {11, UBIDI_LTR}, // '&'
- {12, UBIDI_RTL}, {27, UBIDI_LTR}, // '.'
- {28, UBIDI_RTL}, {29, UBIDI_LTR}, // '/'
- {30, UBIDI_RTL}, {31, UBIDI_LTR}, // ':'
- {32, UBIDI_RTL}, {37, UBIDI_LTR}, // '='
- {38, UBIDI_RTL}, {41, UBIDI_LTR}, // '?'
- {42, UBIDI_RTL}, {43, UBIDI_LTR}, // '@'
- {44, UBIDI_RTL},
- };
-
- ASSERT_EQ(arraysize(expected_runs),
- static_cast<size_t>(iterator()->CountRuns()));
-
- for (size_t i = 0; i < arraysize(expected_runs); ++i) {
- const auto& expected_run = expected_runs[i];
- int expected_run_end = i >= arraysize(expected_runs) - 1
- ? kStringSize
- : expected_runs[i + 1].start;
-
- size_t visual_index = GetParam() == TextDirection::RIGHT_TO_LEFT
- ? arraysize(expected_runs) - 1 - i
- : i;
- int start, length;
- EXPECT_EQ(expected_run.dir,
- iterator()->GetVisualRun(visual_index, &start, &length))
- << "(i = " << i << ")";
- EXPECT_EQ(expected_run.start, start) << "(i = " << i << ")";
- EXPECT_EQ(expected_run_end - expected_run.start, length)
- << "(i = " << i << ")";
-
- int expected_level =
- expected_run.dir == UBIDI_RTL
- ? 1
- : (GetParam() == TextDirection::RIGHT_TO_LEFT ? 2 : 0);
- int end;
- UBiDiLevel level;
- iterator()->GetLogicalRun(expected_run.start, &end, &level);
- EXPECT_EQ(expected_run_end, end) << "(i = " << i << ")";
- EXPECT_EQ(expected_level, level) << "(i = " << i << ")";
- }
-}
-
-INSTANTIATE_TEST_CASE_P(,
- BiDiLineIteratorTest,
- ::testing::Values(TextDirection::LEFT_TO_RIGHT,
- TextDirection::RIGHT_TO_LEFT));
-
-} // namespace
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/break_iterator.cc b/base/i18n/break_iterator.cc
deleted file mode 100644
index 251cd002e7..0000000000
--- a/base/i18n/break_iterator.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (c) 2011 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/i18n/break_iterator.h"
-
-#include <stdint.h>
-
-#include "base/logging.h"
-#include "third_party/icu/source/common/unicode/ubrk.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
-#include "third_party/icu/source/common/unicode/ustring.h"
-
-namespace base {
-namespace i18n {
-
-const size_t npos = static_cast<size_t>(-1);
-
-BreakIterator::BreakIterator(const StringPiece16& str, BreakType break_type)
- : iter_(nullptr),
- string_(str),
- break_type_(break_type),
- prev_(npos),
- pos_(0) {}
-
-BreakIterator::BreakIterator(const StringPiece16& str, const string16& rules)
- : iter_(nullptr),
- string_(str),
- rules_(rules),
- break_type_(RULE_BASED),
- prev_(npos),
- pos_(0) {}
-
-BreakIterator::~BreakIterator() {
- if (iter_)
- ubrk_close(static_cast<UBreakIterator*>(iter_));
-}
-
-bool BreakIterator::Init() {
- UErrorCode status = U_ZERO_ERROR;
- UParseError parse_error;
- UBreakIteratorType break_type;
- switch (break_type_) {
- case BREAK_CHARACTER:
- break_type = UBRK_CHARACTER;
- break;
- case BREAK_WORD:
- break_type = UBRK_WORD;
- break;
- case BREAK_LINE:
- case BREAK_NEWLINE:
- case RULE_BASED: // (Keep compiler happy, break_type not used in this case)
- break_type = UBRK_LINE;
- break;
- default:
- NOTREACHED() << "invalid break_type_";
- return false;
- }
- if (break_type_ == RULE_BASED) {
- iter_ = ubrk_openRules(rules_.c_str(),
- static_cast<int32_t>(rules_.length()),
- string_.data(),
- static_cast<int32_t>(string_.size()),
- &parse_error,
- &status);
- if (U_FAILURE(status)) {
- NOTREACHED() << "ubrk_openRules failed to parse rule string at line "
- << parse_error.line << ", offset " << parse_error.offset;
- }
- } else {
- iter_ = ubrk_open(break_type, nullptr, string_.data(),
- static_cast<int32_t>(string_.size()), &status);
- if (U_FAILURE(status)) {
- NOTREACHED() << "ubrk_open failed for type " << break_type
- << " with error " << status;
- }
- }
-
- if (U_FAILURE(status)) {
- return false;
- }
-
- // Move the iterator to the beginning of the string.
- ubrk_first(static_cast<UBreakIterator*>(iter_));
- return true;
-}
-
-bool BreakIterator::Advance() {
- int32_t pos;
- int32_t status;
- prev_ = pos_;
- switch (break_type_) {
- case BREAK_CHARACTER:
- case BREAK_WORD:
- case BREAK_LINE:
- case RULE_BASED:
- pos = ubrk_next(static_cast<UBreakIterator*>(iter_));
- if (pos == UBRK_DONE) {
- pos_ = npos;
- return false;
- }
- pos_ = static_cast<size_t>(pos);
- return true;
- case BREAK_NEWLINE:
- do {
- pos = ubrk_next(static_cast<UBreakIterator*>(iter_));
- if (pos == UBRK_DONE)
- break;
- pos_ = static_cast<size_t>(pos);
- status = ubrk_getRuleStatus(static_cast<UBreakIterator*>(iter_));
- } while (status >= UBRK_LINE_SOFT && status < UBRK_LINE_SOFT_LIMIT);
- if (pos == UBRK_DONE && prev_ == pos_) {
- pos_ = npos;
- return false;
- }
- return true;
- default:
- NOTREACHED() << "invalid break_type_";
- return false;
- }
-}
-
-bool BreakIterator::SetText(const base::char16* text, const size_t length) {
- UErrorCode status = U_ZERO_ERROR;
- ubrk_setText(static_cast<UBreakIterator*>(iter_),
- text, length, &status);
- pos_ = 0; // implicit when ubrk_setText is done
- prev_ = npos;
- if (U_FAILURE(status)) {
- NOTREACHED() << "ubrk_setText failed";
- return false;
- }
- string_ = StringPiece16(text, length);
- return true;
-}
-
-bool BreakIterator::IsWord() const {
- return GetWordBreakStatus() == IS_WORD_BREAK;
-}
-
-BreakIterator::WordBreakStatus BreakIterator::GetWordBreakStatus() const {
- int32_t status = ubrk_getRuleStatus(static_cast<UBreakIterator*>(iter_));
- if (break_type_ != BREAK_WORD && break_type_ != RULE_BASED)
- return IS_LINE_OR_CHAR_BREAK;
- // In ICU 60, trying to advance past the end of the text does not change
- // |status| so that |pos_| has to be checked as well as |status|.
- // See http://bugs.icu-project.org/trac/ticket/13447 .
- return (status == UBRK_WORD_NONE || pos_ == npos) ? IS_SKIPPABLE_WORD
- : IS_WORD_BREAK;
-}
-
-bool BreakIterator::IsEndOfWord(size_t position) const {
- if (break_type_ != BREAK_WORD && break_type_ != RULE_BASED)
- return false;
-
- UBreakIterator* iter = static_cast<UBreakIterator*>(iter_);
- UBool boundary = ubrk_isBoundary(iter, static_cast<int32_t>(position));
- int32_t status = ubrk_getRuleStatus(iter);
- return (!!boundary && status != UBRK_WORD_NONE);
-}
-
-bool BreakIterator::IsStartOfWord(size_t position) const {
- if (break_type_ != BREAK_WORD && break_type_ != RULE_BASED)
- return false;
-
- UBreakIterator* iter = static_cast<UBreakIterator*>(iter_);
- UBool boundary = ubrk_isBoundary(iter, static_cast<int32_t>(position));
- ubrk_next(iter);
- int32_t next_status = ubrk_getRuleStatus(iter);
- return (!!boundary && next_status != UBRK_WORD_NONE);
-}
-
-bool BreakIterator::IsGraphemeBoundary(size_t position) const {
- if (break_type_ != BREAK_CHARACTER)
- return false;
-
- UBreakIterator* iter = static_cast<UBreakIterator*>(iter_);
- return !!ubrk_isBoundary(iter, static_cast<int32_t>(position));
-}
-
-string16 BreakIterator::GetString() const {
- return GetStringPiece().as_string();
-}
-
-StringPiece16 BreakIterator::GetStringPiece() const {
- DCHECK(prev_ != npos && pos_ != npos);
- return string_.substr(prev_, pos_ - prev_);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/break_iterator.h b/base/i18n/break_iterator.h
deleted file mode 100644
index dc30b644f7..0000000000
--- a/base/i18n/break_iterator.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_BREAK_ITERATOR_H_
-#define BASE_I18N_BREAK_ITERATOR_H_
-
-#include <stddef.h>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-
-// The BreakIterator class iterates through the words, word breaks, and
-// line breaks in a UTF-16 string.
-//
-// It provides several modes, BREAK_WORD, BREAK_LINE, and BREAK_NEWLINE,
-// which modify how characters are aggregated into the returned string.
-//
-// Under BREAK_WORD mode, once a word is encountered any non-word
-// characters are not included in the returned string (e.g. in the
-// UTF-16 equivalent of the string " foo bar! ", the word breaks are at
-// the periods in ". .foo. .bar.!. .").
-// Note that Chinese/Japanese/Thai do not use spaces between words so that
-// boundaries can fall in the middle of a continuous run of non-space /
-// non-punctuation characters.
-//
-// Under BREAK_LINE mode, once a line breaking opportunity is encountered,
-// any non-word characters are included in the returned string, breaking
-// only when a space-equivalent character or a line breaking opportunity
-// is encountered (e.g. in the UTF16-equivalent of the string " foo bar! ",
-// the breaks are at the periods in ". .foo .bar! .").
-//
-// Note that lines can be broken at any character/syllable/grapheme cluster
-// boundary in Chinese/Japanese/Korean and at word boundaries in Thai
-// (Thai does not use spaces between words). Therefore, this is NOT the same
-// as breaking only at space-equivalent characters where its former
-// name (BREAK_SPACE) implied.
-//
-// Under BREAK_NEWLINE mode, all characters are included in the returned
-// string, breaking only when a newline-equivalent character is encountered
-// (eg. in the UTF-16 equivalent of the string "foo\nbar!\n\n", the line
-// breaks are at the periods in ".foo\n.bar\n.\n.").
-//
-// To extract the words from a string, move a BREAK_WORD BreakIterator
-// through the string and test whether IsWord() is true. E.g.,
-// BreakIterator iter(str, BreakIterator::BREAK_WORD);
-// if (!iter.Init())
-// return false;
-// while (iter.Advance()) {
-// if (iter.IsWord()) {
-// // Region [iter.prev(), iter.pos()) contains a word.
-// VLOG(1) << "word: " << iter.GetString();
-// }
-// }
-
-namespace base {
-namespace i18n {
-
-class BASE_I18N_EXPORT BreakIterator {
- public:
- enum BreakType {
- BREAK_WORD,
- BREAK_LINE,
- // TODO(jshin): Remove this after reviewing call sites.
- // If call sites really need break only on space-like characters
- // implement it separately.
- BREAK_SPACE = BREAK_LINE,
- BREAK_NEWLINE,
- BREAK_CHARACTER,
- // But don't remove this one!
- RULE_BASED,
- };
-
- enum WordBreakStatus {
- // The end of text that the iterator recognizes as word characters.
- // Non-word characters are things like punctuation and spaces.
- IS_WORD_BREAK,
- // Characters that the iterator can skip past, such as punctuation,
- // whitespace, and, if using RULE_BASED mode, characters from another
- // character set.
- IS_SKIPPABLE_WORD,
- // Only used if not in BREAK_WORD or RULE_BASED mode. This is returned for
- // newlines, line breaks, and character breaks.
- IS_LINE_OR_CHAR_BREAK
- };
-
- // Requires |str| to live as long as the BreakIterator does.
- BreakIterator(const StringPiece16& str, BreakType break_type);
- // Make a rule-based iterator. BreakType == RULE_BASED is implied.
- // TODO(andrewhayden): This signature could easily be misinterpreted as
- // "(const string16& str, const string16& locale)". We should do something
- // better.
- BreakIterator(const StringPiece16& str, const string16& rules);
- ~BreakIterator();
-
- // Init() must be called before any of the iterators are valid.
- // Returns false if ICU failed to initialize.
- bool Init();
-
- // Advance to the next break. Returns false if we've run past the end of
- // the string. (Note that the very last "break" is after the final
- // character in the string, and when we advance to that position it's the
- // last time Advance() returns true.)
- bool Advance();
-
- // Updates the text used by the iterator, resetting the iterator as if
- // if Init() had been called again. Any old state is lost. Returns true
- // unless there is an error setting the text.
- bool SetText(const base::char16* text, const size_t length);
-
- // Under BREAK_WORD mode, returns true if the break we just hit is the
- // end of a word. (Otherwise, the break iterator just skipped over e.g.
- // whitespace or punctuation.) Under BREAK_LINE and BREAK_NEWLINE modes,
- // this distinction doesn't apply and it always returns false.
- bool IsWord() const;
-
- // Under BREAK_WORD mode:
- // - Returns IS_SKIPPABLE_WORD if non-word characters, such as punctuation or
- // spaces, are found.
- // - Returns IS_WORD_BREAK if the break we just hit is the end of a sequence
- // of word characters.
- // Under RULE_BASED mode:
- // - Returns IS_SKIPPABLE_WORD if characters outside the rules' character set
- // or non-word characters, such as punctuation or spaces, are found.
- // - Returns IS_WORD_BREAK if the break we just hit is the end of a sequence
- // of word characters that are in the rules' character set.
- // Not under BREAK_WORD or RULE_BASED mode:
- // - Returns IS_LINE_OR_CHAR_BREAK.
- BreakIterator::WordBreakStatus GetWordBreakStatus() const;
-
- // Under BREAK_WORD mode, returns true if |position| is at the end of word or
- // at the start of word. It always returns false under BREAK_LINE and
- // BREAK_NEWLINE modes.
- bool IsEndOfWord(size_t position) const;
- bool IsStartOfWord(size_t position) const;
-
- // Under BREAK_CHARACTER mode, returns whether |position| is a Unicode
- // grapheme boundary.
- bool IsGraphemeBoundary(size_t position) const;
-
- // Returns the string between prev() and pos().
- // Advance() must have been called successfully at least once for pos() to
- // have advanced to somewhere useful.
- string16 GetString() const;
-
- StringPiece16 GetStringPiece() const;
-
- // Returns the value of pos() returned before Advance() was last called.
- size_t prev() const { return prev_; }
-
- // Returns the current break position within the string,
- // or BreakIterator::npos when done.
- size_t pos() const { return pos_; }
-
- private:
- // ICU iterator, avoiding ICU ubrk.h dependence.
- // This is actually an ICU UBreakiterator* type, which turns out to be
- // a typedef for a void* in the ICU headers. Using void* directly prevents
- // callers from needing access to the ICU public headers directory.
- void* iter_;
-
- // The string we're iterating over. Can be changed with SetText(...)
- StringPiece16 string_;
-
- // Rules for our iterator. Mutually exclusive with break_type_.
- const string16 rules_;
-
- // The breaking style (word/space/newline). Mutually exclusive with rules_
- BreakType break_type_;
-
- // Previous and current iterator positions.
- size_t prev_, pos_;
-
- DISALLOW_COPY_AND_ASSIGN(BreakIterator);
-};
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_BREAK_ITERATOR_H_
diff --git a/base/i18n/break_iterator_unittest.cc b/base/i18n/break_iterator_unittest.cc
deleted file mode 100644
index ed5de448a4..0000000000
--- a/base/i18n/break_iterator_unittest.cc
+++ /dev/null
@@ -1,584 +0,0 @@
-// Copyright (c) 2011 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/i18n/break_iterator.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace i18n {
-
-TEST(BreakIteratorTest, BreakWordEmpty) {
- string16 empty;
- BreakIterator iter(empty, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakWord) {
- string16 space(UTF8ToUTF16(" "));
- string16 str(UTF8ToUTF16(" foo bar! \npouet boom"));
- BreakIterator iter(str, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("foo"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("bar"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("!"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("\n"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("pouet"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("boom"), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakWordWide16) {
- // Two greek words separated by space.
- const string16 str(WideToUTF16(
- L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
- L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2"));
- const string16 word1(str.substr(0, 10));
- const string16 word2(str.substr(11, 5));
- BreakIterator iter(str, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(word1, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(word2, iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakWordWide32) {
- // U+1D49C MATHEMATICAL SCRIPT CAPITAL A
- const char very_wide_char[] = "\xF0\x9D\x92\x9C";
- const string16 str(
- UTF8ToUTF16(base::StringPrintf("%s a", very_wide_char)));
- const string16 very_wide_word(str.substr(0, 2));
-
- BreakIterator iter(str, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(very_wide_word, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("a"), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakWordThai) {
- // Terms in Thai, without spaces in between.
- const char term1[] = "พิมพ์";
- const char term2[] = "น้อย";
- const char term3[] = "ลง";
- const string16 str(UTF8ToUTF16(base::JoinString({term1, term2, term3}, "")));
-
- BreakIterator iter(str, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term1), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term2), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term3), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
-
-// In some languages, the words are not broken by spaces. ICU provides a huge
-// dictionary to detect word boundaries in Thai, Chinese, Japanese, Burmese,
-// and Khmer. Due to the size of such a table, the part for Chinese and
-// Japanese is not shipped on mobile.
-#if !(defined(OS_IOS) || defined(OS_ANDROID))
-
-TEST(BreakIteratorTest, BreakWordChinese) {
- // Terms in Traditional Chinese, without spaces in between.
- const char term1[] = "瀏覽";
- const char term2[] = "速度";
- const char term3[] = "飛快";
- const string16 str(UTF8ToUTF16(base::JoinString({term1, term2, term3}, "")));
-
- BreakIterator iter(str, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term1), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term2), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term3), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakWordJapanese) {
- // Terms in Japanese, without spaces in between.
- const char term1[] = "モバイル";
- const char term2[] = "でも";
- const string16 str(UTF8ToUTF16(base::JoinString({term1, term2}, "")));
-
- BreakIterator iter(str, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term1), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(term2), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakWordChineseEnglish) {
- // Terms in Simplified Chinese mixed with English and wide punctuations.
- string16 space(UTF8ToUTF16(" "));
- const char token1[] = "下载";
- const char token2[] = "Chrome";
- const char token3[] = "(";
- const char token4[] = "Mac";
- const char token5[] = "版";
- const char token6[] = ")";
- const string16 str(UTF8ToUTF16(base::JoinString(
- {token1, " ", token2, token3, token4, " ", token5, token6}, "")));
-
- BreakIterator iter(str, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(token1), iter.GetString());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetString());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(token2), iter.GetString());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(token3), iter.GetString());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(token4), iter.GetString());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(space, iter.GetString());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(token5), iter.GetString());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(token6), iter.GetString());
-
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
-}
-
-#endif // !(defined(OS_IOS) || defined(OS_ANDROID))
-
-TEST(BreakIteratorTest, BreakSpaceEmpty) {
- string16 empty;
- BreakIterator iter(empty, BreakIterator::BREAK_SPACE);
- ASSERT_TRUE(iter.Init());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakSpace) {
- string16 str(UTF8ToUTF16(" foo bar! \npouet boom"));
- BreakIterator iter(str, BreakIterator::BREAK_SPACE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("foo "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("bar! \n"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("pouet "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("boom"), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakSpaceSP) {
- string16 str(UTF8ToUTF16(" foo bar! \npouet boom "));
- BreakIterator iter(str, BreakIterator::BREAK_SPACE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16(" "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("foo "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("bar! \n"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("pouet "), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("boom "), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakSpacekWide16) {
- // Two Greek words.
- const string16 str(WideToUTF16(
- L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
- L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2"));
- const string16 word1(str.substr(0, 11));
- const string16 word2(str.substr(11, 5));
- BreakIterator iter(str, BreakIterator::BREAK_SPACE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(word1, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(word2, iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakSpaceWide32) {
- // U+1D49C MATHEMATICAL SCRIPT CAPITAL A
- const char very_wide_char[] = "\xF0\x9D\x92\x9C";
- const string16 str(
- UTF8ToUTF16(base::StringPrintf("%s a", very_wide_char)));
- const string16 very_wide_word(str.substr(0, 3));
-
- BreakIterator iter(str, BreakIterator::BREAK_SPACE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(very_wide_word, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("a"), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakLineEmpty) {
- string16 empty;
- BreakIterator iter(empty, BreakIterator::BREAK_NEWLINE);
- ASSERT_TRUE(iter.Init());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakLine) {
- string16 nl(UTF8ToUTF16("\n"));
- string16 str(UTF8ToUTF16("\nfoo bar!\n\npouet boom"));
- BreakIterator iter(str, BreakIterator::BREAK_NEWLINE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(nl, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("foo bar!\n"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(nl, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("pouet boom"), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakLineNL) {
- string16 nl(UTF8ToUTF16("\n"));
- string16 str(UTF8ToUTF16("\nfoo bar!\n\npouet boom\n"));
- BreakIterator iter(str, BreakIterator::BREAK_NEWLINE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(nl, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("foo bar!\n"), iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(nl, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("pouet boom\n"), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakLineWide16) {
- // Two Greek words separated by newline.
- const string16 str(WideToUTF16(
- L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
- L"\x03bf\x03c2\x000a\x0399\x03c3\x03c4\x03cc\x03c2"));
- const string16 line1(str.substr(0, 11));
- const string16 line2(str.substr(11, 5));
- BreakIterator iter(str, BreakIterator::BREAK_NEWLINE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(line1, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(line2, iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakLineWide32) {
- // U+1D49C MATHEMATICAL SCRIPT CAPITAL A
- const char very_wide_char[] = "\xF0\x9D\x92\x9C";
- const string16 str(
- UTF8ToUTF16(base::StringPrintf("%s\na", very_wide_char)));
- const string16 very_wide_line(str.substr(0, 3));
- BreakIterator iter(str, BreakIterator::BREAK_NEWLINE);
- ASSERT_TRUE(iter.Init());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(very_wide_line, iter.GetString());
- EXPECT_TRUE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_EQ(UTF8ToUTF16("a"), iter.GetString());
- EXPECT_FALSE(iter.Advance());
- EXPECT_FALSE(iter.IsWord());
- EXPECT_FALSE(iter.Advance()); // Test unexpected advance after end.
- EXPECT_FALSE(iter.IsWord());
-}
-
-TEST(BreakIteratorTest, BreakCharacter) {
- static const wchar_t* kCharacters[] = {
- // An English word consisting of four ASCII characters.
- L"w", L"o", L"r", L"d", L" ",
- // A Hindi word (which means "Hindi") consisting of three Devanagari
- // characters.
- L"\x0939\x093F", L"\x0928\x094D", L"\x0926\x0940", L" ",
- // A Thai word (which means "feel") consisting of three Thai characters.
- L"\x0E23\x0E39\x0E49", L"\x0E2A\x0E36", L"\x0E01", L" ",
- };
- std::vector<string16> characters;
- string16 text;
- for (size_t i = 0; i < arraysize(kCharacters); ++i) {
- characters.push_back(WideToUTF16(kCharacters[i]));
- text.append(characters.back());
- }
- BreakIterator iter(text, BreakIterator::BREAK_CHARACTER);
- ASSERT_TRUE(iter.Init());
- for (size_t i = 0; i < arraysize(kCharacters); ++i) {
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(characters[i], iter.GetString());
- }
-}
-
-// Test for https://code.google.com/p/chromium/issues/detail?id=411213
-// We should be able to get valid substrings with GetString() function
-// after setting new content by calling SetText().
-TEST(BreakIteratorTest, GetStringAfterSetText) {
- const string16 initial_string(ASCIIToUTF16("str"));
- BreakIterator iter(initial_string, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
-
- const string16 long_string(ASCIIToUTF16("another,string"));
- EXPECT_TRUE(iter.SetText(long_string.c_str(), long_string.size()));
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.Advance()); // Advance to ',' in |long_string|
-
- // Check that the current position is out of bounds of the |initial_string|.
- EXPECT_LT(initial_string.size(), iter.pos());
-
- // Check that we can get a valid substring of |long_string|.
- EXPECT_EQ(ASCIIToUTF16(","), iter.GetString());
-}
-
-TEST(BreakIteratorTest, GetStringPiece) {
- const string16 initial_string(ASCIIToUTF16("some string"));
- BreakIterator iter(initial_string, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(iter.GetString(), iter.GetStringPiece().as_string());
- EXPECT_EQ(StringPiece16(ASCIIToUTF16("some")), iter.GetStringPiece());
-
- EXPECT_TRUE(iter.Advance());
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(iter.GetString(), iter.GetStringPiece().as_string());
- EXPECT_EQ(StringPiece16(ASCIIToUTF16("string")), iter.GetStringPiece());
-}
-
-// Make sure that when not in RULE_BASED or BREAK_WORD mode we're getting
-// IS_LINE_OR_CHAR_BREAK.
-TEST(BreakIteratorTest, GetWordBreakStatusBreakLine) {
- // A string containing the English word "foo", followed by two Khmer
- // characters, the English word "Can", and then two Russian characters and
- // punctuation.
- base::string16 text(
- base::WideToUTF16(L"foo \x1791\x17C1 \nCan \x041C\x0438..."));
- BreakIterator iter(text, BreakIterator::BREAK_LINE);
- ASSERT_TRUE(iter.Init());
-
- EXPECT_TRUE(iter.Advance());
- // Finds "foo" and the space.
- EXPECT_EQ(base::UTF8ToUTF16("foo "), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_LINE_OR_CHAR_BREAK);
- EXPECT_TRUE(iter.Advance());
- // Finds the Khmer characters, the next space, and the newline.
- EXPECT_EQ(base::WideToUTF16(L"\x1791\x17C1 \n"), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_LINE_OR_CHAR_BREAK);
- EXPECT_TRUE(iter.Advance());
- // Finds "Can" and the space.
- EXPECT_EQ(base::UTF8ToUTF16("Can "), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_LINE_OR_CHAR_BREAK);
- EXPECT_TRUE(iter.Advance());
- // Finds the Russian characters and periods.
- EXPECT_EQ(base::WideToUTF16(L"\x041C\x0438..."), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_LINE_OR_CHAR_BREAK);
- EXPECT_FALSE(iter.Advance());
-}
-
-// Make sure that in BREAK_WORD mode we're getting IS_WORD_BREAK and
-// IS_SKIPPABLE_WORD when we should be. IS_WORD_BREAK should be returned when we
-// finish going over non-punctuation characters while IS_SKIPPABLE_WORD should
-// be returned on punctuation and spaces.
-TEST(BreakIteratorTest, GetWordBreakStatusBreakWord) {
- // A string containing the English word "foo", followed by two Khmer
- // characters, the English word "Can", and then two Russian characters and
- // punctuation.
- base::string16 text(
- base::WideToUTF16(L"foo \x1791\x17C1 \nCan \x041C\x0438..."));
- BreakIterator iter(text, BreakIterator::BREAK_WORD);
- ASSERT_TRUE(iter.Init());
-
- EXPECT_TRUE(iter.Advance());
- // Finds "foo".
- EXPECT_EQ(base::UTF8ToUTF16("foo"), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_WORD_BREAK);
- EXPECT_TRUE(iter.Advance());
- // Finds the space, and the Khmer characters.
- EXPECT_EQ(base::UTF8ToUTF16(" "), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_SKIPPABLE_WORD);
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(base::WideToUTF16(L"\x1791\x17C1"), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_WORD_BREAK);
- EXPECT_TRUE(iter.Advance());
- // Finds the space and the newline.
- EXPECT_EQ(base::UTF8ToUTF16(" "), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_SKIPPABLE_WORD);
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(base::UTF8ToUTF16("\n"), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_SKIPPABLE_WORD);
- EXPECT_TRUE(iter.Advance());
- // Finds "Can".
- EXPECT_EQ(base::UTF8ToUTF16("Can"), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_WORD_BREAK);
- EXPECT_TRUE(iter.Advance());
- // Finds the space and the Russian characters.
- EXPECT_EQ(base::UTF8ToUTF16(" "), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_SKIPPABLE_WORD);
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(base::WideToUTF16(L"\x041C\x0438"), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_WORD_BREAK);
- EXPECT_TRUE(iter.Advance());
- // Finds the trailing periods.
- EXPECT_EQ(base::UTF8ToUTF16("."), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_SKIPPABLE_WORD);
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(base::UTF8ToUTF16("."), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_SKIPPABLE_WORD);
- EXPECT_TRUE(iter.Advance());
- EXPECT_EQ(base::UTF8ToUTF16("."), iter.GetString());
- EXPECT_EQ(iter.GetWordBreakStatus(), BreakIterator::IS_SKIPPABLE_WORD);
- EXPECT_FALSE(iter.Advance());
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/build_utf8_validator_tables.cc b/base/i18n/build_utf8_validator_tables.cc
deleted file mode 100644
index 0cdcc3519a..0000000000
--- a/base/i18n/build_utf8_validator_tables.cc
+++ /dev/null
@@ -1,470 +0,0 @@
-// 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.
-
-// Create a state machine for validating UTF-8. The algorithm in brief:
-// 1. Convert the complete unicode range of code points, except for the
-// surrogate code points, to an ordered array of sequences of bytes in
-// UTF-8.
-// 2. Convert individual bytes to ranges, starting from the right of each byte
-// sequence. For each range, ensure the bytes on the left and the ranges
-// on the right are the identical.
-// 3. Convert the resulting list of ranges into a state machine, collapsing
-// identical states.
-// 4. Convert the state machine to an array of bytes.
-// 5. Output as a C++ file.
-//
-// To use:
-// $ ninja -C out/Release build_utf8_validator_tables
-// $ out/Release/build_utf8_validator_tables
-// --output=base/i18n/utf8_validator_tables.cc
-// $ git add base/i18n/utf8_validator_tables.cc
-//
-// Because the table is not expected to ever change, it is checked into the
-// repository rather than being regenerated at build time.
-//
-// This code uses type uint8_t throughout to represent bytes, to avoid
-// signed/unsigned char confusion.
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "third_party/icu/source/common/unicode/utf8.h"
-
-namespace {
-
-const char kHelpText[] =
- "Usage: build_utf8_validator_tables [ --help ] [ --output=<file> ]\n";
-
-const char kProlog[] =
- "// Copyright 2013 The Chromium Authors. All rights reserved.\n"
- "// Use of this source code is governed by a BSD-style license that can "
- "be\n"
- "// found in the LICENSE file.\n"
- "\n"
- "// This file is auto-generated by build_utf8_validator_tables.\n"
- "// DO NOT EDIT.\n"
- "\n"
- "#include \"base/i18n/utf8_validator_tables.h\"\n"
- "\n"
- "namespace base {\n"
- "namespace internal {\n"
- "\n"
- "const uint8_t kUtf8ValidatorTables[] = {\n";
-
-const char kEpilog[] =
- "};\n"
- "\n"
- "const size_t kUtf8ValidatorTablesSize = arraysize(kUtf8ValidatorTables);\n"
- "\n"
- "} // namespace internal\n"
- "} // namespace base\n";
-
-// Ranges are inclusive at both ends--they represent [from, to]
-class Range {
- public:
- // Ranges always start with just one byte.
- explicit Range(uint8_t value) : from_(value), to_(value) {}
-
- // Range objects are copyable and assignable to be used in STL
- // containers. Since they only contain non-pointer POD types, the default copy
- // constructor, assignment operator and destructor will work.
-
- // Add a byte to the range. We intentionally only support adding a byte at the
- // end, since that is the only operation the code needs.
- void AddByte(uint8_t to) {
- CHECK(to == to_ + 1);
- to_ = to;
- }
-
- uint8_t from() const { return from_; }
- uint8_t to() const { return to_; }
-
- bool operator<(const Range& rhs) const {
- return (from() < rhs.from() || (from() == rhs.from() && to() < rhs.to()));
- }
-
- bool operator==(const Range& rhs) const {
- return from() == rhs.from() && to() == rhs.to();
- }
-
- private:
- uint8_t from_;
- uint8_t to_;
-};
-
-// A vector of Ranges is like a simple regular expression--it corresponds to
-// a set of strings of the same length that have bytes in each position in
-// the appropriate range.
-typedef std::vector<Range> StringSet;
-
-// A UTF-8 "character" is represented by a sequence of bytes.
-typedef std::vector<uint8_t> Character;
-
-// In the second stage of the algorithm, we want to convert a large list of
-// Characters into a small list of StringSets.
-struct Pair {
- Character character;
- StringSet set;
-};
-
-typedef std::vector<Pair> PairVector;
-
-// A class to print a table of numbers in the same style as clang-format.
-class TablePrinter {
- public:
- explicit TablePrinter(FILE* stream)
- : stream_(stream), values_on_this_line_(0), current_offset_(0) {}
-
- void PrintValue(uint8_t value) {
- if (values_on_this_line_ == 0) {
- fputs(" ", stream_);
- } else if (values_on_this_line_ == kMaxValuesPerLine) {
- fprintf(stream_, " // 0x%02x\n ", current_offset_);
- values_on_this_line_ = 0;
- }
- fprintf(stream_, " 0x%02x,", static_cast<int>(value));
- ++values_on_this_line_;
- ++current_offset_;
- }
-
- void NewLine() {
- while (values_on_this_line_ < kMaxValuesPerLine) {
- fputs(" ", stream_);
- ++values_on_this_line_;
- }
- fprintf(stream_, " // 0x%02x\n", current_offset_);
- values_on_this_line_ = 0;
- }
-
- private:
- // stdio stream. Not owned.
- FILE* stream_;
-
- // Number of values so far printed on this line.
- int values_on_this_line_;
-
- // Total values printed so far.
- int current_offset_;
-
- static const int kMaxValuesPerLine = 8;
-
- DISALLOW_COPY_AND_ASSIGN(TablePrinter);
-};
-
-// Start by filling a PairVector with characters. The resulting vector goes from
-// "\x00" to "\xf4\x8f\xbf\xbf".
-PairVector InitializeCharacters() {
- PairVector vector;
- for (int i = 0; i <= 0x10FFFF; ++i) {
- if (i >= 0xD800 && i < 0xE000) {
- // Surrogate codepoints are not permitted. Non-character code points are
- // explicitly permitted.
- continue;
- }
- uint8_t bytes[4];
- unsigned int offset = 0;
- UBool is_error = false;
- U8_APPEND(bytes, offset, arraysize(bytes), i, is_error);
- DCHECK(!is_error);
- DCHECK_GT(offset, 0u);
- DCHECK_LE(offset, arraysize(bytes));
- Pair pair = {Character(bytes, bytes + offset), StringSet()};
- vector.push_back(pair);
- }
- return vector;
-}
-
-// Construct a new Pair from |character| and the concatenation of |new_range|
-// and |existing_set|, and append it to |pairs|.
-void ConstructPairAndAppend(const Character& character,
- const Range& new_range,
- const StringSet& existing_set,
- PairVector* pairs) {
- Pair new_pair = {character, StringSet(1, new_range)};
- new_pair.set.insert(
- new_pair.set.end(), existing_set.begin(), existing_set.end());
- pairs->push_back(new_pair);
-}
-
-// Each pass over the PairVector strips one byte off the right-hand-side of the
-// characters and adds a range to the set on the right. For example, the first
-// pass converts the range from "\xe0\xa0\x80" to "\xe0\xa0\xbf" to ("\xe0\xa0",
-// [\x80-\xbf]), then the second pass converts the range from ("\xe0\xa0",
-// [\x80-\xbf]) to ("\xe0\xbf", [\x80-\xbf]) to ("\xe0",
-// [\xa0-\xbf][\x80-\xbf]).
-void MoveRightMostCharToSet(PairVector* pairs) {
- PairVector new_pairs;
- PairVector::const_iterator it = pairs->begin();
- while (it != pairs->end() && it->character.empty()) {
- new_pairs.push_back(*it);
- ++it;
- }
- CHECK(it != pairs->end());
- Character unconverted_bytes(it->character.begin(), it->character.end() - 1);
- Range new_range(it->character.back());
- StringSet converted = it->set;
- ++it;
- while (it != pairs->end()) {
- const Pair& current_pair = *it++;
- if (current_pair.character.size() == unconverted_bytes.size() + 1 &&
- std::equal(unconverted_bytes.begin(),
- unconverted_bytes.end(),
- current_pair.character.begin()) &&
- converted == current_pair.set) {
- // The particular set of UTF-8 codepoints we are validating guarantees
- // that each byte range will be contiguous. This would not necessarily be
- // true for an arbitrary set of UTF-8 codepoints.
- DCHECK_EQ(new_range.to() + 1, current_pair.character.back());
- new_range.AddByte(current_pair.character.back());
- continue;
- }
- ConstructPairAndAppend(unconverted_bytes, new_range, converted, &new_pairs);
- unconverted_bytes = Character(current_pair.character.begin(),
- current_pair.character.end() - 1);
- new_range = Range(current_pair.character.back());
- converted = current_pair.set;
- }
- ConstructPairAndAppend(unconverted_bytes, new_range, converted, &new_pairs);
- new_pairs.swap(*pairs);
-}
-
-void MoveAllCharsToSets(PairVector* pairs) {
- // Since each pass of the function moves one character, and UTF-8 sequences
- // are at most 4 characters long, this simply runs the algorithm four times.
- for (int i = 0; i < 4; ++i) {
- MoveRightMostCharToSet(pairs);
- }
-#if DCHECK_IS_ON()
- for (PairVector::const_iterator it = pairs->begin(); it != pairs->end();
- ++it) {
- DCHECK(it->character.empty());
- }
-#endif
-}
-
-// Logs the generated string sets in regular-expression style, ie. [\x00-\x7f],
-// [\xc2-\xdf][\x80-\xbf], etc. This can be a useful sanity-check that the
-// algorithm is working. Use the command-line option
-// --vmodule=build_utf8_validator_tables=1 to see this output.
-void LogStringSets(const PairVector& pairs) {
- for (PairVector::const_iterator pair_it = pairs.begin();
- pair_it != pairs.end();
- ++pair_it) {
- std::string set_as_string;
- for (StringSet::const_iterator set_it = pair_it->set.begin();
- set_it != pair_it->set.end();
- ++set_it) {
- set_as_string += base::StringPrintf("[\\x%02x-\\x%02x]",
- static_cast<int>(set_it->from()),
- static_cast<int>(set_it->to()));
- }
- VLOG(1) << set_as_string;
- }
-}
-
-// A single state in the state machine is represented by a sorted vector of
-// start bytes and target states. All input bytes in the range between the start
-// byte and the next entry in the vector (or 0xFF) result in a transition to the
-// target state.
-struct StateRange {
- uint8_t from;
- uint8_t target_state;
-};
-
-typedef std::vector<StateRange> State;
-
-// Generates a state where all bytes go to state 1 (invalid). This is also used
-// as an initialiser for other states (since bytes from outside the desired
-// range are invalid).
-State GenerateInvalidState() {
- const StateRange range = {0, 1};
- return State(1, range);
-}
-
-// A map from a state (ie. a set of strings which will match from this state) to
-// a number (which is an index into the array of states).
-typedef std::map<StringSet, uint8_t> StateMap;
-
-// Create a new state corresponding to |set|, add it |states| and |state_map|
-// and return the index it was given in |states|.
-uint8_t MakeState(const StringSet& set,
- std::vector<State>* states,
- StateMap* state_map) {
- DCHECK(!set.empty());
- const Range& range = set.front();
- const StringSet rest(set.begin() + 1, set.end());
- const StateMap::const_iterator where = state_map->find(rest);
- const uint8_t target_state = where == state_map->end()
- ? MakeState(rest, states, state_map)
- : where->second;
- DCHECK_LT(0, range.from());
- DCHECK_LT(range.to(), 0xFF);
- const StateRange new_state_initializer[] = {
- {0, 1},
- {range.from(), target_state},
- {static_cast<uint8_t>(range.to() + 1), 1}};
- states->push_back(
- State(new_state_initializer,
- new_state_initializer + arraysize(new_state_initializer)));
- const uint8_t new_state_number =
- base::checked_cast<uint8_t>(states->size() - 1);
- CHECK(state_map->insert(std::make_pair(set, new_state_number)).second);
- return new_state_number;
-}
-
-std::vector<State> GenerateStates(const PairVector& pairs) {
- // States 0 and 1 are the initial/valid state and invalid state, respectively.
- std::vector<State> states(2, GenerateInvalidState());
- StateMap state_map;
- state_map.insert(std::make_pair(StringSet(), 0));
- for (PairVector::const_iterator it = pairs.begin(); it != pairs.end(); ++it) {
- DCHECK(it->character.empty());
- DCHECK(!it->set.empty());
- const Range& range = it->set.front();
- const StringSet rest(it->set.begin() + 1, it->set.end());
- const StateMap::const_iterator where = state_map.find(rest);
- const uint8_t target_state = where == state_map.end()
- ? MakeState(rest, &states, &state_map)
- : where->second;
- if (states[0].back().from == range.from()) {
- DCHECK_EQ(1, states[0].back().target_state);
- states[0].back().target_state = target_state;
- DCHECK_LT(range.to(), 0xFF);
- const StateRange new_range = {static_cast<uint8_t>(range.to() + 1), 1};
- states[0].push_back(new_range);
- } else {
- DCHECK_LT(range.to(), 0xFF);
- const StateRange new_range_initializer[] = {
- {range.from(), target_state},
- {static_cast<uint8_t>(range.to() + 1), 1}};
- states[0]
- .insert(states[0].end(),
- new_range_initializer,
- new_range_initializer + arraysize(new_range_initializer));
- }
- }
- return states;
-}
-
-// Output the generated states as a C++ table. Two tricks are used to compact
-// the table: each state in the table starts with a shift value which indicates
-// how many bits we can discard from the right-hand-side of the byte before
-// doing the table lookup. Secondly, only the state-transitions for bytes
-// with the top-bit set are included in the table; bytes without the top-bit set
-// are just ASCII and are handled directly by the code.
-void PrintStates(const std::vector<State>& states, FILE* stream) {
- // First calculate the start-offset of each state. This allows the state
- // machine to jump directly to the correct offset, avoiding an extra
- // indirection. State 0 starts at offset 0.
- std::vector<uint8_t> state_offset(1, 0);
- std::vector<uint8_t> shifts;
- uint8_t pos = 0;
-
- for (std::vector<State>::const_iterator state_it = states.begin();
- state_it != states.end();
- ++state_it) {
- // We want to set |shift| to the (0-based) index of the least-significant
- // set bit in any of the ranges for this state, since this tells us how many
- // bits we can discard and still determine what range a byte lies in. Sadly
- // it appears that ffs() is not portable, so we do it clumsily.
- uint8_t shift = 7;
- for (State::const_iterator range_it = state_it->begin();
- range_it != state_it->end();
- ++range_it) {
- while (shift > 0 && range_it->from % (1 << shift) != 0) {
- --shift;
- }
- }
- shifts.push_back(shift);
- pos += 1 + (1 << (7 - shift));
- state_offset.push_back(pos);
- }
-
- DCHECK_EQ(129, state_offset[1]);
-
- fputs(kProlog, stream);
- TablePrinter table_printer(stream);
-
- for (uint8_t state_index = 0; state_index < states.size(); ++state_index) {
- const uint8_t shift = shifts[state_index];
- uint8_t next_range = 0;
- uint8_t target_state = 1;
- fprintf(stream,
- " // State %d, offset 0x%02x\n",
- static_cast<int>(state_index),
- static_cast<int>(state_offset[state_index]));
- table_printer.PrintValue(shift);
- for (int i = 0; i < 0x100; i += (1 << shift)) {
- if (next_range < states[state_index].size() &&
- states[state_index][next_range].from == i) {
- target_state = states[state_index][next_range].target_state;
- ++next_range;
- }
- if (i >= 0x80) {
- table_printer.PrintValue(state_offset[target_state]);
- }
- }
- table_printer.NewLine();
- }
-
- fputs(kEpilog, stream);
-}
-
-} // namespace
-
-int main(int argc, char* argv[]) {
- base::CommandLine::Init(argc, argv);
- logging::LoggingSettings settings;
- settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
- logging::InitLogging(settings);
- if (base::CommandLine::ForCurrentProcess()->HasSwitch("help")) {
- fwrite(kHelpText, 1, arraysize(kHelpText), stdout);
- exit(EXIT_SUCCESS);
- }
- base::FilePath filename =
- base::CommandLine::ForCurrentProcess()->GetSwitchValuePath("output");
-
- FILE* output = stdout;
- if (!filename.empty()) {
- output = base::OpenFile(filename, "wb");
- if (!output)
- PLOG(FATAL) << "Couldn't open '" << filename.AsUTF8Unsafe()
- << "' for writing";
- }
-
- // Step 1: Enumerate the characters
- PairVector pairs = InitializeCharacters();
- // Step 2: Convert to sets.
- MoveAllCharsToSets(&pairs);
- if (VLOG_IS_ON(1)) {
- LogStringSets(pairs);
- }
- // Step 3: Generate states.
- std::vector<State> states = GenerateStates(pairs);
- // Step 4/5: Print output
- PrintStates(states, output);
-
- if (!filename.empty()) {
- if (!base::CloseFile(output))
- PLOG(FATAL) << "Couldn't finish writing '" << filename.AsUTF8Unsafe()
- << "'";
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/base/i18n/case_conversion.cc b/base/i18n/case_conversion.cc
deleted file mode 100644
index a4a104cf97..0000000000
--- a/base/i18n/case_conversion.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2011 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/i18n/case_conversion.h"
-
-#include <stdint.h>
-
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/common/unicode/ustring.h"
-
-namespace base {
-namespace i18n {
-
-namespace {
-
-// Provides a uniform interface for upper/lower/folding which take take
-// slightly varying parameters.
-typedef int32_t (*CaseMapperFunction)(UChar* dest, int32_t dest_capacity,
- const UChar* src, int32_t src_length,
- UErrorCode* error);
-
-int32_t ToUpperMapper(UChar* dest, int32_t dest_capacity,
- const UChar* src, int32_t src_length,
- UErrorCode* error) {
- // Use default locale.
- return u_strToUpper(dest, dest_capacity, src, src_length, nullptr, error);
-}
-
-int32_t ToLowerMapper(UChar* dest, int32_t dest_capacity,
- const UChar* src, int32_t src_length,
- UErrorCode* error) {
- // Use default locale.
- return u_strToLower(dest, dest_capacity, src, src_length, nullptr, error);
-}
-
-int32_t FoldCaseMapper(UChar* dest, int32_t dest_capacity,
- const UChar* src, int32_t src_length,
- UErrorCode* error) {
- return u_strFoldCase(dest, dest_capacity, src, src_length,
- U_FOLD_CASE_DEFAULT, error);
-}
-
-// Provides similar functionality as UnicodeString::caseMap but on string16.
-string16 CaseMap(StringPiece16 string, CaseMapperFunction case_mapper) {
- string16 dest;
- if (string.empty())
- return dest;
-
- // Provide an initial guess that the string length won't change. The typical
- // strings we use will very rarely change length in this process, so don't
- // optimize for that case.
- dest.resize(string.size());
-
- UErrorCode error;
- do {
- error = U_ZERO_ERROR;
-
- // ICU won't terminate the string if there's not enough room for the null
- // terminator, but will otherwise. So we don't need to save room for that.
- // Don't use WriteInto, which assumes null terminators.
- int32_t new_length = case_mapper(
- &dest[0], saturated_cast<int32_t>(dest.size()),
- string.data(), saturated_cast<int32_t>(string.size()),
- &error);
- dest.resize(new_length);
- } while (error == U_BUFFER_OVERFLOW_ERROR);
- return dest;
-}
-
-} // namespace
-
-string16 ToLower(StringPiece16 string) {
- return CaseMap(string, &ToLowerMapper);
-}
-
-string16 ToUpper(StringPiece16 string) {
- return CaseMap(string, &ToUpperMapper);
-}
-
-string16 FoldCase(StringPiece16 string) {
- return CaseMap(string, &FoldCaseMapper);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/case_conversion.h b/base/i18n/case_conversion.h
deleted file mode 100644
index 0631a800b7..0000000000
--- a/base/i18n/case_conversion.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_CASE_CONVERSION_H_
-#define BASE_I18N_CASE_CONVERSION_H_
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-
-namespace base {
-namespace i18n {
-
-// UNICODE CASE-HANDLING ADVICE
-//
-// In English it's always safe to convert to upper-case or lower-case text
-// and get a good answer. But some languages have rules specific to those
-// locales. One example is the Turkish I:
-// http://www.i18nguy.com/unicode/turkish-i18n.html
-//
-// ToLower/ToUpper use the current ICU locale which will take into account
-// the user language preference. Use this when dealing with user typing.
-//
-// FoldCase canonicalizes to a standardized form independent of the current
-// locale. Use this when comparing general Unicode strings that don't
-// necessarily belong in the user's current locale (like commands, protocol
-// names, other strings from the web) for case-insensitive equality.
-//
-// Note that case conversions will change the length of the string in some
-// not-uncommon cases. Never assume that the output is the same length as
-// the input.
-
-// Returns the lower case equivalent of string. Uses ICU's current locale.
-BASE_I18N_EXPORT string16 ToLower(StringPiece16 string);
-
-// Returns the upper case equivalent of string. Uses ICU's current locale.
-BASE_I18N_EXPORT string16 ToUpper(StringPiece16 string);
-
-// Convert the given string to a canonical case, independent of the current
-// locale. For ASCII the canonical form is lower case.
-// See http://unicode.org/faq/casemap_charprop.html#2
-BASE_I18N_EXPORT string16 FoldCase(StringPiece16 string);
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_CASE_CONVERSION_H_
diff --git a/base/i18n/case_conversion_unittest.cc b/base/i18n/case_conversion_unittest.cc
deleted file mode 100644
index ee795bc6e3..0000000000
--- a/base/i18n/case_conversion_unittest.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2011 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/i18n/case_conversion.h"
-#include "base/i18n/rtl.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/icu_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/icu/source/i18n/unicode/usearch.h"
-
-namespace base {
-namespace i18n {
-
-namespace {
-
-const wchar_t kNonASCIIMixed[] =
- L"\xC4\xD6\xE4\xF6\x20\xCF\xEF\x20\xF7\x25"
- L"\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F07\x1F0F"
- L"\x20\x1E00\x1E01";
-const wchar_t kNonASCIILower[] =
- L"\xE4\xF6\xE4\xF6\x20\xEF\xEF"
- L"\x20\xF7\x25\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F07"
- L"\x1F07\x20\x1E01\x1E01";
-const wchar_t kNonASCIIUpper[] =
- L"\xC4\xD6\xC4\xD6\x20\xCF\xCF"
- L"\x20\xF7\x25\xA4\x23\x2A\x5E\x60\x40\xA3\x24\x2030\x201A\x7E\x20\x1F0F"
- L"\x1F0F\x20\x1E00\x1E00";
-
-} // namespace
-
-// Test upper and lower case string conversion.
-TEST(CaseConversionTest, UpperLower) {
- const string16 mixed(ASCIIToUTF16("Text with UPPer & lowER casE."));
- const string16 expected_lower(ASCIIToUTF16("text with upper & lower case."));
- const string16 expected_upper(ASCIIToUTF16("TEXT WITH UPPER & LOWER CASE."));
-
- string16 result = ToLower(mixed);
- EXPECT_EQ(expected_lower, result);
-
- result = ToUpper(mixed);
- EXPECT_EQ(expected_upper, result);
-}
-
-TEST(CaseConversionTest, NonASCII) {
- const string16 mixed(WideToUTF16(kNonASCIIMixed));
- const string16 expected_lower(WideToUTF16(kNonASCIILower));
- const string16 expected_upper(WideToUTF16(kNonASCIIUpper));
-
- string16 result = ToLower(mixed);
- EXPECT_EQ(expected_lower, result);
-
- result = ToUpper(mixed);
- EXPECT_EQ(expected_upper, result);
-}
-
-TEST(CaseConversionTest, TurkishLocaleConversion) {
- const string16 mixed(WideToUTF16(L"\x49\x131"));
- const string16 expected_lower(WideToUTF16(L"\x69\x131"));
- const string16 expected_upper(WideToUTF16(L"\x49\x49"));
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("en_US");
-
- string16 result = ToLower(mixed);
- EXPECT_EQ(expected_lower, result);
-
- result = ToUpper(mixed);
- EXPECT_EQ(expected_upper, result);
-
- i18n::SetICUDefaultLocale("tr");
-
- const string16 expected_lower_turkish(WideToUTF16(L"\x131\x131"));
- const string16 expected_upper_turkish(WideToUTF16(L"\x49\x49"));
-
- result = ToLower(mixed);
- EXPECT_EQ(expected_lower_turkish, result);
-
- result = ToUpper(mixed);
- EXPECT_EQ(expected_upper_turkish, result);
-}
-
-TEST(CaseConversionTest, FoldCase) {
- // Simple ASCII, should lower-case.
- EXPECT_EQ(ASCIIToUTF16("hello, world"),
- FoldCase(ASCIIToUTF16("Hello, World")));
-
- // Non-ASCII cases from above. They should all fold to the same result.
- EXPECT_EQ(FoldCase(WideToUTF16(kNonASCIIMixed)),
- FoldCase(WideToUTF16(kNonASCIILower)));
- EXPECT_EQ(FoldCase(WideToUTF16(kNonASCIIMixed)),
- FoldCase(WideToUTF16(kNonASCIIUpper)));
-
- // Turkish cases from above. This is the lower-case expected result from the
- // US locale. It should be the same even when the current locale is Turkish.
- const string16 turkish(WideToUTF16(L"\x49\x131"));
- const string16 turkish_expected(WideToUTF16(L"\x69\x131"));
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("en_US");
- EXPECT_EQ(turkish_expected, FoldCase(turkish));
-
- i18n::SetICUDefaultLocale("tr");
- EXPECT_EQ(turkish_expected, FoldCase(turkish));
-
- // Test a case that gets bigger when processed.
- // U+130 = LATIN CAPITAL LETTER I WITH DOT ABOVE gets folded to a lower case
- // "i" followed by U+307 COMBINING DOT ABOVE.
- EXPECT_EQ(WideToUTF16(L"i\u0307j"), FoldCase(WideToUTF16(L"\u0130j")));
-
- // U+00DF (SHARP S) and U+1E9E (CAPIRAL SHARP S) are both folded to "ss".
- EXPECT_EQ(ASCIIToUTF16("ssss"), FoldCase(WideToUTF16(L"\u00DF\u1E9E")));
-}
-
-} // namespace i18n
-} // namespace base
-
-
-
diff --git a/base/i18n/char_iterator.cc b/base/i18n/char_iterator.cc
deleted file mode 100644
index d80b8b618d..0000000000
--- a/base/i18n/char_iterator.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2011 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/i18n/char_iterator.h"
-
-#include "third_party/icu/source/common/unicode/utf8.h"
-#include "third_party/icu/source/common/unicode/utf16.h"
-
-namespace base {
-namespace i18n {
-
-UTF8CharIterator::UTF8CharIterator(const std::string* str)
- : str_(reinterpret_cast<const uint8_t*>(str->data())),
- len_(str->size()),
- array_pos_(0),
- next_pos_(0),
- char_pos_(0),
- char_(0) {
- if (len_)
- U8_NEXT(str_, next_pos_, len_, char_);
-}
-
-UTF8CharIterator::~UTF8CharIterator() = default;
-
-bool UTF8CharIterator::Advance() {
- if (array_pos_ >= len_)
- return false;
-
- array_pos_ = next_pos_;
- char_pos_++;
- if (next_pos_ < len_)
- U8_NEXT(str_, next_pos_, len_, char_);
-
- return true;
-}
-
-UTF16CharIterator::UTF16CharIterator(const string16* str)
- : str_(reinterpret_cast<const char16*>(str->data())),
- len_(str->size()),
- array_pos_(0),
- next_pos_(0),
- char_pos_(0),
- char_(0) {
- if (len_)
- ReadChar();
-}
-
-UTF16CharIterator::UTF16CharIterator(const char16* str, size_t str_len)
- : str_(str),
- len_(str_len),
- array_pos_(0),
- next_pos_(0),
- char_pos_(0),
- char_(0) {
- if (len_)
- ReadChar();
-}
-
-UTF16CharIterator::~UTF16CharIterator() = default;
-
-bool UTF16CharIterator::Advance() {
- if (array_pos_ >= len_)
- return false;
-
- array_pos_ = next_pos_;
- char_pos_++;
- if (next_pos_ < len_)
- ReadChar();
-
- return true;
-}
-
-void UTF16CharIterator::ReadChar() {
- // This is actually a huge macro, so is worth having in a separate function.
- U16_NEXT(str_, next_pos_, len_, char_);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/char_iterator.h b/base/i18n/char_iterator.h
deleted file mode 100644
index 24024d4929..0000000000
--- a/base/i18n/char_iterator.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_CHAR_ITERATOR_H_
-#define BASE_I18N_CHAR_ITERATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "build/build_config.h"
-
-// The CharIterator classes iterate through the characters in UTF8 and
-// UTF16 strings. Example usage:
-//
-// UTF8CharIterator iter(&str);
-// while (!iter.end()) {
-// VLOG(1) << iter.get();
-// iter.Advance();
-// }
-
-#if defined(OS_WIN)
-typedef unsigned char uint8_t;
-#endif
-
-namespace base {
-namespace i18n {
-
-class BASE_I18N_EXPORT UTF8CharIterator {
- public:
- // Requires |str| to live as long as the UTF8CharIterator does.
- explicit UTF8CharIterator(const std::string* str);
- ~UTF8CharIterator();
-
- // Return the starting array index of the current character within the
- // string.
- int32_t array_pos() const { return array_pos_; }
-
- // Return the logical index of the current character, independent of the
- // number of bytes each character takes.
- int32_t char_pos() const { return char_pos_; }
-
- // Return the current char.
- int32_t get() const { return char_; }
-
- // Returns true if we're at the end of the string.
- bool end() const { return array_pos_ == len_; }
-
- // Advance to the next actual character. Returns false if we're at the
- // end of the string.
- bool Advance();
-
- private:
- // The string we're iterating over.
- const uint8_t* str_;
-
- // The length of the encoded string.
- int32_t len_;
-
- // Array index.
- int32_t array_pos_;
-
- // The next array index.
- int32_t next_pos_;
-
- // Character index.
- int32_t char_pos_;
-
- // The current character.
- int32_t char_;
-
- DISALLOW_COPY_AND_ASSIGN(UTF8CharIterator);
-};
-
-class BASE_I18N_EXPORT UTF16CharIterator {
- public:
- // Requires |str| to live as long as the UTF16CharIterator does.
- explicit UTF16CharIterator(const string16* str);
- UTF16CharIterator(const char16* str, size_t str_len);
- ~UTF16CharIterator();
-
- // Return the starting array index of the current character within the
- // string.
- int32_t array_pos() const { return array_pos_; }
-
- // Return the logical index of the current character, independent of the
- // number of codewords each character takes.
- int32_t char_pos() const { return char_pos_; }
-
- // Return the current char.
- int32_t get() const { return char_; }
-
- // Returns true if we're at the end of the string.
- bool end() const { return array_pos_ == len_; }
-
- // Advance to the next actual character. Returns false if we're at the
- // end of the string.
- bool Advance();
-
- private:
- // Fills in the current character we found and advances to the next
- // character, updating all flags as necessary.
- void ReadChar();
-
- // The string we're iterating over.
- const char16* str_;
-
- // The length of the encoded string.
- int32_t len_;
-
- // Array index.
- int32_t array_pos_;
-
- // The next array index.
- int32_t next_pos_;
-
- // Character index.
- int32_t char_pos_;
-
- // The current character.
- int32_t char_;
-
- DISALLOW_COPY_AND_ASSIGN(UTF16CharIterator);
-};
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_CHAR_ITERATOR_H_
diff --git a/base/i18n/char_iterator_unittest.cc b/base/i18n/char_iterator_unittest.cc
deleted file mode 100644
index 0cf8e6c07d..0000000000
--- a/base/i18n/char_iterator_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2011 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/i18n/char_iterator.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace i18n {
-
-TEST(CharIteratorsTest, TestUTF8) {
- std::string empty;
- UTF8CharIterator empty_iter(&empty);
- ASSERT_TRUE(empty_iter.end());
- ASSERT_EQ(0, empty_iter.array_pos());
- ASSERT_EQ(0, empty_iter.char_pos());
- ASSERT_FALSE(empty_iter.Advance());
-
- std::string str("s\303\273r"); // [u with circumflex]
- UTF8CharIterator iter(&str);
- ASSERT_FALSE(iter.end());
- ASSERT_EQ(0, iter.array_pos());
- ASSERT_EQ(0, iter.char_pos());
- ASSERT_EQ('s', iter.get());
- ASSERT_TRUE(iter.Advance());
-
- ASSERT_FALSE(iter.end());
- ASSERT_EQ(1, iter.array_pos());
- ASSERT_EQ(1, iter.char_pos());
- ASSERT_EQ(251, iter.get());
- ASSERT_TRUE(iter.Advance());
-
- ASSERT_FALSE(iter.end());
- ASSERT_EQ(3, iter.array_pos());
- ASSERT_EQ(2, iter.char_pos());
- ASSERT_EQ('r', iter.get());
- ASSERT_TRUE(iter.Advance());
-
- ASSERT_TRUE(iter.end());
- ASSERT_EQ(4, iter.array_pos());
- ASSERT_EQ(3, iter.char_pos());
-
- // Don't care what it returns, but this shouldn't crash
- iter.get();
-
- ASSERT_FALSE(iter.Advance());
-}
-
-TEST(CharIteratorsTest, TestUTF16) {
- string16 empty = UTF8ToUTF16("");
- UTF16CharIterator empty_iter(&empty);
- ASSERT_TRUE(empty_iter.end());
- ASSERT_EQ(0, empty_iter.array_pos());
- ASSERT_EQ(0, empty_iter.char_pos());
- ASSERT_FALSE(empty_iter.Advance());
-
- // This test string contains 4 characters:
- // x
- // u with circumflex - 2 bytes in UTF8, 1 codeword in UTF16
- // math double-struck A - 4 bytes in UTF8, 2 codewords in UTF16
- // z
- string16 str = UTF8ToUTF16("x\303\273\360\235\224\270z");
- UTF16CharIterator iter(&str);
- ASSERT_FALSE(iter.end());
- ASSERT_EQ(0, iter.array_pos());
- ASSERT_EQ(0, iter.char_pos());
- ASSERT_EQ('x', iter.get());
- ASSERT_TRUE(iter.Advance());
-
- ASSERT_FALSE(iter.end());
- ASSERT_EQ(1, iter.array_pos());
- ASSERT_EQ(1, iter.char_pos());
- ASSERT_EQ(251, iter.get());
- ASSERT_TRUE(iter.Advance());
-
- ASSERT_FALSE(iter.end());
- ASSERT_EQ(2, iter.array_pos());
- ASSERT_EQ(2, iter.char_pos());
- ASSERT_EQ(120120, iter.get());
- ASSERT_TRUE(iter.Advance());
-
- ASSERT_FALSE(iter.end());
- ASSERT_EQ(4, iter.array_pos());
- ASSERT_EQ(3, iter.char_pos());
- ASSERT_EQ('z', iter.get());
- ASSERT_TRUE(iter.Advance());
-
- ASSERT_TRUE(iter.end());
- ASSERT_EQ(5, iter.array_pos());
- ASSERT_EQ(4, iter.char_pos());
-
- // Don't care what it returns, but this shouldn't crash
- iter.get();
-
- ASSERT_FALSE(iter.Advance());
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/character_encoding.cc b/base/i18n/character_encoding.cc
deleted file mode 100644
index a1068c3c52..0000000000
--- a/base/i18n/character_encoding.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 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/i18n/character_encoding.h"
-
-#include "base/macros.h"
-#include "third_party/icu/source/common/unicode/ucnv.h"
-
-namespace base {
-namespace {
-
-// An array of all supported canonical encoding names.
-const char* const kCanonicalEncodingNames[] = {
- "Big5", "EUC-JP", "EUC-KR", "gb18030",
- "GBK", "IBM866", "ISO-2022-JP", "ISO-8859-10",
- "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16",
- "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5",
- "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-8-I",
- "KOI8-R", "KOI8-U", "macintosh", "Shift_JIS",
- "UTF-16LE", "UTF-8", "windows-1250", "windows-1251",
- "windows-1252", "windows-1253", "windows-1254", "windows-1255",
- "windows-1256", "windows-1257", "windows-1258", "windows-874"};
-
-} // namespace
-
-std::string GetCanonicalEncodingNameByAliasName(const std::string& alias_name) {
- for (auto* encoding_name : kCanonicalEncodingNames) {
- if (alias_name == encoding_name)
- return alias_name;
- }
- static const char* kStandards[3] = {"HTML", "MIME", "IANA"};
- for (auto* standard : kStandards) {
- UErrorCode error_code = U_ZERO_ERROR;
- const char* canonical_name =
- ucnv_getStandardName(alias_name.c_str(), standard, &error_code);
- if (U_SUCCESS(error_code) && canonical_name)
- return canonical_name;
- }
- return std::string();
-}
-} // namespace base
diff --git a/base/i18n/character_encoding.h b/base/i18n/character_encoding.h
deleted file mode 100644
index 974cb5a6f9..0000000000
--- a/base/i18n/character_encoding.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_I18N_CHARACTER_ENCODING_H_
-#define BASE_I18N_CHARACTER_ENCODING_H_
-
-#include <string>
-
-#include "base/i18n/base_i18n_export.h"
-
-namespace base {
-
-// Return canonical encoding name according to the encoding alias name.
-BASE_I18N_EXPORT std::string GetCanonicalEncodingNameByAliasName(
- const std::string& alias_name);
-
-} // namespace base
-
-#endif // BASE_I18N_CHARACTER_ENCODING_H_
diff --git a/base/i18n/character_encoding_unittest.cc b/base/i18n/character_encoding_unittest.cc
deleted file mode 100644
index 3c11ba30aa..0000000000
--- a/base/i18n/character_encoding_unittest.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 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/i18n/character_encoding.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(CharacterEncodingTest, GetCanonicalEncodingNameByAliasName) {
- EXPECT_EQ("Big5", GetCanonicalEncodingNameByAliasName("Big5"));
- EXPECT_EQ("windows-874", GetCanonicalEncodingNameByAliasName("windows-874"));
- EXPECT_EQ("ISO-8859-8", GetCanonicalEncodingNameByAliasName("ISO-8859-8"));
-
- // Non-canonical alias names should be converted to a canonical one.
- EXPECT_EQ("UTF-8", GetCanonicalEncodingNameByAliasName("utf8"));
- EXPECT_EQ("gb18030", GetCanonicalEncodingNameByAliasName("GB18030"));
- EXPECT_EQ("windows-874", GetCanonicalEncodingNameByAliasName("tis-620"));
- EXPECT_EQ("EUC-KR", GetCanonicalEncodingNameByAliasName("ks_c_5601-1987"));
-}
-
-} // namespace base
diff --git a/base/i18n/encoding_detection.cc b/base/i18n/encoding_detection.cc
deleted file mode 100644
index fef34e4ab1..0000000000
--- a/base/i18n/encoding_detection.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 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/i18n/encoding_detection.h"
-
-#include "build/build_config.h"
-#include "third_party/ced/src/compact_enc_det/compact_enc_det.h"
-
-// third_party/ced/src/util/encodings/encodings.h, which is included
-// by the include above, undefs UNICODE because that is a macro used
-// internally in ced. If we later in the same translation unit do
-// anything related to Windows or Windows headers those will then use
-// the ASCII versions which we do not want. To avoid that happening in
-// jumbo builds, we redefine UNICODE again here.
-#if defined(OS_WIN)
-#define UNICODE 1
-#endif // OS_WIN
-
-namespace base {
-
-bool DetectEncoding(const std::string& text, std::string* encoding) {
- int consumed_bytes;
- bool is_reliable;
- Encoding enc = CompactEncDet::DetectEncoding(
- text.c_str(), text.length(), nullptr, nullptr, nullptr,
- UNKNOWN_ENCODING,
- UNKNOWN_LANGUAGE,
- CompactEncDet::QUERY_CORPUS, // plain text
- false, // Include 7-bit encodings
- &consumed_bytes,
- &is_reliable);
-
- if (enc == UNKNOWN_ENCODING)
- return false;
-
- *encoding = MimeEncodingName(enc);
- return true;
-}
-} // namespace base
diff --git a/base/i18n/encoding_detection.h b/base/i18n/encoding_detection.h
deleted file mode 100644
index c8e660c44d..0000000000
--- a/base/i18n/encoding_detection.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_I18N_ENCODING_DETECTION_H_
-#define BASE_I18N_ENCODING_DETECTION_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/i18n/base_i18n_export.h"
-
-namespace base {
-
-// Detect encoding of |text| and put the name of encoding in |encoding|.
-// Returns true on success.
-BASE_I18N_EXPORT bool DetectEncoding(const std::string& text,
- std::string* encoding) WARN_UNUSED_RESULT;
-} // namespace base
-
-#endif // BASE_I18N_ENCODING_DETECTION_H_
diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc
deleted file mode 100644
index c91aea1a44..0000000000
--- a/base/i18n/file_util_icu.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright (c) 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.
-
-// File utilities that use the ICU library go in this file.
-
-#include "base/i18n/file_util_icu.h"
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/files/file_path.h"
-#include "base/i18n/icu_string_conversions.h"
-#include "base/i18n/string_compare.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "third_party/icu/source/common/unicode/uniset.h"
-#include "third_party/icu/source/i18n/unicode/coll.h"
-
-namespace base {
-namespace i18n {
-
-namespace {
-
-class IllegalCharacters {
- public:
- static IllegalCharacters* GetInstance() {
- return Singleton<IllegalCharacters>::get();
- }
-
- bool DisallowedEverywhere(UChar32 ucs4) {
- return !!illegal_anywhere_->contains(ucs4);
- }
-
- bool DisallowedLeadingOrTrailing(UChar32 ucs4) {
- return !!illegal_at_ends_->contains(ucs4);
- }
-
- bool IsAllowedName(const string16& s) {
- return s.empty() || (!!illegal_anywhere_->containsNone(
- icu::UnicodeString(s.c_str(), s.size())) &&
- !illegal_at_ends_->contains(*s.begin()) &&
- !illegal_at_ends_->contains(*s.rbegin()));
- }
-
- private:
- friend class Singleton<IllegalCharacters>;
- friend struct DefaultSingletonTraits<IllegalCharacters>;
-
- IllegalCharacters();
- ~IllegalCharacters() = default;
-
- // set of characters considered invalid anywhere inside a filename.
- std::unique_ptr<icu::UnicodeSet> illegal_anywhere_;
-
- // set of characters considered invalid at either end of a filename.
- std::unique_ptr<icu::UnicodeSet> illegal_at_ends_;
-
- DISALLOW_COPY_AND_ASSIGN(IllegalCharacters);
-};
-
-IllegalCharacters::IllegalCharacters() {
- UErrorCode everywhere_status = U_ZERO_ERROR;
- UErrorCode ends_status = U_ZERO_ERROR;
- // Control characters, formatting characters, non-characters, path separators,
- // and some printable ASCII characters regarded as dangerous ('"*/:<>?\\').
- // See http://blogs.msdn.com/michkap/archive/2006/11/03/941420.aspx
- // and http://msdn2.microsoft.com/en-us/library/Aa365247.aspx
- // Note that code points in the "Other, Format" (Cf) category are ignored on
- // HFS+ despite the ZERO_WIDTH_JOINER and ZERO_WIDTH_NON-JOINER being
- // legitimate in Arabic and some S/SE Asian scripts. In addition tilde (~) is
- // also excluded due to the possibility of interacting poorly with short
- // filenames on VFAT. (Related to CVE-2014-9390)
- illegal_anywhere_.reset(new icu::UnicodeSet(
- UNICODE_STRING_SIMPLE("[[\"~*/:<>?\\\\|][:Cc:][:Cf:]]"),
- everywhere_status));
- illegal_at_ends_.reset(new icu::UnicodeSet(
- UNICODE_STRING_SIMPLE("[[:WSpace:][.]]"), ends_status));
- DCHECK(U_SUCCESS(everywhere_status));
- DCHECK(U_SUCCESS(ends_status));
-
- // Add non-characters. If this becomes a performance bottleneck by
- // any chance, do not add these to |set| and change IsFilenameLegal()
- // to check |ucs4 & 0xFFFEu == 0xFFFEu|, in addiition to calling
- // IsAllowedName().
- illegal_anywhere_->add(0xFDD0, 0xFDEF);
- for (int i = 0; i <= 0x10; ++i) {
- int plane_base = 0x10000 * i;
- illegal_anywhere_->add(plane_base + 0xFFFE, plane_base + 0xFFFF);
- }
- illegal_anywhere_->freeze();
- illegal_at_ends_->freeze();
-}
-
-} // namespace
-
-bool IsFilenameLegal(const string16& file_name) {
- return IllegalCharacters::GetInstance()->IsAllowedName(file_name);
-}
-
-void ReplaceIllegalCharactersInPath(FilePath::StringType* file_name,
- char replace_char) {
- IllegalCharacters* illegal = IllegalCharacters::GetInstance();
-
- DCHECK(!(illegal->DisallowedEverywhere(replace_char)));
- DCHECK(!(illegal->DisallowedLeadingOrTrailing(replace_char)));
-
- int cursor = 0; // The ICU macros expect an int.
- while (cursor < static_cast<int>(file_name->size())) {
- int char_begin = cursor;
- uint32_t code_point;
-#if defined(OS_WIN)
- // Windows uses UTF-16 encoding for filenames.
- U16_NEXT(file_name->data(), cursor, static_cast<int>(file_name->length()),
- code_point);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- // Mac and Chrome OS use UTF-8 encoding for filenames.
- // Linux doesn't actually define file system encoding. Try to parse as
- // UTF-8.
- U8_NEXT(file_name->data(), cursor, static_cast<int>(file_name->length()),
- code_point);
-#else
-#error Unsupported platform
-#endif
-
- if (illegal->DisallowedEverywhere(code_point) ||
- ((char_begin == 0 || cursor == static_cast<int>(file_name->length())) &&
- illegal->DisallowedLeadingOrTrailing(code_point))) {
- file_name->replace(char_begin, cursor - char_begin, 1, replace_char);
- // We just made the potentially multi-byte/word char into one that only
- // takes one byte/word, so need to adjust the cursor to point to the next
- // character again.
- cursor = char_begin + 1;
- }
- }
-}
-
-bool LocaleAwareCompareFilenames(const FilePath& a, const FilePath& b) {
- UErrorCode error_code = U_ZERO_ERROR;
- // Use the default collator. The default locale should have been properly
- // set by the time this constructor is called.
- std::unique_ptr<icu::Collator> collator(
- icu::Collator::createInstance(error_code));
- DCHECK(U_SUCCESS(error_code));
- // Make it case-sensitive.
- collator->setStrength(icu::Collator::TERTIARY);
-
-#if defined(OS_WIN)
- return CompareString16WithCollator(*collator, WideToUTF16(a.value()),
- WideToUTF16(b.value())) == UCOL_LESS;
-
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- // On linux, the file system encoding is not defined. We assume
- // SysNativeMBToWide takes care of it.
- return CompareString16WithCollator(
- *collator, WideToUTF16(SysNativeMBToWide(a.value())),
- WideToUTF16(SysNativeMBToWide(b.value()))) == UCOL_LESS;
-#endif
-}
-
-void NormalizeFileNameEncoding(FilePath* file_name) {
-#if defined(OS_CHROMEOS)
- std::string normalized_str;
- if (ConvertToUtf8AndNormalize(file_name->BaseName().value(), kCodepageUTF8,
- &normalized_str) &&
- !normalized_str.empty()) {
- *file_name = file_name->DirName().Append(FilePath(normalized_str));
- }
-#endif
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/file_util_icu.h b/base/i18n/file_util_icu.h
deleted file mode 100644
index f8bd9f44d5..0000000000
--- a/base/i18n/file_util_icu.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_I18N_FILE_UTIL_ICU_H_
-#define BASE_I18N_FILE_UTIL_ICU_H_
-
-// File utilities that use the ICU library go in this file.
-
-#include "base/files/file_path.h"
-#include "base/i18n/base_i18n_export.h"
-#include "base/strings/string16.h"
-
-namespace base {
-namespace i18n {
-
-// Returns true if file_name does not have any illegal character. The input
-// param has the same restriction as that for ReplaceIllegalCharacters.
-BASE_I18N_EXPORT bool IsFilenameLegal(const string16& file_name);
-
-// Replaces characters in |file_name| that are illegal for file names with
-// |replace_char|. |file_name| must not be a full or relative path, but just the
-// file name component (since slashes are considered illegal). Any leading or
-// trailing whitespace or periods in |file_name| is also replaced with the
-// |replace_char|.
-//
-// Example:
-// "bad:file*name?.txt" will be turned into "bad_file_name_.txt" when
-// |replace_char| is '_'.
-//
-// Warning: Do not use this function as the sole means of sanitizing a filename.
-// While the resulting filename itself would be legal, it doesn't necessarily
-// mean that the file will behave safely. On Windows, certain reserved names
-// refer to devices rather than files (E.g. LPT1), and some filenames could be
-// interpreted as shell namespace extensions (E.g. Foo.{<GUID>}).
-//
-// On Windows, Chrome OS and Mac, the file system encoding is already known and
-// parsed as UTF-8 and UTF-16 accordingly.
-// On Linux, the file name will be parsed as UTF8.
-// TODO(asanka): Move full filename sanitization logic here.
-BASE_I18N_EXPORT void ReplaceIllegalCharactersInPath(
- FilePath::StringType* file_name,
- char replace_char);
-
-// Compares two filenames using the current locale information. This can be
-// used to sort directory listings. It behaves like "operator<" for use in
-// std::sort.
-BASE_I18N_EXPORT bool LocaleAwareCompareFilenames(const FilePath& a,
- const FilePath& b);
-
-// Calculates the canonical file-system representation of |file_name| base name.
-// Modifies |file_name| in place. No-op if not on ChromeOS.
-BASE_I18N_EXPORT void NormalizeFileNameEncoding(FilePath* file_name);
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_FILE_UTIL_ICU_H_
diff --git a/base/i18n/file_util_icu_unittest.cc b/base/i18n/file_util_icu_unittest.cc
deleted file mode 100644
index 062d29b0d8..0000000000
--- a/base/i18n/file_util_icu_unittest.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/i18n/file_util_icu.h"
-
-#include <stddef.h>
-
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace base {
-namespace i18n {
-
-// file_util winds up using autoreleased objects on the Mac, so this needs
-// to be a PlatformTest
-class FileUtilICUTest : public PlatformTest {
-};
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
-
-// On linux, file path is parsed and filtered as UTF-8.
-static const struct GoodBadPairLinux {
- const char* bad_name;
- const char* good_name;
-} kLinuxIllegalCharacterCases[] = {
- {"bad*\\/file:name?.jpg", "bad---file-name-.jpg"},
- {"**********::::.txt", "--------------.txt"},
- {"\xe9\xf0zzzz.\xff", "\xe9\xf0zzzz.\xff"},
- {" _ ", "-_-"},
- {".", "-"},
- {" .( ). ", "-.( ).-"},
- {" ", "- -"},
-};
-
-TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathLinuxTest) {
- for (size_t i = 0; i < arraysize(kLinuxIllegalCharacterCases); ++i) {
- std::string bad_name(kLinuxIllegalCharacterCases[i].bad_name);
- ReplaceIllegalCharactersInPath(&bad_name, '-');
- EXPECT_EQ(kLinuxIllegalCharacterCases[i].good_name, bad_name);
- }
-}
-
-#endif
-
-// For Mac & Windows, which both do Unicode validation on filenames. These
-// characters are given as wide strings since its more convenient to specify
-// unicode characters. For Mac they should be converted to UTF-8.
-static const struct goodbad_pair {
- const wchar_t* bad_name;
- const wchar_t* good_name;
-} kIllegalCharacterCases[] = {
- {L"bad*file:name?.jpg", L"bad-file-name-.jpg"},
- {L"**********::::.txt", L"--------------.txt"},
- // We can't use UCNs (universal character names) for C0/C1 characters and
- // U+007F, but \x escape is interpreted by MSVC and gcc as we intend.
- {L"bad\x0003\x0091 file\u200E\u200Fname.png", L"bad-- file--name.png"},
- {L"bad*file\\?name.jpg", L"bad-file--name.jpg"},
- {L"\t bad*file\\name/.jpg", L"- bad-file-name-.jpg"},
- {L"this_file_name is okay!.mp3", L"this_file_name is okay!.mp3"},
- {L"\u4E00\uAC00.mp3", L"\u4E00\uAC00.mp3"},
- {L"\u0635\u200C\u0644.mp3", L"\u0635-\u0644.mp3"},
- {L"\U00010330\U00010331.mp3", L"\U00010330\U00010331.mp3"},
- // Unassigned codepoints are ok.
- {L"\u0378\U00040001.mp3", L"\u0378\U00040001.mp3"},
- // Non-characters are not allowed.
- {L"bad\uFFFFfile\U0010FFFEname.jpg", L"bad-file-name.jpg"},
- {L"bad\uFDD0file\uFDEFname.jpg", L"bad-file-name.jpg"},
- // CVE-2014-9390
- {L"(\u200C.\u200D.\u200E.\u200F.\u202A.\u202B.\u202C.\u202D.\u202E.\u206A."
- L"\u206B.\u206C.\u206D.\u206F.\uFEFF)",
- L"(-.-.-.-.-.-.-.-.-.-.-.-.-.-.-)"},
- {L"config~1", L"config-1"},
- {L" _ ", L"-_-"},
- {L" ", L"-"},
- {L"\u2008.(\u2007).\u3000", L"-.(\u2007).-"},
- {L" ", L"- -"},
- {L". ", L"- -"}
-};
-
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_POSIX)
-
-TEST_F(FileUtilICUTest, ReplaceIllegalCharactersInPathTest) {
- for (size_t i = 0; i < arraysize(kIllegalCharacterCases); ++i) {
-#if defined(OS_WIN)
- std::wstring bad_name(kIllegalCharacterCases[i].bad_name);
- ReplaceIllegalCharactersInPath(&bad_name, '-');
- EXPECT_EQ(kIllegalCharacterCases[i].good_name, bad_name);
-#else
- std::string bad_name(WideToUTF8(kIllegalCharacterCases[i].bad_name));
- ReplaceIllegalCharactersInPath(&bad_name, '-');
- EXPECT_EQ(WideToUTF8(kIllegalCharacterCases[i].good_name), bad_name);
-#endif
- }
-}
-
-#endif
-
-TEST_F(FileUtilICUTest, IsFilenameLegalTest) {
- EXPECT_TRUE(IsFilenameLegal(string16()));
-
- for (const auto& test_case : kIllegalCharacterCases) {
- string16 bad_name = WideToUTF16(test_case.bad_name);
- string16 good_name = WideToUTF16(test_case.good_name);
-
- EXPECT_TRUE(IsFilenameLegal(good_name)) << good_name;
- if (good_name != bad_name)
- EXPECT_FALSE(IsFilenameLegal(bad_name)) << bad_name;
- }
-}
-
-#if defined(OS_CHROMEOS)
-static const struct normalize_name_encoding_test_cases {
- const char* original_path;
- const char* normalized_path;
-} kNormalizeFileNameEncodingTestCases[] = {
- { "foo_na\xcc\x88me.foo", "foo_n\xc3\xa4me.foo"},
- { "foo_dir_na\xcc\x88me/foo_na\xcc\x88me.foo",
- "foo_dir_na\xcc\x88me/foo_n\xc3\xa4me.foo"},
- { "", ""},
- { "foo_dir_na\xcc\x88me/", "foo_dir_n\xc3\xa4me"}
-};
-
-TEST_F(FileUtilICUTest, NormalizeFileNameEncoding) {
- for (size_t i = 0; i < arraysize(kNormalizeFileNameEncodingTestCases); i++) {
- FilePath path(kNormalizeFileNameEncodingTestCases[i].original_path);
- NormalizeFileNameEncoding(&path);
- EXPECT_EQ(FilePath(kNormalizeFileNameEncodingTestCases[i].normalized_path),
- path);
- }
-}
-
-#endif
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/i18n_constants.cc b/base/i18n/i18n_constants.cc
deleted file mode 100644
index 7d2f5fc053..0000000000
--- a/base/i18n/i18n_constants.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2011 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/i18n/i18n_constants.h"
-
-namespace base {
-
-const char kCodepageLatin1[] = "ISO-8859-1";
-const char kCodepageUTF8[] = "UTF-8";
-
-} // namespace base
-
diff --git a/base/i18n/i18n_constants.h b/base/i18n/i18n_constants.h
deleted file mode 100644
index c1bd87dc48..0000000000
--- a/base/i18n/i18n_constants.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef BASE_I18N_I18N_CONSTANTS_H_
-#define BASE_I18N_I18N_CONSTANTS_H_
-
-#include "base/i18n/base_i18n_export.h"
-
-namespace base {
-
-// Names of codepages (charsets) understood by icu.
-BASE_I18N_EXPORT extern const char kCodepageLatin1[]; // a.k.a. ISO 8859-1
-BASE_I18N_EXPORT extern const char kCodepageUTF8[];
-
-// The other possible options are UTF-16BE and UTF-16LE, but they are unused in
-// Chromium as of this writing.
-
-} // namespace base
-
-#endif // BASE_I18N_I18N_CONSTANTS_H_
diff --git a/base/i18n/icu_string_conversions.cc b/base/i18n/icu_string_conversions.cc
deleted file mode 100644
index 6ec99803a8..0000000000
--- a/base/i18n/icu_string_conversions.cc
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/i18n/icu_string_conversions.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/icu/source/common/unicode/normalizer2.h"
-#include "third_party/icu/source/common/unicode/ucnv.h"
-#include "third_party/icu/source/common/unicode/ucnv_cb.h"
-#include "third_party/icu/source/common/unicode/ucnv_err.h"
-#include "third_party/icu/source/common/unicode/ustring.h"
-
-namespace base {
-
-namespace {
-// ToUnicodeCallbackSubstitute() is based on UCNV_TO_U_CALLBACK_SUBSTITUTE
-// in source/common/ucnv_err.c.
-
-// Copyright (c) 1995-2006 International Business Machines Corporation
-// and others
-//
-// All rights reserved.
-//
-
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the "Software"),
-// to deal in the Software without restriction, including without limitation
-// the rights to use, copy, modify, merge, publish, distribute, and/or
-// sell copies of the Software, and to permit persons to whom the Software
-// is furnished to do so, provided that the above copyright notice(s) and
-// this permission notice appear in all copies of the Software and that
-// both the above copyright notice(s) and this permission notice appear in
-// supporting documentation.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-// OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
-// INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
-// OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-// OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
-// OR PERFORMANCE OF THIS SOFTWARE.
-//
-// Except as contained in this notice, the name of a copyright holder
-// shall not be used in advertising or otherwise to promote the sale, use
-// or other dealings in this Software without prior written authorization
-// of the copyright holder.
-
-// ___________________________________________________________________________
-//
-// All trademarks and registered trademarks mentioned herein are the property
-// of their respective owners.
-
-void ToUnicodeCallbackSubstitute(const void* context,
- UConverterToUnicodeArgs *to_args,
- const char* code_units,
- int32_t length,
- UConverterCallbackReason reason,
- UErrorCode * err) {
- static const UChar kReplacementChar = 0xFFFD;
- if (reason <= UCNV_IRREGULAR) {
- if (context == nullptr ||
- (*(reinterpret_cast<const char*>(context)) == 'i' &&
- reason == UCNV_UNASSIGNED)) {
- *err = U_ZERO_ERROR;
- ucnv_cbToUWriteUChars(to_args, &kReplacementChar, 1, 0, err);
- }
- // else the caller must have set the error code accordingly.
- }
- // else ignore the reset, close and clone calls.
-}
-
-bool ConvertFromUTF16(UConverter* converter, const UChar* uchar_src,
- int uchar_len, OnStringConversionError::Type on_error,
- std::string* encoded) {
- int encoded_max_length = UCNV_GET_MAX_BYTES_FOR_STRING(uchar_len,
- ucnv_getMaxCharSize(converter));
- encoded->resize(encoded_max_length);
-
- UErrorCode status = U_ZERO_ERROR;
-
- // Setup our error handler.
- switch (on_error) {
- case OnStringConversionError::FAIL:
- ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_STOP, nullptr,
- nullptr, nullptr, &status);
- break;
- case OnStringConversionError::SKIP:
- case OnStringConversionError::SUBSTITUTE:
- ucnv_setFromUCallBack(converter, UCNV_FROM_U_CALLBACK_SKIP, nullptr,
- nullptr, nullptr, &status);
- break;
- default:
- NOTREACHED();
- }
-
- // ucnv_fromUChars returns size not including terminating null
- int actual_size = ucnv_fromUChars(converter, &(*encoded)[0],
- encoded_max_length, uchar_src, uchar_len, &status);
- encoded->resize(actual_size);
- ucnv_close(converter);
- if (U_SUCCESS(status))
- return true;
- encoded->clear(); // Make sure the output is empty on error.
- return false;
-}
-
-// Set up our error handler for ToUTF-16 converters
-void SetUpErrorHandlerForToUChars(OnStringConversionError::Type on_error,
- UConverter* converter, UErrorCode* status) {
- switch (on_error) {
- case OnStringConversionError::FAIL:
- ucnv_setToUCallBack(converter, UCNV_TO_U_CALLBACK_STOP, nullptr, nullptr,
- nullptr, status);
- break;
- case OnStringConversionError::SKIP:
- ucnv_setToUCallBack(converter, UCNV_TO_U_CALLBACK_SKIP, nullptr, nullptr,
- nullptr, status);
- break;
- case OnStringConversionError::SUBSTITUTE:
- ucnv_setToUCallBack(converter, ToUnicodeCallbackSubstitute, nullptr,
- nullptr, nullptr, status);
- break;
- default:
- NOTREACHED();
- }
-}
-
-} // namespace
-
-// Codepage <-> Wide/UTF-16 ---------------------------------------------------
-
-bool UTF16ToCodepage(const string16& utf16,
- const char* codepage_name,
- OnStringConversionError::Type on_error,
- std::string* encoded) {
- encoded->clear();
-
- UErrorCode status = U_ZERO_ERROR;
- UConverter* converter = ucnv_open(codepage_name, &status);
- if (!U_SUCCESS(status))
- return false;
-
- return ConvertFromUTF16(converter, utf16.c_str(),
- static_cast<int>(utf16.length()), on_error, encoded);
-}
-
-bool CodepageToUTF16(const std::string& encoded,
- const char* codepage_name,
- OnStringConversionError::Type on_error,
- string16* utf16) {
- utf16->clear();
-
- UErrorCode status = U_ZERO_ERROR;
- UConverter* converter = ucnv_open(codepage_name, &status);
- if (!U_SUCCESS(status))
- return false;
-
- // Even in the worst case, the maximum length in 2-byte units of UTF-16
- // output would be at most the same as the number of bytes in input. There
- // is no single-byte encoding in which a character is mapped to a
- // non-BMP character requiring two 2-byte units.
- //
- // Moreover, non-BMP characters in legacy multibyte encodings
- // (e.g. EUC-JP, GB18030) take at least 2 bytes. The only exceptions are
- // BOCU and SCSU, but we don't care about them.
- size_t uchar_max_length = encoded.length() + 1;
-
- SetUpErrorHandlerForToUChars(on_error, converter, &status);
- std::unique_ptr<char16[]> buffer(new char16[uchar_max_length]);
- int actual_size = ucnv_toUChars(converter, buffer.get(),
- static_cast<int>(uchar_max_length), encoded.data(),
- static_cast<int>(encoded.length()), &status);
- ucnv_close(converter);
- if (!U_SUCCESS(status)) {
- utf16->clear(); // Make sure the output is empty on error.
- return false;
- }
-
- utf16->assign(buffer.get(), actual_size);
- return true;
-}
-
-bool ConvertToUtf8AndNormalize(const std::string& text,
- const std::string& charset,
- std::string* result) {
- result->clear();
- string16 utf16;
- if (!CodepageToUTF16(
- text, charset.c_str(), OnStringConversionError::FAIL, &utf16))
- return false;
-
- UErrorCode status = U_ZERO_ERROR;
- const icu::Normalizer2* normalizer = icu::Normalizer2::getNFCInstance(status);
- DCHECK(U_SUCCESS(status));
- if (U_FAILURE(status))
- return false;
- int32_t utf16_length = static_cast<int32_t>(utf16.length());
- icu::UnicodeString normalized(utf16.data(), utf16_length);
- int32_t normalized_prefix_length =
- normalizer->spanQuickCheckYes(normalized, status);
- if (normalized_prefix_length < utf16_length) {
- icu::UnicodeString un_normalized(normalized, normalized_prefix_length);
- normalized.truncate(normalized_prefix_length);
- normalizer->normalizeSecondAndAppend(normalized, un_normalized, status);
- }
- if (U_FAILURE(status))
- return false;
- normalized.toUTF8String(*result);
- return true;
-}
-
-} // namespace base
diff --git a/base/i18n/icu_string_conversions.h b/base/i18n/icu_string_conversions.h
deleted file mode 100644
index cbdcb99e4c..0000000000
--- a/base/i18n/icu_string_conversions.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_ICU_STRING_CONVERSIONS_H_
-#define BASE_I18N_ICU_STRING_CONVERSIONS_H_
-
-#include <string>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/i18n/i18n_constants.h"
-#include "base/strings/string16.h"
-
-namespace base {
-
-// Defines the error handling modes of UTF16ToCodepage and CodepageToUTF16.
-class OnStringConversionError {
- public:
- enum Type {
- // The function will return failure. The output buffer will be empty.
- FAIL,
-
- // The offending characters are skipped and the conversion will proceed as
- // if they did not exist.
- SKIP,
-
- // When converting to Unicode, the offending byte sequences are substituted
- // by Unicode replacement character (U+FFFD). When converting from Unicode,
- // this is the same as SKIP.
- SUBSTITUTE,
- };
-
- private:
- OnStringConversionError() = delete;
-};
-
-// Converts between UTF-16 strings and the encoding specified. If the
-// encoding doesn't exist or the encoding fails (when on_error is FAIL),
-// returns false.
-BASE_I18N_EXPORT bool UTF16ToCodepage(const string16& utf16,
- const char* codepage_name,
- OnStringConversionError::Type on_error,
- std::string* encoded);
-BASE_I18N_EXPORT bool CodepageToUTF16(const std::string& encoded,
- const char* codepage_name,
- OnStringConversionError::Type on_error,
- string16* utf16);
-
-// Converts from any codepage to UTF-8 and ensures the resulting UTF-8 is
-// normalized.
-BASE_I18N_EXPORT bool ConvertToUtf8AndNormalize(const std::string& text,
- const std::string& charset,
- std::string* result);
-
-} // namespace base
-
-#endif // BASE_I18N_ICU_STRING_CONVERSIONS_H_
diff --git a/base/i18n/icu_string_conversions_unittest.cc b/base/i18n/icu_string_conversions_unittest.cc
deleted file mode 100644
index d1559860cc..0000000000
--- a/base/i18n/icu_string_conversions_unittest.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (c) 2011 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 <math.h>
-#include <stdarg.h>
-#include <stddef.h>
-
-#include <limits>
-#include <sstream>
-
-#include "base/format_macros.h"
-#include "base/i18n/icu_string_conversions.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// Given a null-terminated string of wchar_t with each wchar_t representing
-// a UTF-16 code unit, returns a string16 made up of wchar_t's in the input.
-// Each wchar_t should be <= 0xFFFF and a non-BMP character (> U+FFFF)
-// should be represented as a surrogate pair (two UTF-16 units)
-// *even* where wchar_t is 32-bit (Linux and Mac).
-//
-// This is to help write tests for functions with string16 params until
-// the C++ 0x UTF-16 literal is well-supported by compilers.
-string16 BuildString16(const wchar_t* s) {
-#if defined(WCHAR_T_IS_UTF16)
- return string16(s);
-#elif defined(WCHAR_T_IS_UTF32)
- string16 u16;
- while (*s != 0) {
- DCHECK_LE(static_cast<unsigned int>(*s), 0xFFFFu);
- u16.push_back(*s++);
- }
- return u16;
-#endif
-}
-
-} // namespace
-
-// kConverterCodepageCases is not comprehensive. There are a number of cases
-// to add if we really want to have a comprehensive coverage of various
-// codepages and their 'idiosyncrasies'. Currently, the only implementation
-// for CodepageTo* and *ToCodepage uses ICU, which has a very extensive
-// set of tests for the charset conversion. So, we can get away with a
-// relatively small number of cases listed below.
-//
-// Note about |u16_wide| in the following struct.
-// On Windows, the field is always identical to |wide|. On Mac and Linux,
-// it's identical as long as there's no character outside the
-// BMP (<= U+FFFF). When there is, it is different from |wide| and
-// is not a real wide string (UTF-32 string) in that each wchar_t in
-// the string is a UTF-16 code unit zero-extended to be 32-bit
-// even when the code unit belongs to a surrogate pair.
-// For instance, a Unicode string (U+0041 U+010000) is represented as
-// L"\x0041\xD800\xDC00" instead of L"\x0041\x10000".
-// To avoid the clutter, |u16_wide| will be set to NULL
-// if it's identical to |wide| on *all* platforms.
-
-static const struct {
- const char* codepage_name;
- const char* encoded;
- OnStringConversionError::Type on_error;
- bool success;
- const wchar_t* wide;
- const wchar_t* u16_wide;
-} kConvertCodepageCases[] = {
- // Test a case where the input cannot be decoded, using SKIP, FAIL
- // and SUBSTITUTE error handling rules. "A7 41" is valid, but "A6" isn't.
- {"big5", "\xA7\x41\xA6", OnStringConversionError::FAIL, false, L"",
- nullptr},
- {"big5", "\xA7\x41\xA6", OnStringConversionError::SKIP, true, L"\x4F60",
- nullptr},
- {"big5", "\xA7\x41\xA6", OnStringConversionError::SUBSTITUTE, true,
- L"\x4F60\xFFFD", nullptr},
- // Arabic (ISO-8859)
- {"iso-8859-6",
- "\xC7\xEE\xE4\xD3\xF1\xEE\xE4\xC7\xE5\xEF"
- " "
- "\xD9\xEE\xE4\xEE\xEA\xF2\xE3\xEF\xE5\xF2",
- OnStringConversionError::FAIL, true,
- L"\x0627\x064E\x0644\x0633\x0651\x064E\x0644\x0627\x0645\x064F"
- L" "
- L"\x0639\x064E\x0644\x064E\x064A\x0652\x0643\x064F\x0645\x0652",
- nullptr},
- // Chinese Simplified (GB2312)
- {"gb2312", "\xC4\xE3\xBA\xC3", OnStringConversionError::FAIL, true,
- L"\x4F60\x597D", nullptr},
- // Chinese (GB18030) : 4 byte sequences mapped to BMP characters
- {"gb18030", "\x81\x30\x84\x36\xA1\xA7", OnStringConversionError::FAIL, true,
- L"\x00A5\x00A8", nullptr},
- // Chinese (GB18030) : A 4 byte sequence mapped to plane 2 (U+20000)
- {"gb18030", "\x95\x32\x82\x36\xD2\xBB", OnStringConversionError::FAIL, true,
-#if defined(WCHAR_T_IS_UTF16)
- L"\xD840\xDC00\x4E00",
-#elif defined(WCHAR_T_IS_UTF32)
- L"\x20000\x4E00",
-#endif
- L"\xD840\xDC00\x4E00"},
- {"big5", "\xA7\x41\xA6\x6E", OnStringConversionError::FAIL, true,
- L"\x4F60\x597D", nullptr},
- // Greek (ISO-8859)
- {"iso-8859-7",
- "\xE3\xE5\xE9\xDC"
- " "
- "\xF3\xEF\xF5",
- OnStringConversionError::FAIL, true,
- L"\x03B3\x03B5\x03B9\x03AC"
- L" "
- L"\x03C3\x03BF\x03C5",
- nullptr},
- // Hebrew (Windows)
- {"windows-1255", "\xF9\xD1\xC8\xEC\xE5\xC9\xED",
- OnStringConversionError::FAIL, true,
- L"\x05E9\x05C1\x05B8\x05DC\x05D5\x05B9\x05DD", nullptr},
- // Korean (EUC)
- {"euc-kr", "\xBE\xC8\xB3\xE7\xC7\xCF\xBC\xBC\xBF\xE4",
- OnStringConversionError::FAIL, true, L"\xC548\xB155\xD558\xC138\xC694",
- nullptr},
- // Japanese (EUC)
- {"euc-jp", "\xA4\xB3\xA4\xF3\xA4\xCB\xA4\xC1\xA4\xCF\xB0\xEC\x8E\xA6",
- OnStringConversionError::FAIL, true,
- L"\x3053\x3093\x306B\x3061\x306F\x4E00\xFF66", nullptr},
- // Japanese (ISO-2022)
- {"iso-2022-jp",
- "\x1B$B"
- "\x24\x33\x24\x73\x24\x4B\x24\x41\x24\x4F\x30\x6C"
- "\x1B(B"
- "ab"
- "\x1B(J"
- "\x5C\x7E#$"
- "\x1B(B",
- OnStringConversionError::FAIL, true,
- L"\x3053\x3093\x306B\x3061\x306F\x4E00"
- L"ab\x00A5\x203E#$",
- nullptr},
- // Japanese (Shift-JIS)
- {"sjis", "\x82\xB1\x82\xF1\x82\xC9\x82\xBF\x82\xCD\x88\xEA\xA6",
- OnStringConversionError::FAIL, true,
- L"\x3053\x3093\x306B\x3061\x306F\x4E00\xFF66", nullptr},
- // Russian (KOI8)
- {"koi8-r", "\xDA\xC4\xD2\xC1\xD7\xD3\xD4\xD7\xD5\xCA\xD4\xC5",
- OnStringConversionError::FAIL, true,
- L"\x0437\x0434\x0440\x0430\x0432\x0441\x0442\x0432"
- L"\x0443\x0439\x0442\x0435",
- nullptr},
- // Thai (windows-874)
- {"windows-874",
- "\xCA\xC7\xD1\xCA\xB4\xD5"
- "\xA4\xC3\xD1\xBA",
- OnStringConversionError::FAIL, true,
- L"\x0E2A\x0E27\x0E31\x0E2A\x0E14\x0E35"
- L"\x0E04\x0E23\x0e31\x0E1A",
- nullptr},
-};
-
-TEST(ICUStringConversionsTest, ConvertBetweenCodepageAndUTF16) {
- for (size_t i = 0; i < arraysize(kConvertCodepageCases); ++i) {
- SCOPED_TRACE(base::StringPrintf(
- "Test[%" PRIuS "]: <encoded: %s> <codepage: %s>", i,
- kConvertCodepageCases[i].encoded,
- kConvertCodepageCases[i].codepage_name));
-
- string16 utf16;
- bool success = CodepageToUTF16(kConvertCodepageCases[i].encoded,
- kConvertCodepageCases[i].codepage_name,
- kConvertCodepageCases[i].on_error,
- &utf16);
- string16 utf16_expected;
- if (kConvertCodepageCases[i].u16_wide == nullptr)
- utf16_expected = BuildString16(kConvertCodepageCases[i].wide);
- else
- utf16_expected = BuildString16(kConvertCodepageCases[i].u16_wide);
- EXPECT_EQ(kConvertCodepageCases[i].success, success);
- EXPECT_EQ(utf16_expected, utf16);
-
- // When decoding was successful and nothing was skipped, we also check the
- // reverse conversion. See also the corresponding comment in
- // ConvertBetweenCodepageAndWide.
- if (success &&
- kConvertCodepageCases[i].on_error == OnStringConversionError::FAIL) {
- std::string encoded;
- success = UTF16ToCodepage(utf16, kConvertCodepageCases[i].codepage_name,
- kConvertCodepageCases[i].on_error, &encoded);
- EXPECT_EQ(kConvertCodepageCases[i].success, success);
- EXPECT_EQ(kConvertCodepageCases[i].encoded, encoded);
- }
- }
-}
-
-static const struct {
- const char* encoded;
- const char* codepage_name;
- bool expected_success;
- const char* expected_value;
-} kConvertAndNormalizeCases[] = {
- {"foo-\xe4.html", "iso-8859-1", true, "foo-\xc3\xa4.html"},
- {"foo-\xe4.html", "iso-8859-7", true, "foo-\xce\xb4.html"},
- {"foo-\xe4.html", "foo-bar", false, ""},
- // HTML Encoding spec treats US-ASCII as synonymous with windows-1252
- {"foo-\xff.html", "ascii", true, "foo-\xc3\xbf.html"},
- {"foo.html", "ascii", true, "foo.html"},
- {"foo-a\xcc\x88.html", "utf-8", true, "foo-\xc3\xa4.html"},
- {"\x95\x32\x82\x36\xD2\xBB", "gb18030", true, "\xF0\xA0\x80\x80\xE4\xB8\x80"},
- {"\xA7\x41\xA6\x6E", "big5", true, "\xE4\xBD\xA0\xE5\xA5\xBD"},
- // Windows-1258 does have a combining character at xD2 (which is U+0309).
- // The sequence of (U+00E2, U+0309) is also encoded as U+1EA9.
- {"foo\xE2\xD2", "windows-1258", true, "foo\xE1\xBA\xA9"},
- {"", "iso-8859-1", true, ""},
-};
-TEST(ICUStringConversionsTest, ConvertToUtf8AndNormalize) {
- std::string result;
- for (size_t i = 0; i < arraysize(kConvertAndNormalizeCases); ++i) {
- SCOPED_TRACE(base::StringPrintf(
- "Test[%" PRIuS "]: <encoded: %s> <codepage: %s>", i,
- kConvertAndNormalizeCases[i].encoded,
- kConvertAndNormalizeCases[i].codepage_name));
-
- bool success = ConvertToUtf8AndNormalize(
- kConvertAndNormalizeCases[i].encoded,
- kConvertAndNormalizeCases[i].codepage_name, &result);
- EXPECT_EQ(kConvertAndNormalizeCases[i].expected_success, success);
- EXPECT_EQ(kConvertAndNormalizeCases[i].expected_value, result);
- }
-}
-
-} // namespace base
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc
deleted file mode 100644
index 4d588c6160..0000000000
--- a/base/i18n/icu_util.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/i18n/icu_util.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#include <string>
-
-#include "base/debug/alias.h"
-#include "base/files/file_path.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "build/build_config.h"
-#include "third_party/icu/source/common/unicode/putil.h"
-#include "third_party/icu/source/common/unicode/udata.h"
-#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_ANDROID)
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-#endif
-
-#if defined(OS_ANDROID)
-#include "base/android/apk_assets.h"
-#include "base/android/timezone_utils.h"
-#endif
-
-#if defined(OS_IOS)
-#include "base/ios/ios_util.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "base/mac/foundation_util.h"
-#endif
-
-#if defined(OS_FUCHSIA)
-#include "base/base_paths_fuchsia.h"
-#endif
-
-namespace base {
-namespace i18n {
-
-#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED
-#define ICU_UTIL_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat"
-#if defined(OS_WIN)
-#define ICU_UTIL_DATA_SHARED_MODULE_NAME "icudt.dll"
-#endif
-#endif
-
-namespace {
-#if !defined(OS_NACL)
-#if DCHECK_IS_ON()
-// Assert that we are not called more than once. Even though calling this
-// function isn't harmful (ICU can handle it), being called twice probably
-// indicates a programming error.
-bool g_check_called_once = true;
-bool g_called_once = false;
-#endif // DCHECK_IS_ON()
-
-#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
-
-// To debug http://crbug.com/445616.
-int g_debug_icu_last_error;
-int g_debug_icu_load;
-int g_debug_icu_pf_error_details;
-int g_debug_icu_pf_last_error;
-#if defined(OS_WIN)
-wchar_t g_debug_icu_pf_filename[_MAX_PATH];
-#endif // OS_WIN
-// Use an unversioned file name to simplify a icu version update down the road.
-// No need to change the filename in multiple places (gyp files, windows
-// build pkg configurations, etc). 'l' stands for Little Endian.
-// This variable is exported through the header file.
-const char kIcuDataFileName[] = "icudtl.dat";
-#if defined(OS_ANDROID)
-const char kAndroidAssetsIcuDataFileName[] = "assets/icudtl.dat";
-#endif
-
-// File handle intentionally never closed. Not using File here because its
-// Windows implementation guards against two instances owning the same
-// PlatformFile (which we allow since we know it is never freed).
-PlatformFile g_icudtl_pf = kInvalidPlatformFile;
-MemoryMappedFile* g_icudtl_mapped_file = nullptr;
-MemoryMappedFile::Region g_icudtl_region;
-
-void LazyInitIcuDataFile() {
- if (g_icudtl_pf != kInvalidPlatformFile) {
- return;
- }
-#if defined(OS_ANDROID)
- int fd = base::android::OpenApkAsset(kAndroidAssetsIcuDataFileName,
- &g_icudtl_region);
- g_icudtl_pf = fd;
- if (fd != -1) {
- return;
- }
-// For unit tests, data file is located on disk, so try there as a fallback.
-#endif // defined(OS_ANDROID)
-#if !defined(OS_MACOSX)
- FilePath data_path;
- if (!PathService::Get(DIR_ASSETS, &data_path)) {
- LOG(ERROR) << "Can't find " << kIcuDataFileName;
- return;
- }
-#if defined(OS_WIN)
- // TODO(brucedawson): http://crbug.com/445616
- wchar_t tmp_buffer[_MAX_PATH] = {0};
- wcscpy_s(tmp_buffer, data_path.value().c_str());
- debug::Alias(tmp_buffer);
-#endif
- data_path = data_path.AppendASCII(kIcuDataFileName);
-
-#if defined(OS_WIN)
- // TODO(brucedawson): http://crbug.com/445616
- wchar_t tmp_buffer2[_MAX_PATH] = {0};
- wcscpy_s(tmp_buffer2, data_path.value().c_str());
- debug::Alias(tmp_buffer2);
-#endif
-
-#else // !defined(OS_MACOSX)
- // Assume it is in the framework bundle's Resources directory.
- ScopedCFTypeRef<CFStringRef> data_file_name(
- SysUTF8ToCFStringRef(kIcuDataFileName));
- FilePath data_path = mac::PathForFrameworkBundleResource(data_file_name);
-#if defined(OS_IOS)
- FilePath override_data_path = base::ios::FilePathOfEmbeddedICU();
- if (!override_data_path.empty()) {
- data_path = override_data_path;
- }
-#endif // !defined(OS_IOS)
- if (data_path.empty()) {
- LOG(ERROR) << kIcuDataFileName << " not found in bundle";
- return;
- }
-#endif // !defined(OS_MACOSX)
- File file(data_path, File::FLAG_OPEN | File::FLAG_READ);
- if (file.IsValid()) {
- // TODO(brucedawson): http://crbug.com/445616.
- g_debug_icu_pf_last_error = 0;
- g_debug_icu_pf_error_details = 0;
-#if defined(OS_WIN)
- g_debug_icu_pf_filename[0] = 0;
-#endif // OS_WIN
-
- g_icudtl_pf = file.TakePlatformFile();
- g_icudtl_region = MemoryMappedFile::Region::kWholeFile;
- }
-#if defined(OS_WIN)
- else {
- // TODO(brucedawson): http://crbug.com/445616.
- g_debug_icu_pf_last_error = ::GetLastError();
- g_debug_icu_pf_error_details = file.error_details();
- wcscpy_s(g_debug_icu_pf_filename, data_path.value().c_str());
- }
-#endif // OS_WIN
-}
-
-bool InitializeICUWithFileDescriptorInternal(
- PlatformFile data_fd,
- const MemoryMappedFile::Region& data_region) {
- // This can be called multiple times in tests.
- if (g_icudtl_mapped_file) {
- g_debug_icu_load = 0; // To debug http://crbug.com/445616.
- return true;
- }
- if (data_fd == kInvalidPlatformFile) {
- g_debug_icu_load = 1; // To debug http://crbug.com/445616.
- LOG(ERROR) << "Invalid file descriptor to ICU data received.";
- return false;
- }
-
- std::unique_ptr<MemoryMappedFile> icudtl_mapped_file(new MemoryMappedFile());
- if (!icudtl_mapped_file->Initialize(File(data_fd), data_region)) {
- g_debug_icu_load = 2; // To debug http://crbug.com/445616.
- LOG(ERROR) << "Couldn't mmap icu data file";
- return false;
- }
- g_icudtl_mapped_file = icudtl_mapped_file.release();
-
- UErrorCode err = U_ZERO_ERROR;
- udata_setCommonData(const_cast<uint8_t*>(g_icudtl_mapped_file->data()), &err);
- if (err != U_ZERO_ERROR) {
- g_debug_icu_load = 3; // To debug http://crbug.com/445616.
- g_debug_icu_last_error = err;
- }
-#if defined(OS_ANDROID)
- else {
- // On Android, we can't leave it up to ICU to set the default timezone
- // because ICU's timezone detection does not work in many timezones (e.g.
- // Australia/Sydney, Asia/Seoul, Europe/Paris ). Use JNI to detect the host
- // timezone and set the ICU default timezone accordingly in advance of
- // actual use. See crbug.com/722821 and
- // https://ssl.icu-project.org/trac/ticket/13208 .
- base::string16 timezone_id = base::android::GetDefaultTimeZoneId();
- icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(
- icu::UnicodeString(FALSE, timezone_id.data(), timezone_id.length())));
- }
-#endif
- // Never try to load ICU data from files.
- udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
- return err == U_ZERO_ERROR;
-}
-#endif // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
-#endif // !defined(OS_NACL)
-
-} // namespace
-
-#if !defined(OS_NACL)
-#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
-#if defined(OS_ANDROID)
-bool InitializeICUWithFileDescriptor(
- PlatformFile data_fd,
- const MemoryMappedFile::Region& data_region) {
-#if DCHECK_IS_ON()
- DCHECK(!g_check_called_once || !g_called_once);
- g_called_once = true;
-#endif
- return InitializeICUWithFileDescriptorInternal(data_fd, data_region);
-}
-
-PlatformFile GetIcuDataFileHandle(MemoryMappedFile::Region* out_region) {
- CHECK_NE(g_icudtl_pf, kInvalidPlatformFile);
- *out_region = g_icudtl_region;
- return g_icudtl_pf;
-}
-#endif
-
-const uint8_t* GetRawIcuMemory() {
- CHECK(g_icudtl_mapped_file);
- return g_icudtl_mapped_file->data();
-}
-
-bool InitializeICUFromRawMemory(const uint8_t* raw_memory) {
-#if !defined(COMPONENT_BUILD)
-#if DCHECK_IS_ON()
- DCHECK(!g_check_called_once || !g_called_once);
- g_called_once = true;
-#endif
-
- UErrorCode err = U_ZERO_ERROR;
- udata_setCommonData(const_cast<uint8_t*>(raw_memory), &err);
- // Never try to load ICU data from files.
- udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
- return err == U_ZERO_ERROR;
-#else
- return true;
-#endif
-}
-
-#endif // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
-
-bool InitializeICU() {
-#if DCHECK_IS_ON()
- DCHECK(!g_check_called_once || !g_called_once);
- g_called_once = true;
-#endif
-
- bool result;
-#if (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_SHARED)
- FilePath data_path;
- PathService::Get(DIR_ASSETS, &data_path);
- data_path = data_path.AppendASCII(ICU_UTIL_DATA_SHARED_MODULE_NAME);
-
- HMODULE module = LoadLibrary(data_path.value().c_str());
- if (!module) {
- LOG(ERROR) << "Failed to load " << ICU_UTIL_DATA_SHARED_MODULE_NAME;
- return false;
- }
-
- FARPROC addr = GetProcAddress(module, ICU_UTIL_DATA_SYMBOL);
- if (!addr) {
- LOG(ERROR) << ICU_UTIL_DATA_SYMBOL << ": not found in "
- << ICU_UTIL_DATA_SHARED_MODULE_NAME;
- return false;
- }
-
- UErrorCode err = U_ZERO_ERROR;
- udata_setCommonData(reinterpret_cast<void*>(addr), &err);
- // Never try to load ICU data from files.
- udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
- result = (err == U_ZERO_ERROR);
-#elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_STATIC)
- // The ICU data is statically linked.
- result = true;
-#elif (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE)
- // If the ICU data directory is set, ICU won't actually load the data until
- // it is needed. This can fail if the process is sandboxed at that time.
- // Instead, we map the file in and hand off the data so the sandbox won't
- // cause any problems.
- LazyInitIcuDataFile();
- result =
- InitializeICUWithFileDescriptorInternal(g_icudtl_pf, g_icudtl_region);
-#if defined(OS_WIN)
- int debug_icu_load = g_debug_icu_load;
- debug::Alias(&debug_icu_load);
- int debug_icu_last_error = g_debug_icu_last_error;
- debug::Alias(&debug_icu_last_error);
- int debug_icu_pf_last_error = g_debug_icu_pf_last_error;
- debug::Alias(&debug_icu_pf_last_error);
- int debug_icu_pf_error_details = g_debug_icu_pf_error_details;
- debug::Alias(&debug_icu_pf_error_details);
- wchar_t debug_icu_pf_filename[_MAX_PATH] = {0};
- wcscpy_s(debug_icu_pf_filename, g_debug_icu_pf_filename);
- debug::Alias(&debug_icu_pf_filename);
- CHECK(result); // TODO(brucedawson): http://crbug.com/445616
-#endif
-#endif
-
-// To respond to the timezone change properly, the default timezone
-// cache in ICU has to be populated on starting up.
-// TODO(jungshik): Some callers do not care about tz at all. If necessary,
-// add a boolean argument to this function to init'd the default tz only
-// when requested.
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- if (result)
- std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
-#endif
- return result;
-}
-#endif // !defined(OS_NACL)
-
-void AllowMultipleInitializeCallsForTesting() {
-#if DCHECK_IS_ON() && !defined(OS_NACL)
- g_check_called_once = false;
-#endif
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/icu_util.h b/base/i18n/icu_util.h
deleted file mode 100644
index 5f9948fa65..0000000000
--- a/base/i18n/icu_util.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_ICU_UTIL_H_
-#define BASE_I18N_ICU_UTIL_H_
-
-#include <stdint.h>
-
-#include "base/files/memory_mapped_file.h"
-#include "base/i18n/base_i18n_export.h"
-#include "build/build_config.h"
-
-#define ICU_UTIL_DATA_FILE 0
-#define ICU_UTIL_DATA_SHARED 1
-#define ICU_UTIL_DATA_STATIC 2
-
-namespace base {
-namespace i18n {
-
-#if !defined(OS_NACL)
-// Call this function to load ICU's data tables for the current process. This
-// function should be called before ICU is used.
-BASE_I18N_EXPORT bool InitializeICU();
-
-#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
-#if defined(OS_ANDROID)
-// Returns the PlatformFile and Region that was initialized by InitializeICU().
-// Use with InitializeICUWithFileDescriptor().
-BASE_I18N_EXPORT PlatformFile GetIcuDataFileHandle(
- MemoryMappedFile::Region* out_region);
-
-// Android uses a file descriptor passed by browser process to initialize ICU
-// in render processes.
-BASE_I18N_EXPORT bool InitializeICUWithFileDescriptor(
- PlatformFile data_fd,
- const MemoryMappedFile::Region& data_region);
-#endif
-
-// Returns a void pointer to the memory mapped ICU data file.
-//
-// There are cases on Android where we would be unsafely reusing a file
-// descriptor within the same process when initializing two copies of ICU from
-// different binaries in the same address space. This returns an unowned
-// pointer to the memory mapped icu data file; consumers copies of base must
-// not outlive the copy of base that owns the memory mapped file.
-BASE_I18N_EXPORT const uint8_t* GetRawIcuMemory();
-
-// Initializes ICU memory
-//
-// This does nothing in component builds; this initialization should only be
-// done in cases where there could be two copies of base in a single process in
-// non-component builds. (The big example is standalone service libraries: the
-// Service Manager will have a copy of base linked in, and the majority of
-// service libraries will have base linked in but in non-component builds,
-// these will be separate copies of base.)
-BASE_I18N_EXPORT bool InitializeICUFromRawMemory(const uint8_t* raw_memory);
-#endif // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
-#endif // !defined(OS_NACL)
-
-// In a test binary, the call above might occur twice.
-BASE_I18N_EXPORT void AllowMultipleInitializeCallsForTesting();
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_ICU_UTIL_H_
diff --git a/base/i18n/message_formatter.cc b/base/i18n/message_formatter.cc
deleted file mode 100644
index c69dd07d3d..0000000000
--- a/base/i18n/message_formatter.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2015 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/i18n/message_formatter.h"
-
-#include "base/i18n/unicodestring.h"
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/time/time.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/common/unicode/utypes.h"
-#include "third_party/icu/source/i18n/unicode/fmtable.h"
-#include "third_party/icu/source/i18n/unicode/msgfmt.h"
-
-using icu::UnicodeString;
-
-namespace base {
-namespace i18n {
-namespace {
-UnicodeString UnicodeStringFromStringPiece(StringPiece str) {
- return UnicodeString::fromUTF8(
- icu::StringPiece(str.data(), base::checked_cast<int32_t>(str.size())));
-}
-} // anonymous namespace
-
-namespace internal {
-MessageArg::MessageArg() : formattable(nullptr) {}
-
-MessageArg::MessageArg(const char* s)
- : formattable(new icu::Formattable(UnicodeStringFromStringPiece(s))) {}
-
-MessageArg::MessageArg(StringPiece s)
- : formattable(new icu::Formattable(UnicodeStringFromStringPiece(s))) {}
-
-MessageArg::MessageArg(const std::string& s)
- : formattable(new icu::Formattable(UnicodeString::fromUTF8(s))) {}
-
-MessageArg::MessageArg(const string16& s)
- : formattable(new icu::Formattable(UnicodeString(s.data(), s.size()))) {}
-
-MessageArg::MessageArg(int i) : formattable(new icu::Formattable(i)) {}
-
-MessageArg::MessageArg(int64_t i) : formattable(new icu::Formattable(i)) {}
-
-MessageArg::MessageArg(double d) : formattable(new icu::Formattable(d)) {}
-
-MessageArg::MessageArg(const Time& t)
- : formattable(new icu::Formattable(static_cast<UDate>(t.ToJsTime()))) {}
-
-MessageArg::~MessageArg() = default;
-
-// Tests if this argument has a value, and if so increments *count.
-bool MessageArg::has_value(int *count) const {
- if (formattable == nullptr)
- return false;
-
- ++*count;
- return true;
-}
-
-} // namespace internal
-
-string16 MessageFormatter::FormatWithNumberedArgs(
- StringPiece16 msg,
- const internal::MessageArg& arg0,
- const internal::MessageArg& arg1,
- const internal::MessageArg& arg2,
- const internal::MessageArg& arg3,
- const internal::MessageArg& arg4,
- const internal::MessageArg& arg5,
- const internal::MessageArg& arg6) {
- int32_t args_count = 0;
- icu::Formattable args[] = {
- arg0.has_value(&args_count) ? *arg0.formattable : icu::Formattable(),
- arg1.has_value(&args_count) ? *arg1.formattable : icu::Formattable(),
- arg2.has_value(&args_count) ? *arg2.formattable : icu::Formattable(),
- arg3.has_value(&args_count) ? *arg3.formattable : icu::Formattable(),
- arg4.has_value(&args_count) ? *arg4.formattable : icu::Formattable(),
- arg5.has_value(&args_count) ? *arg5.formattable : icu::Formattable(),
- arg6.has_value(&args_count) ? *arg6.formattable : icu::Formattable(),
- };
-
- UnicodeString msg_string(msg.data(), msg.size());
- UErrorCode error = U_ZERO_ERROR;
- icu::MessageFormat format(msg_string, error);
- icu::UnicodeString formatted;
- icu::FieldPosition ignore(icu::FieldPosition::DONT_CARE);
- format.format(args, args_count, formatted, ignore, error);
- if (U_FAILURE(error)) {
- LOG(ERROR) << "MessageFormat(" << msg.as_string() << ") failed with "
- << u_errorName(error);
- return string16();
- }
- return i18n::UnicodeStringToString16(formatted);
-}
-
-string16 MessageFormatter::FormatWithNamedArgs(
- StringPiece16 msg,
- StringPiece name0, const internal::MessageArg& arg0,
- StringPiece name1, const internal::MessageArg& arg1,
- StringPiece name2, const internal::MessageArg& arg2,
- StringPiece name3, const internal::MessageArg& arg3,
- StringPiece name4, const internal::MessageArg& arg4,
- StringPiece name5, const internal::MessageArg& arg5,
- StringPiece name6, const internal::MessageArg& arg6) {
- icu::UnicodeString names[] = {
- UnicodeStringFromStringPiece(name0),
- UnicodeStringFromStringPiece(name1),
- UnicodeStringFromStringPiece(name2),
- UnicodeStringFromStringPiece(name3),
- UnicodeStringFromStringPiece(name4),
- UnicodeStringFromStringPiece(name5),
- UnicodeStringFromStringPiece(name6),
- };
- int32_t args_count = 0;
- icu::Formattable args[] = {
- arg0.has_value(&args_count) ? *arg0.formattable : icu::Formattable(),
- arg1.has_value(&args_count) ? *arg1.formattable : icu::Formattable(),
- arg2.has_value(&args_count) ? *arg2.formattable : icu::Formattable(),
- arg3.has_value(&args_count) ? *arg3.formattable : icu::Formattable(),
- arg4.has_value(&args_count) ? *arg4.formattable : icu::Formattable(),
- arg5.has_value(&args_count) ? *arg5.formattable : icu::Formattable(),
- arg6.has_value(&args_count) ? *arg6.formattable : icu::Formattable(),
- };
-
- UnicodeString msg_string(msg.data(), msg.size());
- UErrorCode error = U_ZERO_ERROR;
- icu::MessageFormat format(msg_string, error);
-
- icu::UnicodeString formatted;
- format.format(names, args, args_count, formatted, error);
- if (U_FAILURE(error)) {
- LOG(ERROR) << "MessageFormat(" << msg.as_string() << ") failed with "
- << u_errorName(error);
- return string16();
- }
- return i18n::UnicodeStringToString16(formatted);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/message_formatter.h b/base/i18n/message_formatter.h
deleted file mode 100644
index 36a656d771..0000000000
--- a/base/i18n/message_formatter.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_I18N_MESSAGE_FORMATTER_H_
-#define BASE_I18N_MESSAGE_FORMATTER_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-#include "third_party/icu/source/common/unicode/uversion.h"
-
-U_NAMESPACE_BEGIN
-class Formattable;
-U_NAMESPACE_END
-
-namespace base {
-
-class Time;
-
-namespace i18n {
-
-class MessageFormatter;
-
-namespace internal {
-
-class BASE_I18N_EXPORT MessageArg {
- public:
- MessageArg(const char* s);
- MessageArg(StringPiece s);
- MessageArg(const std::string& s);
- MessageArg(const string16& s);
- MessageArg(int i);
- MessageArg(int64_t i);
- MessageArg(double d);
- MessageArg(const Time& t);
- ~MessageArg();
-
- private:
- friend class base::i18n::MessageFormatter;
- MessageArg();
- // Tests if this argument has a value, and if so increments *count.
- bool has_value(int* count) const;
- std::unique_ptr<icu::Formattable> formattable;
- DISALLOW_COPY_AND_ASSIGN(MessageArg);
-};
-
-} // namespace internal
-
-// Message Formatter with the ICU message format syntax support.
-// It can format strings (UTF-8 and UTF-16), numbers and base::Time with
-// plural, gender and other 'selectors' support. This is handy if you
-// have multiple parameters of differnt types and some of them require
-// plural or gender/selector support.
-//
-// To use this API for locale-sensitive formatting, retrieve a 'message
-// template' in the ICU message format from a message bundle (e.g. with
-// l10n_util::GetStringUTF16()) and pass it to FormatWith{Named,Numbered}Args.
-//
-// MessageFormat specs:
-// http://icu-project.org/apiref/icu4j/com/ibm/icu/text/MessageFormat.html
-// http://icu-project.org/apiref/icu4c/classicu_1_1DecimalFormat.html#details
-// Examples:
-// http://userguide.icu-project.org/formatparse/messages
-// message_formatter_unittest.cc
-// go/plurals inside Google.
-// TODO(jshin): Document this API in md format docs.
-// Caveat:
-// When plural/select/gender is used along with other format specifiers such
-// as date or number, plural/select/gender should be at the top level. It's
-// not an ICU restriction but a constraint imposed by Google's translation
-// infrastructure. Message A does not work. It must be revised to Message B.
-//
-// A.
-// Rated <ph name="RATING">{0, number,0.0}<ex>3.2</ex></ph>
-// by {1, plural, =1{a user} other{# users}}
-//
-// B.
-// {1, plural,
-// =1{Rated <ph name="RATING">{0, number,0.0}<ex>3.2</ex></ph>
-// by a user.}
-// other{Rated <ph name="RATING">{0, number,0.0}<ex>3.2</ex></ph>
-// by # users.}}
-
-class BASE_I18N_EXPORT MessageFormatter {
- public:
- static string16 FormatWithNamedArgs(
- StringPiece16 msg,
- StringPiece name0 = StringPiece(),
- const internal::MessageArg& arg0 = internal::MessageArg(),
- StringPiece name1 = StringPiece(),
- const internal::MessageArg& arg1 = internal::MessageArg(),
- StringPiece name2 = StringPiece(),
- const internal::MessageArg& arg2 = internal::MessageArg(),
- StringPiece name3 = StringPiece(),
- const internal::MessageArg& arg3 = internal::MessageArg(),
- StringPiece name4 = StringPiece(),
- const internal::MessageArg& arg4 = internal::MessageArg(),
- StringPiece name5 = StringPiece(),
- const internal::MessageArg& arg5 = internal::MessageArg(),
- StringPiece name6 = StringPiece(),
- const internal::MessageArg& arg6 = internal::MessageArg());
-
- static string16 FormatWithNumberedArgs(
- StringPiece16 msg,
- const internal::MessageArg& arg0 = internal::MessageArg(),
- const internal::MessageArg& arg1 = internal::MessageArg(),
- const internal::MessageArg& arg2 = internal::MessageArg(),
- const internal::MessageArg& arg3 = internal::MessageArg(),
- const internal::MessageArg& arg4 = internal::MessageArg(),
- const internal::MessageArg& arg5 = internal::MessageArg(),
- const internal::MessageArg& arg6 = internal::MessageArg());
-
- private:
- MessageFormatter() = delete;
- DISALLOW_COPY_AND_ASSIGN(MessageFormatter);
-};
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_MESSAGE_FORMATTER_H_
diff --git a/base/i18n/message_formatter_unittest.cc b/base/i18n/message_formatter_unittest.cc
deleted file mode 100644
index a6f461370c..0000000000
--- a/base/i18n/message_formatter_unittest.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright 2015 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/i18n/message_formatter.h"
-
-#include <memory>
-
-#include "base/i18n/rtl.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/i18n/unicode/datefmt.h"
-#include "third_party/icu/source/i18n/unicode/msgfmt.h"
-
-typedef testing::Test MessageFormatterTest;
-
-namespace base {
-namespace i18n {
-
-class MessageFormatterTest : public testing::Test {
- protected:
- MessageFormatterTest() {
- original_locale_ = GetConfiguredLocale();
- SetICUDefaultLocale("en-US");
- }
- ~MessageFormatterTest() override {
- SetICUDefaultLocale(original_locale_);
- }
-
- private:
- std::string original_locale_;
-};
-
-namespace {
-
-void AppendFormattedDateTime(const std::unique_ptr<icu::DateFormat>& df,
- const Time& now,
- std::string* result) {
- icu::UnicodeString formatted;
- df->format(static_cast<UDate>(now.ToJsTime()), formatted).
- toUTF8String(*result);
-}
-
-} // namespace
-
-TEST_F(MessageFormatterTest, PluralNamedArgs) {
- const string16 pattern = ASCIIToUTF16(
- "{num_people, plural, "
- "=0 {I met nobody in {place}.}"
- "=1 {I met a person in {place}.}"
- "other {I met # people in {place}.}}");
-
- std::string result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 0, "place", "Paris"));
- EXPECT_EQ("I met nobody in Paris.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 1, "place", "Paris"));
- EXPECT_EQ("I met a person in Paris.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 5, "place", "Paris"));
- EXPECT_EQ("I met 5 people in Paris.", result);
-}
-
-TEST_F(MessageFormatterTest, PluralNamedArgsWithOffset) {
- const string16 pattern = ASCIIToUTF16(
- "{num_people, plural, offset:1 "
- "=0 {I met nobody in {place}.}"
- "=1 {I met {person} in {place}.}"
- "=2 {I met {person} and one other person in {place}.}"
- "=13 {I met {person} and a dozen other people in {place}.}"
- "other {I met {person} and # other people in {place}.}}");
-
- std::string result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 0, "place", "Paris"));
- EXPECT_EQ("I met nobody in Paris.", result);
- // {person} is ignored if {num_people} is 0.
- result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 0, "place", "Paris", "person", "Peter"));
- EXPECT_EQ("I met nobody in Paris.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 1, "place", "Paris", "person", "Peter"));
- EXPECT_EQ("I met Peter in Paris.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 2, "place", "Paris", "person", "Peter"));
- EXPECT_EQ("I met Peter and one other person in Paris.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 13, "place", "Paris", "person", "Peter"));
- EXPECT_EQ("I met Peter and a dozen other people in Paris.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs(
- pattern, "num_people", 50, "place", "Paris", "person", "Peter"));
- EXPECT_EQ("I met Peter and 49 other people in Paris.", result);
-}
-
-TEST_F(MessageFormatterTest, PluralNumberedArgs) {
- const string16 pattern = ASCIIToUTF16(
- "{1, plural, "
- "=1 {The cert for {0} expired yesterday.}"
- "=7 {The cert for {0} expired a week ago.}"
- "other {The cert for {0} expired # days ago.}}");
-
- std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "example.com", 1));
- EXPECT_EQ("The cert for example.com expired yesterday.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "example.com", 7));
- EXPECT_EQ("The cert for example.com expired a week ago.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "example.com", 15));
- EXPECT_EQ("The cert for example.com expired 15 days ago.", result);
-}
-
-TEST_F(MessageFormatterTest, PluralNumberedArgsWithDate) {
- const string16 pattern = ASCIIToUTF16(
- "{1, plural, "
- "=1 {The cert for {0} expired yesterday. Today is {2,date,full}}"
- "other {The cert for {0} expired # days ago. Today is {2,date,full}}}");
-
- base::Time now = base::Time::Now();
- using icu::DateFormat;
- std::unique_ptr<DateFormat> df(
- DateFormat::createDateInstance(DateFormat::FULL));
- std::string second_sentence = " Today is ";
- AppendFormattedDateTime(df, now, &second_sentence);
-
- std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "example.com", 1, now));
- EXPECT_EQ("The cert for example.com expired yesterday." + second_sentence,
- result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "example.com", 15, now));
- EXPECT_EQ("The cert for example.com expired 15 days ago." + second_sentence,
- result);
-}
-
-TEST_F(MessageFormatterTest, DateTimeAndNumber) {
- // Note that using 'mph' for all locales is not a good i18n practice.
- const string16 pattern = ASCIIToUTF16(
- "At {0,time, short} on {0,date, medium}, "
- "there was {1} at building {2,number,integer}. "
- "The speed of the wind was {3,number,###.#} mph.");
-
- using icu::DateFormat;
- std::unique_ptr<DateFormat> tf(
- DateFormat::createTimeInstance(DateFormat::SHORT));
- std::unique_ptr<DateFormat> df(
- DateFormat::createDateInstance(DateFormat::MEDIUM));
-
- base::Time now = base::Time::Now();
- std::string expected = "At ";
- AppendFormattedDateTime(tf, now, &expected);
- expected.append(" on ");
- AppendFormattedDateTime(df, now, &expected);
- expected.append(", there was an explosion at building 3. "
- "The speed of the wind was 37.4 mph.");
-
- EXPECT_EQ(expected, UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, now, "an explosion", 3, 37.413)));
-}
-
-TEST_F(MessageFormatterTest, SelectorSingleOrMultiple) {
- const string16 pattern = ASCIIToUTF16(
- "{0, select,"
- "single {Select a file to upload.}"
- "multiple {Select files to upload.}"
- "other {UNUSED}}");
-
- std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "single"));
- EXPECT_EQ("Select a file to upload.", result);
- result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "multiple"));
- EXPECT_EQ("Select files to upload.", result);
-
- // fallback if a parameter is not selectors specified in the message pattern.
- result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs(
- pattern, "foobar"));
- EXPECT_EQ("UNUSED", result);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/number_formatting.cc b/base/i18n/number_formatting.cc
deleted file mode 100644
index 0ab031ecaf..0000000000
--- a/base/i18n/number_formatting.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/i18n/number_formatting.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/format_macros.h"
-#include "base/i18n/message_formatter.h"
-#include "base/i18n/unicodestring.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/icu/source/common/unicode/ustring.h"
-#include "third_party/icu/source/i18n/unicode/numfmt.h"
-
-namespace base {
-
-namespace {
-
-// A simple wrapper around icu::NumberFormat that allows for resetting it
-// (as LazyInstance does not).
-struct NumberFormatWrapper {
- NumberFormatWrapper() {
- Reset();
- }
-
- void Reset() {
- // There's no ICU call to destroy a NumberFormat object other than
- // operator delete, so use the default Delete, which calls operator delete.
- // This can cause problems if a different allocator is used by this file
- // than by ICU.
- UErrorCode status = U_ZERO_ERROR;
- number_format.reset(icu::NumberFormat::createInstance(status));
- DCHECK(U_SUCCESS(status));
- }
-
- std::unique_ptr<icu::NumberFormat> number_format;
-};
-
-LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_int =
- LAZY_INSTANCE_INITIALIZER;
-LazyInstance<NumberFormatWrapper>::DestructorAtExit g_number_format_float =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-string16 FormatNumber(int64_t number) {
- icu::NumberFormat* number_format =
- g_number_format_int.Get().number_format.get();
-
- if (!number_format) {
- // As a fallback, just return the raw number in a string.
- return ASCIIToUTF16(StringPrintf("%" PRId64, number));
- }
- icu::UnicodeString ustr;
- number_format->format(number, ustr);
-
- return i18n::UnicodeStringToString16(ustr);
-}
-
-string16 FormatDouble(double number, int fractional_digits) {
- icu::NumberFormat* number_format =
- g_number_format_float.Get().number_format.get();
-
- if (!number_format) {
- // As a fallback, just return the raw number in a string.
- return ASCIIToUTF16(StringPrintf("%f", number));
- }
- number_format->setMaximumFractionDigits(fractional_digits);
- number_format->setMinimumFractionDigits(fractional_digits);
- icu::UnicodeString ustr;
- number_format->format(number, ustr);
-
- return i18n::UnicodeStringToString16(ustr);
-}
-
-string16 FormatPercent(int number) {
- return i18n::MessageFormatter::FormatWithNumberedArgs(
- ASCIIToUTF16("{0,number,percent}"), static_cast<double>(number) / 100.0);
-}
-
-namespace testing {
-
-void ResetFormatters() {
- g_number_format_int.Get().Reset();
- g_number_format_float.Get().Reset();
-}
-
-} // namespace testing
-
-} // namespace base
diff --git a/base/i18n/number_formatting.h b/base/i18n/number_formatting.h
deleted file mode 100644
index 9636bf4d1b..0000000000
--- a/base/i18n/number_formatting.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_NUMBER_FORMATTING_H_
-#define BASE_I18N_NUMBER_FORMATTING_H_
-
-#include <stdint.h>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/strings/string16.h"
-
-namespace base {
-
-// Return a number formatted with separators in the user's locale.
-// Ex: FormatNumber(1234567) => "1,234,567" in English, "1.234.567" in German
-BASE_I18N_EXPORT string16 FormatNumber(int64_t number);
-
-// Return a number formatted with separators in the user's locale.
-// Ex: FormatDouble(1234567.8, 1)
-// => "1,234,567.8" in English, "1.234.567,8" in German
-BASE_I18N_EXPORT string16 FormatDouble(double number, int fractional_digits);
-
-// Return a percentage formatted with space and symbol in the user's locale.
-// Ex: FormatPercent(12) => "12%" in English, "12 %" in Romanian
-BASE_I18N_EXPORT string16 FormatPercent(int number);
-
-namespace testing {
-
-// Causes cached formatters to be discarded and recreated. Only useful for
-// testing.
-BASE_I18N_EXPORT void ResetFormatters();
-
-} // namespace testing
-
-} // namespace base
-
-#endif // BASE_I18N_NUMBER_FORMATTING_H_
diff --git a/base/i18n/number_formatting_unittest.cc b/base/i18n/number_formatting_unittest.cc
deleted file mode 100644
index d2eb568796..0000000000
--- a/base/i18n/number_formatting_unittest.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2011 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 <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/i18n/number_formatting.h"
-#include "base/i18n/rtl.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/icu_test_util.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/icu/source/i18n/unicode/usearch.h"
-
-namespace base {
-namespace {
-
-TEST(NumberFormattingTest, FormatNumber) {
- static const struct {
- int64_t number;
- const char* expected_english;
- const char* expected_german;
- } cases[] = {
- {0, "0", "0"},
- {1024, "1,024", "1.024"},
- {std::numeric_limits<int64_t>::max(),
- "9,223,372,036,854,775,807", "9.223.372.036.854.775.807"},
- {std::numeric_limits<int64_t>::min(),
- "-9,223,372,036,854,775,808", "-9.223.372.036.854.775.808"},
- {-42, "-42", "-42"},
- };
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- i18n::SetICUDefaultLocale("en");
- testing::ResetFormatters();
- EXPECT_EQ(cases[i].expected_english,
- UTF16ToUTF8(FormatNumber(cases[i].number)));
- i18n::SetICUDefaultLocale("de");
- testing::ResetFormatters();
- EXPECT_EQ(cases[i].expected_german,
- UTF16ToUTF8(FormatNumber(cases[i].number)));
- }
-}
-
-TEST(NumberFormattingTest, FormatDouble) {
- static const struct {
- double number;
- int frac_digits;
- const char* expected_english;
- const char* expected_german;
- } cases[] = {
- {0.0, 0, "0", "0"},
-#if !defined(OS_ANDROID)
- // Bionic can't printf negative zero correctly.
- {-0.0, 4, "-0.0000", "-0,0000"},
-#endif
- {1024.2, 0, "1,024", "1.024"},
- {-1024.223, 2, "-1,024.22", "-1.024,22"},
- {std::numeric_limits<double>::max(), 6,
- "179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,"
- "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,"
- "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,"
- "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,"
- "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,"
- "000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,"
- "000.000000",
- "179.769.313.486.231.570.000.000.000.000.000.000.000.000.000.000.000."
- "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000."
- "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000."
- "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000."
- "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000."
- "000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000.000."
- "000,000000"},
- {std::numeric_limits<double>::min(), 2, "0.00", "0,00"},
- {-42.7, 3, "-42.700", "-42,700"},
- };
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- for (size_t i = 0; i < arraysize(cases); ++i) {
- i18n::SetICUDefaultLocale("en");
- testing::ResetFormatters();
- EXPECT_EQ(cases[i].expected_english,
- UTF16ToUTF8(FormatDouble(cases[i].number, cases[i].frac_digits)));
- i18n::SetICUDefaultLocale("de");
- testing::ResetFormatters();
- EXPECT_EQ(cases[i].expected_german,
- UTF16ToUTF8(FormatDouble(cases[i].number, cases[i].frac_digits)));
- }
-}
-
-TEST(NumberFormattingTest, FormatPercent) {
- static const struct {
- int64_t number;
- const char* expected_english;
- const char* expected_german; // Note: Space before % isn't \x20.
- // Note: Eastern Arabic-Indic digits (U+06Fx) for Persian and
- // Arabic-Indic digits (U+066x) for Arabic in Egypt(ar-EG). In Arabic (ar),
- // uses European digits (Google-patch).
- // See https://unicode.org/cldr/trac/ticket/9040 for details.
- // See also https://unicode.org/cldr/trac/ticket/10176 .
- // For now, take what CLDR 32 has (percent sign to the right of
- // a number in Persian).
- const char* expected_persian;
- const char* expected_arabic;
- const char* expected_arabic_egypt;
- } cases[] = {
- {0, "0%", u8"0\u00a0%", u8"\u06f0\u066a", u8"0\u200e%\u200e",
- u8"\u0660\u066a\u061c"},
- {42, "42%", "42\u00a0%", u8"\u06f4\u06f2\u066a", u8"42\u200e%\u200e",
- "\u0664\u0662\u066a\u061c"},
- {1024, "1,024%", "1.024\u00a0%", u8"\u06f1\u066c\u06f0\u06f2\u06f4\u066a",
- "1,024\u200e%\u200e", "\u0661\u066c\u0660\u0662\u0664\u066a\u061c"},
- };
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- for (size_t i = 0; i < arraysize(cases); ++i) {
- i18n::SetICUDefaultLocale("en");
- EXPECT_EQ(ASCIIToUTF16(cases[i].expected_english),
- FormatPercent(cases[i].number));
- i18n::SetICUDefaultLocale("de");
- EXPECT_EQ(UTF8ToUTF16(cases[i].expected_german),
- FormatPercent(cases[i].number));
- i18n::SetICUDefaultLocale("fa");
- EXPECT_EQ(UTF8ToUTF16(cases[i].expected_persian),
- FormatPercent(cases[i].number));
- i18n::SetICUDefaultLocale("ar");
- EXPECT_EQ(UTF8ToUTF16(cases[i].expected_arabic),
- FormatPercent(cases[i].number));
- i18n::SetICUDefaultLocale("ar-EG");
- EXPECT_EQ(UTF8ToUTF16(cases[i].expected_arabic_egypt),
- FormatPercent(cases[i].number));
- }
-}
-
-} // namespace
-} // namespace base
diff --git a/base/i18n/rtl.cc b/base/i18n/rtl.cc
deleted file mode 100644
index 5a8db8ae1c..0000000000
--- a/base/i18n/rtl.cc
+++ /dev/null
@@ -1,496 +0,0 @@
-// Copyright (c) 2011 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/i18n/rtl.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/i18n/base_i18n_switches.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "third_party/icu/source/common/unicode/locid.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
-#include "third_party/icu/source/common/unicode/uscript.h"
-#include "third_party/icu/source/i18n/unicode/coll.h"
-
-#if defined(OS_IOS)
-#include "base/debug/crash_logging.h"
-#include "base/ios/ios_util.h"
-#endif
-
-namespace {
-
-// Extract language, country and variant, but ignore keywords. For example,
-// en-US, ca@valencia, ca-ES@valencia.
-std::string GetLocaleString(const icu::Locale& locale) {
- const char* language = locale.getLanguage();
- const char* country = locale.getCountry();
- const char* variant = locale.getVariant();
-
- std::string result =
- (language != nullptr && *language != '\0') ? language : "und";
-
- if (country != nullptr && *country != '\0') {
- result += '-';
- result += country;
- }
-
- if (variant != nullptr && *variant != '\0')
- result += '@' + base::ToLowerASCII(variant);
-
- return result;
-}
-
-// Returns LEFT_TO_RIGHT or RIGHT_TO_LEFT if |character| has strong
-// directionality, returns UNKNOWN_DIRECTION if it doesn't. Please refer to
-// http://unicode.org/reports/tr9/ for more information.
-base::i18n::TextDirection GetCharacterDirection(UChar32 character) {
- static bool has_switch = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceTextDirection);
- if (has_switch) {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- std::string force_flag =
- command_line->GetSwitchValueASCII(switches::kForceTextDirection);
-
- if (force_flag == switches::kForceDirectionRTL)
- return base::i18n::RIGHT_TO_LEFT;
- if (force_flag == switches::kForceDirectionLTR)
- return base::i18n::LEFT_TO_RIGHT;
- }
- // Now that we have the character, we use ICU in order to query for the
- // appropriate Unicode BiDi character type.
- int32_t property = u_getIntPropertyValue(character, UCHAR_BIDI_CLASS);
- if ((property == U_RIGHT_TO_LEFT) ||
- (property == U_RIGHT_TO_LEFT_ARABIC) ||
- (property == U_RIGHT_TO_LEFT_EMBEDDING) ||
- (property == U_RIGHT_TO_LEFT_OVERRIDE)) {
- return base::i18n::RIGHT_TO_LEFT;
- } else if ((property == U_LEFT_TO_RIGHT) ||
- (property == U_LEFT_TO_RIGHT_EMBEDDING) ||
- (property == U_LEFT_TO_RIGHT_OVERRIDE)) {
- return base::i18n::LEFT_TO_RIGHT;
- }
- return base::i18n::UNKNOWN_DIRECTION;
-}
-
-} // namespace
-
-namespace base {
-namespace i18n {
-
-// Represents the locale-specific ICU text direction.
-static TextDirection g_icu_text_direction = UNKNOWN_DIRECTION;
-
-// Convert the ICU default locale to a string.
-std::string GetConfiguredLocale() {
- return GetLocaleString(icu::Locale::getDefault());
-}
-
-// Convert the ICU canonicalized locale to a string.
-std::string GetCanonicalLocale(const std::string& locale) {
- return GetLocaleString(icu::Locale::createCanonical(locale.c_str()));
-}
-
-// Convert Chrome locale name to ICU locale name
-std::string ICULocaleName(const std::string& locale_string) {
- // If not Spanish, just return it.
- if (locale_string.substr(0, 2) != "es")
- return locale_string;
- // Expand es to es-ES.
- if (LowerCaseEqualsASCII(locale_string, "es"))
- return "es-ES";
- // Map es-419 (Latin American Spanish) to es-FOO depending on the system
- // locale. If it's es-RR other than es-ES, map to es-RR. Otherwise, map
- // to es-MX (the most populous in Spanish-speaking Latin America).
- if (LowerCaseEqualsASCII(locale_string, "es-419")) {
- const icu::Locale& locale = icu::Locale::getDefault();
- std::string language = locale.getLanguage();
- const char* country = locale.getCountry();
- if (LowerCaseEqualsASCII(language, "es") &&
- !LowerCaseEqualsASCII(country, "es")) {
- language += '-';
- language += country;
- return language;
- }
- return "es-MX";
- }
- // Currently, Chrome has only "es" and "es-419", but later we may have
- // more specific "es-RR".
- return locale_string;
-}
-
-void SetICUDefaultLocale(const std::string& locale_string) {
-#if defined(OS_IOS)
- static base::debug::CrashKeyString* crash_key_locale =
- base::debug::AllocateCrashKeyString("icu_locale_input",
- base::debug::CrashKeySize::Size256);
- base::debug::SetCrashKeyString(crash_key_locale, locale_string);
-#endif
- icu::Locale locale(ICULocaleName(locale_string).c_str());
- UErrorCode error_code = U_ZERO_ERROR;
- const char* lang = locale.getLanguage();
- if (lang != nullptr && *lang != '\0') {
- icu::Locale::setDefault(locale, error_code);
- } else {
- LOG(ERROR) << "Failed to set the ICU default locale to " << locale_string
- << ". Falling back to en-US.";
- icu::Locale::setDefault(icu::Locale::getUS(), error_code);
- }
- g_icu_text_direction = UNKNOWN_DIRECTION;
-}
-
-bool IsRTL() {
- return ICUIsRTL();
-}
-
-void SetRTLForTesting(bool rtl) {
- SetICUDefaultLocale(rtl ? "he" : "en");
- DCHECK_EQ(rtl, IsRTL());
-}
-
-bool ICUIsRTL() {
- if (g_icu_text_direction == UNKNOWN_DIRECTION) {
- const icu::Locale& locale = icu::Locale::getDefault();
- g_icu_text_direction = GetTextDirectionForLocaleInStartUp(locale.getName());
- }
- return g_icu_text_direction == RIGHT_TO_LEFT;
-}
-
-TextDirection GetForcedTextDirection() {
-// On iOS, check for RTL forcing.
-#if defined(OS_IOS)
- if (base::ios::IsInForcedRTL())
- return base::i18n::RIGHT_TO_LEFT;
-#endif
-
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kForceUIDirection)) {
- std::string force_flag =
- command_line->GetSwitchValueASCII(switches::kForceUIDirection);
-
- if (force_flag == switches::kForceDirectionLTR)
- return base::i18n::LEFT_TO_RIGHT;
-
- if (force_flag == switches::kForceDirectionRTL)
- return base::i18n::RIGHT_TO_LEFT;
- }
-
- return base::i18n::UNKNOWN_DIRECTION;
-}
-
-TextDirection GetTextDirectionForLocaleInStartUp(const char* locale_name) {
- // Check for direction forcing.
- TextDirection forced_direction = GetForcedTextDirection();
- if (forced_direction != UNKNOWN_DIRECTION)
- return forced_direction;
-
- // This list needs to be updated in alphabetical order if we add more RTL
- // locales.
- static const char kRTLLanguageCodes[][3] = {"ar", "fa", "he", "iw", "ur"};
- std::vector<StringPiece> locale_split =
- SplitStringPiece(locale_name, "-_", KEEP_WHITESPACE, SPLIT_WANT_ALL);
- const StringPiece& language_code = locale_split[0];
- if (std::binary_search(kRTLLanguageCodes,
- kRTLLanguageCodes + arraysize(kRTLLanguageCodes),
- language_code))
- return RIGHT_TO_LEFT;
- return LEFT_TO_RIGHT;
-}
-
-TextDirection GetTextDirectionForLocale(const char* locale_name) {
- // Check for direction forcing.
- TextDirection forced_direction = GetForcedTextDirection();
- if (forced_direction != UNKNOWN_DIRECTION)
- return forced_direction;
-
- UErrorCode status = U_ZERO_ERROR;
- ULayoutType layout_dir = uloc_getCharacterOrientation(locale_name, &status);
- DCHECK(U_SUCCESS(status));
- // Treat anything other than RTL as LTR.
- return (layout_dir != ULOC_LAYOUT_RTL) ? LEFT_TO_RIGHT : RIGHT_TO_LEFT;
-}
-
-TextDirection GetFirstStrongCharacterDirection(const string16& text) {
- const UChar* string = text.c_str();
- size_t length = text.length();
- size_t position = 0;
- while (position < length) {
- UChar32 character;
- size_t next_position = position;
- U16_NEXT(string, next_position, length, character);
- TextDirection direction = GetCharacterDirection(character);
- if (direction != UNKNOWN_DIRECTION)
- return direction;
- position = next_position;
- }
- return LEFT_TO_RIGHT;
-}
-
-TextDirection GetLastStrongCharacterDirection(const string16& text) {
- const UChar* string = text.c_str();
- size_t position = text.length();
- while (position > 0) {
- UChar32 character;
- size_t prev_position = position;
- U16_PREV(string, 0, prev_position, character);
- TextDirection direction = GetCharacterDirection(character);
- if (direction != UNKNOWN_DIRECTION)
- return direction;
- position = prev_position;
- }
- return LEFT_TO_RIGHT;
-}
-
-TextDirection GetStringDirection(const string16& text) {
- const UChar* string = text.c_str();
- size_t length = text.length();
- size_t position = 0;
-
- TextDirection result(UNKNOWN_DIRECTION);
- while (position < length) {
- UChar32 character;
- size_t next_position = position;
- U16_NEXT(string, next_position, length, character);
- TextDirection direction = GetCharacterDirection(character);
- if (direction != UNKNOWN_DIRECTION) {
- if (result != UNKNOWN_DIRECTION && result != direction)
- return UNKNOWN_DIRECTION;
- result = direction;
- }
- position = next_position;
- }
-
- // Handle the case of a string not containing any strong directionality
- // characters defaulting to LEFT_TO_RIGHT.
- if (result == UNKNOWN_DIRECTION)
- return LEFT_TO_RIGHT;
-
- return result;
-}
-
-#if defined(OS_WIN)
-bool AdjustStringForLocaleDirection(string16* text) {
- if (!IsRTL() || text->empty())
- return false;
-
- // Marking the string as LTR if the locale is RTL and the string does not
- // contain strong RTL characters. Otherwise, mark the string as RTL.
- bool has_rtl_chars = StringContainsStrongRTLChars(*text);
- if (!has_rtl_chars)
- WrapStringWithLTRFormatting(text);
- else
- WrapStringWithRTLFormatting(text);
-
- return true;
-}
-
-bool UnadjustStringForLocaleDirection(string16* text) {
- if (!IsRTL() || text->empty())
- return false;
-
- *text = StripWrappingBidiControlCharacters(*text);
- return true;
-}
-#else
-bool AdjustStringForLocaleDirection(string16* text) {
- // On OS X & GTK the directionality of a label is determined by the first
- // strongly directional character.
- // However, we want to make sure that in an LTR-language-UI all strings are
- // left aligned and vice versa.
- // A problem can arise if we display a string which starts with user input.
- // User input may be of the opposite directionality to the UI. So the whole
- // string will be displayed in the opposite directionality, e.g. if we want to
- // display in an LTR UI [such as US English]:
- //
- // EMAN_NOISNETXE is now installed.
- //
- // Since EXTENSION_NAME begins with a strong RTL char, the label's
- // directionality will be set to RTL and the string will be displayed visually
- // as:
- //
- // .is now installed EMAN_NOISNETXE
- //
- // In order to solve this issue, we prepend an LRM to the string. An LRM is a
- // strongly directional LTR char.
- // We also append an LRM at the end, which ensures that we're in an LTR
- // context.
-
- // Unlike Windows, Linux and OS X can correctly display RTL glyphs out of the
- // box so there is no issue with displaying zero-width bidi control characters
- // on any system. Thus no need for the !IsRTL() check here.
- if (text->empty())
- return false;
-
- bool ui_direction_is_rtl = IsRTL();
-
- bool has_rtl_chars = StringContainsStrongRTLChars(*text);
- if (!ui_direction_is_rtl && has_rtl_chars) {
- WrapStringWithRTLFormatting(text);
- text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
- kLeftToRightMark);
- text->push_back(kLeftToRightMark);
- } else if (ui_direction_is_rtl && has_rtl_chars) {
- WrapStringWithRTLFormatting(text);
- text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
- kRightToLeftMark);
- text->push_back(kRightToLeftMark);
- } else if (ui_direction_is_rtl) {
- WrapStringWithLTRFormatting(text);
- text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
- kRightToLeftMark);
- text->push_back(kRightToLeftMark);
- } else {
- return false;
- }
-
- return true;
-}
-
-bool UnadjustStringForLocaleDirection(string16* text) {
- if (text->empty())
- return false;
-
- size_t begin_index = 0;
- char16 begin = text->at(begin_index);
- if (begin == kLeftToRightMark ||
- begin == kRightToLeftMark) {
- ++begin_index;
- }
-
- size_t end_index = text->length() - 1;
- char16 end = text->at(end_index);
- if (end == kLeftToRightMark ||
- end == kRightToLeftMark) {
- --end_index;
- }
-
- string16 unmarked_text =
- text->substr(begin_index, end_index - begin_index + 1);
- *text = StripWrappingBidiControlCharacters(unmarked_text);
- return true;
-}
-
-#endif // !OS_WIN
-
-void EnsureTerminatedDirectionalFormatting(string16* text) {
- int count = 0;
- for (auto c : *text) {
- if (c == kLeftToRightEmbeddingMark || c == kRightToLeftEmbeddingMark ||
- c == kLeftToRightOverride || c == kRightToLeftOverride) {
- ++count;
- } else if (c == kPopDirectionalFormatting && count > 0) {
- --count;
- }
- }
- for (int j = 0; j < count; j++)
- text->push_back(kPopDirectionalFormatting);
-}
-
-void SanitizeUserSuppliedString(string16* text) {
- EnsureTerminatedDirectionalFormatting(text);
- AdjustStringForLocaleDirection(text);
-}
-
-bool StringContainsStrongRTLChars(const string16& text) {
- const UChar* string = text.c_str();
- size_t length = text.length();
- size_t position = 0;
- while (position < length) {
- UChar32 character;
- size_t next_position = position;
- U16_NEXT(string, next_position, length, character);
-
- // Now that we have the character, we use ICU in order to query for the
- // appropriate Unicode BiDi character type.
- int32_t property = u_getIntPropertyValue(character, UCHAR_BIDI_CLASS);
- if ((property == U_RIGHT_TO_LEFT) || (property == U_RIGHT_TO_LEFT_ARABIC))
- return true;
-
- position = next_position;
- }
-
- return false;
-}
-
-void WrapStringWithLTRFormatting(string16* text) {
- if (text->empty())
- return;
-
- // Inserting an LRE (Left-To-Right Embedding) mark as the first character.
- text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
- kLeftToRightEmbeddingMark);
-
- // Inserting a PDF (Pop Directional Formatting) mark as the last character.
- text->push_back(kPopDirectionalFormatting);
-}
-
-void WrapStringWithRTLFormatting(string16* text) {
- if (text->empty())
- return;
-
- // Inserting an RLE (Right-To-Left Embedding) mark as the first character.
- text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
- kRightToLeftEmbeddingMark);
-
- // Inserting a PDF (Pop Directional Formatting) mark as the last character.
- text->push_back(kPopDirectionalFormatting);
-}
-
-void WrapPathWithLTRFormatting(const FilePath& path,
- string16* rtl_safe_path) {
- // Wrap the overall path with LRE-PDF pair which essentialy marks the
- // string as a Left-To-Right string.
- // Inserting an LRE (Left-To-Right Embedding) mark as the first character.
- rtl_safe_path->push_back(kLeftToRightEmbeddingMark);
-#if defined(OS_MACOSX)
- rtl_safe_path->append(UTF8ToUTF16(path.value()));
-#elif defined(OS_WIN)
- rtl_safe_path->append(path.value());
-#else // defined(OS_POSIX) && !defined(OS_MACOSX)
- std::wstring wide_path = base::SysNativeMBToWide(path.value());
- rtl_safe_path->append(WideToUTF16(wide_path));
-#endif
- // Inserting a PDF (Pop Directional Formatting) mark as the last character.
- rtl_safe_path->push_back(kPopDirectionalFormatting);
-}
-
-string16 GetDisplayStringInLTRDirectionality(const string16& text) {
- // Always wrap the string in RTL UI (it may be appended to RTL string).
- // Also wrap strings with an RTL first strong character direction in LTR UI.
- if (IsRTL() || GetFirstStrongCharacterDirection(text) == RIGHT_TO_LEFT) {
- string16 text_mutable(text);
- WrapStringWithLTRFormatting(&text_mutable);
- return text_mutable;
- }
- return text;
-}
-
-string16 StripWrappingBidiControlCharacters(const string16& text) {
- if (text.empty())
- return text;
- size_t begin_index = 0;
- char16 begin = text[begin_index];
- if (begin == kLeftToRightEmbeddingMark ||
- begin == kRightToLeftEmbeddingMark ||
- begin == kLeftToRightOverride ||
- begin == kRightToLeftOverride)
- ++begin_index;
- size_t end_index = text.length() - 1;
- if (text[end_index] == kPopDirectionalFormatting)
- --end_index;
- return text.substr(begin_index, end_index - begin_index + 1);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/rtl_unittest.cc b/base/i18n/rtl_unittest.cc
deleted file mode 100644
index fbdd1a10ab..0000000000
--- a/base/i18n/rtl_unittest.cc
+++ /dev/null
@@ -1,556 +0,0 @@
-// Copyright (c) 2011 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/i18n/rtl.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/icu_test_util.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "third_party/icu/source/common/unicode/locid.h"
-#include "third_party/icu/source/i18n/unicode/usearch.h"
-
-namespace base {
-namespace i18n {
-
-class RTLTest : public PlatformTest {
-};
-
-TEST_F(RTLTest, GetFirstStrongCharacterDirection) {
- struct {
- const wchar_t* text;
- TextDirection direction;
- } cases[] = {
- // Test pure LTR string.
- { L"foo bar", LEFT_TO_RIGHT },
- // Test pure RTL string.
- { L"\x05d0\x05d1\x05d2 \x05d3\x0d4\x05d5", RIGHT_TO_LEFT},
- // Test bidi string in which the first character with strong directionality
- // is a character with type L.
- { L"foo \x05d0 bar", LEFT_TO_RIGHT },
- // Test bidi string in which the first character with strong directionality
- // is a character with type R.
- { L"\x05d0 foo bar", RIGHT_TO_LEFT },
- // Test bidi string which starts with a character with weak directionality
- // and in which the first character with strong directionality is a
- // character with type L.
- { L"!foo \x05d0 bar", LEFT_TO_RIGHT },
- // Test bidi string which starts with a character with weak directionality
- // and in which the first character with strong directionality is a
- // character with type R.
- { L",\x05d0 foo bar", RIGHT_TO_LEFT },
- // Test bidi string in which the first character with strong directionality
- // is a character with type LRE.
- { L"\x202a \x05d0 foo bar", LEFT_TO_RIGHT },
- // Test bidi string in which the first character with strong directionality
- // is a character with type LRO.
- { L"\x202d \x05d0 foo bar", LEFT_TO_RIGHT },
- // Test bidi string in which the first character with strong directionality
- // is a character with type RLE.
- { L"\x202b foo \x05d0 bar", RIGHT_TO_LEFT },
- // Test bidi string in which the first character with strong directionality
- // is a character with type RLO.
- { L"\x202e foo \x05d0 bar", RIGHT_TO_LEFT },
- // Test bidi string in which the first character with strong directionality
- // is a character with type AL.
- { L"\x0622 foo \x05d0 bar", RIGHT_TO_LEFT },
- // Test a string without strong directionality characters.
- { L",!.{}", LEFT_TO_RIGHT },
- // Test empty string.
- { L"", LEFT_TO_RIGHT },
- // Test characters in non-BMP (e.g. Phoenician letters. Please refer to
- // http://demo.icu-project.org/icu-bin/ubrowse?scr=151&b=10910 for more
- // information).
- {
-#if defined(WCHAR_T_IS_UTF32)
- L" ! \x10910" L"abc 123",
-#elif defined(WCHAR_T_IS_UTF16)
- L" ! \xd802\xdd10" L"abc 123",
-#else
-#error wchar_t should be either UTF-16 or UTF-32
-#endif
- RIGHT_TO_LEFT },
- {
-#if defined(WCHAR_T_IS_UTF32)
- L" ! \x10401" L"abc 123",
-#elif defined(WCHAR_T_IS_UTF16)
- L" ! \xd801\xdc01" L"abc 123",
-#else
-#error wchar_t should be either UTF-16 or UTF-32
-#endif
- LEFT_TO_RIGHT },
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i)
- EXPECT_EQ(cases[i].direction,
- GetFirstStrongCharacterDirection(WideToUTF16(cases[i].text)));
-}
-
-
-// Note that the cases with LRE, LRO, RLE and RLO are invalid for
-// GetLastStrongCharacterDirection because they should be followed by PDF
-// character.
-TEST_F(RTLTest, GetLastStrongCharacterDirection) {
- struct {
- const wchar_t* text;
- TextDirection direction;
- } cases[] = {
- // Test pure LTR string.
- { L"foo bar", LEFT_TO_RIGHT },
- // Test pure RTL string.
- { L"\x05d0\x05d1\x05d2 \x05d3\x0d4\x05d5", RIGHT_TO_LEFT},
- // Test bidi string in which the last character with strong directionality
- // is a character with type L.
- { L"foo \x05d0 bar", LEFT_TO_RIGHT },
- // Test bidi string in which the last character with strong directionality
- // is a character with type R.
- { L"\x05d0 foo bar \x05d3", RIGHT_TO_LEFT },
- // Test bidi string which ends with a character with weak directionality
- // and in which the last character with strong directionality is a
- // character with type L.
- { L"!foo \x05d0 bar!", LEFT_TO_RIGHT },
- // Test bidi string which ends with a character with weak directionality
- // and in which the last character with strong directionality is a
- // character with type R.
- { L",\x05d0 foo bar \x05d1,", RIGHT_TO_LEFT },
- // Test bidi string in which the last character with strong directionality
- // is a character with type AL.
- { L"\x0622 foo \x05d0 bar \x0622", RIGHT_TO_LEFT },
- // Test a string without strong directionality characters.
- { L",!.{}", LEFT_TO_RIGHT },
- // Test empty string.
- { L"", LEFT_TO_RIGHT },
- // Test characters in non-BMP (e.g. Phoenician letters. Please refer to
- // http://demo.icu-project.org/icu-bin/ubrowse?scr=151&b=10910 for more
- // information).
- {
-#if defined(WCHAR_T_IS_UTF32)
- L"abc 123" L" ! \x10910 !",
-#elif defined(WCHAR_T_IS_UTF16)
- L"abc 123" L" ! \xd802\xdd10 !",
-#else
-#error wchar_t should be either UTF-16 or UTF-32
-#endif
- RIGHT_TO_LEFT },
- {
-#if defined(WCHAR_T_IS_UTF32)
- L"abc 123" L" ! \x10401 !",
-#elif defined(WCHAR_T_IS_UTF16)
- L"abc 123" L" ! \xd801\xdc01 !",
-#else
-#error wchar_t should be either UTF-16 or UTF-32
-#endif
- LEFT_TO_RIGHT },
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i)
- EXPECT_EQ(cases[i].direction,
- GetLastStrongCharacterDirection(WideToUTF16(cases[i].text)));
-}
-
-TEST_F(RTLTest, GetStringDirection) {
- struct {
- const wchar_t* text;
- TextDirection direction;
- } cases[] = {
- // Test pure LTR string.
- { L"foobar", LEFT_TO_RIGHT },
- { L".foobar", LEFT_TO_RIGHT },
- { L"foo, bar", LEFT_TO_RIGHT },
- // Test pure LTR with strong directionality characters of type LRE.
- { L"\x202a\x202a", LEFT_TO_RIGHT },
- { L".\x202a\x202a", LEFT_TO_RIGHT },
- { L"\x202a, \x202a", LEFT_TO_RIGHT },
- // Test pure LTR with strong directionality characters of type LRO.
- { L"\x202d\x202d", LEFT_TO_RIGHT },
- { L".\x202d\x202d", LEFT_TO_RIGHT },
- { L"\x202d, \x202d", LEFT_TO_RIGHT },
- // Test pure LTR with various types of strong directionality characters.
- { L"foo \x202a\x202d", LEFT_TO_RIGHT },
- { L".\x202d foo \x202a", LEFT_TO_RIGHT },
- { L"\x202a, \x202d foo", LEFT_TO_RIGHT },
- // Test pure RTL with strong directionality characters of type R.
- { L"\x05d0\x05d0", RIGHT_TO_LEFT },
- { L".\x05d0\x05d0", RIGHT_TO_LEFT },
- { L"\x05d0, \x05d0", RIGHT_TO_LEFT },
- // Test pure RTL with strong directionality characters of type RLE.
- { L"\x202b\x202b", RIGHT_TO_LEFT },
- { L".\x202b\x202b", RIGHT_TO_LEFT },
- { L"\x202b, \x202b", RIGHT_TO_LEFT },
- // Test pure RTL with strong directionality characters of type RLO.
- { L"\x202e\x202e", RIGHT_TO_LEFT },
- { L".\x202e\x202e", RIGHT_TO_LEFT },
- { L"\x202e, \x202e", RIGHT_TO_LEFT },
- // Test pure RTL with strong directionality characters of type AL.
- { L"\x0622\x0622", RIGHT_TO_LEFT },
- { L".\x0622\x0622", RIGHT_TO_LEFT },
- { L"\x0622, \x0622", RIGHT_TO_LEFT },
- // Test pure RTL with various types of strong directionality characters.
- { L"\x05d0\x202b\x202e\x0622", RIGHT_TO_LEFT },
- { L".\x202b\x202e\x0622\x05d0", RIGHT_TO_LEFT },
- { L"\x0622\x202e, \x202b\x05d0", RIGHT_TO_LEFT },
- // Test bidi strings.
- { L"foo \x05d0 bar", UNKNOWN_DIRECTION },
- { L"\x202b foo bar", UNKNOWN_DIRECTION },
- { L"!foo \x0622 bar", UNKNOWN_DIRECTION },
- { L"\x202a\x202b", UNKNOWN_DIRECTION },
- { L"\x202e\x202d", UNKNOWN_DIRECTION },
- { L"\x0622\x202a", UNKNOWN_DIRECTION },
- { L"\x202d\x05d0", UNKNOWN_DIRECTION },
- // Test a string without strong directionality characters.
- { L",!.{}", LEFT_TO_RIGHT },
- // Test empty string.
- { L"", LEFT_TO_RIGHT },
- {
-#if defined(WCHAR_T_IS_UTF32)
- L" ! \x10910" L"abc 123",
-#elif defined(WCHAR_T_IS_UTF16)
- L" ! \xd802\xdd10" L"abc 123",
-#else
-#error wchar_t should be either UTF-16 or UTF-32
-#endif
- UNKNOWN_DIRECTION },
- {
-#if defined(WCHAR_T_IS_UTF32)
- L" ! \x10401" L"abc 123",
-#elif defined(WCHAR_T_IS_UTF16)
- L" ! \xd801\xdc01" L"abc 123",
-#else
-#error wchar_t should be either UTF-16 or UTF-32
-#endif
- LEFT_TO_RIGHT },
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i)
- EXPECT_EQ(cases[i].direction,
- GetStringDirection(WideToUTF16(cases[i].text)));
-}
-
-TEST_F(RTLTest, WrapPathWithLTRFormatting) {
- const wchar_t* cases[] = {
- // Test common path, such as "c:\foo\bar".
- L"c:/foo/bar",
- // Test path with file name, such as "c:\foo\bar\test.jpg".
- L"c:/foo/bar/test.jpg",
- // Test path ending with punctuation, such as "c:\(foo)\bar.".
- L"c:/(foo)/bar.",
- // Test path ending with separator, such as "c:\foo\bar\".
- L"c:/foo/bar/",
- // Test path with RTL character.
- L"c:/\x05d0",
- // Test path with 2 level RTL directory names.
- L"c:/\x05d0/\x0622",
- // Test path with mixed RTL/LTR directory names and ending with punctuation.
- L"c:/\x05d0/\x0622/(foo)/b.a.r.",
- // Test path without driver name, such as "/foo/bar/test/jpg".
- L"/foo/bar/test.jpg",
- // Test path start with current directory, such as "./foo".
- L"./foo",
- // Test path start with parent directory, such as "../foo/bar.jpg".
- L"../foo/bar.jpg",
- // Test absolute path, such as "//foo/bar.jpg".
- L"//foo/bar.jpg",
- // Test path with mixed RTL/LTR directory names.
- L"c:/foo/\x05d0/\x0622/\x05d1.jpg",
- // Test empty path.
- L""
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath path;
-#if defined(OS_WIN)
- std::wstring win_path(cases[i]);
- std::replace(win_path.begin(), win_path.end(), '/', '\\');
- path = FilePath(win_path);
- std::wstring wrapped_expected =
- std::wstring(L"\x202a") + win_path + L"\x202c";
-#else
- path = FilePath(base::SysWideToNativeMB(cases[i]));
- std::wstring wrapped_expected =
- std::wstring(L"\x202a") + cases[i] + L"\x202c";
-#endif
- string16 localized_file_path_string;
- WrapPathWithLTRFormatting(path, &localized_file_path_string);
-
- std::wstring wrapped_actual = UTF16ToWide(localized_file_path_string);
- EXPECT_EQ(wrapped_expected, wrapped_actual);
- }
-}
-
-TEST_F(RTLTest, WrapString) {
- const wchar_t* cases[] = {
- L" . ",
- L"abc",
- L"a" L"\x5d0\x5d1",
- L"a" L"\x5d1" L"b",
- L"\x5d0\x5d1\x5d2",
- L"\x5d0\x5d1" L"a",
- L"\x5d0" L"a" L"\x5d1",
- };
-
- const bool was_rtl = IsRTL();
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- for (size_t i = 0; i < 2; ++i) {
- // Toggle the application default text direction (to try each direction).
- SetRTLForTesting(!IsRTL());
-
- string16 empty;
- WrapStringWithLTRFormatting(&empty);
- EXPECT_TRUE(empty.empty());
- WrapStringWithRTLFormatting(&empty);
- EXPECT_TRUE(empty.empty());
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- string16 input = WideToUTF16(cases[i]);
- string16 ltr_wrap = input;
- WrapStringWithLTRFormatting(&ltr_wrap);
- EXPECT_EQ(ltr_wrap[0], kLeftToRightEmbeddingMark);
- EXPECT_EQ(ltr_wrap.substr(1, ltr_wrap.length() - 2), input);
- EXPECT_EQ(ltr_wrap[ltr_wrap.length() -1], kPopDirectionalFormatting);
-
- string16 rtl_wrap = input;
- WrapStringWithRTLFormatting(&rtl_wrap);
- EXPECT_EQ(rtl_wrap[0], kRightToLeftEmbeddingMark);
- EXPECT_EQ(rtl_wrap.substr(1, rtl_wrap.length() - 2), input);
- EXPECT_EQ(rtl_wrap[rtl_wrap.length() -1], kPopDirectionalFormatting);
- }
- }
-
- EXPECT_EQ(was_rtl, IsRTL());
-}
-
-TEST_F(RTLTest, GetDisplayStringInLTRDirectionality) {
- struct {
- const wchar_t* path;
- bool wrap_ltr;
- bool wrap_rtl;
- } cases[] = {
- { L"test", false, true },
- { L"test.html", false, true },
- { L"\x05d0\x05d1\x05d2", true, true },
- { L"\x05d0\x05d1\x05d2.txt", true, true },
- { L"\x05d0" L"abc", true, true },
- { L"\x05d0" L"abc.txt", true, true },
- { L"abc\x05d0\x05d1", false, true },
- { L"abc\x05d0\x05d1.jpg", false, true },
- };
-
- const bool was_rtl = IsRTL();
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- for (size_t i = 0; i < 2; ++i) {
- // Toggle the application default text direction (to try each direction).
- SetRTLForTesting(!IsRTL());
- for (size_t i = 0; i < arraysize(cases); ++i) {
- string16 input = WideToUTF16(cases[i].path);
- string16 output = GetDisplayStringInLTRDirectionality(input);
- // Test the expected wrapping behavior for the current UI directionality.
- if (IsRTL() ? cases[i].wrap_rtl : cases[i].wrap_ltr)
- EXPECT_NE(output, input);
- else
- EXPECT_EQ(output, input);
- }
- }
-
- EXPECT_EQ(was_rtl, IsRTL());
-}
-
-TEST_F(RTLTest, GetTextDirection) {
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ar"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ar_EG"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("he"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("he_IL"));
- // iw is an obsolete code for Hebrew.
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("iw"));
- // Although we're not yet localized to Farsi and Urdu, we
- // do have the text layout direction information for them.
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("fa"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("ur"));
-#if 0
- // Enable these when we include the minimal locale data for Azerbaijani
- // written in Arabic and Dhivehi. At the moment, our copy of
- // ICU data does not have entries for them.
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("az_Arab"));
- // Dhivehi that uses Thaana script.
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocale("dv"));
-#endif
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("en"));
- // Chinese in China with '-'.
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("zh-CN"));
- // Filipino : 3-letter code
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("fil"));
- // Russian
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("ru"));
- // Japanese that uses multiple scripts
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocale("ja"));
-}
-
-TEST_F(RTLTest, GetTextDirectionForLocaleInStartUp) {
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ar"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ar_EG"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("he"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("he_IL"));
- // iw is an obsolete code for Hebrew.
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("iw"));
- // Although we're not yet localized to Farsi and Urdu, we
- // do have the text layout direction information for them.
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("fa"));
- EXPECT_EQ(RIGHT_TO_LEFT, GetTextDirectionForLocaleInStartUp("ur"));
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("en"));
- // Chinese in China with '-'.
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("zh-CN"));
- // Filipino : 3-letter code
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("fil"));
- // Russian
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("ru"));
- // Japanese that uses multiple scripts
- EXPECT_EQ(LEFT_TO_RIGHT, GetTextDirectionForLocaleInStartUp("ja"));
-}
-
-TEST_F(RTLTest, UnadjustStringForLocaleDirection) {
- // These test strings are borrowed from WrapPathWithLTRFormatting
- const wchar_t* cases[] = {
- L"foo bar",
- L"foo \x05d0 bar",
- L"\x05d0 foo bar",
- L"!foo \x05d0 bar",
- L",\x05d0 foo bar",
- L"\x202a \x05d0 foo bar",
- L"\x202d \x05d0 foo bar",
- L"\x202b foo \x05d0 bar",
- L"\x202e foo \x05d0 bar",
- L"\x0622 foo \x05d0 bar",
- };
-
- const bool was_rtl = IsRTL();
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- for (size_t i = 0; i < 2; ++i) {
- // Toggle the application default text direction (to try each direction).
- SetRTLForTesting(!IsRTL());
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- string16 test_case = WideToUTF16(cases[i]);
- string16 adjusted_string = test_case;
-
- if (!AdjustStringForLocaleDirection(&adjusted_string))
- continue;
-
- EXPECT_NE(test_case, adjusted_string);
- EXPECT_TRUE(UnadjustStringForLocaleDirection(&adjusted_string));
- EXPECT_EQ(test_case, adjusted_string) << " for test case [" << test_case
- << "] with IsRTL() == " << IsRTL();
- }
- }
-
- EXPECT_EQ(was_rtl, IsRTL());
-}
-
-TEST_F(RTLTest, EnsureTerminatedDirectionalFormatting) {
- struct {
- const wchar_t* unformated_text;
- const wchar_t* formatted_text;
- } cases[] = {
- // Tests string without any dir-formatting characters.
- {L"google.com", L"google.com"},
- // Tests string with properly terminated dir-formatting character.
- {L"\x202egoogle.com\x202c", L"\x202egoogle.com\x202c"},
- // Tests string with over-terminated dir-formatting characters.
- {L"\x202egoogle\x202c.com\x202c", L"\x202egoogle\x202c.com\x202c"},
- // Tests string beginning with a dir-formatting character.
- {L"\x202emoc.elgoog", L"\x202emoc.elgoog\x202c"},
- // Tests string that over-terminates then re-opens.
- {L"\x202egoogle\x202c\x202c.\x202eom",
- L"\x202egoogle\x202c\x202c.\x202eom\x202c"},
- // Tests string containing a dir-formatting character in the middle.
- {L"google\x202e.com", L"google\x202e.com\x202c"},
- // Tests string with multiple dir-formatting characters.
- {L"\x202egoogle\x202e.com/\x202eguest",
- L"\x202egoogle\x202e.com/\x202eguest\x202c\x202c\x202c"},
- // Test the other dir-formatting characters (U+202A, U+202B, and U+202D).
- {L"\x202agoogle.com", L"\x202agoogle.com\x202c"},
- {L"\x202bgoogle.com", L"\x202bgoogle.com\x202c"},
- {L"\x202dgoogle.com", L"\x202dgoogle.com\x202c"},
- };
-
- const bool was_rtl = IsRTL();
-
- test::ScopedRestoreICUDefaultLocale restore_locale;
- for (size_t i = 0; i < 2; ++i) {
- // Toggle the application default text direction (to try each direction).
- SetRTLForTesting(!IsRTL());
- for (size_t i = 0; i < arraysize(cases); ++i) {
- string16 unsanitized_text = WideToUTF16(cases[i].unformated_text);
- string16 sanitized_text = WideToUTF16(cases[i].formatted_text);
- EnsureTerminatedDirectionalFormatting(&unsanitized_text);
- EXPECT_EQ(sanitized_text, unsanitized_text);
- }
- }
- EXPECT_EQ(was_rtl, IsRTL());
-}
-
-TEST_F(RTLTest, SanitizeUserSuppliedString) {
- struct {
- const wchar_t* unformatted_text;
- const wchar_t* formatted_text;
- } cases[] = {
- // Tests RTL string with properly terminated dir-formatting character.
- {L"\x202eكبير Google التطبيق\x202c", L"\x202eكبير Google التطبيق\x202c"},
- // Tests RTL string with over-terminated dir-formatting characters.
- {L"\x202eكبير Google\x202cالتطبيق\x202c",
- L"\x202eكبير Google\x202cالتطبيق\x202c"},
- // Tests RTL string that over-terminates then re-opens.
- {L"\x202eكبير Google\x202c\x202cالتطبيق\x202e",
- L"\x202eكبير Google\x202c\x202cالتطبيق\x202e\x202c"},
- // Tests RTL string with multiple dir-formatting characters.
- {L"\x202eك\x202eبير Google الت\x202eطبيق",
- L"\x202eك\x202eبير Google الت\x202eطبيق\x202c\x202c\x202c"},
- // Test the other dir-formatting characters (U+202A, U+202B, and U+202D).
- {L"\x202aكبير Google التطبيق", L"\x202aكبير Google التطبيق\x202c"},
- {L"\x202bكبير Google التطبيق", L"\x202bكبير Google التطبيق\x202c"},
- {L"\x202dكبير Google التطبيق", L"\x202dكبير Google التطبيق\x202c"},
-
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- // On Windows for an LTR locale, no changes to the string are made.
- string16 prefix, suffix = WideToUTF16(L"");
-#if !defined(OS_WIN)
- prefix = WideToUTF16(L"\x200e\x202b");
- suffix = WideToUTF16(L"\x202c\x200e");
-#endif // !OS_WIN
- string16 unsanitized_text = WideToUTF16(cases[i].unformatted_text);
- string16 sanitized_text =
- prefix + WideToUTF16(cases[i].formatted_text) + suffix;
- SanitizeUserSuppliedString(&unsanitized_text);
- EXPECT_EQ(sanitized_text, unsanitized_text);
- }
-}
-
-class SetICULocaleTest : public PlatformTest {};
-
-TEST_F(SetICULocaleTest, OverlongLocaleId) {
- test::ScopedRestoreICUDefaultLocale restore_locale;
- std::string id("fr-ca-x-foo");
- while (id.length() < 152)
- id.append("-x-foo");
- SetICUDefaultLocale(id);
- EXPECT_STRNE("en_US", icu::Locale::getDefault().getName());
- id.append("zzz");
- SetICUDefaultLocale(id);
- EXPECT_STREQ("en_US", icu::Locale::getDefault().getName());
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/streaming_utf8_validator.cc b/base/i18n/streaming_utf8_validator.cc
deleted file mode 100644
index 19c86a37a4..0000000000
--- a/base/i18n/streaming_utf8_validator.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.
-
-// This implementation doesn't use ICU. The ICU macros are oriented towards
-// character-at-a-time processing, whereas byte-at-a-time processing is easier
-// with streaming input.
-
-#include "base/i18n/streaming_utf8_validator.h"
-
-#include "base/i18n/utf8_validator_tables.h"
-#include "base/logging.h"
-
-namespace base {
-namespace {
-
-uint8_t StateTableLookup(uint8_t offset) {
- DCHECK_LT(offset, internal::kUtf8ValidatorTablesSize);
- return internal::kUtf8ValidatorTables[offset];
-}
-
-} // namespace
-
-StreamingUtf8Validator::State StreamingUtf8Validator::AddBytes(const char* data,
- size_t size) {
- // Copy |state_| into a local variable so that the compiler doesn't have to be
- // careful of aliasing.
- uint8_t state = state_;
- for (const char* p = data; p != data + size; ++p) {
- if ((*p & 0x80) == 0) {
- if (state == 0)
- continue;
- state = internal::I18N_UTF8_VALIDATOR_INVALID_INDEX;
- break;
- }
- const uint8_t shift_amount = StateTableLookup(state);
- const uint8_t shifted_char = (*p & 0x7F) >> shift_amount;
- state = StateTableLookup(state + shifted_char + 1);
- // State may be INVALID here, but this code is optimised for the case of
- // valid UTF-8 and it is more efficient (by about 2%) to not attempt an
- // early loop exit unless we hit an ASCII character.
- }
- state_ = state;
- return state == 0 ? VALID_ENDPOINT
- : state == internal::I18N_UTF8_VALIDATOR_INVALID_INDEX
- ? INVALID
- : VALID_MIDPOINT;
-}
-
-void StreamingUtf8Validator::Reset() {
- state_ = 0u;
-}
-
-bool StreamingUtf8Validator::Validate(const std::string& string) {
- return StreamingUtf8Validator().AddBytes(string.data(), string.size()) ==
- VALID_ENDPOINT;
-}
-
-} // namespace base
diff --git a/base/i18n/streaming_utf8_validator.h b/base/i18n/streaming_utf8_validator.h
deleted file mode 100644
index ebf38a69b3..0000000000
--- a/base/i18n/streaming_utf8_validator.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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.
-
-// A streaming validator for UTF-8. Validation is based on the definition in
-// RFC-3629. In particular, it does not reject the invalid characters rejected
-// by base::IsStringUTF8().
-//
-// The implementation detects errors on the first possible byte.
-
-#ifndef BASE_I18N_STREAMING_UTF8_VALIDATOR_H_
-#define BASE_I18N_STREAMING_UTF8_VALIDATOR_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/macros.h"
-
-namespace base {
-
-class BASE_I18N_EXPORT StreamingUtf8Validator {
- public:
- // The validator exposes 3 states. It starts in state VALID_ENDPOINT. As it
- // processes characters it alternates between VALID_ENDPOINT and
- // VALID_MIDPOINT. If it encounters an invalid byte or UTF-8 sequence the
- // state changes permanently to INVALID.
- enum State {
- VALID_ENDPOINT,
- VALID_MIDPOINT,
- INVALID
- };
-
- StreamingUtf8Validator() : state_(0u) {}
- // Trivial destructor intentionally omitted.
-
- // Validate |size| bytes starting at |data|. If the concatenation of all calls
- // to AddBytes() since this object was constructed or reset is a valid UTF-8
- // string, returns VALID_ENDPOINT. If it could be the prefix of a valid UTF-8
- // string, returns VALID_MIDPOINT. If an invalid byte or UTF-8 sequence was
- // present, returns INVALID.
- State AddBytes(const char* data, size_t size);
-
- // Return the object to a freshly-constructed state so that it can be re-used.
- void Reset();
-
- // Validate a complete string using the same criteria. Returns true if the
- // string only contains complete, valid UTF-8 codepoints.
- static bool Validate(const std::string& string);
-
- private:
- // The current state of the validator. Value 0 is the initial/valid state.
- // The state is stored as an offset into |kUtf8ValidatorTables|. The special
- // state |kUtf8InvalidState| is invalid.
- uint8_t state_;
-
- // This type could be made copyable but there is currently no use-case for
- // it.
- DISALLOW_COPY_AND_ASSIGN(StreamingUtf8Validator);
-};
-
-} // namespace base
-
-#endif // BASE_I18N_STREAMING_UTF8_VALIDATOR_H_
diff --git a/base/i18n/streaming_utf8_validator_perftest.cc b/base/i18n/streaming_utf8_validator_perftest.cc
deleted file mode 100644
index ad328f886d..0000000000
--- a/base/i18n/streaming_utf8_validator_perftest.cc
+++ /dev/null
@@ -1,240 +0,0 @@
-// 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.
-
-// All data that is passed through a WebSocket with type "Text" needs to be
-// validated as UTF8. Since this is done on the IO thread, it needs to be
-// reasonably fast.
-
-// We are only interested in the performance on valid UTF8. Invalid UTF8 will
-// result in a connection failure, so is unlikely to become a source of
-// performance issues.
-
-#include "base/i18n/streaming_utf8_validator.h"
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/perf_time_logger.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-// We want to test ranges of valid UTF-8 sequences. These ranges are inclusive.
-// They are intended to be large enough that the validator needs to do
-// meaningful work while being in some sense "realistic" (eg. control characters
-// are not included).
-const char kOneByteSeqRangeStart[] = " "; // U+0020
-const char kOneByteSeqRangeEnd[] = "~"; // U+007E
-
-const char kTwoByteSeqRangeStart[] = "\xc2\xa0"; // U+00A0 non-breaking space
-const char kTwoByteSeqRangeEnd[] = "\xc9\x8f"; // U+024F small y with stroke
-
-const char kThreeByteSeqRangeStart[] = "\xe3\x81\x82"; // U+3042 Hiragana "a"
-const char kThreeByteSeqRangeEnd[] = "\xe9\xbf\x83"; // U+9FC3 "to blink"
-
-const char kFourByteSeqRangeStart[] = "\xf0\xa0\x80\x8b"; // U+2000B
-const char kFourByteSeqRangeEnd[] = "\xf0\xaa\x9a\xb2"; // U+2A6B2
-
-// The different lengths of strings to test.
-const size_t kTestLengths[] = {1, 32, 256, 32768, 1 << 20};
-
-// Simplest possible byte-at-a-time validator, to provide a baseline
-// for comparison. This is only tried on 1-byte UTF-8 sequences, as
-// the results will not be meaningful with sequences containing
-// top-bit-set bytes.
-bool IsString7Bit(const std::string& s) {
- for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
- if (*it & 0x80)
- return false;
- }
- return true;
-}
-
-// Assumes that |previous| is a valid UTF-8 sequence, and attempts to return
-// the next one. Is just barely smart enough to iterate through the ranges
-// defined about.
-std::string NextUtf8Sequence(const std::string& previous) {
- DCHECK(StreamingUtf8Validator::Validate(previous));
- std::string next = previous;
- for (int i = static_cast<int>(previous.length() - 1); i >= 0; --i) {
- // All bytes in a UTF-8 sequence except the first one are
- // constrained to the range 0x80 to 0xbf, inclusive. When we
- // increment past 0xbf, we carry into the previous byte.
- if (i > 0 && next[i] == '\xbf') {
- next[i] = '\x80';
- continue; // carry
- }
- ++next[i];
- break; // no carry
- }
- DCHECK(StreamingUtf8Validator::Validate(next))
- << "Result \"" << next << "\" failed validation";
- return next;
-}
-
-typedef bool (*TestTargetType)(const std::string&);
-
-// Run fuction |target| over |test_string| |times| times, and report the results
-// using |description|.
-bool RunTest(const std::string& description,
- TestTargetType target,
- const std::string& test_string,
- int times) {
- base::PerfTimeLogger timer(description.c_str());
- bool result = true;
- for (int i = 0; i < times; ++i) {
- result = target(test_string) && result;
- }
- timer.Done();
- return result;
-}
-
-// Construct a string by repeating |input| enough times to equal or exceed
-// |length|.
-std::string ConstructRepeatedTestString(const std::string& input,
- size_t length) {
- std::string output = input;
- while (output.length() * 2 < length) {
- output += output;
- }
- if (output.length() < length) {
- output += ConstructRepeatedTestString(input, length - output.length());
- }
- return output;
-}
-
-// Construct a string by expanding the range of UTF-8 sequences
-// between |input_start| and |input_end|, inclusive, and then
-// repeating the resulting string until it equals or exceeds |length|
-// bytes. |input_start| and |input_end| must be valid UTF-8
-// sequences.
-std::string ConstructRangedTestString(const std::string& input_start,
- const std::string& input_end,
- size_t length) {
- std::string output = input_start;
- std::string input = input_start;
- while (output.length() < length && input != input_end) {
- input = NextUtf8Sequence(input);
- output += input;
- }
- if (output.length() < length) {
- output = ConstructRepeatedTestString(output, length);
- }
- return output;
-}
-
-struct TestFunctionDescription {
- TestTargetType function;
- const char* function_name;
-};
-
-bool IsStringUTF8(const std::string& str) {
- return base::IsStringUTF8(base::StringPiece(str));
-}
-
-// IsString7Bit is intentionally placed last so it can be excluded easily.
-const TestFunctionDescription kTestFunctions[] = {
- {&StreamingUtf8Validator::Validate, "StreamingUtf8Validator"},
- {&IsStringUTF8, "IsStringUTF8"}, {&IsString7Bit, "IsString7Bit"}};
-
-// Construct a test string from |construct_test_string| for each of the lengths
-// in |kTestLengths| in turn. For each string, run each test in |test_functions|
-// for a number of iterations such that the total number of bytes validated
-// is around 16MB.
-void RunSomeTests(
- const char format[],
- base::Callback<std::string(size_t length)> construct_test_string,
- const TestFunctionDescription* test_functions,
- size_t test_count) {
- for (size_t i = 0; i < arraysize(kTestLengths); ++i) {
- const size_t length = kTestLengths[i];
- const std::string test_string = construct_test_string.Run(length);
- const int real_length = static_cast<int>(test_string.length());
- const int times = (1 << 24) / real_length;
- for (size_t test_index = 0; test_index < test_count; ++test_index) {
- EXPECT_TRUE(RunTest(StringPrintf(format,
- test_functions[test_index].function_name,
- real_length,
- times),
- test_functions[test_index].function,
- test_string,
- times));
- }
- }
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, OneByteRepeated) {
- RunSomeTests("%s: bytes=1 repeated length=%d repeat=%d",
- base::Bind(ConstructRepeatedTestString, kOneByteSeqRangeStart),
- kTestFunctions,
- 3);
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, OneByteRange) {
- RunSomeTests("%s: bytes=1 ranged length=%d repeat=%d",
- base::Bind(ConstructRangedTestString,
- kOneByteSeqRangeStart,
- kOneByteSeqRangeEnd),
- kTestFunctions,
- 3);
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, TwoByteRepeated) {
- RunSomeTests("%s: bytes=2 repeated length=%d repeat=%d",
- base::Bind(ConstructRepeatedTestString, kTwoByteSeqRangeStart),
- kTestFunctions,
- 2);
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, TwoByteRange) {
- RunSomeTests("%s: bytes=2 ranged length=%d repeat=%d",
- base::Bind(ConstructRangedTestString,
- kTwoByteSeqRangeStart,
- kTwoByteSeqRangeEnd),
- kTestFunctions,
- 2);
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, ThreeByteRepeated) {
- RunSomeTests(
- "%s: bytes=3 repeated length=%d repeat=%d",
- base::Bind(ConstructRepeatedTestString, kThreeByteSeqRangeStart),
- kTestFunctions,
- 2);
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, ThreeByteRange) {
- RunSomeTests("%s: bytes=3 ranged length=%d repeat=%d",
- base::Bind(ConstructRangedTestString,
- kThreeByteSeqRangeStart,
- kThreeByteSeqRangeEnd),
- kTestFunctions,
- 2);
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, FourByteRepeated) {
- RunSomeTests("%s: bytes=4 repeated length=%d repeat=%d",
- base::Bind(ConstructRepeatedTestString, kFourByteSeqRangeStart),
- kTestFunctions,
- 2);
-}
-
-TEST(StreamingUtf8ValidatorPerfTest, FourByteRange) {
- RunSomeTests("%s: bytes=4 ranged length=%d repeat=%d",
- base::Bind(ConstructRangedTestString,
- kFourByteSeqRangeStart,
- kFourByteSeqRangeEnd),
- kTestFunctions,
- 2);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/i18n/streaming_utf8_validator_unittest.cc b/base/i18n/streaming_utf8_validator_unittest.cc
deleted file mode 100644
index f9772d098a..0000000000
--- a/base/i18n/streaming_utf8_validator_unittest.cc
+++ /dev/null
@@ -1,412 +0,0 @@
-// 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/i18n/streaming_utf8_validator.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Define BASE_I18N_UTF8_VALIDATOR_THOROUGH_TEST to verify that this class
-// accepts exactly the same set of 4-byte strings as ICU-based validation. This
-// tests every possible 4-byte string, so it is too slow to run routinely on
-// low-powered machines.
-//
-// #define BASE_I18N_UTF8_VALIDATOR_THOROUGH_TEST
-
-#ifdef BASE_I18N_UTF8_VALIDATOR_THOROUGH_TEST
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversion_utils.h"
-#include "base/synchronization/lock.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "third_party/icu/source/common/unicode/utf8.h"
-
-#endif // BASE_I18N_UTF8_VALIDATOR_THOROUGH_TEST
-
-namespace base {
-namespace {
-
-// Avoid having to qualify the enum values in the tests.
-const StreamingUtf8Validator::State VALID_ENDPOINT =
- StreamingUtf8Validator::VALID_ENDPOINT;
-const StreamingUtf8Validator::State VALID_MIDPOINT =
- StreamingUtf8Validator::VALID_MIDPOINT;
-const StreamingUtf8Validator::State INVALID = StreamingUtf8Validator::INVALID;
-
-#ifdef BASE_I18N_UTF8_VALIDATOR_THOROUGH_TEST
-
-const uint32_t kThoroughTestChunkSize = 1 << 24;
-
-class StreamingUtf8ValidatorThoroughTest : public ::testing::Test {
- protected:
- StreamingUtf8ValidatorThoroughTest()
- : tasks_dispatched_(0), tasks_finished_(0) {}
-
- // This uses the same logic as base::IsStringUTF8 except it considers
- // non-characters valid (and doesn't require a string as input).
- static bool IsStringUtf8(const char* src, int32_t src_len) {
- int32_t char_index = 0;
-
- while (char_index < src_len) {
- int32_t code_point;
- U8_NEXT(src, char_index, src_len, code_point);
- if (!base::IsValidCodepoint(code_point))
- return false;
- }
- return true;
- }
-
- // Converts the passed-in integer to a 4 byte string and then
- // verifies that IsStringUtf8 and StreamingUtf8Validator agree on
- // whether it is valid UTF-8 or not.
- void TestNumber(uint32_t n) const {
- char test[sizeof n];
- memcpy(test, &n, sizeof n);
- StreamingUtf8Validator validator;
- EXPECT_EQ(IsStringUtf8(test, sizeof n),
- validator.AddBytes(test, sizeof n) == VALID_ENDPOINT)
- << "Difference of opinion for \""
- << base::StringPrintf("\\x%02X\\x%02X\\x%02X\\x%02X",
- test[0] & 0xFF,
- test[1] & 0xFF,
- test[2] & 0xFF,
- test[3] & 0xFF) << "\"";
- }
-
- public:
- // Tests the 4-byte sequences corresponding to the |size| integers
- // starting at |begin|. This is intended to be run from a worker
- // pool. Signals |all_done_| at the end if it thinks all tasks are
- // finished.
- void TestRange(uint32_t begin, uint32_t size) {
- for (uint32_t i = 0; i < size; ++i) {
- TestNumber(begin + i);
- }
- base::AutoLock al(lock_);
- ++tasks_finished_;
- LOG(INFO) << tasks_finished_ << " / " << tasks_dispatched_
- << " tasks done\n";
- }
-
- protected:
- base::Lock lock_;
- int tasks_dispatched_;
- int tasks_finished_;
-};
-
-TEST_F(StreamingUtf8ValidatorThoroughTest, TestEverything) {
- base::TaskScheduler::CreateAndStartWithDefaultParams(
- "StreamingUtf8ValidatorThoroughTest");
- {
- base::AutoLock al(lock_);
- uint32_t begin = 0;
- do {
- base::PostTaskWithTraits(
- FROM_HERE, {base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
- base::BindOnce(&StreamingUtf8ValidatorThoroughTest::TestRange,
- base::Unretained(this), begin,
- kThoroughTestChunkSize));
- ++tasks_dispatched_;
- begin += kThoroughTestChunkSize;
- } while (begin != 0);
- }
- base::TaskScheduler::GetInstance()->Shutdown();
- base::TaskScheduler::GetInstance()->JoinForTesting();
- base::TaskScheduler::SetInstance(nullptr);
-}
-
-#endif // BASE_I18N_UTF8_VALIDATOR_THOROUGH_TEST
-
-// These valid and invalid UTF-8 sequences are based on the tests from
-// base/strings/string_util_unittest.cc
-
-// All of the strings in |valid| must represent a single codepoint, because
-// partial sequences are constructed by taking non-empty prefixes of these
-// strings.
-const char* const valid[] = {"\r", "\n", "a",
- "\xc2\x81", "\xe1\x80\xbf", "\xf1\x80\xa0\xbf",
- "\xef\xbb\xbf", // UTF-8 BOM
-};
-
-const char* const* const valid_end = valid + arraysize(valid);
-
-const char* const invalid[] = {
- // always invalid bytes
- "\xc0", "\xc1",
- "\xf5", "\xf6", "\xf7",
- "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff",
- // surrogate code points
- "\xed\xa0\x80", "\xed\x0a\x8f", "\xed\xbf\xbf",
- //
- // overlong sequences
- "\xc0\x80", // U+0000
- "\xc1\x80", // "A"
- "\xc1\x81", // "B"
- "\xe0\x80\x80", // U+0000
- "\xe0\x82\x80", // U+0080
- "\xe0\x9f\xbf", // U+07ff
- "\xf0\x80\x80\x8D", // U+000D
- "\xf0\x80\x82\x91", // U+0091
- "\xf0\x80\xa0\x80", // U+0800
- "\xf0\x8f\xbb\xbf", // U+FEFF (BOM)
- "\xf8\x80\x80\x80\xbf", // U+003F
- "\xfc\x80\x80\x80\xa0\xa5",
- //
- // Beyond U+10FFFF
- "\xf4\x90\x80\x80", // U+110000
- "\xf8\xa0\xbf\x80\xbf", // 5 bytes
- "\xfc\x9c\xbf\x80\xbf\x80", // 6 bytes
- //
- // BOMs in UTF-16(BE|LE)
- "\xfe\xff", "\xff\xfe",
-};
-
-const char* const* const invalid_end = invalid + arraysize(invalid);
-
-// A ForwardIterator which returns all the non-empty prefixes of the elements of
-// "valid".
-class PartialIterator {
- public:
- // The constructor returns the first iterator, ie. it is equivalent to
- // begin().
- PartialIterator() : index_(0), prefix_length_(0) { Advance(); }
- // The trivial destructor left intentionally undefined.
- // This is a value type; the default copy constructor and assignment operator
- // generated by the compiler are used.
-
- static PartialIterator end() { return PartialIterator(arraysize(valid), 1); }
-
- PartialIterator& operator++() {
- Advance();
- return *this;
- }
-
- base::StringPiece operator*() const {
- return base::StringPiece(valid[index_], prefix_length_);
- }
-
- bool operator==(const PartialIterator& rhs) const {
- return index_ == rhs.index_ && prefix_length_ == rhs.prefix_length_;
- }
-
- bool operator!=(const PartialIterator& rhs) const { return !(rhs == *this); }
-
- private:
- // This constructor is used by the end() method.
- PartialIterator(size_t index, size_t prefix_length)
- : index_(index), prefix_length_(prefix_length) {}
-
- void Advance() {
- if (index_ < arraysize(valid) && prefix_length_ < strlen(valid[index_]))
- ++prefix_length_;
- while (index_ < arraysize(valid) &&
- prefix_length_ == strlen(valid[index_])) {
- ++index_;
- prefix_length_ = 1;
- }
- }
-
- // The UTF-8 sequence, as an offset into the |valid| array.
- size_t index_;
- size_t prefix_length_;
-};
-
-// A test fixture for tests which test one UTF-8 sequence (or invalid
-// byte sequence) at a time.
-class StreamingUtf8ValidatorSingleSequenceTest : public ::testing::Test {
- protected:
- // Iterator must be convertible when de-referenced to StringPiece.
- template <typename Iterator>
- void CheckRange(Iterator begin,
- Iterator end,
- StreamingUtf8Validator::State expected) {
- for (Iterator it = begin; it != end; ++it) {
- StreamingUtf8Validator validator;
- base::StringPiece sequence = *it;
- EXPECT_EQ(expected,
- validator.AddBytes(sequence.data(), sequence.size()))
- << "Failed for \"" << sequence << "\"";
- }
- }
-
- // Adding input a byte at a time should make absolutely no difference.
- template <typename Iterator>
- void CheckRangeByteAtATime(Iterator begin,
- Iterator end,
- StreamingUtf8Validator::State expected) {
- for (Iterator it = begin; it != end; ++it) {
- StreamingUtf8Validator validator;
- base::StringPiece sequence = *it;
- StreamingUtf8Validator::State state = VALID_ENDPOINT;
- for (base::StringPiece::const_iterator cit = sequence.begin();
- cit != sequence.end();
- ++cit) {
- state = validator.AddBytes(&*cit, 1);
- }
- EXPECT_EQ(expected, state) << "Failed for \"" << sequence << "\"";
- }
- }
-};
-
-// A test fixture for tests which test the concatenation of byte sequences.
-class StreamingUtf8ValidatorDoubleSequenceTest : public ::testing::Test {
- protected:
- // Check every possible concatenation of byte sequences from two
- // ranges, and verify that the combination matches the expected
- // state.
- template <typename Iterator1, typename Iterator2>
- void CheckCombinations(Iterator1 begin1,
- Iterator1 end1,
- Iterator2 begin2,
- Iterator2 end2,
- StreamingUtf8Validator::State expected) {
- StreamingUtf8Validator validator;
- for (Iterator1 it1 = begin1; it1 != end1; ++it1) {
- base::StringPiece c1 = *it1;
- for (Iterator2 it2 = begin2; it2 != end2; ++it2) {
- base::StringPiece c2 = *it2;
- validator.AddBytes(c1.data(), c1.size());
- EXPECT_EQ(expected, validator.AddBytes(c2.data(), c2.size()))
- << "Failed for \"" << c1 << c2 << "\"";
- validator.Reset();
- }
- }
- }
-};
-
-TEST(StreamingUtf8ValidatorTest, NothingIsValid) {
- static const char kNothing[] = "";
- EXPECT_EQ(VALID_ENDPOINT, StreamingUtf8Validator().AddBytes(kNothing, 0));
-}
-
-// Because the members of the |valid| array need to be non-zero length
-// sequences and are measured with strlen(), |valid| cannot be used it
-// to test the NUL character '\0', so the NUL character gets its own
-// test.
-TEST(StreamingUtf8ValidatorTest, NulIsValid) {
- static const char kNul[] = "\x00";
- EXPECT_EQ(VALID_ENDPOINT, StreamingUtf8Validator().AddBytes(kNul, 1));
-}
-
-// Just a basic sanity test before we start getting fancy.
-TEST(StreamingUtf8ValidatorTest, HelloWorld) {
- static const char kHelloWorld[] = "Hello, World!";
- EXPECT_EQ(
- VALID_ENDPOINT,
- StreamingUtf8Validator().AddBytes(kHelloWorld, strlen(kHelloWorld)));
-}
-
-// Check that the Reset() method works.
-TEST(StreamingUtf8ValidatorTest, ResetWorks) {
- StreamingUtf8Validator validator;
- EXPECT_EQ(INVALID, validator.AddBytes("\xC0", 1));
- EXPECT_EQ(INVALID, validator.AddBytes("a", 1));
- validator.Reset();
- EXPECT_EQ(VALID_ENDPOINT, validator.AddBytes("a", 1));
-}
-
-TEST_F(StreamingUtf8ValidatorSingleSequenceTest, Valid) {
- CheckRange(valid, valid_end, VALID_ENDPOINT);
-}
-
-TEST_F(StreamingUtf8ValidatorSingleSequenceTest, Partial) {
- CheckRange(PartialIterator(), PartialIterator::end(), VALID_MIDPOINT);
-}
-
-TEST_F(StreamingUtf8ValidatorSingleSequenceTest, Invalid) {
- CheckRange(invalid, invalid_end, INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorSingleSequenceTest, ValidByByte) {
- CheckRangeByteAtATime(valid, valid_end, VALID_ENDPOINT);
-}
-
-TEST_F(StreamingUtf8ValidatorSingleSequenceTest, PartialByByte) {
- CheckRangeByteAtATime(
- PartialIterator(), PartialIterator::end(), VALID_MIDPOINT);
-}
-
-TEST_F(StreamingUtf8ValidatorSingleSequenceTest, InvalidByByte) {
- CheckRangeByteAtATime(invalid, invalid_end, INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, ValidPlusValidIsValid) {
- CheckCombinations(valid, valid_end, valid, valid_end, VALID_ENDPOINT);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, ValidPlusPartialIsPartial) {
- CheckCombinations(valid,
- valid_end,
- PartialIterator(),
- PartialIterator::end(),
- VALID_MIDPOINT);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, PartialPlusValidIsInvalid) {
- CheckCombinations(
- PartialIterator(), PartialIterator::end(), valid, valid_end, INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, PartialPlusPartialIsInvalid) {
- CheckCombinations(PartialIterator(),
- PartialIterator::end(),
- PartialIterator(),
- PartialIterator::end(),
- INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, ValidPlusInvalidIsInvalid) {
- CheckCombinations(valid, valid_end, invalid, invalid_end, INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, InvalidPlusValidIsInvalid) {
- CheckCombinations(invalid, invalid_end, valid, valid_end, INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, InvalidPlusInvalidIsInvalid) {
- CheckCombinations(invalid, invalid_end, invalid, invalid_end, INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, InvalidPlusPartialIsInvalid) {
- CheckCombinations(
- invalid, invalid_end, PartialIterator(), PartialIterator::end(), INVALID);
-}
-
-TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, PartialPlusInvalidIsInvalid) {
- CheckCombinations(
- PartialIterator(), PartialIterator::end(), invalid, invalid_end, INVALID);
-}
-
-TEST(StreamingUtf8ValidatorValidateTest, EmptyIsValid) {
- EXPECT_TRUE(StreamingUtf8Validator::Validate(std::string()));
-}
-
-TEST(StreamingUtf8ValidatorValidateTest, SimpleValidCase) {
- EXPECT_TRUE(StreamingUtf8Validator::Validate("\xc2\x81"));
-}
-
-TEST(StreamingUtf8ValidatorValidateTest, SimpleInvalidCase) {
- EXPECT_FALSE(StreamingUtf8Validator::Validate("\xc0\x80"));
-}
-
-TEST(StreamingUtf8ValidatorValidateTest, TruncatedIsInvalid) {
- EXPECT_FALSE(StreamingUtf8Validator::Validate("\xc2"));
-}
-
-} // namespace
-} // namespace base
diff --git a/base/i18n/string_compare.cc b/base/i18n/string_compare.cc
deleted file mode 100644
index 649c28119f..0000000000
--- a/base/i18n/string_compare.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2013 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/i18n/string_compare.h"
-
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-
-namespace base {
-namespace i18n {
-
-// Compares the character data stored in two different string16 strings by
-// specified Collator instance.
-UCollationResult CompareString16WithCollator(const icu::Collator& collator,
- const string16& lhs,
- const string16& rhs) {
- UErrorCode error = U_ZERO_ERROR;
- UCollationResult result = collator.compare(
- icu::UnicodeString(FALSE, lhs.c_str(), static_cast<int>(lhs.length())),
- icu::UnicodeString(FALSE, rhs.c_str(), static_cast<int>(rhs.length())),
- error);
- DCHECK(U_SUCCESS(error));
- return result;
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/string_compare.h b/base/i18n/string_compare.h
deleted file mode 100644
index 5fcc5feaed..0000000000
--- a/base/i18n/string_compare.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef BASE_I18N_STRING_COMPARE_H_
-#define BASE_I18N_STRING_COMPARE_H_
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/strings/string16.h"
-#include "third_party/icu/source/i18n/unicode/coll.h"
-
-namespace base {
-namespace i18n {
-
-// Compares the two strings using the specified collator.
-BASE_I18N_EXPORT UCollationResult
-CompareString16WithCollator(const icu::Collator& collator,
- const string16& lhs,
- const string16& rhs);
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_STRING_COMPARE_H_
diff --git a/base/i18n/string_search.cc b/base/i18n/string_search.cc
deleted file mode 100644
index 2f6fee4fe6..0000000000
--- a/base/i18n/string_search.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2011 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 <stdint.h>
-
-#include "base/i18n/string_search.h"
-#include "base/logging.h"
-
-#include "third_party/icu/source/i18n/unicode/usearch.h"
-
-namespace base {
-namespace i18n {
-
-FixedPatternStringSearchIgnoringCaseAndAccents::
-FixedPatternStringSearchIgnoringCaseAndAccents(const string16& find_this)
- : find_this_(find_this) {
- // usearch_open requires a valid string argument to be searched, even if we
- // want to set it by usearch_setText afterwards. So, supplying a dummy text.
- const string16& dummy = find_this_;
-
- UErrorCode status = U_ZERO_ERROR;
- search_ = usearch_open(find_this_.data(), find_this_.size(), dummy.data(),
- dummy.size(), uloc_getDefault(),
- nullptr, // breakiter
- &status);
- if (U_SUCCESS(status)) {
- UCollator* collator = usearch_getCollator(search_);
- ucol_setStrength(collator, UCOL_PRIMARY);
- usearch_reset(search_);
- }
-}
-
-FixedPatternStringSearchIgnoringCaseAndAccents::
-~FixedPatternStringSearchIgnoringCaseAndAccents() {
- if (search_)
- usearch_close(search_);
-}
-
-bool FixedPatternStringSearchIgnoringCaseAndAccents::Search(
- const string16& in_this, size_t* match_index, size_t* match_length) {
- UErrorCode status = U_ZERO_ERROR;
- usearch_setText(search_, in_this.data(), in_this.size(), &status);
-
- // Default to basic substring search if usearch fails. According to
- // http://icu-project.org/apiref/icu4c/usearch_8h.html, usearch_open will fail
- // if either |find_this| or |in_this| are empty. In either case basic
- // substring search will give the correct return value.
- if (!U_SUCCESS(status)) {
- size_t index = in_this.find(find_this_);
- if (index == string16::npos) {
- return false;
- } else {
- if (match_index)
- *match_index = index;
- if (match_length)
- *match_length = find_this_.size();
- return true;
- }
- }
-
- int32_t index = usearch_first(search_, &status);
- if (!U_SUCCESS(status) || index == USEARCH_DONE)
- return false;
- if (match_index)
- *match_index = static_cast<size_t>(index);
- if (match_length)
- *match_length = static_cast<size_t>(usearch_getMatchedLength(search_));
- return true;
-}
-
-bool StringSearchIgnoringCaseAndAccents(const string16& find_this,
- const string16& in_this,
- size_t* match_index,
- size_t* match_length) {
- return FixedPatternStringSearchIgnoringCaseAndAccents(find_this).Search(
- in_this, match_index, match_length);
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/string_search.h b/base/i18n/string_search.h
deleted file mode 100644
index 07a29c19b7..0000000000
--- a/base/i18n/string_search.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_I18N_STRING_SEARCH_H_
-#define BASE_I18N_STRING_SEARCH_H_
-
-#include <stddef.h>
-
-#include "base/i18n/base_i18n_export.h"
-#include "base/strings/string16.h"
-
-struct UStringSearch;
-
-namespace base {
-namespace i18n {
-
-// Returns true if |in_this| contains |find_this|. If |match_index| or
-// |match_length| are non-NULL, they are assigned the start position and total
-// length of the match.
-//
-// Only differences between base letters are taken into consideration. Case and
-// accent differences are ignored. Please refer to 'primary level' in
-// http://userguide.icu-project.org/collation/concepts for additional details.
-BASE_I18N_EXPORT
- bool StringSearchIgnoringCaseAndAccents(const string16& find_this,
- const string16& in_this,
- size_t* match_index,
- size_t* match_length);
-
-// This class is for speeding up multiple StringSearchIgnoringCaseAndAccents()
-// with the same |find_this| argument. |find_this| is passed as the constructor
-// argument, and precomputation for searching is done only at that timing.
-class BASE_I18N_EXPORT FixedPatternStringSearchIgnoringCaseAndAccents {
- public:
- explicit FixedPatternStringSearchIgnoringCaseAndAccents(
- const string16& find_this);
- ~FixedPatternStringSearchIgnoringCaseAndAccents();
-
- // Returns true if |in_this| contains |find_this|. If |match_index| or
- // |match_length| are non-NULL, they are assigned the start position and total
- // length of the match.
- bool Search(const string16& in_this,
- size_t* match_index,
- size_t* match_length);
-
- private:
- string16 find_this_;
- UStringSearch* search_;
-};
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_I18N_STRING_SEARCH_H_
diff --git a/base/i18n/string_search_unittest.cc b/base/i18n/string_search_unittest.cc
deleted file mode 100644
index 69501d6c99..0000000000
--- a/base/i18n/string_search_unittest.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (c) 2011 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 <stddef.h>
-
-#include <string>
-
-#include "base/i18n/rtl.h"
-#include "base/i18n/string_search.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/icu/source/i18n/unicode/usearch.h"
-
-namespace base {
-namespace i18n {
-
-// Note on setting default locale for testing: The current default locale on
-// the Mac trybot is en_US_POSIX, with which primary-level collation strength
-// string search is case-sensitive, when normally it should be
-// case-insensitive. In other locales (including en_US which English speakers
-// in the U.S. use), this search would be case-insensitive as expected.
-
-TEST(StringSearchTest, ASCII) {
- std::string default_locale(uloc_getDefault());
- bool locale_is_posix = (default_locale == "en_US_POSIX");
- if (locale_is_posix)
- SetICUDefaultLocale("en_US");
-
- size_t index = 0;
- size_t length = 0;
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- ASCIIToUTF16("hello"), ASCIIToUTF16("hello world"), &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(5U, length);
-
- EXPECT_FALSE(StringSearchIgnoringCaseAndAccents(
- ASCIIToUTF16("h e l l o"), ASCIIToUTF16("h e l l o"),
- &index, &length));
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- ASCIIToUTF16("aabaaa"), ASCIIToUTF16("aaabaabaaa"), &index, &length));
- EXPECT_EQ(4U, index);
- EXPECT_EQ(6U, length);
-
- EXPECT_FALSE(StringSearchIgnoringCaseAndAccents(
- ASCIIToUTF16("searching within empty string"), string16(),
- &index, &length));
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- string16(), ASCIIToUTF16("searching for empty string"), &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(0U, length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- ASCIIToUTF16("case insensitivity"), ASCIIToUTF16("CaSe InSeNsItIvItY"),
- &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(18U, length);
-
- if (locale_is_posix)
- SetICUDefaultLocale(default_locale.data());
-}
-
-TEST(StringSearchTest, UnicodeLocaleIndependent) {
- // Base characters
- const string16 e_base = WideToUTF16(L"e");
- const string16 E_base = WideToUTF16(L"E");
- const string16 a_base = WideToUTF16(L"a");
-
- // Composed characters
- const string16 e_with_acute_accent = WideToUTF16(L"\u00e9");
- const string16 E_with_acute_accent = WideToUTF16(L"\u00c9");
- const string16 e_with_grave_accent = WideToUTF16(L"\u00e8");
- const string16 E_with_grave_accent = WideToUTF16(L"\u00c8");
- const string16 a_with_acute_accent = WideToUTF16(L"\u00e1");
-
- // Decomposed characters
- const string16 e_with_acute_combining_mark = WideToUTF16(L"e\u0301");
- const string16 E_with_acute_combining_mark = WideToUTF16(L"E\u0301");
- const string16 e_with_grave_combining_mark = WideToUTF16(L"e\u0300");
- const string16 E_with_grave_combining_mark = WideToUTF16(L"E\u0300");
- const string16 a_with_acute_combining_mark = WideToUTF16(L"a\u0301");
-
- std::string default_locale(uloc_getDefault());
- bool locale_is_posix = (default_locale == "en_US_POSIX");
- if (locale_is_posix)
- SetICUDefaultLocale("en_US");
-
- size_t index = 0;
- size_t length = 0;
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_base, e_with_acute_accent, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_accent.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_acute_accent, e_base, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_base.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_base, e_with_acute_combining_mark, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_combining_mark.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_acute_combining_mark, e_base, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_base.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_acute_combining_mark, e_with_acute_accent,
- &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_accent.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_acute_accent, e_with_acute_combining_mark,
- &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_combining_mark.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_acute_combining_mark, e_with_grave_combining_mark,
- &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_grave_combining_mark.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_grave_combining_mark, e_with_acute_combining_mark,
- &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_combining_mark.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_acute_combining_mark, e_with_grave_accent, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_grave_accent.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- e_with_grave_accent, e_with_acute_combining_mark, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_combining_mark.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- E_with_acute_accent, e_with_acute_accent, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_accent.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- E_with_grave_accent, e_with_acute_accent, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_accent.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- E_with_acute_combining_mark, e_with_grave_accent, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_grave_accent.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- E_with_grave_combining_mark, e_with_acute_accent, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_acute_accent.size(), length);
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(
- E_base, e_with_grave_accent, &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(e_with_grave_accent.size(), length);
-
- EXPECT_FALSE(StringSearchIgnoringCaseAndAccents(
- a_with_acute_accent, e_with_acute_accent, &index, &length));
-
- EXPECT_FALSE(StringSearchIgnoringCaseAndAccents(
- a_with_acute_combining_mark, e_with_acute_combining_mark,
- &index, &length));
-
- if (locale_is_posix)
- SetICUDefaultLocale(default_locale.data());
-}
-
-TEST(StringSearchTest, UnicodeLocaleDependent) {
- // Base characters
- const string16 a_base = WideToUTF16(L"a");
-
- // Composed characters
- const string16 a_with_ring = WideToUTF16(L"\u00e5");
-
- EXPECT_TRUE(StringSearchIgnoringCaseAndAccents(a_base, a_with_ring, nullptr,
- nullptr));
-
- const char* default_locale = uloc_getDefault();
- SetICUDefaultLocale("da");
-
- EXPECT_FALSE(StringSearchIgnoringCaseAndAccents(a_base, a_with_ring, nullptr,
- nullptr));
-
- SetICUDefaultLocale(default_locale);
-}
-
-TEST(StringSearchTest, FixedPatternMultipleSearch) {
- std::string default_locale(uloc_getDefault());
- bool locale_is_posix = (default_locale == "en_US_POSIX");
- if (locale_is_posix)
- SetICUDefaultLocale("en_US");
-
- size_t index = 0;
- size_t length = 0;
-
- // Search "hello" over multiple texts.
- FixedPatternStringSearchIgnoringCaseAndAccents query(ASCIIToUTF16("hello"));
- EXPECT_TRUE(query.Search(ASCIIToUTF16("12hello34"), &index, &length));
- EXPECT_EQ(2U, index);
- EXPECT_EQ(5U, length);
- EXPECT_FALSE(query.Search(ASCIIToUTF16("bye"), &index, &length));
- EXPECT_TRUE(query.Search(ASCIIToUTF16("hELLo"), &index, &length));
- EXPECT_EQ(0U, index);
- EXPECT_EQ(5U, length);
-
- if (locale_is_posix)
- SetICUDefaultLocale(default_locale.data());
-}
-
-} // namespace i18n
-} // namespace base
diff --git a/base/i18n/time_formatting.cc b/base/i18n/time_formatting.cc
deleted file mode 100644
index 3a5394ae3a..0000000000
--- a/base/i18n/time_formatting.cc
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright (c) 2011 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/i18n/time_formatting.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/i18n/unicodestring.h"
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "third_party/icu/source/common/unicode/utypes.h"
-#include "third_party/icu/source/i18n/unicode/datefmt.h"
-#include "third_party/icu/source/i18n/unicode/dtitvfmt.h"
-#include "third_party/icu/source/i18n/unicode/dtptngen.h"
-#include "third_party/icu/source/i18n/unicode/fmtable.h"
-#include "third_party/icu/source/i18n/unicode/measfmt.h"
-#include "third_party/icu/source/i18n/unicode/smpdtfmt.h"
-
-namespace base {
-namespace {
-
-string16 TimeFormat(const icu::DateFormat* formatter,
- const Time& time) {
- DCHECK(formatter);
- icu::UnicodeString date_string;
-
- formatter->format(static_cast<UDate>(time.ToDoubleT() * 1000), date_string);
- return i18n::UnicodeStringToString16(date_string);
-}
-
-string16 TimeFormatWithoutAmPm(const icu::DateFormat* formatter,
- const Time& time) {
- DCHECK(formatter);
- icu::UnicodeString time_string;
-
- icu::FieldPosition ampm_field(icu::DateFormat::kAmPmField);
- formatter->format(
- static_cast<UDate>(time.ToDoubleT() * 1000), time_string, ampm_field);
- int ampm_length = ampm_field.getEndIndex() - ampm_field.getBeginIndex();
- if (ampm_length) {
- int begin = ampm_field.getBeginIndex();
- // Doesn't include any spacing before the field.
- if (begin)
- begin--;
- time_string.removeBetween(begin, ampm_field.getEndIndex());
- }
- return i18n::UnicodeStringToString16(time_string);
-}
-
-icu::SimpleDateFormat CreateSimpleDateFormatter(const char* pattern) {
- // Generate a locale-dependent format pattern. The generator will take
- // care of locale-dependent formatting issues like which separator to
- // use (some locales use '.' instead of ':'), and where to put the am/pm
- // marker.
- UErrorCode status = U_ZERO_ERROR;
- std::unique_ptr<icu::DateTimePatternGenerator> generator(
- icu::DateTimePatternGenerator::createInstance(status));
- DCHECK(U_SUCCESS(status));
- icu::UnicodeString generated_pattern =
- generator->getBestPattern(icu::UnicodeString(pattern), status);
- DCHECK(U_SUCCESS(status));
-
- // Then, format the time using the generated pattern.
- icu::SimpleDateFormat formatter(generated_pattern, status);
- DCHECK(U_SUCCESS(status));
-
- return formatter;
-}
-
-UMeasureFormatWidth DurationWidthToMeasureWidth(DurationFormatWidth width) {
- switch (width) {
- case DURATION_WIDTH_WIDE: return UMEASFMT_WIDTH_WIDE;
- case DURATION_WIDTH_SHORT: return UMEASFMT_WIDTH_SHORT;
- case DURATION_WIDTH_NARROW: return UMEASFMT_WIDTH_NARROW;
- case DURATION_WIDTH_NUMERIC: return UMEASFMT_WIDTH_NUMERIC;
- }
- NOTREACHED();
- return UMEASFMT_WIDTH_COUNT;
-}
-
-const char* DateFormatToString(DateFormat format) {
- switch (format) {
- case DATE_FORMAT_YEAR_MONTH:
- return UDAT_YEAR_MONTH;
- case DATE_FORMAT_MONTH_WEEKDAY_DAY:
- return UDAT_MONTH_WEEKDAY_DAY;
- }
- NOTREACHED();
- return UDAT_YEAR_MONTH_DAY;
-}
-
-} // namespace
-
-string16 TimeFormatTimeOfDay(const Time& time) {
- // We can omit the locale parameter because the default should match
- // Chrome's application locale.
- std::unique_ptr<icu::DateFormat> formatter(
- icu::DateFormat::createTimeInstance(icu::DateFormat::kShort));
- return TimeFormat(formatter.get(), time);
-}
-
-string16 TimeFormatTimeOfDayWithMilliseconds(const Time& time) {
- icu::SimpleDateFormat formatter = CreateSimpleDateFormatter("HmsSSS");
- return TimeFormatWithoutAmPm(&formatter, time);
-}
-
-string16 TimeFormatTimeOfDayWithHourClockType(const Time& time,
- HourClockType type,
- AmPmClockType ampm) {
- // Just redirect to the normal function if the default type matches the
- // given type.
- HourClockType default_type = GetHourClockType();
- if (default_type == type && (type == k24HourClock || ampm == kKeepAmPm)) {
- return TimeFormatTimeOfDay(time);
- }
-
- const char* base_pattern = (type == k12HourClock ? "ahm" : "Hm");
- icu::SimpleDateFormat formatter = CreateSimpleDateFormatter(base_pattern);
-
- if (ampm == kKeepAmPm) {
- return TimeFormat(&formatter, time);
- } else {
- return TimeFormatWithoutAmPm(&formatter, time);
- }
-}
-
-string16 TimeFormatShortDate(const Time& time) {
- std::unique_ptr<icu::DateFormat> formatter(
- icu::DateFormat::createDateInstance(icu::DateFormat::kMedium));
- return TimeFormat(formatter.get(), time);
-}
-
-string16 TimeFormatShortDateNumeric(const Time& time) {
- std::unique_ptr<icu::DateFormat> formatter(
- icu::DateFormat::createDateInstance(icu::DateFormat::kShort));
- return TimeFormat(formatter.get(), time);
-}
-
-string16 TimeFormatShortDateAndTime(const Time& time) {
- std::unique_ptr<icu::DateFormat> formatter(
- icu::DateFormat::createDateTimeInstance(icu::DateFormat::kShort));
- return TimeFormat(formatter.get(), time);
-}
-
-string16 TimeFormatShortDateAndTimeWithTimeZone(const Time& time) {
- std::unique_ptr<icu::DateFormat> formatter(
- icu::DateFormat::createDateTimeInstance(icu::DateFormat::kShort,
- icu::DateFormat::kLong));
- return TimeFormat(formatter.get(), time);
-}
-
-string16 TimeFormatMonthAndYear(const Time& time) {
- icu::SimpleDateFormat formatter =
- CreateSimpleDateFormatter(DateFormatToString(DATE_FORMAT_YEAR_MONTH));
- return TimeFormat(&formatter, time);
-}
-
-string16 TimeFormatFriendlyDateAndTime(const Time& time) {
- std::unique_ptr<icu::DateFormat> formatter(
- icu::DateFormat::createDateTimeInstance(icu::DateFormat::kFull));
- return TimeFormat(formatter.get(), time);
-}
-
-string16 TimeFormatFriendlyDate(const Time& time) {
- std::unique_ptr<icu::DateFormat> formatter(
- icu::DateFormat::createDateInstance(icu::DateFormat::kFull));
- return TimeFormat(formatter.get(), time);
-}
-
-string16 TimeFormatWithPattern(const Time& time, const char* pattern) {
- icu::SimpleDateFormat formatter = CreateSimpleDateFormatter(pattern);
- return TimeFormat(&formatter, time);
-}
-
-bool TimeDurationFormat(const TimeDelta time,
- const DurationFormatWidth width,
- string16* out) {
- DCHECK(out);
- UErrorCode status = U_ZERO_ERROR;
- const int total_minutes = static_cast<int>(time.InSecondsF() / 60 + 0.5);
- const int hours = total_minutes / 60;
- const int minutes = total_minutes % 60;
- UMeasureFormatWidth u_width = DurationWidthToMeasureWidth(width);
-
- // TODO(derat): Delete the |status| checks and LOG(ERROR) calls throughout
- // this function once the cause of http://crbug.com/677043 is tracked down.
- const icu::Measure measures[] = {
- icu::Measure(hours, icu::MeasureUnit::createHour(status), status),
- icu::Measure(minutes, icu::MeasureUnit::createMinute(status), status)};
- if (U_FAILURE(status)) {
- LOG(ERROR) << "Creating MeasureUnit or Measure for " << hours << "h"
- << minutes << "m failed: " << u_errorName(status);
- return false;
- }
-
- icu::MeasureFormat measure_format(icu::Locale::getDefault(), u_width, status);
- if (U_FAILURE(status)) {
- LOG(ERROR) << "Creating MeasureFormat for "
- << icu::Locale::getDefault().getName()
- << " failed: " << u_errorName(status);
- return false;
- }
-
- icu::UnicodeString formatted;
- icu::FieldPosition ignore(icu::FieldPosition::DONT_CARE);
- measure_format.formatMeasures(measures, 2, formatted, ignore, status);
- if (U_FAILURE(status)) {
- LOG(ERROR) << "formatMeasures failed: " << u_errorName(status);
- return false;
- }
-
- *out = i18n::UnicodeStringToString16(formatted);
- return true;
-}
-
-bool TimeDurationFormatWithSeconds(const TimeDelta time,
- const DurationFormatWidth width,
- string16* out) {
- DCHECK(out);
- UErrorCode status = U_ZERO_ERROR;
- const int64_t total_seconds = static_cast<int>(time.InSecondsF() + 0.5);
- const int hours = total_seconds / 3600;
- const int minutes = (total_seconds - hours * 3600) / 60;
- const int seconds = total_seconds % 60;
- UMeasureFormatWidth u_width = DurationWidthToMeasureWidth(width);
-
- const icu::Measure measures[] = {
- icu::Measure(hours, icu::MeasureUnit::createHour(status), status),
- icu::Measure(minutes, icu::MeasureUnit::createMinute(status), status),
- icu::Measure(seconds, icu::MeasureUnit::createSecond(status), status)};
- icu::MeasureFormat measure_format(icu::Locale::getDefault(), u_width, status);
- icu::UnicodeString formatted;
- icu::FieldPosition ignore(icu::FieldPosition::DONT_CARE);
- measure_format.formatMeasures(measures, 3, formatted, ignore, status);
- *out = i18n::UnicodeStringToString16(formatted);
- return U_SUCCESS(status) == TRUE;
-}
-
-string16 DateIntervalFormat(const Time& begin_time,
- const Time& end_time,
- DateFormat format) {
- UErrorCode status = U_ZERO_ERROR;
-
- std::unique_ptr<icu::DateIntervalFormat> formatter(
- icu::DateIntervalFormat::createInstance(DateFormatToString(format),
- status));
-
- icu::FieldPosition pos = 0;
- UDate start_date = static_cast<UDate>(begin_time.ToDoubleT() * 1000);
- UDate end_date = static_cast<UDate>(end_time.ToDoubleT() * 1000);
- icu::DateInterval interval(start_date, end_date);
- icu::UnicodeString formatted;
- formatter->format(&interval, formatted, pos, status);
- return i18n::UnicodeStringToString16(formatted);
-}
-
-HourClockType GetHourClockType() {
- // TODO(satorux,jshin): Rework this with ures_getByKeyWithFallback()
- // once it becomes public. The short time format can be found at
- // "calendar/gregorian/DateTimePatterns/3" in the resources.
- std::unique_ptr<icu::SimpleDateFormat> formatter(
- static_cast<icu::SimpleDateFormat*>(
- icu::DateFormat::createTimeInstance(icu::DateFormat::kShort)));
- // Retrieve the short time format.
- icu::UnicodeString pattern_unicode;
- formatter->toPattern(pattern_unicode);
-
- // Determine what hour clock type the current locale uses, by checking
- // "a" (am/pm marker) in the short time format. This is reliable as "a"
- // is used by all of 12-hour clock formats, but not any of 24-hour clock
- // formats, as shown below.
- //
- // % grep -A4 DateTimePatterns third_party/icu/source/data/locales/*.txt |
- // grep -B1 -- -- |grep -v -- '--' |
- // perl -nle 'print $1 if /^\S+\s+"(.*)"/' |sort -u
- //
- // H.mm
- // H:mm
- // HH.mm
- // HH:mm
- // a h:mm
- // ah:mm
- // ahh:mm
- // h-mm a
- // h:mm a
- // hh:mm a
- //
- // See http://userguide.icu-project.org/formatparse/datetime for details
- // about the date/time format syntax.
- if (pattern_unicode.indexOf('a') == -1) {
- return k24HourClock;
- } else {
- return k12HourClock;
- }
-}
-
-} // namespace base
diff --git a/base/i18n/time_formatting.h b/base/i18n/time_formatting.h
deleted file mode 100644
index 41793b339c..0000000000
--- a/base/i18n/time_formatting.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2011 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.
-
-// Basic time formatting methods. These methods use the current locale
-// formatting for displaying the time.
-
-#ifndef BASE_I18N_TIME_FORMATTING_H_
-#define BASE_I18N_TIME_FORMATTING_H_
-
-#include "base/compiler_specific.h"
-#include "base/i18n/base_i18n_export.h"
-#include "base/strings/string16.h"
-
-namespace base {
-
-class Time;
-class TimeDelta;
-
-// Argument type used to specify the hour clock type.
-enum HourClockType {
- k12HourClock, // Uses 1-12. e.g., "3:07 PM"
- k24HourClock, // Uses 0-23. e.g., "15:07"
-};
-
-// Argument type used to specify whether or not to include AM/PM sign.
-enum AmPmClockType {
- kDropAmPm, // Drops AM/PM sign. e.g., "3:07"
- kKeepAmPm, // Keeps AM/PM sign. e.g., "3:07 PM"
-};
-
-// Should match UMeasureFormatWidth in measfmt.h; replicated here to avoid
-// requiring third_party/icu dependencies with this file.
-enum DurationFormatWidth {
- DURATION_WIDTH_WIDE, // "3 hours, 7 minutes"
- DURATION_WIDTH_SHORT, // "3 hr, 7 min"
- DURATION_WIDTH_NARROW, // "3h 7m"
- DURATION_WIDTH_NUMERIC // "3:07"
-};
-
-// Date formats from third_party/icu/source/i18n/unicode/udat.h. Add more as
-// necessary.
-enum DateFormat {
- // November 2007
- DATE_FORMAT_YEAR_MONTH,
- // Tuesday, 7 November
- DATE_FORMAT_MONTH_WEEKDAY_DAY,
-};
-
-// TODO(derat@chromium.org): Update all of these functions to return boolean
-// "success" values and use out-params for formatted strings:
-// http://crbug.com/698802
-
-// Returns the time of day, e.g., "3:07 PM".
-BASE_I18N_EXPORT string16 TimeFormatTimeOfDay(const Time& time);
-
-// Returns the time of day in 24-hour clock format with millisecond accuracy,
-// e.g., "15:07:30.568"
-BASE_I18N_EXPORT string16 TimeFormatTimeOfDayWithMilliseconds(const Time& time);
-
-// Returns the time of day in the specified hour clock type. e.g.
-// "3:07 PM" (type == k12HourClock, ampm == kKeepAmPm).
-// "3:07" (type == k12HourClock, ampm == kDropAmPm).
-// "15:07" (type == k24HourClock).
-BASE_I18N_EXPORT string16 TimeFormatTimeOfDayWithHourClockType(
- const Time& time,
- HourClockType type,
- AmPmClockType ampm);
-
-// Returns a shortened date, e.g. "Nov 7, 2007"
-BASE_I18N_EXPORT string16 TimeFormatShortDate(const Time& time);
-
-// Returns a numeric date such as 12/13/52.
-BASE_I18N_EXPORT string16 TimeFormatShortDateNumeric(const Time& time);
-
-// Returns a numeric date and time such as "12/13/52 2:44:30 PM".
-BASE_I18N_EXPORT string16 TimeFormatShortDateAndTime(const Time& time);
-
-// Returns a month and year, e.g. "November 2007"
-BASE_I18N_EXPORT string16 TimeFormatMonthAndYear(const Time& time);
-
-// Returns a numeric date and time with time zone such as
-// "12/13/52 2:44:30 PM PST".
-BASE_I18N_EXPORT string16
-TimeFormatShortDateAndTimeWithTimeZone(const Time& time);
-
-// Formats a time in a friendly sentence format, e.g.
-// "Monday, March 6, 2008 2:44:30 PM".
-BASE_I18N_EXPORT string16 TimeFormatFriendlyDateAndTime(const Time& time);
-
-// Formats a time in a friendly sentence format, e.g.
-// "Monday, March 6, 2008".
-BASE_I18N_EXPORT string16 TimeFormatFriendlyDate(const Time& time);
-
-// Formats a time using a skeleton to produce a format for different locales
-// when an unusual time format is needed, e.g. "Feb. 2, 18:00".
-//
-// See http://userguide.icu-project.org/formatparse/datetime for details.
-BASE_I18N_EXPORT string16 TimeFormatWithPattern(const Time& time,
- const char* pattern);
-
-// Formats a time duration of hours and minutes into various formats, e.g.,
-// "3:07" or "3 hours, 7 minutes", and returns true on success. See
-// DurationFormatWidth for details.
-//
-// Please don't use width = DURATION_WIDTH_NUMERIC when the time duration
-// can possibly be larger than 24h, as the hour value will be cut below 24
-// after formatting.
-// TODO(chengx): fix function output when width = DURATION_WIDTH_NUMERIC
-// (http://crbug.com/675791)
-BASE_I18N_EXPORT bool TimeDurationFormat(const TimeDelta time,
- const DurationFormatWidth width,
- string16* out) WARN_UNUSED_RESULT;
-
-// Formats a time duration of hours, minutes and seconds into various formats,
-// e.g., "3:07:30" or "3 hours, 7 minutes, 30 seconds", and returns true on
-// success. See DurationFormatWidth for details.
-//
-// Please don't use width = DURATION_WIDTH_NUMERIC when the time duration
-// can possibly be larger than 24h, as the hour value will be cut below 24
-// after formatting.
-// TODO(chengx): fix function output when width = DURATION_WIDTH_NUMERIC
-// (http://crbug.com/675791)
-BASE_I18N_EXPORT bool TimeDurationFormatWithSeconds(
- const TimeDelta time,
- const DurationFormatWidth width,
- string16* out) WARN_UNUSED_RESULT;
-
-// Formats a date interval into various formats, e.g. "2 December - 4 December"
-// or "March 2016 - December 2016". See DateFormat for details.
-BASE_I18N_EXPORT string16 DateIntervalFormat(const Time& begin_time,
- const Time& end_time,
- DateFormat format);
-
-// Gets the hour clock type of the current locale. e.g.
-// k12HourClock (en-US).
-// k24HourClock (en-GB).
-BASE_I18N_EXPORT HourClockType GetHourClockType();
-
-} // namespace base
-
-#endif // BASE_I18N_TIME_FORMATTING_H_
diff --git a/base/i18n/time_formatting_unittest.cc b/base/i18n/time_formatting_unittest.cc
deleted file mode 100644
index 29b25972d2..0000000000
--- a/base/i18n/time_formatting_unittest.cc
+++ /dev/null
@@ -1,433 +0,0 @@
-// Copyright (c) 2011 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/i18n/time_formatting.h"
-
-#include <memory>
-
-#include "base/i18n/rtl.h"
-#include "base/i18n/unicodestring.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/icu_test_util.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/icu/source/common/unicode/uversion.h"
-#include "third_party/icu/source/i18n/unicode/calendar.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-#include "third_party/icu/source/i18n/unicode/tzfmt.h"
-
-namespace base {
-namespace {
-
-const Time::Exploded kTestDateTimeExploded = {
- 2011, 4, 6, 30, // Sat, Apr 30, 2011
- 22, 42, 7, 0 // 22:42:07.000 in UTC = 15:42:07 in US PDT.
-};
-
-// Returns difference between the local time and GMT formatted as string.
-// This function gets |time| because the difference depends on time,
-// see https://en.wikipedia.org/wiki/Daylight_saving_time for details.
-string16 GetShortTimeZone(const Time& time) {
- UErrorCode status = U_ZERO_ERROR;
- std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
- std::unique_ptr<icu::TimeZoneFormat> zone_formatter(
- icu::TimeZoneFormat::createInstance(icu::Locale::getDefault(), status));
- EXPECT_TRUE(U_SUCCESS(status));
- icu::UnicodeString name;
- zone_formatter->format(UTZFMT_STYLE_SPECIFIC_SHORT, *zone,
- static_cast<UDate>(time.ToDoubleT() * 1000),
- name, nullptr);
- return i18n::UnicodeStringToString16(name);
-}
-
-// Calls TimeDurationFormat() with |delta| and |width| and returns the resulting
-// string. On failure, adds a failed expectation and returns an empty string.
-string16 TimeDurationFormatString(const TimeDelta& delta,
- DurationFormatWidth width) {
- string16 str;
- EXPECT_TRUE(TimeDurationFormat(delta, width, &str))
- << "Failed to format " << delta.ToInternalValue() << " with width "
- << width;
- return str;
-}
-
-// Calls TimeDurationFormatWithSeconds() with |delta| and |width| and returns
-// the resulting string. On failure, adds a failed expectation and returns an
-// empty string.
-string16 TimeDurationFormatWithSecondsString(const TimeDelta& delta,
- DurationFormatWidth width) {
- string16 str;
- EXPECT_TRUE(TimeDurationFormatWithSeconds(delta, width, &str))
- << "Failed to format " << delta.ToInternalValue() << " with width "
- << width;
- return str;
-}
-
-class ScopedRestoreDefaultTimezone {
- public:
- ScopedRestoreDefaultTimezone(const char* zoneid) {
- original_zone_.reset(icu::TimeZone::createDefault());
- icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(zoneid));
- }
- ~ScopedRestoreDefaultTimezone() {
- icu::TimeZone::adoptDefault(original_zone_.release());
- }
-
- ScopedRestoreDefaultTimezone(const ScopedRestoreDefaultTimezone&) = delete;
- ScopedRestoreDefaultTimezone& operator=(const ScopedRestoreDefaultTimezone&) =
- delete;
-
- private:
- std::unique_ptr<icu::TimeZone> original_zone_;
-};
-
-TEST(TimeFormattingTest, TimeFormatTimeOfDayDefault12h) {
- // Test for a locale defaulted to 12h clock.
- // As an instance, we use third_party/icu/source/data/locales/en.txt.
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("en_US");
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &time));
- string16 clock24h(ASCIIToUTF16("15:42"));
- string16 clock12h_pm(ASCIIToUTF16("3:42 PM"));
- string16 clock12h(ASCIIToUTF16("3:42"));
- string16 clock24h_millis(ASCIIToUTF16("15:42:07.000"));
-
- // The default is 12h clock.
- EXPECT_EQ(clock12h_pm, TimeFormatTimeOfDay(time));
- EXPECT_EQ(clock24h_millis, TimeFormatTimeOfDayWithMilliseconds(time));
- EXPECT_EQ(k12HourClock, GetHourClockType());
- // k{Keep,Drop}AmPm should not affect for 24h clock.
- EXPECT_EQ(clock24h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k24HourClock,
- kKeepAmPm));
- EXPECT_EQ(clock24h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k24HourClock,
- kDropAmPm));
- // k{Keep,Drop}AmPm affects for 12h clock.
- EXPECT_EQ(clock12h_pm,
- TimeFormatTimeOfDayWithHourClockType(time,
- k12HourClock,
- kKeepAmPm));
- EXPECT_EQ(clock12h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k12HourClock,
- kDropAmPm));
-}
-
-TEST(TimeFormattingTest, TimeFormatTimeOfDayDefault24h) {
- // Test for a locale defaulted to 24h clock.
- // As an instance, we use third_party/icu/source/data/locales/en_GB.txt.
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("en_GB");
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &time));
- string16 clock24h(ASCIIToUTF16("15:42"));
- string16 clock12h_pm(ASCIIToUTF16("3:42 pm"));
- string16 clock12h(ASCIIToUTF16("3:42"));
- string16 clock24h_millis(ASCIIToUTF16("15:42:07.000"));
-
- // The default is 24h clock.
- EXPECT_EQ(clock24h, TimeFormatTimeOfDay(time));
- EXPECT_EQ(clock24h_millis, TimeFormatTimeOfDayWithMilliseconds(time));
- EXPECT_EQ(k24HourClock, GetHourClockType());
- // k{Keep,Drop}AmPm should not affect for 24h clock.
- EXPECT_EQ(clock24h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k24HourClock,
- kKeepAmPm));
- EXPECT_EQ(clock24h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k24HourClock,
- kDropAmPm));
- // k{Keep,Drop}AmPm affects for 12h clock.
- EXPECT_EQ(clock12h_pm,
- TimeFormatTimeOfDayWithHourClockType(time,
- k12HourClock,
- kKeepAmPm));
- EXPECT_EQ(clock12h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k12HourClock,
- kDropAmPm));
-}
-
-TEST(TimeFormattingTest, TimeFormatTimeOfDayJP) {
- // Test for a locale that uses different mark than "AM" and "PM".
- // As an instance, we use third_party/icu/source/data/locales/ja.txt.
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("ja_JP");
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &time));
- string16 clock24h(ASCIIToUTF16("15:42"));
- string16 clock12h_pm(UTF8ToUTF16(u8"午後3:42"));
- string16 clock12h(ASCIIToUTF16("3:42"));
-
- // The default is 24h clock.
- EXPECT_EQ(clock24h, TimeFormatTimeOfDay(time));
- EXPECT_EQ(k24HourClock, GetHourClockType());
- // k{Keep,Drop}AmPm should not affect for 24h clock.
- EXPECT_EQ(clock24h, TimeFormatTimeOfDayWithHourClockType(time, k24HourClock,
- kKeepAmPm));
- EXPECT_EQ(clock24h, TimeFormatTimeOfDayWithHourClockType(time, k24HourClock,
- kDropAmPm));
- // k{Keep,Drop}AmPm affects for 12h clock.
- EXPECT_EQ(clock12h_pm, TimeFormatTimeOfDayWithHourClockType(
- time, k12HourClock, kKeepAmPm));
- EXPECT_EQ(clock12h, TimeFormatTimeOfDayWithHourClockType(time, k12HourClock,
- kDropAmPm));
-}
-
-TEST(TimeFormattingTest, TimeFormatTimeOfDayDE) {
- // German uses 24h by default, but uses 'AM', 'PM' for 12h format.
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("de");
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &time));
- string16 clock24h(ASCIIToUTF16("15:42"));
- string16 clock12h_pm(UTF8ToUTF16("3:42 PM"));
- string16 clock12h(ASCIIToUTF16("3:42"));
-
- // The default is 24h clock.
- EXPECT_EQ(clock24h, TimeFormatTimeOfDay(time));
- EXPECT_EQ(k24HourClock, GetHourClockType());
- // k{Keep,Drop}AmPm should not affect for 24h clock.
- EXPECT_EQ(clock24h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k24HourClock,
- kKeepAmPm));
- EXPECT_EQ(clock24h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k24HourClock,
- kDropAmPm));
- // k{Keep,Drop}AmPm affects for 12h clock.
- EXPECT_EQ(clock12h_pm,
- TimeFormatTimeOfDayWithHourClockType(time,
- k12HourClock,
- kKeepAmPm));
- EXPECT_EQ(clock12h,
- TimeFormatTimeOfDayWithHourClockType(time,
- k12HourClock,
- kDropAmPm));
-}
-
-TEST(TimeFormattingTest, TimeFormatDateUS) {
- // See third_party/icu/source/data/locales/en.txt.
- // The date patterns are "EEEE, MMMM d, y", "MMM d, y", and "M/d/yy".
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("en_US");
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &time));
-
- EXPECT_EQ(ASCIIToUTF16("Apr 30, 2011"), TimeFormatShortDate(time));
- EXPECT_EQ(ASCIIToUTF16("4/30/11"), TimeFormatShortDateNumeric(time));
-
- EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM"),
- TimeFormatShortDateAndTime(time));
- EXPECT_EQ(ASCIIToUTF16("4/30/11, 3:42:07 PM ") + GetShortTimeZone(time),
- TimeFormatShortDateAndTimeWithTimeZone(time));
-
- EXPECT_EQ(ASCIIToUTF16("April 2011"), TimeFormatMonthAndYear(time));
-
- EXPECT_EQ(ASCIIToUTF16("Saturday, April 30, 2011 at 3:42:07 PM"),
- TimeFormatFriendlyDateAndTime(time));
-
- EXPECT_EQ(ASCIIToUTF16("Saturday, April 30, 2011"),
- TimeFormatFriendlyDate(time));
-}
-
-TEST(TimeFormattingTest, TimeFormatDateGB) {
- // See third_party/icu/source/data/locales/en_GB.txt.
- // The date patterns are "EEEE, d MMMM y", "d MMM y", and "dd/MM/yyyy".
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("en_GB");
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &time));
-
- EXPECT_EQ(ASCIIToUTF16("30 Apr 2011"), TimeFormatShortDate(time));
- EXPECT_EQ(ASCIIToUTF16("30/04/2011"), TimeFormatShortDateNumeric(time));
- EXPECT_EQ(ASCIIToUTF16("30/04/2011, 15:42:07"),
- TimeFormatShortDateAndTime(time));
- EXPECT_EQ(ASCIIToUTF16("30/04/2011, 15:42:07 ") + GetShortTimeZone(time),
- TimeFormatShortDateAndTimeWithTimeZone(time));
- EXPECT_EQ(ASCIIToUTF16("April 2011"), TimeFormatMonthAndYear(time));
- EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011 at 15:42:07"),
- TimeFormatFriendlyDateAndTime(time));
- EXPECT_EQ(ASCIIToUTF16("Saturday, 30 April 2011"),
- TimeFormatFriendlyDate(time));
-}
-
-TEST(TimeFormattingTest, TimeFormatWithPattern) {
- test::ScopedRestoreICUDefaultLocale restore_locale;
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &time));
-
- i18n::SetICUDefaultLocale("en_US");
- EXPECT_EQ(ASCIIToUTF16("Apr 30, 2011"), TimeFormatWithPattern(time, "yMMMd"));
- EXPECT_EQ(ASCIIToUTF16("April 30, 3:42:07 PM"),
- TimeFormatWithPattern(time, "MMMMdjmmss"));
-
- i18n::SetICUDefaultLocale("en_GB");
- EXPECT_EQ(ASCIIToUTF16("30 Apr 2011"), TimeFormatWithPattern(time, "yMMMd"));
- EXPECT_EQ(ASCIIToUTF16("30 April, 15:42:07"),
- TimeFormatWithPattern(time, "MMMMdjmmss"));
-
- i18n::SetICUDefaultLocale("ja_JP");
- EXPECT_EQ(UTF8ToUTF16(u8"2011年4月30日"),
- TimeFormatWithPattern(time, "yMMMd"));
- EXPECT_EQ(UTF8ToUTF16(u8"4月30日 15:42:07"),
- TimeFormatWithPattern(time, "MMMMdjmmss"));
-}
-
-TEST(TimeFormattingTest, TimeDurationFormat) {
- test::ScopedRestoreICUDefaultLocale restore_locale;
- TimeDelta delta = TimeDelta::FromMinutes(15 * 60 + 42);
-
- // US English.
- i18n::SetICUDefaultLocale("en_US");
- EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes"),
- TimeDurationFormatString(delta, DURATION_WIDTH_WIDE));
- EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min"),
- TimeDurationFormatString(delta, DURATION_WIDTH_SHORT));
- EXPECT_EQ(ASCIIToUTF16("15h 42m"),
- TimeDurationFormatString(delta, DURATION_WIDTH_NARROW));
- EXPECT_EQ(ASCIIToUTF16("15:42"),
- TimeDurationFormatString(delta, DURATION_WIDTH_NUMERIC));
-
- // Danish, with Latin alphabet but different abbreviations and punctuation.
- i18n::SetICUDefaultLocale("da");
- EXPECT_EQ(ASCIIToUTF16("15 timer og 42 minutter"),
- TimeDurationFormatString(delta, DURATION_WIDTH_WIDE));
- EXPECT_EQ(ASCIIToUTF16("15 t og 42 min."),
- TimeDurationFormatString(delta, DURATION_WIDTH_SHORT));
- EXPECT_EQ(ASCIIToUTF16("15 t og 42 min"),
- TimeDurationFormatString(delta, DURATION_WIDTH_NARROW));
- EXPECT_EQ(ASCIIToUTF16("15.42"),
- TimeDurationFormatString(delta, DURATION_WIDTH_NUMERIC));
-
- // Persian, with non-Arabic numbers.
- i18n::SetICUDefaultLocale("fa");
- string16 fa_wide = UTF8ToUTF16(
- u8"\u06f1\u06f5 \u0633\u0627\u0639\u062a \u0648 \u06f4\u06f2 \u062f\u0642"
- u8"\u06cc\u0642\u0647");
- string16 fa_short = UTF8ToUTF16(
- u8"\u06f1\u06f5 \u0633\u0627\u0639\u062a\u060c\u200f \u06f4\u06f2 \u062f"
- u8"\u0642\u06cc\u0642\u0647");
- string16 fa_narrow = UTF8ToUTF16(
- u8"\u06f1\u06f5 \u0633\u0627\u0639\u062a \u06f4\u06f2 \u062f\u0642\u06cc"
- u8"\u0642\u0647");
- string16 fa_numeric = UTF8ToUTF16(u8"\u06f1\u06f5:\u06f4\u06f2");
- EXPECT_EQ(fa_wide, TimeDurationFormatString(delta, DURATION_WIDTH_WIDE));
- EXPECT_EQ(fa_short, TimeDurationFormatString(delta, DURATION_WIDTH_SHORT));
- EXPECT_EQ(fa_narrow, TimeDurationFormatString(delta, DURATION_WIDTH_NARROW));
- EXPECT_EQ(fa_numeric,
- TimeDurationFormatString(delta, DURATION_WIDTH_NUMERIC));
-}
-
-TEST(TimeFormattingTest, TimeDurationFormatWithSeconds) {
- test::ScopedRestoreICUDefaultLocale restore_locale;
-
- // US English.
- i18n::SetICUDefaultLocale("en_US");
-
- // Test different formats.
- TimeDelta delta = TimeDelta::FromSeconds(15 * 3600 + 42 * 60 + 30);
- EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes, 30 seconds"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE));
- EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min, 30 sec"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT));
- EXPECT_EQ(ASCIIToUTF16("15h 42m 30s"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW));
- EXPECT_EQ(ASCIIToUTF16("15:42:30"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NUMERIC));
-
- // Test edge case when hour >= 100.
- delta = TimeDelta::FromSeconds(125 * 3600 + 42 * 60 + 30);
- EXPECT_EQ(ASCIIToUTF16("125 hours, 42 minutes, 30 seconds"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE));
- EXPECT_EQ(ASCIIToUTF16("125 hr, 42 min, 30 sec"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT));
- EXPECT_EQ(ASCIIToUTF16("125h 42m 30s"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW));
-
- // Test edge case when minute = 0.
- delta = TimeDelta::FromSeconds(15 * 3600 + 0 * 60 + 30);
- EXPECT_EQ(ASCIIToUTF16("15 hours, 0 minutes, 30 seconds"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE));
- EXPECT_EQ(ASCIIToUTF16("15 hr, 0 min, 30 sec"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT));
- EXPECT_EQ(ASCIIToUTF16("15h 0m 30s"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW));
- EXPECT_EQ(ASCIIToUTF16("15:00:30"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NUMERIC));
-
- // Test edge case when second = 0.
- delta = TimeDelta::FromSeconds(15 * 3600 + 42 * 60 + 0);
- EXPECT_EQ(ASCIIToUTF16("15 hours, 42 minutes, 0 seconds"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_WIDE));
- EXPECT_EQ(ASCIIToUTF16("15 hr, 42 min, 0 sec"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_SHORT));
- EXPECT_EQ(ASCIIToUTF16("15h 42m 0s"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NARROW));
- EXPECT_EQ(ASCIIToUTF16("15:42:00"),
- TimeDurationFormatWithSecondsString(delta, DURATION_WIDTH_NUMERIC));
-}
-
-TEST(TimeFormattingTest, TimeIntervalFormat) {
- test::ScopedRestoreICUDefaultLocale restore_locale;
- i18n::SetICUDefaultLocale("en_US");
- ScopedRestoreDefaultTimezone la_time("America/Los_Angeles");
-
- const Time::Exploded kTestIntervalEndTimeExploded = {
- 2011, 5, 6, 28, // Sat, May 28, 2012
- 22, 42, 7, 0 // 22:42:07.000
- };
-
- Time begin_time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestDateTimeExploded, &begin_time));
- Time end_time;
- EXPECT_TRUE(Time::FromUTCExploded(kTestIntervalEndTimeExploded, &end_time));
-
- EXPECT_EQ(
- UTF8ToUTF16(u8"Saturday, April 30 – Saturday, May 28"),
- DateIntervalFormat(begin_time, end_time, DATE_FORMAT_MONTH_WEEKDAY_DAY));
-
- const Time::Exploded kTestIntervalBeginTimeExploded = {
- 2011, 5, 1, 16, // Mon, May 16, 2012
- 22, 42, 7, 0 // 22:42:07.000
- };
- EXPECT_TRUE(
- Time::FromUTCExploded(kTestIntervalBeginTimeExploded, &begin_time));
- EXPECT_EQ(
- UTF8ToUTF16(u8"Monday, May 16 – Saturday, May 28"),
- DateIntervalFormat(begin_time, end_time, DATE_FORMAT_MONTH_WEEKDAY_DAY));
-
- i18n::SetICUDefaultLocale("en_GB");
- EXPECT_EQ(
- UTF8ToUTF16(u8"Monday 16 – Saturday 28 May"),
- DateIntervalFormat(begin_time, end_time, DATE_FORMAT_MONTH_WEEKDAY_DAY));
-
- i18n::SetICUDefaultLocale("ja");
- EXPECT_EQ(
- UTF8ToUTF16(u8"5月16日(月曜日)~28日(土曜日)"),
- DateIntervalFormat(begin_time, end_time, DATE_FORMAT_MONTH_WEEKDAY_DAY));
-}
-
-} // namespace
-} // namespace base
diff --git a/base/i18n/timezone.cc b/base/i18n/timezone.cc
deleted file mode 100644
index 8624e07e7c..0000000000
--- a/base/i18n/timezone.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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/i18n/timezone.h"
-
-#include <memory>
-#include <string>
-
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-namespace base {
-
-std::string CountryCodeForCurrentTimezone() {
- std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
- icu::UnicodeString id;
- // ICU returns '001' (world) for Etc/GMT. Preserve the old behavior
- // only for Etc/GMT while returning an empty string for Etc/UTC and
- // Etc/UCT because they're less likely to be chosen by mistake in UK in
- // place of Europe/London (Briitish Time).
- if (zone->getID(id) == UNICODE_STRING_SIMPLE("Etc/GMT"))
- return "GB";
- char region_code[4];
- UErrorCode status = U_ZERO_ERROR;
- int length = zone->getRegion(id, region_code, 4, status);
- // Return an empty string if region_code is a 3-digit numeric code such
- // as 001 (World) for Etc/UTC, Etc/UCT.
- return (U_SUCCESS(status) && length == 2)
- ? std::string(region_code, static_cast<size_t>(length))
- : std::string();
-}
-
-} // namespace base
diff --git a/base/i18n/timezone.h b/base/i18n/timezone.h
deleted file mode 100644
index 7557d44f36..0000000000
--- a/base/i18n/timezone.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_I18N_TIMEZONE_H_
-#define BASE_I18N_TIMEZONE_H_
-
-#include <string>
-
-#include "base/i18n/base_i18n_export.h"
-
-namespace base {
-
-// Checks the system timezone and turns it into a two-character ISO 3166 country
-// code. This may fail (for example, it used to always fail on Android), in
-// which case it will return an empty string. It'll also return an empty string
-// when the timezone is Etc/UTC or Etc/UCT, but will return 'GB" for Etc/GMT
-// because people in the UK tends to select Etc/GMT by mistake instead of
-// Europe/London (British Time).
-BASE_I18N_EXPORT std::string CountryCodeForCurrentTimezone();
-
-} // namespace base
-
-#endif // BASE_I18N_TIMEZONE_H_
diff --git a/base/i18n/timezone_unittest.cc b/base/i18n/timezone_unittest.cc
deleted file mode 100644
index 57467dced1..0000000000
--- a/base/i18n/timezone_unittest.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 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/i18n/timezone.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-TEST(TimezoneTest, CountryCodeForCurrentTimezone) {
- std::string country_code = CountryCodeForCurrentTimezone();
- // On some systems (such as Android or some flavors of Linux), ICU may come up
- // empty. With https://chromium-review.googlesource.com/c/512282/ , ICU will
- // not fail any more. See also http://bugs.icu-project.org/trac/ticket/13208 .
- // Even with that, ICU returns '001' (world) for region-agnostic timezones
- // such as Etc/UTC and |CountryCodeForCurrentTimezone| returns an empty
- // string so that the next fallback can be tried by a customer.
- // TODO(jshin): Revise this to test for actual timezones using
- // use ScopedRestoreICUDefaultTimezone.
- if (!country_code.empty())
- EXPECT_EQ(2U, country_code.size()) << "country_code = " << country_code;
-}
-
-} // namespace
-} // namespace base
diff --git a/base/i18n/unicodestring.h b/base/i18n/unicodestring.h
deleted file mode 100644
index b62c5264de..0000000000
--- a/base/i18n/unicodestring.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2017 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.
-
-#ifndef BASE_I18N_UNICODESTRING_H_
-#define BASE_I18N_UNICODESTRING_H_
-
-#include "base/strings/string16.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/common/unicode/uvernum.h"
-
-#if U_ICU_VERSION_MAJOR_NUM >= 59
-#include "third_party/icu/source/common/unicode/char16ptr.h"
-#endif
-
-namespace base {
-namespace i18n {
-
-inline string16 UnicodeStringToString16(const icu::UnicodeString& unistr) {
-#if U_ICU_VERSION_MAJOR_NUM >= 59
- return base::string16(icu::toUCharPtr(unistr.getBuffer()),
- static_cast<size_t>(unistr.length()));
-#else
- return base::string16(unistr.getBuffer(),
- static_cast<size_t>(unistr.length()));
-#endif
-}
-
-} // namespace i18n
-} // namespace base
-
-#endif // BASE_UNICODESTRING_H_
diff --git a/base/i18n/utf8_validator_tables.cc b/base/i18n/utf8_validator_tables.cc
deleted file mode 100644
index 913afc77c3..0000000000
--- a/base/i18n/utf8_validator_tables.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-// This file is auto-generated by build_utf8_validator_tables.
-// DO NOT EDIT.
-
-#include "base/i18n/utf8_validator_tables.h"
-
-namespace base {
-namespace internal {
-
-const uint8_t kUtf8ValidatorTables[] = {
- // State 0, offset 0x00
- 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x08
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x10
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x18
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x20
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x28
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x30
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x38
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x40
- 0x81, 0x81, 0x81, 0x83, 0x83, 0x83, 0x83, 0x83, // 0x48
- 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, // 0x50
- 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, // 0x58
- 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, // 0x60
- 0x83, 0x86, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, // 0x68
- 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8e, 0x8b, // 0x70
- 0x8b, 0x93, 0x9c, 0x9c, 0x9c, 0x9f, 0x81, 0x81, // 0x78
- 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0x80
- 0x81, // 0x81
- // State 1, offset 0x81
- 0x07, 0x81, // 0x83
- // State 2, offset 0x83
- 0x06, 0x00, 0x81, // 0x86
- // State 3, offset 0x86
- 0x05, 0x81, 0x83, 0x81, 0x81, // 0x8b
- // State 4, offset 0x8b
- 0x06, 0x83, 0x81, // 0x8e
- // State 5, offset 0x8e
- 0x05, 0x83, 0x81, 0x81, 0x81, // 0x93
- // State 6, offset 0x93
- 0x04, 0x81, 0x8b, 0x8b, 0x8b, 0x81, 0x81, 0x81, // 0x9b
- 0x81, // 0x9c
- // State 7, offset 0x9c
- 0x06, 0x8b, 0x81, // 0x9f
- // State 8, offset 0x9f
- 0x04, 0x8b, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, // 0xa7
- 0x81, // 0xa8
-};
-
-const size_t kUtf8ValidatorTablesSize = arraysize(kUtf8ValidatorTables);
-
-} // namespace internal
-} // namespace base
diff --git a/base/i18n/utf8_validator_tables.h b/base/i18n/utf8_validator_tables.h
deleted file mode 100644
index 939616b804..0000000000
--- a/base/i18n/utf8_validator_tables.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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.
-
-#ifndef BASE_I18N_UTF8_VALIDATOR_TABLES_H_
-#define BASE_I18N_UTF8_VALIDATOR_TABLES_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-
-namespace base {
-namespace internal {
-
-// The tables for all states; a list of entries of the form (right_shift,
-// next_state, next_state, ....). The right_shifts are used to reduce the
-// overall size of the table. The table only covers bytes in the range
-// [0x80, 0xFF] to save space.
-extern const uint8_t kUtf8ValidatorTables[];
-
-extern const size_t kUtf8ValidatorTablesSize;
-
-// The offset of the INVALID state in kUtf8ValidatorTables.
-enum {
- I18N_UTF8_VALIDATOR_INVALID_INDEX = 129
-};
-
-} // namespace internal
-} // namespace base
-
-#endif // BASE_I18N_UTF8_VALIDATOR_TABLES_H_
diff --git a/base/json/json_perftest.cc b/base/json/json_perftest.cc
deleted file mode 100644
index fc05bdca61..0000000000
--- a/base/json/json_perftest.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 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/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-
-namespace base {
-
-namespace {
-// Generates a simple dictionary value with simple data types, a string and a
-// list.
-std::unique_ptr<DictionaryValue> GenerateDict() {
- auto root = std::make_unique<DictionaryValue>();
- root->SetDouble("Double", 3.141);
- root->SetBoolean("Bool", true);
- root->SetInteger("Int", 42);
- root->SetString("String", "Foo");
-
- auto list = std::make_unique<ListValue>();
- list->Set(0, std::make_unique<Value>(2.718));
- list->Set(1, std::make_unique<Value>(false));
- list->Set(2, std::make_unique<Value>(123));
- list->Set(3, std::make_unique<Value>("Bar"));
- root->Set("List", std::move(list));
-
- return root;
-}
-
-// Generates a tree-like dictionary value with a size of O(breadth ** depth).
-std::unique_ptr<DictionaryValue> GenerateLayeredDict(int breadth, int depth) {
- if (depth == 1)
- return GenerateDict();
-
- auto root = GenerateDict();
- auto next = GenerateLayeredDict(breadth, depth - 1);
-
- for (int i = 0; i < breadth; ++i) {
- root->Set("Dict" + std::to_string(i), next->CreateDeepCopy());
- }
-
- return root;
-}
-
-} // namespace
-
-class JSONPerfTest : public testing::Test {
- public:
- void TestWriteAndRead(int breadth, int depth) {
- std::string description = "Breadth: " + std::to_string(breadth) +
- ", Depth: " + std::to_string(depth);
- auto dict = GenerateLayeredDict(breadth, depth);
- std::string json;
-
- TimeTicks start_write = TimeTicks::Now();
- JSONWriter::Write(*dict, &json);
- TimeTicks end_write = TimeTicks::Now();
- perf_test::PrintResult("Write", "", description,
- (end_write - start_write).InMillisecondsF(), "ms",
- true);
-
- TimeTicks start_read = TimeTicks::Now();
- JSONReader::Read(json);
- TimeTicks end_read = TimeTicks::Now();
- perf_test::PrintResult("Read", "", description,
- (end_read - start_read).InMillisecondsF(), "ms",
- true);
- }
-};
-
-TEST_F(JSONPerfTest, StressTest) {
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 12; ++j) {
- TestWriteAndRead(i + 1, j + 1);
- }
- }
-}
-
-} // namespace base
diff --git a/base/linux_util.cc b/base/linux_util.cc
deleted file mode 100644
index ddf848eeb7..0000000000
--- a/base/linux_util.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/linux_util.h"
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/memory/singleton.h"
-#include "base/process/launch.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/string_util.h"
-#include "base/synchronization/lock.h"
-#include "build/build_config.h"
-
-namespace {
-
-// Not needed for OS_CHROMEOS.
-#if defined(OS_LINUX)
-enum LinuxDistroState {
- STATE_DID_NOT_CHECK = 0,
- STATE_CHECK_STARTED = 1,
- STATE_CHECK_FINISHED = 2,
-};
-
-// Helper class for GetLinuxDistro().
-class LinuxDistroHelper {
- public:
- // Retrieves the Singleton.
- static LinuxDistroHelper* GetInstance() {
- return base::Singleton<LinuxDistroHelper>::get();
- }
-
- // The simple state machine goes from:
- // STATE_DID_NOT_CHECK -> STATE_CHECK_STARTED -> STATE_CHECK_FINISHED.
- LinuxDistroHelper() : state_(STATE_DID_NOT_CHECK) {}
- ~LinuxDistroHelper() = default;
-
- // Retrieve the current state, if we're in STATE_DID_NOT_CHECK,
- // we automatically move to STATE_CHECK_STARTED so nobody else will
- // do the check.
- LinuxDistroState State() {
- base::AutoLock scoped_lock(lock_);
- if (STATE_DID_NOT_CHECK == state_) {
- state_ = STATE_CHECK_STARTED;
- return STATE_DID_NOT_CHECK;
- }
- return state_;
- }
-
- // Indicate the check finished, move to STATE_CHECK_FINISHED.
- void CheckFinished() {
- base::AutoLock scoped_lock(lock_);
- DCHECK_EQ(STATE_CHECK_STARTED, state_);
- state_ = STATE_CHECK_FINISHED;
- }
-
- private:
- base::Lock lock_;
- LinuxDistroState state_;
-};
-#endif // if defined(OS_LINUX)
-
-bool GetTasksForProcess(pid_t pid, std::vector<pid_t>* tids) {
- char buf[256];
- snprintf(buf, sizeof(buf), "/proc/%d/task", pid);
-
- DIR* task = opendir(buf);
- if (!task) {
- DLOG(WARNING) << "Cannot open " << buf;
- return false;
- }
-
- struct dirent* dent;
- while ((dent = readdir(task))) {
- char* endptr;
- const unsigned long int tid_ul = strtoul(dent->d_name, &endptr, 10);
- if (tid_ul == ULONG_MAX || *endptr)
- continue;
- tids->push_back(tid_ul);
- }
- closedir(task);
- return true;
-}
-
-} // namespace
-
-namespace base {
-
-// Account for the terminating null character.
-static const int kDistroSize = 128 + 1;
-
-// We use this static string to hold the Linux distro info. If we
-// crash, the crash handler code will send this in the crash dump.
-char g_linux_distro[kDistroSize] =
-#if defined(OS_CHROMEOS)
- "CrOS";
-#elif defined(OS_ANDROID)
- "Android";
-#else // if defined(OS_LINUX)
- "Unknown";
-#endif
-
-std::string GetLinuxDistro() {
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
- return g_linux_distro;
-#elif defined(OS_LINUX)
- LinuxDistroHelper* distro_state_singleton = LinuxDistroHelper::GetInstance();
- LinuxDistroState state = distro_state_singleton->State();
- if (STATE_CHECK_FINISHED == state)
- return g_linux_distro;
- if (STATE_CHECK_STARTED == state)
- return "Unknown"; // Don't wait for other thread to finish.
- DCHECK_EQ(state, STATE_DID_NOT_CHECK);
- // We do this check only once per process. If it fails, there's
- // little reason to believe it will work if we attempt to run
- // lsb_release again.
- std::vector<std::string> argv;
- argv.push_back("lsb_release");
- argv.push_back("-d");
- std::string output;
- GetAppOutput(CommandLine(argv), &output);
- if (output.length() > 0) {
- // lsb_release -d should return: Description:<tab>Distro Info
- const char field[] = "Description:\t";
- if (output.compare(0, strlen(field), field) == 0) {
- SetLinuxDistro(output.substr(strlen(field)));
- }
- }
- distro_state_singleton->CheckFinished();
- return g_linux_distro;
-#else
- NOTIMPLEMENTED();
- return "Unknown";
-#endif
-}
-
-void SetLinuxDistro(const std::string& distro) {
- std::string trimmed_distro;
- TrimWhitespaceASCII(distro, TRIM_ALL, &trimmed_distro);
- strlcpy(g_linux_distro, trimmed_distro.c_str(), kDistroSize);
-}
-
-pid_t FindThreadIDWithSyscall(pid_t pid, const std::string& expected_data,
- bool* syscall_supported) {
- if (syscall_supported != nullptr)
- *syscall_supported = false;
-
- std::vector<pid_t> tids;
- if (!GetTasksForProcess(pid, &tids))
- return -1;
-
- std::unique_ptr<char[]> syscall_data(new char[expected_data.length()]);
- for (pid_t tid : tids) {
- char buf[256];
- snprintf(buf, sizeof(buf), "/proc/%d/task/%d/syscall", pid, tid);
- int fd = open(buf, O_RDONLY);
- if (fd < 0)
- continue;
- if (syscall_supported != nullptr)
- *syscall_supported = true;
- bool read_ret = ReadFromFD(fd, syscall_data.get(), expected_data.length());
- close(fd);
- if (!read_ret)
- continue;
-
- if (0 == strncmp(expected_data.c_str(), syscall_data.get(),
- expected_data.length())) {
- return tid;
- }
- }
- return -1;
-}
-
-pid_t FindThreadID(pid_t pid, pid_t ns_tid, bool* ns_pid_supported) {
- if (ns_pid_supported)
- *ns_pid_supported = false;
-
- std::vector<pid_t> tids;
- if (!GetTasksForProcess(pid, &tids))
- return -1;
-
- for (pid_t tid : tids) {
- char buf[256];
- snprintf(buf, sizeof(buf), "/proc/%d/task/%d/status", pid, tid);
- std::string status;
- if (!ReadFileToString(FilePath(buf), &status))
- return -1;
- StringTokenizer tokenizer(status, "\n");
- while (tokenizer.GetNext()) {
- StringPiece value_str(tokenizer.token_piece());
- if (!value_str.starts_with("NSpid"))
- continue;
- if (ns_pid_supported)
- *ns_pid_supported = true;
- std::vector<StringPiece> split_value_str = SplitStringPiece(
- value_str, "\t", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
- DCHECK_GE(split_value_str.size(), 2u);
- int value;
- // The last value in the list is the PID in the namespace.
- if (StringToInt(split_value_str.back(), &value) && value == ns_tid) {
- // The second value in the list is the real PID.
- if (StringToInt(split_value_str[1], &value))
- return value;
- }
- break;
- }
- }
- return -1;
-}
-
-} // namespace base
diff --git a/base/linux_util.h b/base/linux_util.h
deleted file mode 100644
index 272e06b7d8..0000000000
--- a/base/linux_util.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_LINUX_UTIL_H_
-#define BASE_LINUX_UTIL_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <string>
-
-#include "base/base_export.h"
-
-namespace base {
-
-// This is declared here so the crash reporter can access the memory directly
-// in compromised context without going through the standard library.
-BASE_EXPORT extern char g_linux_distro[];
-
-// Get the Linux Distro if we can, or return "Unknown".
-BASE_EXPORT std::string GetLinuxDistro();
-
-// Set the Linux Distro string.
-BASE_EXPORT void SetLinuxDistro(const std::string& distro);
-
-// For a given process |pid|, look through all its threads and find the first
-// thread with /proc/[pid]/task/[thread_id]/syscall whose first N bytes matches
-// |expected_data|, where N is the length of |expected_data|.
-// Returns the thread id or -1 on error. If |syscall_supported| is
-// set to false the kernel does not support syscall in procfs.
-BASE_EXPORT pid_t FindThreadIDWithSyscall(pid_t pid,
- const std::string& expected_data,
- bool* syscall_supported);
-
-// For a given process |pid|, look through all its threads and find the first
-// thread with /proc/[pid]/task/[thread_id]/status where NSpid matches |ns_tid|.
-// Returns the thread id or -1 on error. If |ns_pid_supported| is
-// set to false the kernel does not support NSpid in procfs.
-BASE_EXPORT pid_t FindThreadID(pid_t pid, pid_t ns_tid, bool* ns_pid_supported);
-
-} // namespace base
-
-#endif // BASE_LINUX_UTIL_H_
diff --git a/base/logging.cc b/base/logging.cc
index 5781c637c9..112afb8e08 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -58,7 +58,7 @@ typedef HANDLE MutexHandle;
#include <zircon/syscalls.h>
#endif
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(__ANDROID__)
#include <android/log.h>
#endif
@@ -757,7 +757,7 @@ LogMessage::~LogMessage() {
str_newline.c_str());
#endif // defined(USE_ASL)
}
-#elif defined(OS_ANDROID)
+#elif defined(OS_ANDROID) || defined(__ANDROID__)
android_LogPriority priority =
(severity_ < 0) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_UNKNOWN;
switch (severity_) {
@@ -774,7 +774,7 @@ LogMessage::~LogMessage() {
priority = ANDROID_LOG_FATAL;
break;
}
-#if 0 // This is for building Chromium browser on Android.
+#if defined(OS_ANDROID)
__android_log_write(priority, "chromium", str_newline.c_str());
#else
__android_log_write(
@@ -783,8 +783,8 @@ LogMessage::~LogMessage() {
base::CommandLine::ForCurrentProcess()->
GetProgram().BaseName().value().c_str() : nullptr,
str_newline.c_str());
-#endif // 0
#endif // defined(OS_ANDROID)
+#endif
ignore_result(fwrite(str_newline.data(), str_newline.size(), 1, stderr));
fflush(stderr);
} else if (severity_ >= kAlwaysPrintErrorLevel) {
diff --git a/base/memory/discardable_memory.cc b/base/memory/discardable_memory.cc
deleted file mode 100644
index f0730aa403..0000000000
--- a/base/memory/discardable_memory.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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/memory/discardable_memory.h"
-
-namespace base {
-
-DiscardableMemory::DiscardableMemory() = default;
-
-DiscardableMemory::~DiscardableMemory() = default;
-
-} // namespace base
diff --git a/base/memory/discardable_memory.h b/base/memory/discardable_memory.h
deleted file mode 100644
index 5c632d1c95..0000000000
--- a/base/memory/discardable_memory.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_H_
-
-#include "base/base_export.h"
-#include "base/compiler_specific.h"
-
-namespace base {
-
-namespace trace_event {
-class MemoryAllocatorDump;
-class ProcessMemoryDump;
-}
-
-// Discardable memory is used to cache large objects without worrying about
-// blowing out memory, both on mobile devices where there is no swap, and
-// desktop devices where unused free memory should be used to help the user
-// experience. This is preferable to releasing memory in response to an OOM
-// signal because it is simpler and provides system-wide management of
-// purgable memory, though it has less flexibility as to which objects get
-// discarded.
-//
-// Discardable memory has two states: locked and unlocked. While the memory is
-// locked, it will not be discarded. Unlocking the memory allows the
-// discardable memory system and the OS to reclaim it if needed. Locks do not
-// nest.
-//
-// Notes:
-// - The paging behavior of memory while it is locked is not specified. While
-// mobile platforms will not swap it out, it may qualify for swapping
-// on desktop platforms. It is not expected that this will matter, as the
-// preferred pattern of usage for DiscardableMemory is to lock down the
-// memory, use it as quickly as possible, and then unlock it.
-// - Because of memory alignment, the amount of memory allocated can be
-// larger than the requested memory size. It is not very efficient for
-// small allocations.
-// - A discardable memory instance is not thread safe. It is the
-// responsibility of users of discardable memory to ensure there are no
-// races.
-//
-class BASE_EXPORT DiscardableMemory {
- public:
- DiscardableMemory();
- virtual ~DiscardableMemory();
-
- // Locks the memory so that it will not be purged by the system. Returns
- // true on success. If the return value is false then this object should be
- // discarded and a new one should be created.
- virtual bool Lock() WARN_UNUSED_RESULT = 0;
-
- // Unlocks the memory so that it can be purged by the system. Must be called
- // after every successful lock call.
- virtual void Unlock() = 0;
-
- // Returns the memory address held by this object. The object must be locked
- // before calling this.
- virtual void* data() const = 0;
-
- // Handy method to simplify calling data() with a reinterpret_cast.
- template<typename T> T* data_as() const {
- return reinterpret_cast<T*>(data());
- }
-
- // Used for dumping the statistics of discardable memory allocated in tracing.
- // Returns a new MemoryAllocatorDump in the |pmd| with the size of the
- // discardable memory. The MemoryAllocatorDump created is owned by |pmd|. See
- // ProcessMemoryDump::CreateAllocatorDump.
- virtual trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump(
- const char* name,
- trace_event::ProcessMemoryDump* pmd) const = 0;
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_DISCARDABLE_MEMORY_H_
diff --git a/base/memory/discardable_memory_allocator.cc b/base/memory/discardable_memory_allocator.cc
deleted file mode 100644
index 3dbb27672b..0000000000
--- a/base/memory/discardable_memory_allocator.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 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/memory/discardable_memory_allocator.h"
-
-#include "base/logging.h"
-
-namespace base {
-namespace {
-
-DiscardableMemoryAllocator* g_discardable_allocator = nullptr;
-
-} // namespace
-
-// static
-void DiscardableMemoryAllocator::SetInstance(
- DiscardableMemoryAllocator* allocator) {
- DCHECK(!allocator || !g_discardable_allocator);
- g_discardable_allocator = allocator;
-}
-
-// static
-DiscardableMemoryAllocator* DiscardableMemoryAllocator::GetInstance() {
- DCHECK(g_discardable_allocator);
- return g_discardable_allocator;
-}
-
-} // namespace base
diff --git a/base/memory/discardable_memory_allocator.h b/base/memory/discardable_memory_allocator.h
deleted file mode 100644
index 8d74b16959..0000000000
--- a/base/memory/discardable_memory_allocator.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_ALLOCATOR_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_ALLOCATOR_H_
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/base_export.h"
-
-namespace base {
-class DiscardableMemory;
-
-class BASE_EXPORT DiscardableMemoryAllocator {
- public:
- // Returns the allocator instance.
- static DiscardableMemoryAllocator* GetInstance();
-
- // Sets the allocator instance. Can only be called once, e.g. on startup.
- // Ownership of |instance| remains with the caller.
- static void SetInstance(DiscardableMemoryAllocator* allocator);
-
- // Giant WARNING: Discardable[Shared]Memory is only implemented on Android. On
- // non-Android platforms, it behaves exactly the same as SharedMemory.
- // See LockPages() in discardable_shared_memory.cc.
- virtual std::unique_ptr<DiscardableMemory> AllocateLockedDiscardableMemory(
- size_t size) = 0;
-
- protected:
- virtual ~DiscardableMemoryAllocator() = default;
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_DISCARDABLE_MEMORY_ALLOCATOR_H_
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
deleted file mode 100644
index 3b6b4dbfa9..0000000000
--- a/base/memory/discardable_shared_memory.cc
+++ /dev/null
@@ -1,514 +0,0 @@
-// 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/memory/discardable_shared_memory.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "base/atomicops.h"
-#include "base/bits.h"
-#include "base/logging.h"
-#include "base/memory/shared_memory_tracker.h"
-#include "base/numerics/safe_math.h"
-#include "base/process/process_metrics.h"
-#include "base/trace_event/memory_allocator_dump.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "build/build_config.h"
-
-#if defined(OS_POSIX) && !defined(OS_NACL)
-// For madvise() which is available on all POSIX compatible systems.
-#include <sys/mman.h>
-#endif
-
-#if defined(OS_ANDROID)
-#include "third_party/ashmem/ashmem.h"
-#endif
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include "base/win/windows_version.h"
-#endif
-
-namespace base {
-namespace {
-
-// Use a machine-sized pointer as atomic type. It will use the Atomic32 or
-// Atomic64 routines, depending on the architecture.
-typedef intptr_t AtomicType;
-typedef uintptr_t UAtomicType;
-
-// Template specialization for timestamp serialization/deserialization. This
-// is used to serialize timestamps using Unix time on systems where AtomicType
-// does not have enough precision to contain a timestamp in the standard
-// serialized format.
-template <int>
-Time TimeFromWireFormat(int64_t value);
-template <int>
-int64_t TimeToWireFormat(Time time);
-
-// Serialize to Unix time when using 4-byte wire format.
-// Note: 19 January 2038, this will cease to work.
-template <>
-Time ALLOW_UNUSED_TYPE TimeFromWireFormat<4>(int64_t value) {
- return value ? Time::UnixEpoch() + TimeDelta::FromSeconds(value) : Time();
-}
-template <>
-int64_t ALLOW_UNUSED_TYPE TimeToWireFormat<4>(Time time) {
- return time > Time::UnixEpoch() ? (time - Time::UnixEpoch()).InSeconds() : 0;
-}
-
-// Standard serialization format when using 8-byte wire format.
-template <>
-Time ALLOW_UNUSED_TYPE TimeFromWireFormat<8>(int64_t value) {
- return Time::FromInternalValue(value);
-}
-template <>
-int64_t ALLOW_UNUSED_TYPE TimeToWireFormat<8>(Time time) {
- return time.ToInternalValue();
-}
-
-struct SharedState {
- enum LockState { UNLOCKED = 0, LOCKED = 1 };
-
- explicit SharedState(AtomicType ivalue) { value.i = ivalue; }
- SharedState(LockState lock_state, Time timestamp) {
- int64_t wire_timestamp = TimeToWireFormat<sizeof(AtomicType)>(timestamp);
- DCHECK_GE(wire_timestamp, 0);
- DCHECK_EQ(lock_state & ~1, 0);
- value.u = (static_cast<UAtomicType>(wire_timestamp) << 1) | lock_state;
- }
-
- LockState GetLockState() const { return static_cast<LockState>(value.u & 1); }
-
- Time GetTimestamp() const {
- return TimeFromWireFormat<sizeof(AtomicType)>(value.u >> 1);
- }
-
- // Bit 1: Lock state. Bit is set when locked.
- // Bit 2..sizeof(AtomicType)*8: Usage timestamp. NULL time when locked or
- // purged.
- union {
- AtomicType i;
- UAtomicType u;
- } value;
-};
-
-// Shared state is stored at offset 0 in shared memory segments.
-SharedState* SharedStateFromSharedMemory(
- const WritableSharedMemoryMapping& shared_memory) {
- DCHECK(shared_memory.IsValid());
- return static_cast<SharedState*>(shared_memory.memory());
-}
-
-// Round up |size| to a multiple of page size.
-size_t AlignToPageSize(size_t size) {
- return bits::Align(size, base::GetPageSize());
-}
-
-} // namespace
-
-DiscardableSharedMemory::DiscardableSharedMemory()
- : mapped_size_(0), locked_page_count_(0) {
-}
-
-DiscardableSharedMemory::DiscardableSharedMemory(
- UnsafeSharedMemoryRegion shared_memory_region)
- : shared_memory_region_(std::move(shared_memory_region)),
- mapped_size_(0),
- locked_page_count_(0) {}
-
-DiscardableSharedMemory::~DiscardableSharedMemory() = default;
-
-bool DiscardableSharedMemory::CreateAndMap(size_t size) {
- CheckedNumeric<size_t> checked_size = size;
- checked_size += AlignToPageSize(sizeof(SharedState));
- if (!checked_size.IsValid())
- return false;
-
- shared_memory_region_ =
- UnsafeSharedMemoryRegion::Create(checked_size.ValueOrDie());
-
- if (!shared_memory_region_.IsValid())
- return false;
-
- shared_memory_mapping_ = shared_memory_region_.Map();
- if (!shared_memory_mapping_.IsValid())
- return false;
-
- mapped_size_ = shared_memory_mapping_.mapped_size() -
- AlignToPageSize(sizeof(SharedState));
-
- locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize();
-#if DCHECK_IS_ON()
- for (size_t page = 0; page < locked_page_count_; ++page)
- locked_pages_.insert(page);
-#endif
-
- DCHECK(last_known_usage_.is_null());
- SharedState new_state(SharedState::LOCKED, Time());
- subtle::Release_Store(
- &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
- new_state.value.i);
- return true;
-}
-
-bool DiscardableSharedMemory::Map(size_t size) {
- DCHECK(!shared_memory_mapping_.IsValid());
- if (shared_memory_mapping_.IsValid())
- return false;
-
- shared_memory_mapping_ = shared_memory_region_.MapAt(
- 0, AlignToPageSize(sizeof(SharedState)) + size);
- if (!shared_memory_mapping_.IsValid())
- return false;
-
- mapped_size_ = shared_memory_mapping_.mapped_size() -
- AlignToPageSize(sizeof(SharedState));
-
- locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize();
-#if DCHECK_IS_ON()
- for (size_t page = 0; page < locked_page_count_; ++page)
- locked_pages_.insert(page);
-#endif
-
- return true;
-}
-
-bool DiscardableSharedMemory::Unmap() {
- if (!shared_memory_mapping_.IsValid())
- return false;
-
- shared_memory_mapping_ = WritableSharedMemoryMapping();
- locked_page_count_ = 0;
-#if DCHECK_IS_ON()
- locked_pages_.clear();
-#endif
- mapped_size_ = 0;
- return true;
-}
-
-DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock(
- size_t offset, size_t length) {
- DCHECK_EQ(AlignToPageSize(offset), offset);
- DCHECK_EQ(AlignToPageSize(length), length);
-
- // Calls to this function must be synchronized properly.
- DFAKE_SCOPED_LOCK(thread_collision_warner_);
-
- DCHECK(shared_memory_mapping_.IsValid());
-
- // We need to successfully acquire the platform independent lock before
- // individual pages can be locked.
- if (!locked_page_count_) {
- // Return false when instance has been purged or not initialized properly
- // by checking if |last_known_usage_| is NULL.
- if (last_known_usage_.is_null())
- return FAILED;
-
- SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
- SharedState new_state(SharedState::LOCKED, Time());
- SharedState result(subtle::Acquire_CompareAndSwap(
- &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
- old_state.value.i, new_state.value.i));
- if (result.value.u != old_state.value.u) {
- // Update |last_known_usage_| in case the above CAS failed because of
- // an incorrect timestamp.
- last_known_usage_ = result.GetTimestamp();
- return FAILED;
- }
- }
-
- // Zero for length means "everything onward".
- if (!length)
- length = AlignToPageSize(mapped_size_) - offset;
-
- size_t start = offset / base::GetPageSize();
- size_t end = start + length / base::GetPageSize();
- DCHECK_LE(start, end);
- DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize());
-
- // Add pages to |locked_page_count_|.
- // Note: Locking a page that is already locked is an error.
- locked_page_count_ += end - start;
-#if DCHECK_IS_ON()
- // Detect incorrect usage by keeping track of exactly what pages are locked.
- for (auto page = start; page < end; ++page) {
- auto result = locked_pages_.insert(page);
- DCHECK(result.second);
- }
- DCHECK_EQ(locked_pages_.size(), locked_page_count_);
-#endif
-
- // Always behave as if memory was purged when trying to lock a 0 byte segment.
- if (!length)
- return PURGED;
-
-#if defined(OS_ANDROID)
- // Ensure that the platform won't discard the required pages.
- return LockPages(shared_memory_region_,
- AlignToPageSize(sizeof(SharedState)) + offset, length);
-#elif defined(OS_MACOSX)
- // On macOS, there is no mechanism to lock pages. However, we do need to call
- // madvise(MADV_FREE_REUSE) in order to correctly update accounting for memory
- // footprint via task_info().
- //
- // Note that calling madvise(MADV_FREE_REUSE) on regions that haven't had
- // madvise(MADV_FREE_REUSABLE) called on them has no effect.
- //
- // Note that the corresponding call to MADV_FREE_REUSABLE is in Purge(), since
- // that's where the memory is actually released, rather than Unlock(), which
- // is a no-op on macOS.
- //
- // For more information, see
- // https://bugs.chromium.org/p/chromium/issues/detail?id=823915.
- if (madvise(reinterpret_cast<char*>(shared_memory_mapping_.memory()) +
- AlignToPageSize(sizeof(SharedState)),
- AlignToPageSize(mapped_size_), MADV_FREE_REUSE))
- ;
- return DiscardableSharedMemory::SUCCESS;
-#else
- return DiscardableSharedMemory::SUCCESS;
-#endif
-}
-
-void DiscardableSharedMemory::Unlock(size_t offset, size_t length) {
- DCHECK_EQ(AlignToPageSize(offset), offset);
- DCHECK_EQ(AlignToPageSize(length), length);
-
- // Calls to this function must be synchronized properly.
- DFAKE_SCOPED_LOCK(thread_collision_warner_);
-
- // Passing zero for |length| means "everything onward". Note that |length| may
- // still be zero after this calculation, e.g. if |mapped_size_| is zero.
- if (!length)
- length = AlignToPageSize(mapped_size_) - offset;
-
- DCHECK(shared_memory_mapping_.IsValid());
-
- // Allow the pages to be discarded by the platform, if supported.
- UnlockPages(shared_memory_region_,
- AlignToPageSize(sizeof(SharedState)) + offset, length);
-
- size_t start = offset / base::GetPageSize();
- size_t end = start + length / base::GetPageSize();
- DCHECK_LE(start, end);
- DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize());
-
- // Remove pages from |locked_page_count_|.
- // Note: Unlocking a page that is not locked is an error.
- DCHECK_GE(locked_page_count_, end - start);
- locked_page_count_ -= end - start;
-#if DCHECK_IS_ON()
- // Detect incorrect usage by keeping track of exactly what pages are locked.
- for (auto page = start; page < end; ++page) {
- auto erased_count = locked_pages_.erase(page);
- DCHECK_EQ(1u, erased_count);
- }
- DCHECK_EQ(locked_pages_.size(), locked_page_count_);
-#endif
-
- // Early out and avoid releasing the platform independent lock if some pages
- // are still locked.
- if (locked_page_count_)
- return;
-
- Time current_time = Now();
- DCHECK(!current_time.is_null());
-
- SharedState old_state(SharedState::LOCKED, Time());
- SharedState new_state(SharedState::UNLOCKED, current_time);
- // Note: timestamp cannot be NULL as that is a unique value used when
- // locked or purged.
- DCHECK(!new_state.GetTimestamp().is_null());
- // Timestamp precision should at least be accurate to the second.
- DCHECK_EQ((new_state.GetTimestamp() - Time::UnixEpoch()).InSeconds(),
- (current_time - Time::UnixEpoch()).InSeconds());
- SharedState result(subtle::Release_CompareAndSwap(
- &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
- old_state.value.i, new_state.value.i));
-
- DCHECK_EQ(old_state.value.u, result.value.u);
-
- last_known_usage_ = current_time;
-}
-
-void* DiscardableSharedMemory::memory() const {
- return reinterpret_cast<uint8_t*>(shared_memory_mapping_.memory()) +
- AlignToPageSize(sizeof(SharedState));
-}
-
-bool DiscardableSharedMemory::Purge(Time current_time) {
- // Calls to this function must be synchronized properly.
- DFAKE_SCOPED_LOCK(thread_collision_warner_);
- DCHECK(shared_memory_mapping_.IsValid());
-
- SharedState old_state(SharedState::UNLOCKED, last_known_usage_);
- SharedState new_state(SharedState::UNLOCKED, Time());
- SharedState result(subtle::Acquire_CompareAndSwap(
- &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i,
- old_state.value.i, new_state.value.i));
-
- // Update |last_known_usage_| to |current_time| if the memory is locked. This
- // allows the caller to determine if purging failed because last known usage
- // was incorrect or memory was locked. In the second case, the caller should
- // most likely wait for some amount of time before attempting to purge the
- // the memory again.
- if (result.value.u != old_state.value.u) {
- last_known_usage_ = result.GetLockState() == SharedState::LOCKED
- ? current_time
- : result.GetTimestamp();
- return false;
- }
-
-// The next section will release as much resource as can be done
-// from the purging process, until the client process notices the
-// purge and releases its own references.
-// Note: this memory will not be accessed again. The segment will be
-// freed asynchronously at a later time, so just do the best
-// immediately.
-#if defined(OS_POSIX) && !defined(OS_NACL)
-// Linux and Android provide MADV_REMOVE which is preferred as it has a
-// behavior that can be verified in tests. Other POSIX flavors (MacOSX, BSDs),
-// provide MADV_FREE which has the same result but memory is purged lazily.
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#define MADV_PURGE_ARGUMENT MADV_REMOVE
-#elif defined(OS_MACOSX)
-// MADV_FREE_REUSABLE is similar to MADV_FREE, but also marks the pages with the
-// reusable bit, which allows both Activity Monitor and memory-infra to
-// correctly track the pages.
-#define MADV_PURGE_ARGUMENT MADV_FREE_REUSABLE
-#else
-#define MADV_PURGE_ARGUMENT MADV_FREE
-#endif
- // Advise the kernel to remove resources associated with purged pages.
- // Subsequent accesses of memory pages will succeed, but might result in
- // zero-fill-on-demand pages.
- if (madvise(reinterpret_cast<char*>(shared_memory_mapping_.memory()) +
- AlignToPageSize(sizeof(SharedState)),
- AlignToPageSize(mapped_size_), MADV_PURGE_ARGUMENT)) {
- DPLOG(ERROR) << "madvise() failed";
- }
-#elif defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_WIN8_1) {
- // Discard the purged pages, which releases the physical storage (resident
- // memory, compressed or swapped), but leaves them reserved & committed.
- // This does not free commit for use by other applications, but allows the
- // system to avoid compressing/swapping these pages to free physical memory.
- static const auto discard_virtual_memory =
- reinterpret_cast<decltype(&::DiscardVirtualMemory)>(GetProcAddress(
- GetModuleHandle(L"kernel32.dll"), "DiscardVirtualMemory"));
- if (discard_virtual_memory) {
- DWORD discard_result = discard_virtual_memory(
- reinterpret_cast<char*>(shared_memory_mapping_.memory()) +
- AlignToPageSize(sizeof(SharedState)),
- AlignToPageSize(mapped_size_));
- if (discard_result != ERROR_SUCCESS) {
- DLOG(DCHECK) << "DiscardVirtualMemory() failed in Purge(): "
- << logging::SystemErrorCodeToString(discard_result);
- }
- }
- }
-#endif
-
- last_known_usage_ = Time();
- return true;
-}
-
-bool DiscardableSharedMemory::IsMemoryResident() const {
- DCHECK(shared_memory_mapping_.IsValid());
-
- SharedState result(subtle::NoBarrier_Load(
- &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i));
-
- return result.GetLockState() == SharedState::LOCKED ||
- !result.GetTimestamp().is_null();
-}
-
-bool DiscardableSharedMemory::IsMemoryLocked() const {
- DCHECK(shared_memory_mapping_.IsValid());
-
- SharedState result(subtle::NoBarrier_Load(
- &SharedStateFromSharedMemory(shared_memory_mapping_)->value.i));
-
- return result.GetLockState() == SharedState::LOCKED;
-}
-
-void DiscardableSharedMemory::Close() {
- shared_memory_region_ = UnsafeSharedMemoryRegion();
-}
-
-void DiscardableSharedMemory::CreateSharedMemoryOwnershipEdge(
- trace_event::MemoryAllocatorDump* local_segment_dump,
- trace_event::ProcessMemoryDump* pmd,
- bool is_owned) const {
- auto* shared_memory_dump = SharedMemoryTracker::GetOrCreateSharedMemoryDump(
- shared_memory_mapping_, pmd);
- // TODO(ssid): Clean this by a new api to inherit size of parent dump once the
- // we send the full PMD and calculate sizes inside chrome, crbug.com/704203.
- size_t resident_size = shared_memory_dump->GetSizeInternal();
- local_segment_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize,
- trace_event::MemoryAllocatorDump::kUnitsBytes,
- resident_size);
-
- // By creating an edge with a higher |importance| (w.r.t non-owned dumps)
- // the tracing UI will account the effective size of the segment to the
- // client instead of manager.
- // TODO(ssid): Define better constants in MemoryAllocatorDump for importance
- // values, crbug.com/754793.
- const int kImportance = is_owned ? 2 : 0;
- auto shared_memory_guid = shared_memory_mapping_.guid();
- local_segment_dump->AddString("id", "hash", shared_memory_guid.ToString());
-
- // Owned discardable segments which are allocated by client process, could
- // have been cleared by the discardable manager. So, the segment need not
- // exist in memory and weak dumps are created to indicate the UI that the dump
- // should exist only if the manager also created the global dump edge.
- if (is_owned) {
- pmd->CreateWeakSharedMemoryOwnershipEdge(local_segment_dump->guid(),
- shared_memory_guid, kImportance);
- } else {
- pmd->CreateSharedMemoryOwnershipEdge(local_segment_dump->guid(),
- shared_memory_guid, kImportance);
- }
-}
-
-// static
-DiscardableSharedMemory::LockResult DiscardableSharedMemory::LockPages(
- const UnsafeSharedMemoryRegion& region,
- size_t offset,
- size_t length) {
-#if defined(OS_ANDROID)
- if (region.IsValid()) {
- int pin_result =
- ashmem_pin_region(region.GetPlatformHandle(), offset, length);
- if (pin_result == ASHMEM_WAS_PURGED)
- return PURGED;
- if (pin_result < 0)
- return FAILED;
- }
-#endif
- return SUCCESS;
-}
-
-// static
-void DiscardableSharedMemory::UnlockPages(
- const UnsafeSharedMemoryRegion& region,
- size_t offset,
- size_t length) {
-#if defined(OS_ANDROID)
- if (region.IsValid()) {
- int unpin_result =
- ashmem_unpin_region(region.GetPlatformHandle(), offset, length);
- DCHECK_EQ(0, unpin_result);
- }
-#endif
-}
-
-Time DiscardableSharedMemory::Now() const {
- return Time::Now();
-}
-
-} // namespace base
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h
deleted file mode 100644
index 52a78b131e..0000000000
--- a/base/memory/discardable_shared_memory.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// 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.
-
-#ifndef BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_
-#define BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_
-
-#include <stddef.h>
-
-#include "base/base_export.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory_mapping.h"
-#include "base/memory/unsafe_shared_memory_region.h"
-#include "base/threading/thread_collision_warner.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-
-#if DCHECK_IS_ON()
-#include <set>
-#endif
-
-// Linux (including Android) support the MADV_REMOVE argument with madvise()
-// which has the behavior of reliably causing zero-fill-on-demand pages to
-// be returned after a call. Here we define
-// DISCARDABLE_SHARED_MEMORY_ZERO_FILL_ON_DEMAND_PAGES_AFTER_PURGE on Linux
-// and Android to indicate that this type of behavior can be expected on
-// those platforms. Note that madvise() will still be used on other POSIX
-// platforms but doesn't provide the zero-fill-on-demand pages guarantee.
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#define DISCARDABLE_SHARED_MEMORY_ZERO_FILL_ON_DEMAND_PAGES_AFTER_PURGE
-#endif
-
-namespace base {
-
-namespace trace_event {
-class MemoryAllocatorDump;
-class ProcessMemoryDump;
-} // namespace trace_event
-
-// Platform abstraction for discardable shared memory.
-//
-// This class is not thread-safe. Clients are responsible for synchronizing
-// access to an instance of this class.
-class BASE_EXPORT DiscardableSharedMemory {
- public:
- enum LockResult { SUCCESS, PURGED, FAILED };
-
- DiscardableSharedMemory();
-
- // Create a new DiscardableSharedMemory object from an existing, open shared
- // memory file. Memory must be locked.
- explicit DiscardableSharedMemory(UnsafeSharedMemoryRegion region);
-
- // Closes any open files.
- virtual ~DiscardableSharedMemory();
-
- // Creates and maps a locked DiscardableSharedMemory object with |size|.
- // Returns true on success and false on failure.
- bool CreateAndMap(size_t size);
-
- // Maps the locked discardable memory into the caller's address space.
- // Returns true on success, false otherwise.
- bool Map(size_t size);
-
- // Unmaps the discardable shared memory from the caller's address space.
- // Unmapping won't unlock previously locked range.
- // Returns true if successful; returns false on error or if the memory is
- // not mapped.
- bool Unmap();
-
- // The actual size of the mapped memory (may be larger than requested).
- size_t mapped_size() const { return mapped_size_; }
-
- // Returns a duplicated shared memory region for this DiscardableSharedMemory
- // object.
- UnsafeSharedMemoryRegion DuplicateRegion() const {
- return shared_memory_region_.Duplicate();
- }
-
- // Returns an ID for the shared memory region. This is ID of the mapped region
- // consistent across all processes and is valid as long as the region is not
- // unmapped.
- const UnguessableToken& mapped_id() const {
- return shared_memory_mapping_.guid();
- }
-
- // Locks a range of memory so that it will not be purged by the system.
- // The range of memory must be unlocked. The result of trying to lock an
- // already locked range is undefined. |offset| and |length| must both be
- // a multiple of the page size as returned by GetPageSize().
- // Passing 0 for |length| means "everything onward".
- // Returns SUCCESS if range was successfully locked and the memory is still
- // resident, PURGED if range was successfully locked but has been purged
- // since last time it was locked and FAILED if range could not be locked.
- // Locking can fail for two reasons; object might have been purged, our
- // last known usage timestamp might be out of date. Last known usage time
- // is updated to the actual last usage timestamp if memory is still resident
- // or 0 if not.
- LockResult Lock(size_t offset, size_t length);
-
- // Unlock a previously successfully locked range of memory. The range of
- // memory must be locked. The result of trying to unlock a not
- // previously locked range is undefined.
- // |offset| and |length| must both be a multiple of the page size as returned
- // by GetPageSize().
- // Passing 0 for |length| means "everything onward".
- void Unlock(size_t offset, size_t length);
-
- // Gets a pointer to the opened discardable memory space. Discardable memory
- // must have been mapped via Map().
- void* memory() const;
-
- // Returns the last known usage time for DiscardableSharedMemory object. This
- // may be earlier than the "true" usage time when memory has been used by a
- // different process. Returns NULL time if purged.
- Time last_known_usage() const { return last_known_usage_; }
-
- // This returns true and sets |last_known_usage_| to 0 if
- // DiscardableSharedMemory object was successfully purged. Purging can fail
- // for two reasons; object might be locked or our last known usage timestamp
- // might be out of date. Last known usage time is updated to |current_time|
- // if locked or the actual last usage timestamp if unlocked. It is often
- // necessary to call this function twice for the object to successfully be
- // purged. First call, updates |last_known_usage_|. Second call, successfully
- // purges the object using the updated |last_known_usage_|.
- // Note: there is no guarantee that multiple calls to this function will
- // successfully purge object. DiscardableSharedMemory object might be locked
- // or another thread/process might be able to lock and unlock it in between
- // each call.
- bool Purge(Time current_time);
-
- // Returns true if memory is still resident.
- bool IsMemoryResident() const;
-
- // Returns true if memory is locked.
- bool IsMemoryLocked() const;
-
- // Closes the open discardable memory segment.
- // It is safe to call Close repeatedly.
- void Close();
-
- // For tracing: Creates ownership edge to the underlying shared memory dump
- // which is cross process in the given |pmd|. |local_segment_dump| is the dump
- // associated with the local discardable shared memory segment and |is_owned|
- // is true when the current process owns the segment and the effective memory
- // is assigned to the current process.
- void CreateSharedMemoryOwnershipEdge(
- trace_event::MemoryAllocatorDump* local_segment_dump,
- trace_event::ProcessMemoryDump* pmd,
- bool is_owned) const;
-
- private:
- // LockPages/UnlockPages are platform-native discardable page management
- // helper functions. Both expect |offset| to be specified relative to the
- // base address at which |memory| is mapped, and that |offset| and |length|
- // are page-aligned by the caller.
- // Returns SUCCESS on platforms which do not support discardable pages.
- static LockResult LockPages(const UnsafeSharedMemoryRegion& region,
- size_t offset,
- size_t length);
- // UnlockPages() is a no-op on platforms not supporting discardable pages.
- static void UnlockPages(const UnsafeSharedMemoryRegion& region,
- size_t offset,
- size_t length);
-
- // Virtual for tests.
- virtual Time Now() const;
-
- UnsafeSharedMemoryRegion shared_memory_region_;
- WritableSharedMemoryMapping shared_memory_mapping_;
- size_t mapped_size_;
- size_t locked_page_count_;
-#if DCHECK_IS_ON()
- std::set<size_t> locked_pages_;
-#endif
- // Implementation is not thread-safe but still usable if clients are
- // synchronized somehow. Use a collision warner to detect incorrect usage.
- DFAKE_MUTEX(thread_collision_warner_);
- Time last_known_usage_;
-
- DISALLOW_COPY_AND_ASSIGN(DiscardableSharedMemory);
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_DISCARDABLE_SHARED_MEMORY_H_
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc
deleted file mode 100644
index b3d21a7bd5..0000000000
--- a/base/memory/discardable_shared_memory_unittest.cc
+++ /dev/null
@@ -1,456 +0,0 @@
-// 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 <fcntl.h>
-#include <stdint.h>
-
-#include "base/files/scoped_file.h"
-#include "base/memory/discardable_shared_memory.h"
-#include "base/memory/shared_memory_tracker.h"
-#include "base/process/process_metrics.h"
-#include "base/trace_event/memory_allocator_dump.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class TestDiscardableSharedMemory : public DiscardableSharedMemory {
- public:
- TestDiscardableSharedMemory() = default;
-
- explicit TestDiscardableSharedMemory(UnsafeSharedMemoryRegion region)
- : DiscardableSharedMemory(std::move(region)) {}
-
- void SetNow(Time now) { now_ = now; }
-
- private:
- // Overriden from DiscardableSharedMemory:
- Time Now() const override { return now_; }
-
- Time now_;
-};
-
-TEST(DiscardableSharedMemoryTest, CreateAndMap) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory;
- bool rv = memory.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
- EXPECT_GE(memory.mapped_size(), kDataSize);
- EXPECT_TRUE(memory.IsMemoryLocked());
-}
-
-TEST(DiscardableSharedMemoryTest, CreateFromHandle) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
- ASSERT_TRUE(shared_region.IsValid());
-
- TestDiscardableSharedMemory memory2(std::move(shared_region));
- rv = memory2.Map(kDataSize);
- ASSERT_TRUE(rv);
- EXPECT_TRUE(memory2.IsMemoryLocked());
-}
-
-TEST(DiscardableSharedMemoryTest, LockAndUnlock) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- // Memory is initially locked. Unlock it.
- memory1.SetNow(Time::FromDoubleT(1));
- memory1.Unlock(0, 0);
- EXPECT_FALSE(memory1.IsMemoryLocked());
-
- // Lock and unlock memory.
- DiscardableSharedMemory::LockResult lock_rv = memory1.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv);
- memory1.SetNow(Time::FromDoubleT(2));
- memory1.Unlock(0, 0);
-
- // Lock again before duplicating and passing ownership to new instance.
- lock_rv = memory1.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv);
- EXPECT_TRUE(memory1.IsMemoryLocked());
-
- UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
- ASSERT_TRUE(shared_region.IsValid());
-
- TestDiscardableSharedMemory memory2(std::move(shared_region));
- rv = memory2.Map(kDataSize);
- ASSERT_TRUE(rv);
-
- // Unlock second instance.
- memory2.SetNow(Time::FromDoubleT(3));
- memory2.Unlock(0, 0);
-
- // Both memory instances should be unlocked now.
- EXPECT_FALSE(memory2.IsMemoryLocked());
- EXPECT_FALSE(memory1.IsMemoryLocked());
-
- // Lock second instance before passing ownership back to first instance.
- lock_rv = memory2.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv);
-
- // Memory should still be resident and locked.
- rv = memory1.IsMemoryResident();
- EXPECT_TRUE(rv);
- EXPECT_TRUE(memory1.IsMemoryLocked());
-
- // Unlock first instance.
- memory1.SetNow(Time::FromDoubleT(4));
- memory1.Unlock(0, 0);
-}
-
-TEST(DiscardableSharedMemoryTest, Purge) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
- ASSERT_TRUE(shared_region.IsValid());
-
- TestDiscardableSharedMemory memory2(std::move(shared_region));
- rv = memory2.Map(kDataSize);
- ASSERT_TRUE(rv);
-
- // This should fail as memory is locked.
- rv = memory1.Purge(Time::FromDoubleT(1));
- EXPECT_FALSE(rv);
-
- memory2.SetNow(Time::FromDoubleT(2));
- memory2.Unlock(0, 0);
-
- ASSERT_TRUE(memory2.IsMemoryResident());
-
- // Memory is unlocked, but our usage timestamp is incorrect.
- rv = memory1.Purge(Time::FromDoubleT(3));
- EXPECT_FALSE(rv);
-
- ASSERT_TRUE(memory2.IsMemoryResident());
-
- // Memory is unlocked and our usage timestamp should be correct.
- rv = memory1.Purge(Time::FromDoubleT(4));
- EXPECT_TRUE(rv);
-
- // Lock should fail as memory has been purged.
- DiscardableSharedMemory::LockResult lock_rv = memory2.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
-
- ASSERT_FALSE(memory2.IsMemoryResident());
-}
-
-TEST(DiscardableSharedMemoryTest, LastUsed) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
- ASSERT_TRUE(shared_region.IsValid());
-
- TestDiscardableSharedMemory memory2(std::move(shared_region));
- rv = memory2.Map(kDataSize);
- ASSERT_TRUE(rv);
-
- memory2.SetNow(Time::FromDoubleT(1));
- memory2.Unlock(0, 0);
-
- EXPECT_EQ(memory2.last_known_usage(), Time::FromDoubleT(1));
-
- DiscardableSharedMemory::LockResult lock_rv = memory2.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv);
-
- // This should fail as memory is locked.
- rv = memory1.Purge(Time::FromDoubleT(2));
- ASSERT_FALSE(rv);
-
- // Last usage should have been updated to timestamp passed to Purge above.
- EXPECT_EQ(memory1.last_known_usage(), Time::FromDoubleT(2));
-
- memory2.SetNow(Time::FromDoubleT(3));
- memory2.Unlock(0, 0);
-
- // Usage time should be correct for |memory2| instance.
- EXPECT_EQ(memory2.last_known_usage(), Time::FromDoubleT(3));
-
- // However, usage time has not changed as far as |memory1| instance knows.
- EXPECT_EQ(memory1.last_known_usage(), Time::FromDoubleT(2));
-
- // Memory is unlocked, but our usage timestamp is incorrect.
- rv = memory1.Purge(Time::FromDoubleT(4));
- EXPECT_FALSE(rv);
-
- // The failed purge attempt should have updated usage time to the correct
- // value.
- EXPECT_EQ(memory1.last_known_usage(), Time::FromDoubleT(3));
-
- // Purge memory through |memory2| instance. The last usage time should be
- // set to 0 as a result of this.
- rv = memory2.Purge(Time::FromDoubleT(5));
- EXPECT_TRUE(rv);
- EXPECT_TRUE(memory2.last_known_usage().is_null());
-
- // This should fail as memory has already been purged and |memory1|'s usage
- // time is incorrect as a result.
- rv = memory1.Purge(Time::FromDoubleT(6));
- EXPECT_FALSE(rv);
-
- // The failed purge attempt should have updated usage time to the correct
- // value.
- EXPECT_TRUE(memory1.last_known_usage().is_null());
-
- // Purge should succeed now that usage time is correct.
- rv = memory1.Purge(Time::FromDoubleT(7));
- EXPECT_TRUE(rv);
-}
-
-TEST(DiscardableSharedMemoryTest, LockShouldAlwaysFailAfterSuccessfulPurge) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
- ASSERT_TRUE(shared_region.IsValid());
-
- TestDiscardableSharedMemory memory2(std::move(shared_region));
- rv = memory2.Map(kDataSize);
- ASSERT_TRUE(rv);
-
- memory2.SetNow(Time::FromDoubleT(1));
- memory2.Unlock(0, 0);
-
- rv = memory2.Purge(Time::FromDoubleT(2));
- EXPECT_TRUE(rv);
-
- // Lock should fail as memory has been purged.
- DiscardableSharedMemory::LockResult lock_rv = memory2.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
-}
-
-#if defined(OS_ANDROID)
-TEST(DiscardableSharedMemoryTest, LockShouldFailIfPlatformLockPagesFails) {
- const uint32_t kDataSize = 1024;
-
- DiscardableSharedMemory memory1;
- bool rv1 = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv1);
-
- base::UnsafeSharedMemoryRegion region = memory1.DuplicateRegion();
- int fd = region.GetPlatformHandle();
- DiscardableSharedMemory memory2(std::move(region));
- bool rv2 = memory2.Map(kDataSize);
- ASSERT_TRUE(rv2);
-
- // Unlock() the first page of memory, so we can test Lock()ing it.
- memory2.Unlock(0, base::GetPageSize());
- // To cause ashmem_pin_region() to fail, we arrange for it to be called with
- // an invalid file-descriptor, which requires a valid-looking fd (i.e. we
- // can't just Close() |memory|), but one on which the operation is invalid.
- // We can overwrite the |memory| fd with a handle to a different file using
- // dup2(), which has the nice properties that |memory| still has a valid fd
- // that it can close, etc without errors, but on which ashmem_pin_region()
- // will fail.
- base::ScopedFD null(open("/dev/null", O_RDONLY));
- ASSERT_EQ(fd, dup2(null.get(), fd));
-
- // Now re-Lock()ing the first page should fail.
- DiscardableSharedMemory::LockResult lock_rv =
- memory2.Lock(0, base::GetPageSize());
- EXPECT_EQ(DiscardableSharedMemory::FAILED, lock_rv);
-}
-#endif // defined(OS_ANDROID)
-
-TEST(DiscardableSharedMemoryTest, LockAndUnlockRange) {
- const uint32_t kDataSize = 32;
-
- uint32_t data_size_in_bytes = kDataSize * base::GetPageSize();
-
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(data_size_in_bytes);
- ASSERT_TRUE(rv);
-
- UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
- ASSERT_TRUE(shared_region.IsValid());
-
- TestDiscardableSharedMemory memory2(std::move(shared_region));
- rv = memory2.Map(data_size_in_bytes);
- ASSERT_TRUE(rv);
-
- // Unlock first page.
- memory2.SetNow(Time::FromDoubleT(1));
- memory2.Unlock(0, base::GetPageSize());
-
- rv = memory1.Purge(Time::FromDoubleT(2));
- EXPECT_FALSE(rv);
-
- // Lock first page again.
- memory2.SetNow(Time::FromDoubleT(3));
- DiscardableSharedMemory::LockResult lock_rv =
- memory2.Lock(0, base::GetPageSize());
- EXPECT_NE(DiscardableSharedMemory::FAILED, lock_rv);
-
- // Unlock first page.
- memory2.SetNow(Time::FromDoubleT(4));
- memory2.Unlock(0, base::GetPageSize());
-
- rv = memory1.Purge(Time::FromDoubleT(5));
- EXPECT_FALSE(rv);
-
- // Unlock second page.
- memory2.SetNow(Time::FromDoubleT(6));
- memory2.Unlock(base::GetPageSize(), base::GetPageSize());
-
- rv = memory1.Purge(Time::FromDoubleT(7));
- EXPECT_FALSE(rv);
-
- // Unlock anything onwards.
- memory2.SetNow(Time::FromDoubleT(8));
- memory2.Unlock(2 * base::GetPageSize(), 0);
-
- // Memory is unlocked, but our usage timestamp is incorrect.
- rv = memory1.Purge(Time::FromDoubleT(9));
- EXPECT_FALSE(rv);
-
- // The failed purge attempt should have updated usage time to the correct
- // value.
- EXPECT_EQ(Time::FromDoubleT(8), memory1.last_known_usage());
-
- // Purge should now succeed.
- rv = memory1.Purge(Time::FromDoubleT(10));
- EXPECT_TRUE(rv);
-}
-
-TEST(DiscardableSharedMemoryTest, MappedSize) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory;
- bool rv = memory.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- EXPECT_LE(kDataSize, memory.mapped_size());
-
- // Mapped size should be 0 after memory segment has been unmapped.
- rv = memory.Unmap();
- EXPECT_TRUE(rv);
- EXPECT_EQ(0u, memory.mapped_size());
-}
-
-TEST(DiscardableSharedMemoryTest, Close) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory;
- bool rv = memory.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- // Mapped size should be unchanged after memory segment has been closed.
- memory.Close();
- EXPECT_LE(kDataSize, memory.mapped_size());
-
- // Memory is initially locked. Unlock it.
- memory.SetNow(Time::FromDoubleT(1));
- memory.Unlock(0, 0);
-
- // Lock and unlock memory.
- DiscardableSharedMemory::LockResult lock_rv = memory.Lock(0, 0);
- EXPECT_EQ(DiscardableSharedMemory::SUCCESS, lock_rv);
- memory.SetNow(Time::FromDoubleT(2));
- memory.Unlock(0, 0);
-}
-
-TEST(DiscardableSharedMemoryTest, ZeroSize) {
- TestDiscardableSharedMemory memory;
- bool rv = memory.CreateAndMap(0);
- ASSERT_TRUE(rv);
-
- EXPECT_LE(0u, memory.mapped_size());
-
- // Memory is initially locked. Unlock it.
- memory.SetNow(Time::FromDoubleT(1));
- memory.Unlock(0, 0);
-
- // Lock and unlock memory.
- DiscardableSharedMemory::LockResult lock_rv = memory.Lock(0, 0);
- EXPECT_NE(DiscardableSharedMemory::FAILED, lock_rv);
- memory.SetNow(Time::FromDoubleT(2));
- memory.Unlock(0, 0);
-}
-
-// This test checks that zero-filled pages are returned after purging a segment
-// when DISCARDABLE_SHARED_MEMORY_ZERO_FILL_ON_DEMAND_PAGES_AFTER_PURGE is
-// defined and MADV_REMOVE is supported.
-#if defined(DISCARDABLE_SHARED_MEMORY_ZERO_FILL_ON_DEMAND_PAGES_AFTER_PURGE)
-TEST(DiscardableSharedMemoryTest, ZeroFilledPagesAfterPurge) {
- const uint32_t kDataSize = 1024;
-
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- UnsafeSharedMemoryRegion shared_region = memory1.DuplicateRegion();
- ASSERT_TRUE(shared_region.IsValid());
-
- TestDiscardableSharedMemory memory2(std::move(shared_region));
- rv = memory2.Map(kDataSize);
- ASSERT_TRUE(rv);
-
- // Initialize all memory to '0xaa'.
- memset(memory2.memory(), 0xaa, kDataSize);
-
- // Unlock memory.
- memory2.SetNow(Time::FromDoubleT(1));
- memory2.Unlock(0, 0);
- EXPECT_FALSE(memory1.IsMemoryLocked());
-
- // Memory is unlocked, but our usage timestamp is incorrect.
- rv = memory1.Purge(Time::FromDoubleT(2));
- EXPECT_FALSE(rv);
- rv = memory1.Purge(Time::FromDoubleT(3));
- EXPECT_TRUE(rv);
-
- // Check that reading memory after it has been purged is returning
- // zero-filled pages.
- uint8_t expected_data[kDataSize] = {};
- EXPECT_EQ(memcmp(memory2.memory(), expected_data, kDataSize), 0);
-}
-#endif
-
-TEST(DiscardableSharedMemoryTest, TracingOwnershipEdges) {
- const uint32_t kDataSize = 1024;
- TestDiscardableSharedMemory memory1;
- bool rv = memory1.CreateAndMap(kDataSize);
- ASSERT_TRUE(rv);
-
- base::trace_event::MemoryDumpArgs args = {
- base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
- trace_event::ProcessMemoryDump pmd(args);
- trace_event::MemoryAllocatorDump* client_dump =
- pmd.CreateAllocatorDump("discardable_manager/map1");
- const bool is_owned = false;
- memory1.CreateSharedMemoryOwnershipEdge(client_dump, &pmd, is_owned);
- const auto* shm_dump = pmd.GetAllocatorDump(
- SharedMemoryTracker::GetDumpNameForTracing(memory1.mapped_id()));
- EXPECT_TRUE(shm_dump);
- EXPECT_EQ(shm_dump->GetSizeInternal(), client_dump->GetSizeInternal());
- const auto edges = pmd.allocator_dumps_edges();
- EXPECT_EQ(2u, edges.size());
- EXPECT_NE(edges.end(), edges.find(shm_dump->guid()));
- EXPECT_NE(edges.end(), edges.find(client_dump->guid()));
- // TODO(ssid): test for weak global dump once the
- // CreateWeakSharedMemoryOwnershipEdge() is fixed, crbug.com/661257.
-}
-
-} // namespace base
diff --git a/base/memory/memory_coordinator_client.cc b/base/memory/memory_coordinator_client.cc
deleted file mode 100644
index 7fa6232177..0000000000
--- a/base/memory/memory_coordinator_client.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2016 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/memory/memory_coordinator_client.h"
-
-#include "base/logging.h"
-
-namespace base {
-
-const char* MemoryStateToString(MemoryState state) {
- switch (state) {
- case MemoryState::UNKNOWN:
- return "unknown";
- case MemoryState::NORMAL:
- return "normal";
- case MemoryState::THROTTLED:
- return "throttled";
- case MemoryState::SUSPENDED:
- return "suspended";
- default:
- NOTREACHED();
- }
- return "";
-}
-
-} // namespace base
diff --git a/base/memory/memory_coordinator_client.h b/base/memory/memory_coordinator_client.h
deleted file mode 100644
index 804f0a6b85..0000000000
--- a/base/memory/memory_coordinator_client.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_
-#define BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_
-
-#include "base/base_export.h"
-
-namespace base {
-
-// OVERVIEW:
-//
-// MemoryCoordinatorClient is an interface which a component can implement to
-// adjust "future allocation" and "existing allocation". For "future allocation"
-// it provides a callback to observe memory state changes, and for "existing
-// allocation" it provides a callback to purge memory.
-//
-// Unlike MemoryPressureListener, memory state changes are stateful. State
-// transitions are throttled to avoid thrashing; the exact throttling period is
-// platform dependent, but will be at least 5-10 seconds. When a state change
-// notification is dispatched, clients are expected to update their allocation
-// policies (e.g. setting cache limit) that persist for the duration of the
-// memory state. Note that clients aren't expected to free up memory on memory
-// state changes. Clients should wait for a separate purge request to free up
-// memory. Purging requests will be throttled as well.
-
-// MemoryState is an indicator that processes can use to guide their memory
-// allocation policies. For example, a process that receives the throttled
-// state can use that as as signal to decrease memory cache limits.
-// NOTE: This enum is used to back an UMA histogram, and therefore should be
-// treated as append-only.
-enum class MemoryState : int {
- // The state is unknown.
- UNKNOWN = -1,
- // No memory constraints.
- NORMAL = 0,
- // Running and interactive but memory allocation should be throttled.
- // Clients should set lower budget for any memory that is used as an
- // optimization but that is not necessary for the process to run.
- // (e.g. caches)
- THROTTLED = 1,
- // Still resident in memory but core processing logic has been suspended.
- // In most cases, OnPurgeMemory() will be called before entering this state.
- SUSPENDED = 2,
-};
-
-const int kMemoryStateMax = static_cast<int>(MemoryState::SUSPENDED) + 1;
-
-// Returns a string representation of MemoryState.
-BASE_EXPORT const char* MemoryStateToString(MemoryState state);
-
-// This is an interface for components which can respond to memory status
-// changes. An initial state is NORMAL. See MemoryCoordinatorClientRegistry for
-// threading guarantees and ownership management.
-class BASE_EXPORT MemoryCoordinatorClient {
- public:
- // Called when memory state has changed. Any transition can occur except for
- // UNKNOWN. General guidelines are:
- // * NORMAL: Restore the default settings for memory allocation/usage if
- // it has changed.
- // * THROTTLED: Use smaller limits for future memory allocations. You don't
- // need to take any action on existing allocations.
- // * SUSPENDED: Use much smaller limits for future memory allocations. You
- // don't need to take any action on existing allocations.
- virtual void OnMemoryStateChange(MemoryState state) {}
-
- // Called to purge memory.
- // This callback should free up any memory that is used as an optimization, or
- // any memory whose contents can be reproduced.
- virtual void OnPurgeMemory() {}
-
- protected:
- virtual ~MemoryCoordinatorClient() = default;
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_MEMORY_COORDINATOR_CLIENT_H_
diff --git a/base/memory/memory_coordinator_client_registry.cc b/base/memory/memory_coordinator_client_registry.cc
deleted file mode 100644
index 45b4a7f5bc..0000000000
--- a/base/memory/memory_coordinator_client_registry.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 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/memory/memory_coordinator_client_registry.h"
-
-namespace base {
-
-// static
-MemoryCoordinatorClientRegistry*
-MemoryCoordinatorClientRegistry::GetInstance() {
- return Singleton<
- MemoryCoordinatorClientRegistry,
- LeakySingletonTraits<MemoryCoordinatorClientRegistry>>::get();
-}
-
-MemoryCoordinatorClientRegistry::MemoryCoordinatorClientRegistry()
- : clients_(new ClientList) {}
-
-MemoryCoordinatorClientRegistry::~MemoryCoordinatorClientRegistry() = default;
-
-void MemoryCoordinatorClientRegistry::Register(
- MemoryCoordinatorClient* client) {
- clients_->AddObserver(client);
-}
-
-void MemoryCoordinatorClientRegistry::Unregister(
- MemoryCoordinatorClient* client) {
- clients_->RemoveObserver(client);
-}
-
-void MemoryCoordinatorClientRegistry::Notify(MemoryState state) {
- clients_->Notify(FROM_HERE,
- &base::MemoryCoordinatorClient::OnMemoryStateChange, state);
-}
-
-void MemoryCoordinatorClientRegistry::PurgeMemory() {
- clients_->Notify(FROM_HERE, &base::MemoryCoordinatorClient::OnPurgeMemory);
-}
-
-} // namespace base
diff --git a/base/memory/memory_coordinator_client_registry.h b/base/memory/memory_coordinator_client_registry.h
deleted file mode 100644
index e2c81b7187..0000000000
--- a/base/memory/memory_coordinator_client_registry.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_
-#define BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_
-
-#include "base/base_export.h"
-#include "base/memory/memory_coordinator_client.h"
-#include "base/memory/singleton.h"
-#include "base/observer_list_threadsafe.h"
-
-namespace base {
-
-// MemoryCoordinatorClientRegistry is the registry of MemoryCoordinatorClients.
-// This class manages clients and provides a way to notify memory state changes
-// to clients, but this isn't responsible to determine how/when to change
-// memory states.
-//
-// Threading guarantees:
-// This class uses ObserverListThreadsafe internally, which means that
-// * Registering/unregistering callbacks are thread-safe.
-// * Callbacks are invoked on the same thread on which they are registered.
-// See base/observer_list_threadsafe.h for reference.
-//
-// Ownership management:
-// This class doesn't take the ownership of clients. Clients must be
-// unregistered before they are destroyed.
-class BASE_EXPORT MemoryCoordinatorClientRegistry {
- public:
- static MemoryCoordinatorClientRegistry* GetInstance();
-
- ~MemoryCoordinatorClientRegistry();
-
- // Registers/unregisters a client. Does not take ownership of client.
- void Register(MemoryCoordinatorClient* client);
- void Unregister(MemoryCoordinatorClient* client);
-
- // Notify clients of a memory state change.
- void Notify(MemoryState state);
-
- // Requests purging memory.
- void PurgeMemory();
-
- private:
- friend struct DefaultSingletonTraits<MemoryCoordinatorClientRegistry>;
-
- MemoryCoordinatorClientRegistry();
-
- using ClientList = ObserverListThreadSafe<MemoryCoordinatorClient>;
- scoped_refptr<ClientList> clients_;
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_MEMORY_CLIENT_REGISTRY_H_
diff --git a/base/memory/memory_coordinator_client_registry_unittest.cc b/base/memory/memory_coordinator_client_registry_unittest.cc
deleted file mode 100644
index 37ed7673d9..0000000000
--- a/base/memory/memory_coordinator_client_registry_unittest.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2017 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/memory/memory_coordinator_client_registry.h"
-
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class TestMemoryCoordinatorClient : public MemoryCoordinatorClient {
- public:
- void OnMemoryStateChange(MemoryState state) override { state_ = state; }
-
- void OnPurgeMemory() override { ++purge_count_; }
-
- MemoryState state() const { return state_; }
- size_t purge_count() const { return purge_count_; }
-
- private:
- MemoryState state_ = MemoryState::UNKNOWN;
- size_t purge_count_ = 0;
-};
-
-void RunUntilIdle() {
- base::RunLoop loop;
- loop.RunUntilIdle();
-}
-
-TEST(MemoryCoordinatorClientRegistryTest, NotifyStateChange) {
- MessageLoop loop;
- auto* registry = MemoryCoordinatorClientRegistry::GetInstance();
- TestMemoryCoordinatorClient client;
- registry->Register(&client);
- registry->Notify(MemoryState::THROTTLED);
- RunUntilIdle();
- ASSERT_EQ(MemoryState::THROTTLED, client.state());
- registry->Unregister(&client);
-}
-
-TEST(MemoryCoordinatorClientRegistryTest, PurgeMemory) {
- MessageLoop loop;
- auto* registry = MemoryCoordinatorClientRegistry::GetInstance();
- TestMemoryCoordinatorClient client;
- registry->Register(&client);
- registry->PurgeMemory();
- RunUntilIdle();
- ASSERT_EQ(1u, client.purge_count());
- registry->Unregister(&client);
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/memory/memory_coordinator_proxy.cc b/base/memory/memory_coordinator_proxy.cc
deleted file mode 100644
index 4e22fe04fc..0000000000
--- a/base/memory/memory_coordinator_proxy.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 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/memory/memory_coordinator_proxy.h"
-
-namespace base {
-
-namespace {
-
-MemoryCoordinator* g_memory_coordinator = nullptr;
-
-} // namespace
-
-MemoryCoordinatorProxy::MemoryCoordinatorProxy() = default;
-
-MemoryCoordinatorProxy::~MemoryCoordinatorProxy() = default;
-
-// static
-MemoryCoordinatorProxy* MemoryCoordinatorProxy::GetInstance() {
- return Singleton<base::MemoryCoordinatorProxy>::get();
-}
-
-// static
-void MemoryCoordinatorProxy::SetMemoryCoordinator(
- MemoryCoordinator* coordinator) {
- DCHECK(!g_memory_coordinator || !coordinator);
- g_memory_coordinator = coordinator;
-}
-
-MemoryState MemoryCoordinatorProxy::GetCurrentMemoryState() const {
- if (!g_memory_coordinator)
- return MemoryState::NORMAL;
- return g_memory_coordinator->GetCurrentMemoryState();
-}
-
-} // namespace base
diff --git a/base/memory/memory_coordinator_proxy.h b/base/memory/memory_coordinator_proxy.h
deleted file mode 100644
index b6e7b3f6ef..0000000000
--- a/base/memory/memory_coordinator_proxy.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_MEMORY_MEMORY_COORDINATOR_PROXY_H_
-#define BASE_MEMORY_MEMORY_COORDINATOR_PROXY_H_
-
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/memory/memory_coordinator_client.h"
-#include "base/memory/singleton.h"
-
-namespace base {
-
-// The MemoryCoordinator interface. See comments in MemoryCoordinatorProxy for
-// method descriptions.
-class BASE_EXPORT MemoryCoordinator {
- public:
- virtual ~MemoryCoordinator() = default;
-
- virtual MemoryState GetCurrentMemoryState() const = 0;
-};
-
-// The proxy of MemoryCoordinator to be accessed from components that are not
-// in content/browser e.g. net.
-class BASE_EXPORT MemoryCoordinatorProxy {
- public:
- static MemoryCoordinatorProxy* GetInstance();
-
- // Sets an implementation of MemoryCoordinator. MemoryCoordinatorProxy doesn't
- // take the ownership of |coordinator|. It must outlive this proxy.
- // This should be called before any components starts using this proxy.
- static void SetMemoryCoordinator(MemoryCoordinator* coordinator);
-
- // Returns the current memory state.
- MemoryState GetCurrentMemoryState() const;
-
- private:
- friend struct base::DefaultSingletonTraits<MemoryCoordinatorProxy>;
-
- MemoryCoordinatorProxy();
- virtual ~MemoryCoordinatorProxy();
-
- DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorProxy);
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_MEMORY_COORDINATOR_PROXY_H_
diff --git a/base/memory/memory_pressure_listener.cc b/base/memory/memory_pressure_listener.cc
deleted file mode 100644
index 669fb17b7a..0000000000
--- a/base/memory/memory_pressure_listener.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2013 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/memory/memory_pressure_listener.h"
-
-#include "base/observer_list_threadsafe.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-
-namespace {
-
-// This class is thread safe and internally synchronized.
-class MemoryPressureObserver {
- public:
- // There is at most one MemoryPressureObserver and it is never deleted.
- ~MemoryPressureObserver() = delete;
-
- void AddObserver(MemoryPressureListener* listener, bool sync) {
- async_observers_->AddObserver(listener);
- if (sync) {
- AutoLock lock(sync_observers_lock_);
- sync_observers_.AddObserver(listener);
- }
- }
-
- void RemoveObserver(MemoryPressureListener* listener) {
- async_observers_->RemoveObserver(listener);
- AutoLock lock(sync_observers_lock_);
- sync_observers_.RemoveObserver(listener);
- }
-
- void Notify(
- MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
- async_observers_->Notify(FROM_HERE, &MemoryPressureListener::Notify,
- memory_pressure_level);
- AutoLock lock(sync_observers_lock_);
- for (auto& observer : sync_observers_)
- observer.SyncNotify(memory_pressure_level);
- }
-
- private:
- const scoped_refptr<ObserverListThreadSafe<MemoryPressureListener>>
- async_observers_ = base::MakeRefCounted<
- ObserverListThreadSafe<MemoryPressureListener>>();
- ObserverList<MemoryPressureListener> sync_observers_;
- Lock sync_observers_lock_;
-};
-
-// Gets the shared MemoryPressureObserver singleton instance.
-MemoryPressureObserver* GetMemoryPressureObserver() {
- static auto* const observer = new MemoryPressureObserver();
- return observer;
-}
-
-subtle::Atomic32 g_notifications_suppressed = 0;
-
-} // namespace
-
-MemoryPressureListener::MemoryPressureListener(
- const MemoryPressureListener::MemoryPressureCallback& callback)
- : callback_(callback) {
- GetMemoryPressureObserver()->AddObserver(this, false);
-}
-
-MemoryPressureListener::MemoryPressureListener(
- const MemoryPressureListener::MemoryPressureCallback& callback,
- const MemoryPressureListener::SyncMemoryPressureCallback&
- sync_memory_pressure_callback)
- : callback_(callback),
- sync_memory_pressure_callback_(sync_memory_pressure_callback) {
- GetMemoryPressureObserver()->AddObserver(this, true);
-}
-
-MemoryPressureListener::~MemoryPressureListener() {
- GetMemoryPressureObserver()->RemoveObserver(this);
-}
-
-void MemoryPressureListener::Notify(MemoryPressureLevel memory_pressure_level) {
- callback_.Run(memory_pressure_level);
-}
-
-void MemoryPressureListener::SyncNotify(
- MemoryPressureLevel memory_pressure_level) {
- if (!sync_memory_pressure_callback_.is_null()) {
- sync_memory_pressure_callback_.Run(memory_pressure_level);
- }
-}
-
-// static
-void MemoryPressureListener::NotifyMemoryPressure(
- MemoryPressureLevel memory_pressure_level) {
- DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE);
- TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("memory-infra"),
- "MemoryPressureListener::NotifyMemoryPressure",
- TRACE_EVENT_SCOPE_THREAD, "level",
- memory_pressure_level);
- if (AreNotificationsSuppressed())
- return;
- DoNotifyMemoryPressure(memory_pressure_level);
-}
-
-// static
-bool MemoryPressureListener::AreNotificationsSuppressed() {
- return subtle::Acquire_Load(&g_notifications_suppressed) == 1;
-}
-
-// static
-void MemoryPressureListener::SetNotificationsSuppressed(bool suppress) {
- subtle::Release_Store(&g_notifications_suppressed, suppress ? 1 : 0);
-}
-
-// static
-void MemoryPressureListener::SimulatePressureNotification(
- MemoryPressureLevel memory_pressure_level) {
- // Notify all listeners even if regular pressure notifications are suppressed.
- DoNotifyMemoryPressure(memory_pressure_level);
-}
-
-// static
-void MemoryPressureListener::DoNotifyMemoryPressure(
- MemoryPressureLevel memory_pressure_level) {
- DCHECK_NE(memory_pressure_level, MEMORY_PRESSURE_LEVEL_NONE);
-
- GetMemoryPressureObserver()->Notify(memory_pressure_level);
-}
-
-} // namespace base
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h
deleted file mode 100644
index 7e97010085..0000000000
--- a/base/memory/memory_pressure_listener.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2013 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.
-
-// MemoryPressure provides static APIs for handling memory pressure on
-// platforms that have such signals, such as Android and ChromeOS.
-// The app will try to discard buffers that aren't deemed essential (individual
-// modules will implement their own policy).
-
-#ifndef BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
-#define BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
-
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/macros.h"
-
-namespace base {
-
-// To start listening, create a new instance, passing a callback to a
-// function that takes a MemoryPressureLevel parameter. To stop listening,
-// simply delete the listener object. The implementation guarantees
-// that the callback will always be called on the thread that created
-// the listener.
-// Note that even on the same thread, the callback is not guaranteed to be
-// called synchronously within the system memory pressure broadcast.
-// Please see notes in MemoryPressureLevel enum below: some levels are
-// absolutely critical, and if not enough memory is returned to the system,
-// it'll potentially kill the app, and then later the app will have to be
-// cold-started.
-//
-// Example:
-//
-// void OnMemoryPressure(MemoryPressureLevel memory_pressure_level) {
-// ...
-// }
-//
-// // Start listening.
-// MemoryPressureListener* my_listener =
-// new MemoryPressureListener(base::Bind(&OnMemoryPressure));
-//
-// ...
-//
-// // Stop listening.
-// delete my_listener;
-//
-class BASE_EXPORT MemoryPressureListener {
- public:
- // A Java counterpart will be generated for this enum.
- // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base
- enum MemoryPressureLevel {
- // No problems, there is enough memory to use. This event is not sent via
- // callback, but the enum is used in other places to find out the current
- // state of the system.
- MEMORY_PRESSURE_LEVEL_NONE,
-
- // Modules are advised to free buffers that are cheap to re-allocate and not
- // immediately needed.
- MEMORY_PRESSURE_LEVEL_MODERATE,
-
- // At this level, modules are advised to free all possible memory. The
- // alternative is to be killed by the system, which means all memory will
- // have to be re-created, plus the cost of a cold start.
- MEMORY_PRESSURE_LEVEL_CRITICAL,
- };
-
- typedef Callback<void(MemoryPressureLevel)> MemoryPressureCallback;
- typedef Callback<void(MemoryPressureLevel)> SyncMemoryPressureCallback;
-
- explicit MemoryPressureListener(
- const MemoryPressureCallback& memory_pressure_callback);
- MemoryPressureListener(
- const MemoryPressureCallback& memory_pressure_callback,
- const SyncMemoryPressureCallback& sync_memory_pressure_callback);
-
- ~MemoryPressureListener();
-
- // Intended for use by the platform specific implementation.
- static void NotifyMemoryPressure(MemoryPressureLevel memory_pressure_level);
-
- // These methods should not be used anywhere else but in memory measurement
- // code, where they are intended to maintain stable conditions across
- // measurements.
- static bool AreNotificationsSuppressed();
- static void SetNotificationsSuppressed(bool suppressed);
- static void SimulatePressureNotification(
- MemoryPressureLevel memory_pressure_level);
-
- void Notify(MemoryPressureLevel memory_pressure_level);
- void SyncNotify(MemoryPressureLevel memory_pressure_level);
-
- private:
- static void DoNotifyMemoryPressure(MemoryPressureLevel memory_pressure_level);
-
- MemoryPressureCallback callback_;
- SyncMemoryPressureCallback sync_memory_pressure_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryPressureListener);
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_MEMORY_PRESSURE_LISTENER_H_
diff --git a/base/memory/memory_pressure_listener_unittest.cc b/base/memory/memory_pressure_listener_unittest.cc
deleted file mode 100644
index 87d5f4cbbe..0000000000
--- a/base/memory/memory_pressure_listener_unittest.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2015 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/memory/memory_pressure_listener.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace base {
-
-using MemoryPressureLevel = MemoryPressureListener::MemoryPressureLevel;
-
-class MemoryPressureListenerTest : public testing::Test {
- public:
- void SetUp() override {
- message_loop_.reset(new MessageLoopForUI());
- listener_.reset(new MemoryPressureListener(
- Bind(&MemoryPressureListenerTest::OnMemoryPressure, Unretained(this))));
- }
-
- void TearDown() override {
- listener_.reset();
- message_loop_.reset();
- }
-
- protected:
- void ExpectNotification(
- void (*notification_function)(MemoryPressureLevel),
- MemoryPressureLevel level) {
- EXPECT_CALL(*this, OnMemoryPressure(level)).Times(1);
- notification_function(level);
- RunLoop().RunUntilIdle();
- }
-
- void ExpectNoNotification(
- void (*notification_function)(MemoryPressureLevel),
- MemoryPressureLevel level) {
- EXPECT_CALL(*this, OnMemoryPressure(testing::_)).Times(0);
- notification_function(level);
- RunLoop().RunUntilIdle();
- }
-
- private:
- MOCK_METHOD1(OnMemoryPressure,
- void(MemoryPressureListener::MemoryPressureLevel));
-
- std::unique_ptr<MessageLoopForUI> message_loop_;
- std::unique_ptr<MemoryPressureListener> listener_;
-};
-
-TEST_F(MemoryPressureListenerTest, NotifyMemoryPressure) {
- // Memory pressure notifications are not suppressed by default.
- EXPECT_FALSE(MemoryPressureListener::AreNotificationsSuppressed());
- ExpectNotification(&MemoryPressureListener::NotifyMemoryPressure,
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE);
- ExpectNotification(&MemoryPressureListener::SimulatePressureNotification,
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE);
-
- // Enable suppressing memory pressure notifications.
- MemoryPressureListener::SetNotificationsSuppressed(true);
- EXPECT_TRUE(MemoryPressureListener::AreNotificationsSuppressed());
- ExpectNoNotification(&MemoryPressureListener::NotifyMemoryPressure,
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE);
- ExpectNotification(&MemoryPressureListener::SimulatePressureNotification,
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE);
-
- // Disable suppressing memory pressure notifications.
- MemoryPressureListener::SetNotificationsSuppressed(false);
- EXPECT_FALSE(MemoryPressureListener::AreNotificationsSuppressed());
- ExpectNotification(&MemoryPressureListener::NotifyMemoryPressure,
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL);
- ExpectNotification(&MemoryPressureListener::SimulatePressureNotification,
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL);
-}
-
-} // namespace base
diff --git a/base/memory/memory_pressure_monitor.cc b/base/memory/memory_pressure_monitor.cc
deleted file mode 100644
index ed350b81b9..0000000000
--- a/base/memory/memory_pressure_monitor.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 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/memory/memory_pressure_monitor.h"
-
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-
-namespace base {
-namespace {
-
-MemoryPressureMonitor* g_monitor = nullptr;
-
-// Enumeration of UMA memory pressure levels. This needs to be kept in sync with
-// histograms.xml and the memory pressure levels defined in
-// MemoryPressureListener.
-enum MemoryPressureLevelUMA {
- UMA_MEMORY_PRESSURE_LEVEL_NONE = 0,
- UMA_MEMORY_PRESSURE_LEVEL_MODERATE = 1,
- UMA_MEMORY_PRESSURE_LEVEL_CRITICAL = 2,
- // This must be the last value in the enum.
- UMA_MEMORY_PRESSURE_LEVEL_COUNT,
-};
-
-// Converts a memory pressure level to an UMA enumeration value.
-MemoryPressureLevelUMA MemoryPressureLevelToUmaEnumValue(
- base::MemoryPressureListener::MemoryPressureLevel level) {
- switch (level) {
- case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
- return UMA_MEMORY_PRESSURE_LEVEL_NONE;
- case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
- return UMA_MEMORY_PRESSURE_LEVEL_MODERATE;
- case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
- return UMA_MEMORY_PRESSURE_LEVEL_CRITICAL;
- }
- NOTREACHED();
- return UMA_MEMORY_PRESSURE_LEVEL_NONE;
-}
-
-} // namespace
-
-MemoryPressureMonitor::MemoryPressureMonitor() {
- DCHECK(!g_monitor);
- g_monitor = this;
-}
-
-MemoryPressureMonitor::~MemoryPressureMonitor() {
- DCHECK(g_monitor);
- g_monitor = nullptr;
-}
-
-// static
-MemoryPressureMonitor* MemoryPressureMonitor::Get() {
- return g_monitor;
-}
-void MemoryPressureMonitor::RecordMemoryPressure(
- base::MemoryPressureListener::MemoryPressureLevel level,
- int ticks) {
- // Use the more primitive STATIC_HISTOGRAM_POINTER_BLOCK macro because the
- // simple UMA_HISTOGRAM macros don't expose 'AddCount' functionality.
- STATIC_HISTOGRAM_POINTER_BLOCK(
- "Memory.PressureLevel",
- AddCount(MemoryPressureLevelToUmaEnumValue(level), ticks),
- base::LinearHistogram::FactoryGet(
- "Memory.PressureLevel", 1, UMA_MEMORY_PRESSURE_LEVEL_COUNT,
- UMA_MEMORY_PRESSURE_LEVEL_COUNT + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag));
-}
-
-} // namespace base
diff --git a/base/memory/memory_pressure_monitor.h b/base/memory/memory_pressure_monitor.h
deleted file mode 100644
index e48244b433..0000000000
--- a/base/memory/memory_pressure_monitor.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
-#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
-
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/memory_pressure_listener.h"
-
-namespace base {
-
-// TODO(chrisha): Make this a concrete class with per-OS implementations rather
-// than an abstract base class.
-
-// Declares the interface for a MemoryPressureMonitor. There are multiple
-// OS specific implementations of this class. An instance of the memory
-// pressure observer is created at the process level, tracks memory usage, and
-// pushes memory state change notifications to the static function
-// base::MemoryPressureListener::NotifyMemoryPressure. This is turn notifies
-// all MemoryPressureListener instances via a callback.
-class BASE_EXPORT MemoryPressureMonitor {
- public:
- using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
- using DispatchCallback = base::Callback<void(MemoryPressureLevel level)>;
-
- virtual ~MemoryPressureMonitor();
-
- // Return the singleton MemoryPressureMonitor.
- static MemoryPressureMonitor* Get();
-
- // Record memory pressure UMA statistic. A tick is 5 seconds.
- static void RecordMemoryPressure(MemoryPressureLevel level, int ticks);
-
- // Returns the currently observed memory pressure.
- virtual MemoryPressureLevel GetCurrentPressureLevel() = 0;
-
- // Sets a notification callback. The default callback invokes
- // base::MemoryPressureListener::NotifyMemoryPressure.
- virtual void SetDispatchCallback(const DispatchCallback& callback) = 0;
-
- protected:
- MemoryPressureMonitor();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor);
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_H_
diff --git a/base/memory/memory_pressure_monitor_chromeos.cc b/base/memory/memory_pressure_monitor_chromeos.cc
deleted file mode 100644
index b4e4b94787..0000000000
--- a/base/memory/memory_pressure_monitor_chromeos.cc
+++ /dev/null
@@ -1,288 +0,0 @@
-// 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/memory/memory_pressure_monitor_chromeos.h"
-
-#include <fcntl.h>
-#include <sys/select.h>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/process/process_metrics.h"
-#include "base/single_thread_task_runner.h"
-#include "base/sys_info.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-
-namespace base {
-namespace chromeos {
-
-namespace {
-
-// The time between memory pressure checks. While under critical pressure, this
-// is also the timer to repeat cleanup attempts.
-const int kMemoryPressureIntervalMs = 1000;
-
-// The time which should pass between two moderate memory pressure calls.
-const int kModerateMemoryPressureCooldownMs = 10000;
-
-// Number of event polls before the next moderate pressure event can be sent.
-const int kModerateMemoryPressureCooldown =
- kModerateMemoryPressureCooldownMs / kMemoryPressureIntervalMs;
-
-// Threshold constants to emit pressure events.
-const int kNormalMemoryPressureModerateThresholdPercent = 60;
-const int kNormalMemoryPressureCriticalThresholdPercent = 95;
-const int kAggressiveMemoryPressureModerateThresholdPercent = 35;
-const int kAggressiveMemoryPressureCriticalThresholdPercent = 70;
-
-// The possible state for memory pressure level. The values should be in line
-// with values in MemoryPressureListener::MemoryPressureLevel and should be
-// updated if more memory pressure levels are introduced.
-enum MemoryPressureLevelUMA {
- MEMORY_PRESSURE_LEVEL_NONE = 0,
- MEMORY_PRESSURE_LEVEL_MODERATE,
- MEMORY_PRESSURE_LEVEL_CRITICAL,
- NUM_MEMORY_PRESSURE_LEVELS
-};
-
-// This is the file that will exist if low memory notification is available
-// on the device. Whenever it becomes readable, it signals a low memory
-// condition.
-const char kLowMemFile[] = "/dev/chromeos-low-mem";
-
-// Converts a |MemoryPressureThreshold| value into a used memory percentage for
-// the moderate pressure event.
-int GetModerateMemoryThresholdInPercent(
- MemoryPressureMonitor::MemoryPressureThresholds thresholds) {
- return thresholds == MemoryPressureMonitor::
- THRESHOLD_AGGRESSIVE_CACHE_DISCARD ||
- thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE
- ? kAggressiveMemoryPressureModerateThresholdPercent
- : kNormalMemoryPressureModerateThresholdPercent;
-}
-
-// Converts a |MemoryPressureThreshold| value into a used memory percentage for
-// the critical pressure event.
-int GetCriticalMemoryThresholdInPercent(
- MemoryPressureMonitor::MemoryPressureThresholds thresholds) {
- return thresholds == MemoryPressureMonitor::
- THRESHOLD_AGGRESSIVE_TAB_DISCARD ||
- thresholds == MemoryPressureMonitor::THRESHOLD_AGGRESSIVE
- ? kAggressiveMemoryPressureCriticalThresholdPercent
- : kNormalMemoryPressureCriticalThresholdPercent;
-}
-
-// Converts free percent of memory into a memory pressure value.
-MemoryPressureListener::MemoryPressureLevel GetMemoryPressureLevelFromFillLevel(
- int actual_fill_level,
- int moderate_threshold,
- int critical_threshold) {
- if (actual_fill_level < moderate_threshold)
- return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
- return actual_fill_level < critical_threshold
- ? MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE
- : MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
-}
-
-// This function will be called less than once a second. It will check if
-// the kernel has detected a low memory situation.
-bool IsLowMemoryCondition(int file_descriptor) {
- fd_set fds;
- struct timeval tv;
-
- FD_ZERO(&fds);
- FD_SET(file_descriptor, &fds);
-
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- return HANDLE_EINTR(select(file_descriptor + 1, &fds, NULL, NULL, &tv)) > 0;
-}
-
-} // namespace
-
-MemoryPressureMonitor::MemoryPressureMonitor(
- MemoryPressureThresholds thresholds)
- : current_memory_pressure_level_(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
- moderate_pressure_repeat_count_(0),
- seconds_since_reporting_(0),
- moderate_pressure_threshold_percent_(
- GetModerateMemoryThresholdInPercent(thresholds)),
- critical_pressure_threshold_percent_(
- GetCriticalMemoryThresholdInPercent(thresholds)),
- low_mem_file_(HANDLE_EINTR(::open(kLowMemFile, O_RDONLY))),
- dispatch_callback_(
- base::Bind(&MemoryPressureListener::NotifyMemoryPressure)),
- weak_ptr_factory_(this) {
- StartObserving();
- LOG_IF(ERROR,
- base::SysInfo::IsRunningOnChromeOS() && !low_mem_file_.is_valid())
- << "Cannot open kernel listener";
-}
-
-MemoryPressureMonitor::~MemoryPressureMonitor() {
- StopObserving();
-}
-
-void MemoryPressureMonitor::ScheduleEarlyCheck() {
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&MemoryPressureMonitor::CheckMemoryPressure,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-MemoryPressureListener::MemoryPressureLevel
-MemoryPressureMonitor::GetCurrentPressureLevel() {
- return current_memory_pressure_level_;
-}
-
-// static
-MemoryPressureMonitor* MemoryPressureMonitor::Get() {
- return static_cast<MemoryPressureMonitor*>(
- base::MemoryPressureMonitor::Get());
-}
-
-void MemoryPressureMonitor::StartObserving() {
- timer_.Start(FROM_HERE,
- TimeDelta::FromMilliseconds(kMemoryPressureIntervalMs),
- Bind(&MemoryPressureMonitor::
- CheckMemoryPressureAndRecordStatistics,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void MemoryPressureMonitor::StopObserving() {
- // If StartObserving failed, StopObserving will still get called.
- timer_.Stop();
-}
-
-void MemoryPressureMonitor::CheckMemoryPressureAndRecordStatistics() {
- CheckMemoryPressure();
- if (seconds_since_reporting_++ == 5) {
- seconds_since_reporting_ = 0;
- RecordMemoryPressure(current_memory_pressure_level_, 1);
- }
- // Record UMA histogram statistics for the current memory pressure level.
- // TODO(lgrey): Remove this once there's a usable history for the
- // "Memory.PressureLevel" statistic
- MemoryPressureLevelUMA memory_pressure_level_uma(MEMORY_PRESSURE_LEVEL_NONE);
- switch (current_memory_pressure_level_) {
- case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
- memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_NONE;
- break;
- case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
- memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_MODERATE;
- break;
- case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
- memory_pressure_level_uma = MEMORY_PRESSURE_LEVEL_CRITICAL;
- break;
- }
-
- UMA_HISTOGRAM_ENUMERATION("ChromeOS.MemoryPressureLevel",
- memory_pressure_level_uma,
- NUM_MEMORY_PRESSURE_LEVELS);
-}
-
-void MemoryPressureMonitor::CheckMemoryPressure() {
- MemoryPressureListener::MemoryPressureLevel old_pressure =
- current_memory_pressure_level_;
-
- // If we have the kernel low memory observer, we use it's flag instead of our
- // own computation (for now). Note that in "simulation mode" it can be null.
- // TODO(skuhne): We need to add code which makes sure that the kernel and this
- // computation come to similar results and then remove this override again.
- // TODO(skuhne): Add some testing framework here to see how close the kernel
- // and the internal functions are.
- if (low_mem_file_.is_valid() && IsLowMemoryCondition(low_mem_file_.get())) {
- current_memory_pressure_level_ =
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
- } else {
- current_memory_pressure_level_ = GetMemoryPressureLevelFromFillLevel(
- GetUsedMemoryInPercent(),
- moderate_pressure_threshold_percent_,
- critical_pressure_threshold_percent_);
-
- // When listening to the kernel, we ignore the reported memory pressure
- // level from our own computation and reduce critical to moderate.
- if (low_mem_file_.is_valid() &&
- current_memory_pressure_level_ ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
- current_memory_pressure_level_ =
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
- }
- }
-
- // In case there is no memory pressure we do not notify.
- if (current_memory_pressure_level_ ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
- return;
- }
- if (old_pressure == current_memory_pressure_level_) {
- // If the memory pressure is still at the same level, we notify again for a
- // critical level. In case of a moderate level repeat however, we only send
- // a notification after a certain time has passed.
- if (current_memory_pressure_level_ ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
- ++moderate_pressure_repeat_count_ <
- kModerateMemoryPressureCooldown) {
- return;
- }
- } else if (current_memory_pressure_level_ ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE &&
- old_pressure ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
- // When we reducing the pressure level from critical to moderate, we
- // restart the timeout and do not send another notification.
- moderate_pressure_repeat_count_ = 0;
- return;
- }
- moderate_pressure_repeat_count_ = 0;
- dispatch_callback_.Run(current_memory_pressure_level_);
-}
-
-// Gets the used ChromeOS memory in percent.
-int MemoryPressureMonitor::GetUsedMemoryInPercent() {
- base::SystemMemoryInfoKB info;
- if (!base::GetSystemMemoryInfo(&info)) {
- VLOG(1) << "Cannot determine the free memory of the system.";
- return 0;
- }
- // TODO(skuhne): Instead of adding the kernel memory pressure calculation
- // logic here, we should have a kernel mechanism similar to the low memory
- // notifier in ChromeOS which offers multiple pressure states.
- // To track this, we have crbug.com/381196.
-
- // The available memory consists of "real" and virtual (z)ram memory.
- // Since swappable memory uses a non pre-deterministic compression and
- // the compression creates its own "dynamic" in the system, it gets
- // de-emphasized by the |kSwapWeight| factor.
- const int kSwapWeight = 4;
-
- // The total memory we have is the "real memory" plus the virtual (z)ram.
- int total_memory = info.total + info.swap_total / kSwapWeight;
-
- // The kernel internally uses 50MB.
- const int kMinFileMemory = 50 * 1024;
-
- // Most file memory can be easily reclaimed.
- int file_memory = info.active_file + info.inactive_file;
- // unless it is dirty or it's a minimal portion which is required.
- file_memory -= info.dirty + kMinFileMemory;
-
- // Available memory is the sum of free, swap and easy reclaimable memory.
- int available_memory =
- info.free + info.swap_free / kSwapWeight + file_memory;
-
- DCHECK(available_memory < total_memory);
- int percentage = ((total_memory - available_memory) * 100) / total_memory;
- return percentage;
-}
-
-void MemoryPressureMonitor::SetDispatchCallback(
- const DispatchCallback& callback) {
- dispatch_callback_ = callback;
-}
-
-} // namespace chromeos
-} // namespace base
diff --git a/base/memory/memory_pressure_monitor_chromeos.h b/base/memory/memory_pressure_monitor_chromeos.h
deleted file mode 100644
index 563ba85081..0000000000
--- a/base/memory/memory_pressure_monitor_chromeos.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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.
-
-#ifndef BASE_MEMORY_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
-#define BASE_MEMORY_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
-
-#include "base/base_export.h"
-#include "base/files/scoped_file.h"
-#include "base/macros.h"
-#include "base/memory/memory_pressure_listener.h"
-#include "base/memory/memory_pressure_monitor.h"
-#include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
-
-namespace base {
-namespace chromeos {
-
-class TestMemoryPressureMonitor;
-
-////////////////////////////////////////////////////////////////////////////////
-// MemoryPressureMonitor
-//
-// A class to handle the observation of our free memory. It notifies the
-// MemoryPressureListener of memory fill level changes, so that it can take
-// action to reduce memory resources accordingly.
-//
-class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor {
- public:
- using GetUsedMemoryInPercentCallback = int (*)();
-
- // There are two memory pressure events:
- // MODERATE - which will mainly release caches.
- // CRITICAL - which will discard tabs.
- // The |MemoryPressureThresholds| enum selects the strategy of firing these
- // events: A conservative strategy will keep as much content in memory as
- // possible (causing the system to swap to zram) and an aggressive strategy
- // will release memory earlier to avoid swapping.
- enum MemoryPressureThresholds {
- // Use the system default.
- THRESHOLD_DEFAULT = 0,
- // Try to keep as much content in memory as possible.
- THRESHOLD_CONSERVATIVE = 1,
- // Discard caches earlier, allowing to keep more tabs in memory.
- THRESHOLD_AGGRESSIVE_CACHE_DISCARD = 2,
- // Discard tabs earlier, allowing the system to get faster.
- THRESHOLD_AGGRESSIVE_TAB_DISCARD = 3,
- // Discard caches and tabs earlier to allow the system to be faster.
- THRESHOLD_AGGRESSIVE = 4
- };
-
- explicit MemoryPressureMonitor(MemoryPressureThresholds thresholds);
- ~MemoryPressureMonitor() override;
-
- // Redo the memory pressure calculation soon and call again if a critical
- // memory pressure prevails. Note that this call will trigger an asynchronous
- // action which gives the system time to release memory back into the pool.
- void ScheduleEarlyCheck();
-
- // Get the current memory pressure level.
- MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel()
- override;
- void SetDispatchCallback(const DispatchCallback& callback) override;
-
- // Returns a type-casted version of the current memory pressure monitor. A
- // simple wrapper to base::MemoryPressureMonitor::Get.
- static MemoryPressureMonitor* Get();
-
- private:
- friend TestMemoryPressureMonitor;
- // Starts observing the memory fill level.
- // Calls to StartObserving should always be matched with calls to
- // StopObserving.
- void StartObserving();
-
- // Stop observing the memory fill level.
- // May be safely called if StartObserving has not been called.
- void StopObserving();
-
- // The function which gets periodically called to check any changes in the
- // memory pressure. It will report pressure changes as well as continuous
- // critical pressure levels.
- void CheckMemoryPressure();
-
- // The function periodically checks the memory pressure changes and records
- // the UMA histogram statistics for the current memory pressure level.
- void CheckMemoryPressureAndRecordStatistics();
-
- // Get the memory pressure in percent (virtual for testing).
- virtual int GetUsedMemoryInPercent();
-
- // The current memory pressure.
- base::MemoryPressureListener::MemoryPressureLevel
- current_memory_pressure_level_;
-
- // A periodic timer to check for resource pressure changes. This will get
- // replaced by a kernel triggered event system (see crbug.com/381196).
- base::RepeatingTimer timer_;
-
- // To slow down the amount of moderate pressure event calls, this counter
- // gets used to count the number of events since the last event occured.
- int moderate_pressure_repeat_count_;
-
- // The "Memory.PressureLevel" statistic is recorded every
- // 5 seconds, but the timer to report "ChromeOS.MemoryPressureLevel"
- // fires every second. This counter is used to allow reporting
- // "Memory.PressureLevel" correctly without adding another
- // timer.
- int seconds_since_reporting_;
-
- // The thresholds for moderate and critical pressure.
- const int moderate_pressure_threshold_percent_;
- const int critical_pressure_threshold_percent_;
-
- // File descriptor used to detect low memory condition.
- ScopedFD low_mem_file_;
-
- DispatchCallback dispatch_callback_;
-
- base::WeakPtrFactory<MemoryPressureMonitor> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor);
-};
-
-} // namespace chromeos
-} // namespace base
-
-#endif // BASE_MEMORY_MEMORY_PRESSURE_MONITOR_CHROMEOS_H_
diff --git a/base/memory/memory_pressure_monitor_chromeos_unittest.cc b/base/memory/memory_pressure_monitor_chromeos_unittest.cc
deleted file mode 100644
index ee000911ea..0000000000
--- a/base/memory/memory_pressure_monitor_chromeos_unittest.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// 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/memory/memory_pressure_monitor_chromeos.h"
-
-#include "base/macros.h"
-#include "base/memory/memory_pressure_listener.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/sys_info.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace chromeos {
-
-namespace {
-
-// True if the memory notifier got called.
-// Do not read/modify value directly.
-bool on_memory_pressure_called = false;
-
-// If the memory notifier got called, this is the memory pressure reported.
-MemoryPressureListener::MemoryPressureLevel on_memory_pressure_level =
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
-
-// Processes OnMemoryPressure calls.
-void OnMemoryPressure(MemoryPressureListener::MemoryPressureLevel level) {
- on_memory_pressure_called = true;
- on_memory_pressure_level = level;
-}
-
-// Resets the indicator for memory pressure.
-void ResetOnMemoryPressureCalled() {
- on_memory_pressure_called = false;
-}
-
-// Returns true when OnMemoryPressure was called (and resets it).
-bool WasOnMemoryPressureCalled() {
- bool b = on_memory_pressure_called;
- ResetOnMemoryPressureCalled();
- return b;
-}
-
-} // namespace
-
-class TestMemoryPressureMonitor : public MemoryPressureMonitor {
- public:
- TestMemoryPressureMonitor()
- : MemoryPressureMonitor(THRESHOLD_DEFAULT),
- memory_in_percent_override_(0) {
- // Disable any timers which are going on and set a special memory reporting
- // function.
- StopObserving();
- }
- ~TestMemoryPressureMonitor() override = default;
-
- void SetMemoryInPercentOverride(int percent) {
- memory_in_percent_override_ = percent;
- }
-
- void CheckMemoryPressureForTest() {
- CheckMemoryPressure();
- }
-
- private:
- int GetUsedMemoryInPercent() override {
- return memory_in_percent_override_;
- }
-
- int memory_in_percent_override_;
- DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
-};
-
-// This test tests the various transition states from memory pressure, looking
-// for the correct behavior on event reposting as well as state updates.
-TEST(ChromeOSMemoryPressureMonitorTest, CheckMemoryPressure) {
- // crbug.com/844102:
- if (base::SysInfo::IsRunningOnChromeOS())
- return;
-
- base::MessageLoopForUI message_loop;
- std::unique_ptr<TestMemoryPressureMonitor> monitor(
- new TestMemoryPressureMonitor);
- std::unique_ptr<MemoryPressureListener> listener(
- new MemoryPressureListener(base::Bind(&OnMemoryPressure)));
- // Checking the memory pressure while 0% are used should not produce any
- // events.
- monitor->SetMemoryInPercentOverride(0);
- ResetOnMemoryPressureCalled();
-
- monitor->CheckMemoryPressureForTest();
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(WasOnMemoryPressureCalled());
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- monitor->GetCurrentPressureLevel());
-
- // Setting the memory level to 80% should produce a moderate pressure level.
- monitor->SetMemoryInPercentOverride(80);
- monitor->CheckMemoryPressureForTest();
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(WasOnMemoryPressureCalled());
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor->GetCurrentPressureLevel());
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- on_memory_pressure_level);
-
- // We need to check that the event gets reposted after a while.
- int i = 0;
- for (; i < 100; i++) {
- monitor->CheckMemoryPressureForTest();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor->GetCurrentPressureLevel());
- if (WasOnMemoryPressureCalled()) {
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- on_memory_pressure_level);
- break;
- }
- }
- // Should be more than 5 and less than 100.
- EXPECT_LE(5, i);
- EXPECT_GE(99, i);
-
- // Setting the memory usage to 99% should produce critical levels.
- monitor->SetMemoryInPercentOverride(99);
- monitor->CheckMemoryPressureForTest();
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(WasOnMemoryPressureCalled());
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- on_memory_pressure_level);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- monitor->GetCurrentPressureLevel());
-
- // Calling it again should immediately produce a second call.
- monitor->CheckMemoryPressureForTest();
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(WasOnMemoryPressureCalled());
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- on_memory_pressure_level);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- monitor->GetCurrentPressureLevel());
-
- // When lowering the pressure again we should not get an event, but the
- // pressure should go back to moderate.
- monitor->SetMemoryInPercentOverride(80);
- monitor->CheckMemoryPressureForTest();
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(WasOnMemoryPressureCalled());
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor->GetCurrentPressureLevel());
-
- // We should need exactly the same amount of calls as before, before the next
- // call comes in.
- int j = 0;
- for (; j < 100; j++) {
- monitor->CheckMemoryPressureForTest();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor->GetCurrentPressureLevel());
- if (WasOnMemoryPressureCalled()) {
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- on_memory_pressure_level);
- break;
- }
- }
- // We should have needed exactly the same amount of checks as before.
- EXPECT_EQ(j, i);
-}
-
-} // namespace chromeos
-} // namespace base
diff --git a/base/memory/memory_pressure_monitor_unittest.cc b/base/memory/memory_pressure_monitor_unittest.cc
deleted file mode 100644
index 10d9d2428f..0000000000
--- a/base/memory/memory_pressure_monitor_unittest.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 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/memory/memory_pressure_monitor.h"
-
-#include "base/macros.h"
-#include "base/memory/memory_pressure_listener.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(MemoryPressureMonitorTest, RecordMemoryPressure) {
- base::HistogramTester tester;
- const char* kHistogram = "Memory.PressureLevel";
-
- MemoryPressureMonitor::RecordMemoryPressure(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, 3);
- tester.ExpectTotalCount(kHistogram, 3);
- tester.ExpectBucketCount(kHistogram, 0, 3);
-
- MemoryPressureMonitor::RecordMemoryPressure(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, 2);
- tester.ExpectTotalCount(kHistogram, 5);
- tester.ExpectBucketCount(kHistogram, 1, 2);
-
- MemoryPressureMonitor::RecordMemoryPressure(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, 1);
- tester.ExpectTotalCount(kHistogram, 6);
- tester.ExpectBucketCount(kHistogram, 2, 1);
-}
-} // namespace base
diff --git a/base/memory/platform_shared_memory_region_android.cc b/base/memory/platform_shared_memory_region_android.cc
deleted file mode 100644
index 154e9e52df..0000000000
--- a/base/memory/platform_shared_memory_region_android.cc
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright 2018 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/memory/platform_shared_memory_region.h"
-
-#include <sys/mman.h>
-
-#include "base/posix/eintr_wrapper.h"
-#include "third_party/ashmem/ashmem.h"
-
-namespace base {
-namespace subtle {
-
-// For Android, we use ashmem to implement SharedMemory. ashmem_create_region
-// will automatically pin the region. We never explicitly call pin/unpin. When
-// all the file descriptors from different processes associated with the region
-// are closed, the memory buffer will go away.
-
-namespace {
-
-static int GetAshmemRegionProtectionMask(int fd) {
- int prot = ashmem_get_prot_region(fd);
- if (prot < 0) {
- DPLOG(ERROR) << "ashmem_get_prot_region failed";
- return -1;
- }
- return prot;
-}
-
-} // namespace
-
-// static
-PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Take(
- ScopedFD fd,
- Mode mode,
- size_t size,
- const UnguessableToken& guid) {
- if (!fd.is_valid())
- return {};
-
- if (size == 0)
- return {};
-
- if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
- return {};
-
- CHECK(CheckPlatformHandlePermissionsCorrespondToMode(fd.get(), mode, size));
-
- return PlatformSharedMemoryRegion(std::move(fd), mode, size, guid);
-}
-
-int PlatformSharedMemoryRegion::GetPlatformHandle() const {
- return handle_.get();
-}
-
-bool PlatformSharedMemoryRegion::IsValid() const {
- return handle_.is_valid();
-}
-
-PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Duplicate() const {
- if (!IsValid())
- return {};
-
- CHECK_NE(mode_, Mode::kWritable)
- << "Duplicating a writable shared memory region is prohibited";
-
- ScopedFD duped_fd(HANDLE_EINTR(dup(handle_.get())));
- if (!duped_fd.is_valid()) {
- DPLOG(ERROR) << "dup(" << handle_.get() << ") failed";
- return {};
- }
-
- return PlatformSharedMemoryRegion(std::move(duped_fd), mode_, size_, guid_);
-}
-
-bool PlatformSharedMemoryRegion::ConvertToReadOnly() {
- if (!IsValid())
- return false;
-
- CHECK_EQ(mode_, Mode::kWritable)
- << "Only writable shared memory region can be converted to read-only";
-
- ScopedFD handle_copy(handle_.release());
-
- int prot = GetAshmemRegionProtectionMask(handle_copy.get());
- if (prot < 0)
- return false;
-
- prot &= ~PROT_WRITE;
- int ret = ashmem_set_prot_region(handle_copy.get(), prot);
- if (ret != 0) {
- DPLOG(ERROR) << "ashmem_set_prot_region failed";
- return false;
- }
-
- handle_ = std::move(handle_copy);
- mode_ = Mode::kReadOnly;
- return true;
-}
-
-bool PlatformSharedMemoryRegion::ConvertToUnsafe() {
- if (!IsValid())
- return false;
-
- CHECK_EQ(mode_, Mode::kWritable)
- << "Only writable shared memory region can be converted to unsafe";
-
- mode_ = Mode::kUnsafe;
- return true;
-}
-
-bool PlatformSharedMemoryRegion::MapAt(off_t offset,
- size_t size,
- void** memory,
- size_t* mapped_size) const {
- if (!IsValid())
- return false;
-
- size_t end_byte;
- if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) {
- return false;
- }
-
- bool write_allowed = mode_ != Mode::kReadOnly;
- *memory = mmap(nullptr, size, PROT_READ | (write_allowed ? PROT_WRITE : 0),
- MAP_SHARED, handle_.get(), offset);
-
- bool mmap_succeeded = *memory && *memory != reinterpret_cast<void*>(-1);
- if (!mmap_succeeded) {
- DPLOG(ERROR) << "mmap " << handle_.get() << " failed";
- return false;
- }
-
- *mapped_size = size;
- DCHECK_EQ(0U,
- reinterpret_cast<uintptr_t>(*memory) & (kMapMinimumAlignment - 1));
- return true;
-}
-
-// static
-PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode,
- size_t size) {
- if (size == 0)
- return {};
-
- if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
- return {};
-
- CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will "
- "lead to this region being non-modifiable";
-
- UnguessableToken guid = UnguessableToken::Create();
-
- // trace_event is not supported in libchrome. To avoid includes of more
- // trace_event code by base/memory/shared_memory_tracker.h, replace
- // SharedMemoryTracker::GetDumpNameForTracing by the actual implementation.
- ScopedFD fd(ashmem_create_region(
- ("shared_memory/"+guid.ToString()).c_str(), size));
- if (!fd.is_valid()) {
- DPLOG(ERROR) << "ashmem_create_region failed";
- return {};
- }
-
- int err = ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE);
- if (err < 0) {
- DPLOG(ERROR) << "ashmem_set_prot_region failed";
- return {};
- }
-
- return PlatformSharedMemoryRegion(std::move(fd), mode, size, guid);
-}
-
-bool PlatformSharedMemoryRegion::CheckPlatformHandlePermissionsCorrespondToMode(
- PlatformHandle handle,
- Mode mode,
- size_t size) {
- int prot = GetAshmemRegionProtectionMask(handle);
- if (prot < 0)
- return false;
-
- bool is_read_only = (prot & PROT_WRITE) == 0;
- bool expected_read_only = mode == Mode::kReadOnly;
-
- if (is_read_only != expected_read_only) {
- DLOG(ERROR) << "Ashmem region has a wrong protection mask: it is"
- << (is_read_only ? " " : " not ") << "read-only but it should"
- << (expected_read_only ? " " : " not ") << "be";
- return false;
- }
-
- return true;
-}
-
-PlatformSharedMemoryRegion::PlatformSharedMemoryRegion(
- ScopedFD fd,
- Mode mode,
- size_t size,
- const UnguessableToken& guid)
- : handle_(std::move(fd)), mode_(mode), size_(size), guid_(guid) {}
-
-} // namespace subtle
-} // namespace base
diff --git a/base/memory/platform_shared_memory_region_mac.cc b/base/memory/platform_shared_memory_region_mac.cc
new file mode 100644
index 0000000000..4a8b440c26
--- /dev/null
+++ b/base/memory/platform_shared_memory_region_mac.cc
@@ -0,0 +1,233 @@
+// Copyright 2018 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/memory/platform_shared_memory_region.h"
+
+#include <mach/mach_vm.h>
+
+#include "base/mac/mach_logging.h"
+#include "base/mac/scoped_mach_vm.h"
+#include "base/numerics/checked_math.h"
+#include "build/build_config.h"
+
+#if defined(OS_IOS)
+#error "MacOS only - iOS uses platform_shared_memory_region_posix.cc"
+#endif
+
+namespace base {
+namespace subtle {
+
+// static
+PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Take(
+ mac::ScopedMachSendRight handle,
+ Mode mode,
+ size_t size,
+ const UnguessableToken& guid) {
+ if (!handle.is_valid())
+ return {};
+
+ if (size == 0)
+ return {};
+
+ if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
+ return {};
+
+ CHECK(
+ CheckPlatformHandlePermissionsCorrespondToMode(handle.get(), mode, size));
+
+ return PlatformSharedMemoryRegion(std::move(handle), mode, size, guid);
+}
+
+mach_port_t PlatformSharedMemoryRegion::GetPlatformHandle() const {
+ return handle_.get();
+}
+
+bool PlatformSharedMemoryRegion::IsValid() const {
+ return handle_.is_valid();
+}
+
+PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Duplicate() const {
+ if (!IsValid())
+ return {};
+
+ CHECK_NE(mode_, Mode::kWritable)
+ << "Duplicating a writable shared memory region is prohibited";
+
+ // Increment the ref count.
+ kern_return_t kr = mach_port_mod_refs(mach_task_self(), handle_.get(),
+ MACH_PORT_RIGHT_SEND, 1);
+ if (kr != KERN_SUCCESS) {
+ MACH_DLOG(ERROR, kr) << "mach_port_mod_refs";
+ return {};
+ }
+
+ return PlatformSharedMemoryRegion(mac::ScopedMachSendRight(handle_.get()),
+ mode_, size_, guid_);
+}
+
+bool PlatformSharedMemoryRegion::ConvertToReadOnly() {
+ return ConvertToReadOnly(nullptr);
+}
+
+bool PlatformSharedMemoryRegion::ConvertToReadOnly(void* mapped_addr) {
+ if (!IsValid())
+ return false;
+
+ CHECK_EQ(mode_, Mode::kWritable)
+ << "Only writable shared memory region can be converted to read-only";
+
+ mac::ScopedMachSendRight handle_copy(handle_.release());
+
+ void* temp_addr = mapped_addr;
+ mac::ScopedMachVM scoped_memory;
+ if (!temp_addr) {
+ // Intentionally lower current prot and max prot to |VM_PROT_READ|.
+ kern_return_t kr = mach_vm_map(
+ mach_task_self(), reinterpret_cast<mach_vm_address_t*>(&temp_addr),
+ size_, 0, VM_FLAGS_ANYWHERE, handle_copy.get(), 0, FALSE, VM_PROT_READ,
+ VM_PROT_READ, VM_INHERIT_NONE);
+ if (kr != KERN_SUCCESS) {
+ MACH_DLOG(ERROR, kr) << "mach_vm_map";
+ return false;
+ }
+ scoped_memory.reset(reinterpret_cast<vm_address_t>(temp_addr),
+ mach_vm_round_page(size_));
+ }
+
+ // Make new memory object.
+ memory_object_size_t allocation_size = size_;
+ mac::ScopedMachSendRight named_right;
+ kern_return_t kr = mach_make_memory_entry_64(
+ mach_task_self(), &allocation_size,
+ reinterpret_cast<memory_object_offset_t>(temp_addr), VM_PROT_READ,
+ named_right.receive(), MACH_PORT_NULL);
+ if (kr != KERN_SUCCESS) {
+ MACH_DLOG(ERROR, kr) << "mach_make_memory_entry_64";
+ return false;
+ }
+ DCHECK_GE(allocation_size, size_);
+
+ handle_ = std::move(named_right);
+ mode_ = Mode::kReadOnly;
+ return true;
+}
+
+bool PlatformSharedMemoryRegion::ConvertToUnsafe() {
+ if (!IsValid())
+ return false;
+
+ CHECK_EQ(mode_, Mode::kWritable)
+ << "Only writable shared memory region can be converted to unsafe";
+
+ mode_ = Mode::kUnsafe;
+ return true;
+}
+
+bool PlatformSharedMemoryRegion::MapAt(off_t offset,
+ size_t size,
+ void** memory,
+ size_t* mapped_size) const {
+ if (!IsValid())
+ return false;
+
+ size_t end_byte;
+ if (!CheckAdd(offset, size).AssignIfValid(&end_byte) || end_byte > size_) {
+ return false;
+ }
+
+ bool write_allowed = mode_ != Mode::kReadOnly;
+ vm_prot_t vm_prot_write = write_allowed ? VM_PROT_WRITE : 0;
+ kern_return_t kr = mach_vm_map(
+ mach_task_self(),
+ reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter
+ size,
+ 0, // Alignment mask
+ VM_FLAGS_ANYWHERE, handle_.get(), offset,
+ FALSE, // Copy
+ VM_PROT_READ | vm_prot_write, // Current protection
+ VM_PROT_READ | vm_prot_write, // Maximum protection
+ VM_INHERIT_NONE);
+ if (kr != KERN_SUCCESS) {
+ MACH_DLOG(ERROR, kr) << "mach_vm_map";
+ return false;
+ }
+
+ *mapped_size = size;
+ DCHECK_EQ(0U,
+ reinterpret_cast<uintptr_t>(*memory) & (kMapMinimumAlignment - 1));
+ return true;
+}
+
+// static
+PlatformSharedMemoryRegion PlatformSharedMemoryRegion::Create(Mode mode,
+ size_t size) {
+ if (size == 0)
+ return {};
+
+ if (size > static_cast<size_t>(std::numeric_limits<int>::max()))
+ return {};
+
+ CHECK_NE(mode, Mode::kReadOnly) << "Creating a region in read-only mode will "
+ "lead to this region being non-modifiable";
+
+ mach_vm_size_t vm_size = size;
+ mac::ScopedMachSendRight named_right;
+ kern_return_t kr = mach_make_memory_entry_64(
+ mach_task_self(), &vm_size,
+ 0, // Address.
+ MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE,
+ named_right.receive(),
+ MACH_PORT_NULL); // Parent handle.
+ if (kr != KERN_SUCCESS) {
+ MACH_DLOG(ERROR, kr) << "mach_make_memory_entry_64";
+ return {};
+ }
+ DCHECK_GE(vm_size, size);
+
+ return PlatformSharedMemoryRegion(std::move(named_right), mode, size,
+ UnguessableToken::Create());
+}
+
+// static
+bool PlatformSharedMemoryRegion::CheckPlatformHandlePermissionsCorrespondToMode(
+ PlatformHandle handle,
+ Mode mode,
+ size_t size) {
+ mach_vm_address_t temp_addr = 0;
+ kern_return_t kr =
+ mach_vm_map(mach_task_self(), &temp_addr, size, 0, VM_FLAGS_ANYWHERE,
+ handle, 0, FALSE, VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_READ | VM_PROT_WRITE, VM_INHERIT_NONE);
+ if (kr == KERN_SUCCESS) {
+ kern_return_t kr_deallocate =
+ mach_vm_deallocate(mach_task_self(), temp_addr, size);
+ MACH_DLOG_IF(ERROR, kr_deallocate != KERN_SUCCESS, kr_deallocate)
+ << "mach_vm_deallocate";
+ } else if (kr != KERN_INVALID_RIGHT) {
+ MACH_DLOG(ERROR, kr) << "mach_vm_map";
+ return false;
+ }
+
+ bool is_read_only = kr == KERN_INVALID_RIGHT;
+ bool expected_read_only = mode == Mode::kReadOnly;
+
+ if (is_read_only != expected_read_only) {
+ DLOG(ERROR) << "VM region has a wrong protection mask: it is"
+ << (is_read_only ? " " : " not ") << "read-only but it should"
+ << (expected_read_only ? " " : " not ") << "be";
+ return false;
+ }
+
+ return true;
+}
+
+PlatformSharedMemoryRegion::PlatformSharedMemoryRegion(
+ mac::ScopedMachSendRight handle,
+ Mode mode,
+ size_t size,
+ const UnguessableToken& guid)
+ : handle_(std::move(handle)), mode_(mode), size_(size), guid_(guid) {}
+
+} // namespace subtle
+} // namespace base
diff --git a/base/memory/ptr_util_unittest.cc b/base/memory/ptr_util_unittest.cc
deleted file mode 100644
index 3fa40d8098..0000000000
--- a/base/memory/ptr_util_unittest.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 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/memory/ptr_util.h"
-
-#include <stddef.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class DeleteCounter {
- public:
- DeleteCounter() { ++count_; }
- ~DeleteCounter() { --count_; }
-
- static size_t count() { return count_; }
-
- private:
- static size_t count_;
-};
-
-size_t DeleteCounter::count_ = 0;
-
-} // namespace
-
-TEST(PtrUtilTest, WrapUnique) {
- EXPECT_EQ(0u, DeleteCounter::count());
- DeleteCounter* counter = new DeleteCounter;
- EXPECT_EQ(1u, DeleteCounter::count());
- std::unique_ptr<DeleteCounter> owned_counter = WrapUnique(counter);
- EXPECT_EQ(1u, DeleteCounter::count());
- owned_counter.reset();
- EXPECT_EQ(0u, DeleteCounter::count());
-}
-
-} // namespace base
diff --git a/base/memory/ref_counted_unittest.nc b/base/memory/ref_counted_unittest.nc
deleted file mode 100644
index b8c371f748..0000000000
--- a/base/memory/ref_counted_unittest.nc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 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/memory/ref_counted.h"
-
-namespace base {
-
-class InitialRefCountIsZero : public base::RefCounted<InitialRefCountIsZero> {
- public:
- InitialRefCountIsZero() {}
- private:
- friend class base::RefCounted<InitialRefCountIsZero>;
- ~InitialRefCountIsZero() {}
-};
-
-// TODO(hans): Remove .* and update the static_assert expectations once we roll
-// past Clang r313315. https://crbug.com/765692.
-
-#if defined(NCTEST_ADOPT_REF_TO_ZERO_START) // [r"fatal error: static_assert failed .*\"Use AdoptRef only for the reference count starts from one\.\""]
-
-void WontCompile() {
- AdoptRef(new InitialRefCountIsZero());
-}
-
-#endif
-
-} // namespace base
diff --git a/base/memory/shared_memory_handle.h b/base/memory/shared_memory_handle.h
index dd3d47aa0c..7367188c8b 100644
--- a/base/memory/shared_memory_handle.h
+++ b/base/memory/shared_memory_handle.h
@@ -146,7 +146,7 @@ class BASE_EXPORT SharedMemoryHandle {
int Release();
#endif
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(__ANDROID__)
// Marks the current file descriptor as read-only, for the purpose of
// mapping. This is independent of the region's read-only status.
void SetReadOnly() { read_only_ = true; }
@@ -218,7 +218,7 @@ class BASE_EXPORT SharedMemoryHandle {
bool ownership_passes_to_ipc_ = false;
};
};
-#elif defined(OS_ANDROID)
+#elif defined(OS_ANDROID) || defined(__ANDROID__)
friend class SharedMemory;
FileDescriptor file_descriptor_;
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc
index 6b811b9f66..aa718957cf 100644
--- a/base/memory/shared_memory_posix.cc
+++ b/base/memory/shared_memory_posix.cc
@@ -30,6 +30,8 @@
#if defined(OS_ANDROID)
#include "base/os_compat_android.h"
+#endif
+#if defined(OS_ANDROID) || defined(__ANDROID__)
#include "third_party/ashmem/ashmem.h"
#endif
@@ -81,7 +83,7 @@ bool SharedMemory::CreateAndMapAnonymous(size_t size) {
return CreateAnonymous(size) && Map(size);
}
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) && !defined(__ANDROID__)
// Chromium mostly only uses the unique/private shmem as specified by
// "name == L"". The exception is in the StatsTable.
@@ -253,7 +255,7 @@ bool SharedMemory::Open(const std::string& name, bool read_only) {
FileDescriptor(readonly_mapped_file, false), 0, shm_.GetGUID());
return result;
}
-#endif // !defined(OS_ANDROID)
+#endif // !defined(OS_ANDROID) && !defined(__ANDROID__)
bool SharedMemory::MapAt(off_t offset, size_t bytes) {
if (!shm_.IsValid())
@@ -265,7 +267,7 @@ bool SharedMemory::MapAt(off_t offset, size_t bytes) {
if (memory_)
return false;
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(__ANDROID__)
// On Android, Map can be called with a size and offset of zero to use the
// ashmem-determined size.
if (bytes == 0) {
@@ -278,19 +280,19 @@ bool SharedMemory::MapAt(off_t offset, size_t bytes) {
// Sanity check. This shall catch invalid uses of the SharedMemory APIs
// but will not protect against direct mmap() attempts.
- if (shm_.IsReadOnly()) {
- // Use a DCHECK() to call writable mappings with read-only descriptors
- // in debug builds immediately. Return an error for release builds
- // or during unit-testing (assuming a ScopedLogAssertHandler was installed).
- DCHECK(read_only_)
- << "Trying to map a region writable with a read-only descriptor.";
- if (!read_only_) {
- return false;
- }
- if (!shm_.SetRegionReadOnly()) { // Ensure the region is read-only.
- return false;
- }
- }
+ // if (shm_.IsReadOnly()) {
+ // // Use a DCHECK() to call writable mappings with read-only descriptors
+ // // in debug builds immediately. Return an error for release builds
+ // // or during unit-testing (assuming a ScopedLogAssertHandler was installed).
+ // DCHECK(read_only_)
+ // << "Trying to map a region writable with a read-only descriptor.";
+ // if (!read_only_) {
+ // return false;
+ // }
+ // if (!shm_.SetRegionReadOnly()) { // Ensure the region is read-only.
+ // return false;
+ // }
+ // }
#endif
memory_ = mmap(nullptr, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
@@ -337,7 +339,7 @@ SharedMemoryHandle SharedMemory::TakeHandle() {
return handle_copy;
}
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) && !defined(__ANDROID__)
void SharedMemory::Close() {
if (shm_.IsValid()) {
shm_.Close();
@@ -377,6 +379,6 @@ SharedMemoryHandle SharedMemory::GetReadOnlyHandle() const {
CHECK(readonly_shm_.IsValid());
return readonly_shm_.Duplicate();
}
-#endif // !defined(OS_ANDROID)
+#endif // !defined(OS_ANDROID) && !defined(__ANDROID__)
} // namespace base
diff --git a/base/memory/shared_memory_tracker.cc b/base/memory/shared_memory_tracker.cc
deleted file mode 100644
index 5ca7c840be..0000000000
--- a/base/memory/shared_memory_tracker.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2017 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/memory/shared_memory_tracker.h"
-
-#include "base/memory/shared_memory.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/trace_event/memory_allocator_dump_guid.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/process_memory_dump.h"
-
-namespace base {
-
-const char SharedMemoryTracker::kDumpRootName[] = "shared_memory";
-
-// static
-SharedMemoryTracker* SharedMemoryTracker::GetInstance() {
- static SharedMemoryTracker* instance = new SharedMemoryTracker;
- return instance;
-}
-
-// static
-std::string SharedMemoryTracker::GetDumpNameForTracing(
- const UnguessableToken& id) {
- DCHECK(!id.is_empty());
- return std::string(kDumpRootName) + "/" + id.ToString();
-}
-
-// static
-trace_event::MemoryAllocatorDumpGuid
-SharedMemoryTracker::GetGlobalDumpIdForTracing(const UnguessableToken& id) {
- std::string dump_name = GetDumpNameForTracing(id);
- return trace_event::MemoryAllocatorDumpGuid(dump_name);
-}
-
-// static
-const trace_event::MemoryAllocatorDump*
-SharedMemoryTracker::GetOrCreateSharedMemoryDump(
- const SharedMemory* shared_memory,
- trace_event::ProcessMemoryDump* pmd) {
- return GetOrCreateSharedMemoryDumpInternal(shared_memory->memory(),
- shared_memory->mapped_size(),
- shared_memory->mapped_id(), pmd);
-}
-
-const trace_event::MemoryAllocatorDump*
-SharedMemoryTracker::GetOrCreateSharedMemoryDump(
- const SharedMemoryMapping& shared_memory,
- trace_event::ProcessMemoryDump* pmd) {
- return GetOrCreateSharedMemoryDumpInternal(shared_memory.raw_memory_ptr(),
- shared_memory.mapped_size(),
- shared_memory.guid(), pmd);
-}
-
-void SharedMemoryTracker::IncrementMemoryUsage(
- const SharedMemory& shared_memory) {
- AutoLock hold(usages_lock_);
- DCHECK(usages_.find(shared_memory.memory()) == usages_.end());
- usages_.emplace(shared_memory.memory(), UsageInfo(shared_memory.mapped_size(),
- shared_memory.mapped_id()));
-}
-
-void SharedMemoryTracker::IncrementMemoryUsage(
- const SharedMemoryMapping& mapping) {
- AutoLock hold(usages_lock_);
- DCHECK(usages_.find(mapping.raw_memory_ptr()) == usages_.end());
- usages_.emplace(mapping.raw_memory_ptr(),
- UsageInfo(mapping.mapped_size(), mapping.guid()));
-}
-
-void SharedMemoryTracker::DecrementMemoryUsage(
- const SharedMemory& shared_memory) {
- AutoLock hold(usages_lock_);
- DCHECK(usages_.find(shared_memory.memory()) != usages_.end());
- usages_.erase(shared_memory.memory());
-}
-
-void SharedMemoryTracker::DecrementMemoryUsage(
- const SharedMemoryMapping& mapping) {
- AutoLock hold(usages_lock_);
- DCHECK(usages_.find(mapping.raw_memory_ptr()) != usages_.end());
- usages_.erase(mapping.raw_memory_ptr());
-}
-
-SharedMemoryTracker::SharedMemoryTracker() {
- trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
- this, "SharedMemoryTracker", nullptr);
-}
-
-SharedMemoryTracker::~SharedMemoryTracker() = default;
-
-bool SharedMemoryTracker::OnMemoryDump(const trace_event::MemoryDumpArgs& args,
- trace_event::ProcessMemoryDump* pmd) {
- AutoLock hold(usages_lock_);
- for (const auto& usage : usages_) {
- const trace_event::MemoryAllocatorDump* dump =
- GetOrCreateSharedMemoryDumpInternal(
- usage.first, usage.second.mapped_size, usage.second.mapped_id, pmd);
- DCHECK(dump);
- }
- return true;
-}
-
-// static
-const trace_event::MemoryAllocatorDump*
-SharedMemoryTracker::GetOrCreateSharedMemoryDumpInternal(
- void* mapped_memory,
- size_t mapped_size,
- const UnguessableToken& mapped_id,
- trace_event::ProcessMemoryDump* pmd) {
- const std::string dump_name = GetDumpNameForTracing(mapped_id);
- trace_event::MemoryAllocatorDump* local_dump =
- pmd->GetAllocatorDump(dump_name);
- if (local_dump)
- return local_dump;
-
- size_t virtual_size = mapped_size;
- // If resident size is not available, a virtual size is used as fallback.
- size_t size = virtual_size;
-#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
- base::Optional<size_t> resident_size =
- trace_event::ProcessMemoryDump::CountResidentBytesInSharedMemory(
- mapped_memory, mapped_size);
- if (resident_size.has_value())
- size = resident_size.value();
-#endif
-
- local_dump = pmd->CreateAllocatorDump(dump_name);
- local_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize,
- trace_event::MemoryAllocatorDump::kUnitsBytes, size);
- local_dump->AddScalar("virtual_size",
- trace_event::MemoryAllocatorDump::kUnitsBytes,
- virtual_size);
- auto global_dump_guid = GetGlobalDumpIdForTracing(mapped_id);
- trace_event::MemoryAllocatorDump* global_dump =
- pmd->CreateSharedGlobalAllocatorDump(global_dump_guid);
- global_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize,
- trace_event::MemoryAllocatorDump::kUnitsBytes, size);
-
- // The edges will be overriden by the clients with correct importance.
- pmd->AddOverridableOwnershipEdge(local_dump->guid(), global_dump->guid(),
- 0 /* importance */);
- return local_dump;
-}
-
-} // namespace
diff --git a/base/memory/shared_memory_tracker.h b/base/memory/shared_memory_tracker.h
deleted file mode 100644
index 499b1728cb..0000000000
--- a/base/memory/shared_memory_tracker.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_MEMORY_SHARED_MEMORY_TRACKER_H_
-#define BASE_MEMORY_SHARED_MEMORY_TRACKER_H_
-
-#include <map>
-#include <string>
-
-#include "base/memory/shared_memory.h"
-#include "base/memory/shared_memory_mapping.h"
-#include "base/synchronization/lock.h"
-#include "base/trace_event/memory_dump_provider.h"
-
-namespace base {
-
-namespace trace_event {
-class MemoryAllocatorDump;
-class MemoryAllocatorDumpGuid;
-class ProcessMemoryDump;
-}
-
-// SharedMemoryTracker tracks shared memory usage.
-class BASE_EXPORT SharedMemoryTracker : public trace_event::MemoryDumpProvider {
- public:
- // Returns a singleton instance.
- static SharedMemoryTracker* GetInstance();
-
- static std::string GetDumpNameForTracing(const UnguessableToken& id);
-
- static trace_event::MemoryAllocatorDumpGuid GetGlobalDumpIdForTracing(
- const UnguessableToken& id);
-
- // Gets or creates if non-existant, a memory dump for the |shared_memory|
- // inside the given |pmd|. Also adds the necessary edges for the dump when
- // creating the dump.
- static const trace_event::MemoryAllocatorDump* GetOrCreateSharedMemoryDump(
- const SharedMemory* shared_memory,
- trace_event::ProcessMemoryDump* pmd);
- // We're in the middle of a refactor https://crbug.com/795291. Eventually, the
- // first call will go away.
- static const trace_event::MemoryAllocatorDump* GetOrCreateSharedMemoryDump(
- const SharedMemoryMapping& shared_memory,
- trace_event::ProcessMemoryDump* pmd);
-
- // Records shared memory usage on valid mapping.
- void IncrementMemoryUsage(const SharedMemory& shared_memory);
- void IncrementMemoryUsage(const SharedMemoryMapping& mapping);
-
- // Records shared memory usage on unmapping.
- void DecrementMemoryUsage(const SharedMemory& shared_memory);
- void DecrementMemoryUsage(const SharedMemoryMapping& mapping);
-
- // Root dump name for all shared memory dumps.
- static const char kDumpRootName[];
-
- private:
- SharedMemoryTracker();
- ~SharedMemoryTracker() override;
-
- // trace_event::MemoryDumpProvider implementation.
- bool OnMemoryDump(const trace_event::MemoryDumpArgs& args,
- trace_event::ProcessMemoryDump* pmd) override;
-
- static const trace_event::MemoryAllocatorDump*
- GetOrCreateSharedMemoryDumpInternal(void* mapped_memory,
- size_t mapped_size,
- const UnguessableToken& mapped_id,
- trace_event::ProcessMemoryDump* pmd);
-
- // Information associated with each mapped address.
- struct UsageInfo {
- UsageInfo(size_t size, const UnguessableToken& id)
- : mapped_size(size), mapped_id(id) {}
-
- size_t mapped_size;
- UnguessableToken mapped_id;
- };
-
- // Used to lock when |usages_| is modified or read.
- Lock usages_lock_;
- std::map<void*, UsageInfo> usages_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedMemoryTracker);
-};
-
-} // namespace base
-
-#endif // BASE_MEMORY_SHARED_MEMORY_TRACKER_H_
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 9149a672d9..b3e32de0ef 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -243,7 +243,6 @@ bool MessageLoop::InitMessagePumpForUIFactory(MessagePumpFactory* factory) {
// static
std::unique_ptr<MessagePump> MessageLoop::CreateMessagePumpForType(Type type) {
-#if !defined(OS_ANDROID)
if (type == MessageLoop::TYPE_UI) {
if (message_pump_for_ui_factory_)
return message_pump_for_ui_factory_();
@@ -258,12 +257,11 @@ std::unique_ptr<MessagePump> MessageLoop::CreateMessagePumpForType(Type type) {
return std::make_unique<MessagePumpForUI>();
#endif
}
-#endif
if (type == MessageLoop::TYPE_IO)
return std::unique_ptr<MessagePump>(new MessagePumpForIO());
-#if defined(OS_ANDROID) && 0
+#if defined(OS_ANDROID)
if (type == MessageLoop::TYPE_JAVA)
return std::unique_ptr<MessagePump>(new MessagePumpForUI());
#endif
@@ -362,7 +360,7 @@ void MessageLoop::BindToCurrentThread() {
RunLoop::RegisterDelegateForCurrentThread(this);
-#if defined(OS_ANDROID) && 0
+#if defined(OS_ANDROID)
// On Android, attach to the native loop when there is one.
if (type_ == TYPE_UI || type_ == TYPE_JAVA)
static_cast<MessagePumpForUI*>(pump_.get())->Attach(this);
@@ -676,7 +674,7 @@ bool MessageLoop::DoIdleWork() {
return false;
}
-#if !defined(OS_NACL) && !defined(OS_ANDROID)
+#if !defined(OS_NACL)
//------------------------------------------------------------------------------
// MessageLoopForUI
@@ -726,7 +724,7 @@ void MessageLoopForUI::EnableWmQuit() {
}
#endif // defined(OS_WIN)
-#endif // !defined(OS_NACL) && !defined(OS_ANDROID)
+#endif // !defined(OS_NACL)
//------------------------------------------------------------------------------
// MessageLoopForIO
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index 196e466001..e093502061 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -344,10 +344,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
DISALLOW_COPY_AND_ASSIGN(MessageLoop);
};
-// MessageLoopForUI is unsupported in libchrome for android target.
-// The Android UI thread is tied to the Android framework and is not used.
-// This is to avoid dependency on libandroid ALooper.
-#if !defined(OS_NACL) && !defined(OS_ANDROID)
+#if !defined(OS_NACL)
//-----------------------------------------------------------------------------
// MessageLoopForUI extends MessageLoop with methods that are particular to a
@@ -401,7 +398,7 @@ class BASE_EXPORT MessageLoopForUI : public MessageLoop {
static_assert(sizeof(MessageLoop) == sizeof(MessageLoopForUI),
"MessageLoopForUI should not have extra member variables");
-#endif // !defined(OS_NACL) && !defined(OS_ANDROID)
+#endif // !defined(OS_NACL)
//-----------------------------------------------------------------------------
// MessageLoopForIO extends MessageLoop with methods that are particular to a
diff --git a/base/message_loop/message_loop_current.cc b/base/message_loop/message_loop_current.cc
index f8bce70c3f..4959b70e06 100644
--- a/base/message_loop/message_loop_current.cc
+++ b/base/message_loop/message_loop_current.cc
@@ -117,7 +117,7 @@ bool MessageLoopCurrent::IsBoundToCurrentThreadInternal(
return GetTLSMessageLoop()->Get() == message_loop;
}
-#if !defined(OS_NACL) && !defined(OS_ANDROID)
+#if !defined(OS_NACL)
//------------------------------------------------------------------------------
// MessageLoopCurrentForUI
@@ -173,7 +173,7 @@ void MessageLoopCurrentForUI::Abort() {
}
#endif // defined(OS_ANDROID)
-#endif // !defined(OS_NACL) && !defined(OS_ANDROID)
+#endif // !defined(OS_NACL)
//------------------------------------------------------------------------------
// MessageLoopCurrentForIO
diff --git a/base/message_loop/message_loop_current.h b/base/message_loop/message_loop_current.h
index 5eebcad944..61d1607e31 100644
--- a/base/message_loop/message_loop_current.h
+++ b/base/message_loop/message_loop_current.h
@@ -190,7 +190,7 @@ class BASE_EXPORT MessageLoopCurrent {
MessageLoop* const current_;
};
-#if !defined(OS_NACL) && !defined(OS_ANDROID)
+#if !defined(OS_NACL)
// ForUI extension of MessageLoopCurrent.
class BASE_EXPORT MessageLoopCurrentForUI : public MessageLoopCurrent {
@@ -241,7 +241,7 @@ class BASE_EXPORT MessageLoopCurrentForUI : public MessageLoopCurrent {
MessagePumpForUI* const pump_;
};
-#endif // !defined(OS_NACL) && !defined(OS_ANDROID)
+#endif // !defined(OS_NACL)
// ForIO extension of MessageLoopCurrent.
class BASE_EXPORT MessageLoopCurrentForIO : public MessageLoopCurrent {
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index 2e339bd11a..6cf6bc309d 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -34,7 +34,7 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_ANDROID) && 0
+#if defined(OS_ANDROID)
#include "base/android/java_handler_thread.h"
#include "base/android/jni_android.h"
#include "base/test/android/java_handler_thread_helpers.h"
@@ -315,7 +315,7 @@ class MessageLoopTest
DISALLOW_COPY_AND_ASSIGN(MessageLoopTest);
};
-#if defined(OS_ANDROID) && 0
+#if defined(OS_ANDROID)
void DoNotRun() {
ASSERT_TRUE(false);
}
@@ -396,7 +396,7 @@ TEST_P(MessageLoopTest, RunTasksWhileShuttingDownJavaThread) {
EXPECT_EQ(kNumPosts, observer.num_tasks_started());
EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
}
-#endif // defined(OS_ANDROID) && 0
+#endif // defined(OS_ANDROID)
#if defined(OS_WIN)
diff --git a/base/message_loop/message_pump_android.cc b/base/message_loop/message_pump_android.cc
deleted file mode 100644
index 3fd5567e6b..0000000000
--- a/base/message_loop/message_pump_android.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/message_loop/message_pump_android.h"
-
-#include <android/looper.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <jni.h>
-#include <sys/eventfd.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <utility>
-
-#include "base/android/jni_android.h"
-#include "base/android/scoped_java_ref.h"
-#include "base/callback_helpers.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/run_loop.h"
-
-// Android stripped sys/timerfd.h out of their platform headers, so we have to
-// use syscall to make use of timerfd. Once the min API level is 20, we can
-// directly use timerfd.h.
-#ifndef __NR_timerfd_create
-#error "Unable to find syscall for __NR_timerfd_create"
-#endif
-
-#ifndef TFD_TIMER_ABSTIME
-#define TFD_TIMER_ABSTIME (1 << 0)
-#endif
-
-using base::android::JavaParamRef;
-using base::android::ScopedJavaLocalRef;
-
-namespace base {
-
-namespace {
-
-// See sys/timerfd.h
-int timerfd_create(int clockid, int flags) {
- return syscall(__NR_timerfd_create, clockid, flags);
-}
-
-// See sys/timerfd.h
-int timerfd_settime(int ufc,
- int flags,
- const struct itimerspec* utmr,
- struct itimerspec* otmr) {
- return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr);
-}
-
-int NonDelayedLooperCallback(int fd, int events, void* data) {
- if (events & ALOOPER_EVENT_HANGUP)
- return 0;
-
- DCHECK(events & ALOOPER_EVENT_INPUT);
- MessagePumpForUI* pump = reinterpret_cast<MessagePumpForUI*>(data);
- pump->OnNonDelayedLooperCallback();
- return 1; // continue listening for events
-}
-
-int DelayedLooperCallback(int fd, int events, void* data) {
- if (events & ALOOPER_EVENT_HANGUP)
- return 0;
-
- DCHECK(events & ALOOPER_EVENT_INPUT);
- MessagePumpForUI* pump = reinterpret_cast<MessagePumpForUI*>(data);
- pump->OnDelayedLooperCallback();
- return 1; // continue listening for events
-}
-
-} // namespace
-
-MessagePumpForUI::MessagePumpForUI() {
- // The Android native ALooper uses epoll to poll our file descriptors and wake
- // us up. We use a simple level-triggered eventfd to signal that non-delayed
- // work is available, and a timerfd to signal when delayed work is ready to
- // be run.
- non_delayed_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
- CHECK_NE(non_delayed_fd_, -1);
- DCHECK_EQ(TimeTicks::GetClock(), TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
-
- // We can't create the timerfd with TFD_NONBLOCK | TFD_CLOEXEC as we can't
- // include timerfd.h. See comments above on __NR_timerfd_create. It looks like
- // they're just aliases to O_NONBLOCK and O_CLOEXEC anyways, so this should be
- // fine.
- delayed_fd_ = timerfd_create(CLOCK_MONOTONIC, O_NONBLOCK | O_CLOEXEC);
- CHECK_NE(delayed_fd_, -1);
-
- looper_ = ALooper_prepare(0);
- DCHECK(looper_);
- // Add a reference to the looper so it isn't deleted on us.
- ALooper_acquire(looper_);
- ALooper_addFd(looper_, non_delayed_fd_, 0, ALOOPER_EVENT_INPUT,
- &NonDelayedLooperCallback, reinterpret_cast<void*>(this));
- ALooper_addFd(looper_, delayed_fd_, 0, ALOOPER_EVENT_INPUT,
- &DelayedLooperCallback, reinterpret_cast<void*>(this));
-}
-
-MessagePumpForUI::~MessagePumpForUI() {
- DCHECK_EQ(ALooper_forThread(), looper_);
- ALooper_removeFd(looper_, non_delayed_fd_);
- ALooper_removeFd(looper_, delayed_fd_);
- ALooper_release(looper_);
- looper_ = nullptr;
-
- close(non_delayed_fd_);
- close(delayed_fd_);
-}
-
-void MessagePumpForUI::OnDelayedLooperCallback() {
- if (ShouldQuit())
- return;
-
- // Clear the fd.
- uint64_t value;
- int ret = read(delayed_fd_, &value, sizeof(value));
- DCHECK_GE(ret, 0);
- delayed_scheduled_time_ = base::TimeTicks();
-
- base::TimeTicks next_delayed_work_time;
- delegate_->DoDelayedWork(&next_delayed_work_time);
- if (!next_delayed_work_time.is_null()) {
- ScheduleDelayedWork(next_delayed_work_time);
- }
- if (ShouldQuit())
- return;
- // We may be idle now, so pump the loop to find out.
- ScheduleWork();
-}
-
-void MessagePumpForUI::OnNonDelayedLooperCallback() {
- base::TimeTicks next_delayed_work_time;
- bool did_any_work = false;
-
- // Runs all native tasks scheduled to run, scheduling delayed work if
- // necessary.
- while (true) {
- bool did_work_this_loop = false;
- if (ShouldQuit())
- return;
- did_work_this_loop = delegate_->DoWork();
- if (ShouldQuit())
- return;
-
- did_work_this_loop |= delegate_->DoDelayedWork(&next_delayed_work_time);
-
- did_any_work |= did_work_this_loop;
-
- // If we didn't do any work, we're out of native tasks to run, and we should
- // return control to the looper to run Java tasks.
- if (!did_work_this_loop)
- break;
- }
- // If we did any work, return control to the looper to run java tasks before
- // we call DoIdleWork(). We haven't cleared the fd yet, so we'll get woken up
- // again soon to check for idle-ness.
- if (did_any_work)
- return;
- if (ShouldQuit())
- return;
-
- // Read the file descriptor, resetting its contents to 0 and reading back the
- // stored value.
- // See http://man7.org/linux/man-pages/man2/eventfd.2.html
- uint64_t value = 0;
- int ret = read(non_delayed_fd_, &value, sizeof(value));
- DCHECK_GE(ret, 0);
-
- // If we read a value > 1, it means we lost the race to clear the fd before a
- // new task was posted. This is okay, we can just re-schedule work.
- if (value > 1) {
- ScheduleWork();
- } else {
- // At this point, the java looper might not be idle - it's impossible to
- // know pre-Android-M, so we may end up doing Idle work while java tasks are
- // still queued up. Note that this won't cause us to fail to run java tasks
- // using QuitWhenIdle, as the JavaHandlerThread will finish running all
- // currently scheduled tasks before it quits. Also note that we can't just
- // add an idle callback to the java looper, as that will fire even if native
- // tasks are still queued up.
- DoIdleWork();
- if (!next_delayed_work_time.is_null()) {
- ScheduleDelayedWork(next_delayed_work_time);
- }
- }
-}
-
-void MessagePumpForUI::DoIdleWork() {
- if (delegate_->DoIdleWork()) {
- // If DoIdleWork() resulted in any work, we're not idle yet. We need to pump
- // the loop here because we may in fact be idle after doing idle work
- // without any new tasks being queued.
- ScheduleWork();
- }
-}
-
-void MessagePumpForUI::Run(Delegate* delegate) {
- DCHECK(IsTestImplementation());
- // This function is only called in tests. We manually pump the native looper
- // which won't run any java tasks.
- quit_ = false;
-
- SetDelegate(delegate);
-
- // Pump the loop once in case we're starting off idle as ALooper_pollOnce will
- // never return in that case.
- ScheduleWork();
- while (true) {
- // Waits for either the delayed, or non-delayed fds to be signalled, calling
- // either OnDelayedLooperCallback, or OnNonDelayedLooperCallback,
- // respectively. This uses Android's Looper implementation, which is based
- // off of epoll.
- ALooper_pollOnce(-1, nullptr, nullptr, nullptr);
- if (quit_)
- break;
- }
-}
-
-void MessagePumpForUI::Attach(Delegate* delegate) {
- DCHECK(!quit_);
-
- // Since the Looper is controlled by the UI thread or JavaHandlerThread, we
- // can't use Run() like we do on other platforms or we would prevent Java
- // tasks from running. Instead we create and initialize a run loop here, then
- // return control back to the Looper.
-
- SetDelegate(delegate);
- run_loop_ = std::make_unique<RunLoop>();
- // Since the RunLoop was just created above, BeforeRun should be guaranteed to
- // return true (it only returns false if the RunLoop has been Quit already).
- if (!run_loop_->BeforeRun())
- NOTREACHED();
-}
-
-void MessagePumpForUI::Quit() {
- if (quit_)
- return;
-
- quit_ = true;
-
- int64_t value;
- // Clear any pending timer.
- read(delayed_fd_, &value, sizeof(value));
- // Clear the eventfd.
- read(non_delayed_fd_, &value, sizeof(value));
-
- if (run_loop_) {
- run_loop_->AfterRun();
- run_loop_ = nullptr;
- }
- if (on_quit_callback_) {
- std::move(on_quit_callback_).Run();
- }
-}
-
-void MessagePumpForUI::ScheduleWork() {
- if (ShouldQuit())
- return;
-
- // Write (add) 1 to the eventfd. This tells the Looper to wake up and call our
- // callback, allowing us to run tasks. This also allows us to detect, when we
- // clear the fd, whether additional work was scheduled after we finished
- // performing work, but before we cleared the fd, as we'll read back >=2
- // instead of 1 in that case.
- // See the eventfd man pages
- // (http://man7.org/linux/man-pages/man2/eventfd.2.html) for details on how
- // the read and write APIs for this file descriptor work, specifically without
- // EFD_SEMAPHORE.
- uint64_t value = 1;
- int ret = write(non_delayed_fd_, &value, sizeof(value));
- DCHECK_GE(ret, 0);
-}
-
-void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
- if (ShouldQuit())
- return;
-
- if (!delayed_scheduled_time_.is_null() &&
- delayed_work_time >= delayed_scheduled_time_) {
- return;
- }
-
- DCHECK(!delayed_work_time.is_null());
- delayed_scheduled_time_ = delayed_work_time;
- int64_t nanos = delayed_work_time.since_origin().InNanoseconds();
- struct itimerspec ts;
- ts.it_interval.tv_sec = 0; // Don't repeat.
- ts.it_interval.tv_nsec = 0;
- ts.it_value.tv_sec = nanos / TimeTicks::kNanosecondsPerSecond;
- ts.it_value.tv_nsec = nanos % TimeTicks::kNanosecondsPerSecond;
-
- int ret = timerfd_settime(delayed_fd_, TFD_TIMER_ABSTIME, &ts, nullptr);
- DCHECK_GE(ret, 0);
-}
-
-void MessagePumpForUI::QuitWhenIdle(base::OnceClosure callback) {
- DCHECK(!on_quit_callback_);
- DCHECK(run_loop_);
- on_quit_callback_ = std::move(callback);
- run_loop_->QuitWhenIdle();
- // Pump the loop in case we're already idle.
- ScheduleWork();
-}
-
-bool MessagePumpForUI::IsTestImplementation() const {
- return false;
-}
-
-} // namespace base
diff --git a/base/message_loop/message_pump_android.h b/base/message_loop/message_pump_android.h
deleted file mode 100644
index d7e0f50fde..0000000000
--- a/base/message_loop/message_pump_android.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_ANDROID_H_
-#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_ANDROID_H_
-
-#include <jni.h>
-#include <memory>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/message_loop/message_pump.h"
-#include "base/time/time.h"
-
-struct ALooper;
-
-namespace base {
-
-class RunLoop;
-
-// This class implements a MessagePump needed for TYPE_UI MessageLoops on
-// OS_ANDROID platform.
-class BASE_EXPORT MessagePumpForUI : public MessagePump {
- public:
- MessagePumpForUI();
- ~MessagePumpForUI() override;
-
- void Run(Delegate* delegate) override;
- void Quit() override;
- void ScheduleWork() override;
- void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
-
- // Attaches |delegate| to this native MessagePump. |delegate| will from then
- // on be invoked by the native loop to process application tasks.
- virtual void Attach(Delegate* delegate);
-
- // We call Abort when there is a pending JNI exception, meaning that the
- // current thread will crash when we return to Java.
- // We can't call any JNI-methods before returning to Java as we would then
- // cause a native crash (instead of the original Java crash).
- void Abort() { should_abort_ = true; }
- bool IsAborted() { return should_abort_; }
- bool ShouldQuit() const { return should_abort_ || quit_; }
-
- // Tells the RunLoop to quit when idle, calling the callback when it's safe
- // for the Thread to stop.
- void QuitWhenIdle(base::OnceClosure callback);
-
- // These functions are only public so that the looper callbacks can call them,
- // and should not be called from outside this class.
- void OnDelayedLooperCallback();
- void OnNonDelayedLooperCallback();
-
- protected:
- void SetDelegate(Delegate* delegate) { delegate_ = delegate; }
- virtual bool IsTestImplementation() const;
-
- private:
- void DoIdleWork();
-
- // Unlike other platforms, we don't control the message loop as it's
- // controlled by the Android Looper, so we can't run a RunLoop to keep the
- // Thread this pump belongs to alive. However, threads are expected to have an
- // active run loop, so we manage a RunLoop internally here, starting/stopping
- // it as necessary.
- std::unique_ptr<RunLoop> run_loop_;
-
- // See Abort().
- bool should_abort_ = false;
-
- // Whether this message pump is quitting, or has quit.
- bool quit_ = false;
-
- // The MessageLoop::Delegate for this pump.
- Delegate* delegate_ = nullptr;
-
- // The time at which we are currently scheduled to wake up and perform a
- // delayed task.
- base::TimeTicks delayed_scheduled_time_;
-
- // If set, a callback to fire when the message pump is quit.
- base::OnceClosure on_quit_callback_;
-
- // The file descriptor used to signal that non-delayed work is available.
- int non_delayed_fd_;
-
- // The file descriptor used to signal that delayed work is available.
- int delayed_fd_;
-
- // The Android Looper for this thread.
- ALooper* looper_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(MessagePumpForUI);
-};
-
-} // namespace base
-
-#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_ANDROID_H_
diff --git a/base/message_loop/message_pump_for_ui.h b/base/message_loop/message_pump_for_ui.h
index ff6f788317..6614f3dfbf 100644
--- a/base/message_loop/message_pump_for_ui.h
+++ b/base/message_loop/message_pump_for_ui.h
@@ -12,7 +12,7 @@
#if defined(OS_WIN)
#include "base/message_loop/message_pump_win.h"
-#elif defined(OS_ANDROID) && 0
+#elif defined(OS_ANDROID)
#include "base/message_loop/message_pump_android.h"
#elif defined(OS_MACOSX)
#include "base/message_loop/message_pump.h"
@@ -32,10 +32,8 @@ namespace base {
// Windows defines it as-is.
using MessagePumpForUI = MessagePumpForUI;
#elif defined(OS_ANDROID)
-#if 0 // Drop support for MessagePumpForUI for libchrome on Android targets.
// Android defines it as-is.
using MessagePumpForUI = MessagePumpForUI;
-#endif
#elif defined(OS_MACOSX)
// MessagePumpForUI isn't bound to a specific impl on Mac. While each impl can
// be represented by a plain MessagePump: MessagePumpMac::Create() must be used
diff --git a/base/message_loop/message_pump_libevent_unittest.cc b/base/message_loop/message_pump_libevent_unittest.cc
deleted file mode 100644
index 55eb0b4d72..0000000000
--- a/base/message_loop/message_pump_libevent_unittest.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/message_loop/message_pump_libevent.h"
-
-#include <unistd.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_util.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/synchronization/waitable_event_watcher.h"
-#include "base/test/gtest_util.h"
-#include "base/third_party/libevent/event.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class MessagePumpLibeventTest : public testing::Test {
- protected:
- MessagePumpLibeventTest()
- : ui_loop_(new MessageLoop(MessageLoop::TYPE_UI)),
- io_thread_("MessagePumpLibeventTestIOThread") {}
- ~MessagePumpLibeventTest() override = default;
-
- void SetUp() override {
- Thread::Options options(MessageLoop::TYPE_IO, 0);
- ASSERT_TRUE(io_thread_.StartWithOptions(options));
- ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type());
- int ret = pipe(pipefds_);
- ASSERT_EQ(0, ret);
- }
-
- void TearDown() override {
- if (IGNORE_EINTR(close(pipefds_[0])) < 0)
- PLOG(ERROR) << "close";
- if (IGNORE_EINTR(close(pipefds_[1])) < 0)
- PLOG(ERROR) << "close";
- }
-
- void WaitUntilIoThreadStarted() {
- ASSERT_TRUE(io_thread_.WaitUntilThreadStarted());
- }
-
- scoped_refptr<SingleThreadTaskRunner> io_runner() const {
- return io_thread_.task_runner();
- }
-
- void OnLibeventNotification(
- MessagePumpLibevent* pump,
- MessagePumpLibevent::FdWatchController* controller) {
- pump->OnLibeventNotification(0, EV_WRITE | EV_READ, controller);
- }
-
- int pipefds_[2];
- std::unique_ptr<MessageLoop> ui_loop_;
-
- private:
- Thread io_thread_;
-};
-
-namespace {
-
-// Concrete implementation of MessagePumpLibevent::FdWatcher that does
-// nothing useful.
-class StupidWatcher : public MessagePumpLibevent::FdWatcher {
- public:
- ~StupidWatcher() override = default;
-
- // base:MessagePumpLibevent::FdWatcher interface
- void OnFileCanReadWithoutBlocking(int fd) override {}
- void OnFileCanWriteWithoutBlocking(int fd) override {}
-};
-
-TEST_F(MessagePumpLibeventTest, QuitOutsideOfRun) {
- std::unique_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
- ASSERT_DCHECK_DEATH(pump->Quit());
-}
-
-class BaseWatcher : public MessagePumpLibevent::FdWatcher {
- public:
- explicit BaseWatcher(MessagePumpLibevent::FdWatchController* controller)
- : controller_(controller) {
- DCHECK(controller_);
- }
- ~BaseWatcher() override = default;
-
- // base:MessagePumpLibevent::FdWatcher interface
- void OnFileCanReadWithoutBlocking(int /* fd */) override { NOTREACHED(); }
-
- void OnFileCanWriteWithoutBlocking(int /* fd */) override { NOTREACHED(); }
-
- protected:
- MessagePumpLibevent::FdWatchController* controller_;
-};
-
-class DeleteWatcher : public BaseWatcher {
- public:
- explicit DeleteWatcher(MessagePumpLibevent::FdWatchController* controller)
- : BaseWatcher(controller) {}
-
- ~DeleteWatcher() override { DCHECK(!controller_); }
-
- void OnFileCanWriteWithoutBlocking(int /* fd */) override {
- DCHECK(controller_);
- delete controller_;
- controller_ = nullptr;
- }
-};
-
-TEST_F(MessagePumpLibeventTest, DeleteWatcher) {
- std::unique_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
- MessagePumpLibevent::FdWatchController* watcher =
- new MessagePumpLibevent::FdWatchController(FROM_HERE);
- DeleteWatcher delegate(watcher);
- pump->WatchFileDescriptor(pipefds_[1],
- false, MessagePumpLibevent::WATCH_READ_WRITE, watcher, &delegate);
-
- // Spoof a libevent notification.
- OnLibeventNotification(pump.get(), watcher);
-}
-
-class StopWatcher : public BaseWatcher {
- public:
- explicit StopWatcher(MessagePumpLibevent::FdWatchController* controller)
- : BaseWatcher(controller) {}
-
- ~StopWatcher() override = default;
-
- void OnFileCanWriteWithoutBlocking(int /* fd */) override {
- controller_->StopWatchingFileDescriptor();
- }
-};
-
-TEST_F(MessagePumpLibeventTest, StopWatcher) {
- std::unique_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
- MessagePumpLibevent::FdWatchController watcher(FROM_HERE);
- StopWatcher delegate(&watcher);
- pump->WatchFileDescriptor(pipefds_[1],
- false, MessagePumpLibevent::WATCH_READ_WRITE, &watcher, &delegate);
-
- // Spoof a libevent notification.
- OnLibeventNotification(pump.get(), &watcher);
-}
-
-void QuitMessageLoopAndStart(const Closure& quit_closure) {
- quit_closure.Run();
-
- RunLoop runloop(RunLoop::Type::kNestableTasksAllowed);
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, runloop.QuitClosure());
- runloop.Run();
-}
-
-class NestedPumpWatcher : public MessagePumpLibevent::FdWatcher {
- public:
- NestedPumpWatcher() = default;
- ~NestedPumpWatcher() override = default;
-
- void OnFileCanReadWithoutBlocking(int /* fd */) override {
- RunLoop runloop;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&QuitMessageLoopAndStart, runloop.QuitClosure()));
- runloop.Run();
- }
-
- void OnFileCanWriteWithoutBlocking(int /* fd */) override {}
-};
-
-TEST_F(MessagePumpLibeventTest, NestedPumpWatcher) {
- std::unique_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
- MessagePumpLibevent::FdWatchController watcher(FROM_HERE);
- NestedPumpWatcher delegate;
- pump->WatchFileDescriptor(pipefds_[1],
- false, MessagePumpLibevent::WATCH_READ, &watcher, &delegate);
-
- // Spoof a libevent notification.
- OnLibeventNotification(pump.get(), &watcher);
-}
-
-void FatalClosure() {
- FAIL() << "Reached fatal closure.";
-}
-
-class QuitWatcher : public BaseWatcher {
- public:
- QuitWatcher(MessagePumpLibevent::FdWatchController* controller,
- base::Closure quit_closure)
- : BaseWatcher(controller), quit_closure_(std::move(quit_closure)) {}
-
- void OnFileCanReadWithoutBlocking(int /* fd */) override {
- // Post a fatal closure to the MessageLoop before we quit it.
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, BindOnce(&FatalClosure));
-
- quit_closure_.Run();
- }
-
- private:
- base::Closure quit_closure_;
-};
-
-void WriteFDWrapper(const int fd,
- const char* buf,
- int size,
- WaitableEvent* event) {
- ASSERT_TRUE(WriteFileDescriptor(fd, buf, size));
-}
-
-// Tests that MessagePumpLibevent quits immediately when it is quit from
-// libevent's event_base_loop().
-TEST_F(MessagePumpLibeventTest, QuitWatcher) {
- // Delete the old MessageLoop so that we can manage our own one here.
- ui_loop_.reset();
-
- MessagePumpLibevent* pump = new MessagePumpLibevent; // owned by |loop|.
- MessageLoop loop(WrapUnique(pump));
- RunLoop run_loop;
- MessagePumpLibevent::FdWatchController controller(FROM_HERE);
- QuitWatcher delegate(&controller, run_loop.QuitClosure());
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<WaitableEventWatcher> watcher(new WaitableEventWatcher);
-
- // Tell the pump to watch the pipe.
- pump->WatchFileDescriptor(pipefds_[0], false, MessagePumpLibevent::WATCH_READ,
- &controller, &delegate);
-
- // Make the IO thread wait for |event| before writing to pipefds[1].
- const char buf = 0;
- WaitableEventWatcher::EventCallback write_fd_task =
- BindOnce(&WriteFDWrapper, pipefds_[1], &buf, 1);
- io_runner()->PostTask(
- FROM_HERE, BindOnce(IgnoreResult(&WaitableEventWatcher::StartWatching),
- Unretained(watcher.get()), &event,
- std::move(write_fd_task), io_runner()));
-
- // Queue |event| to signal on |loop|.
- loop.task_runner()->PostTask(
- FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&event)));
-
- // Now run the MessageLoop.
- run_loop.Run();
-
- // StartWatching can move |watcher| to IO thread. Release on IO thread.
- io_runner()->PostTask(FROM_HERE, BindOnce(&WaitableEventWatcher::StopWatching,
- Owned(watcher.release())));
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/message_loop/message_pump_perftest.cc b/base/message_loop/message_pump_perftest.cc
deleted file mode 100644
index 71ed4912d8..0000000000
--- a/base/message_loop/message_pump_perftest.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-// 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 <stddef.h>
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/format_macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/java_handler_thread.h"
-#endif
-
-namespace base {
-
-class ScheduleWorkTest : public testing::Test {
- public:
- ScheduleWorkTest() : counter_(0) {}
-
- void SetUp() override {
- if (base::ThreadTicks::IsSupported())
- base::ThreadTicks::WaitUntilInitialized();
- }
-
- void Increment(uint64_t amount) { counter_ += amount; }
-
- void Schedule(int index) {
- base::TimeTicks start = base::TimeTicks::Now();
- base::ThreadTicks thread_start;
- if (ThreadTicks::IsSupported())
- thread_start = base::ThreadTicks::Now();
- base::TimeDelta minimum = base::TimeDelta::Max();
- base::TimeDelta maximum = base::TimeDelta();
- base::TimeTicks now, lastnow = start;
- uint64_t schedule_calls = 0u;
- do {
- for (size_t i = 0; i < kBatchSize; ++i) {
- target_message_loop()->ScheduleWork();
- schedule_calls++;
- }
- now = base::TimeTicks::Now();
- base::TimeDelta laptime = now - lastnow;
- lastnow = now;
- minimum = std::min(minimum, laptime);
- maximum = std::max(maximum, laptime);
- } while (now - start < base::TimeDelta::FromSeconds(kTargetTimeSec));
-
- scheduling_times_[index] = now - start;
- if (ThreadTicks::IsSupported())
- scheduling_thread_times_[index] =
- base::ThreadTicks::Now() - thread_start;
- min_batch_times_[index] = minimum;
- max_batch_times_[index] = maximum;
- target_message_loop()->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ScheduleWorkTest::Increment,
- base::Unretained(this), schedule_calls));
- }
-
- void ScheduleWork(MessageLoop::Type target_type, int num_scheduling_threads) {
-#if defined(OS_ANDROID)
- if (target_type == MessageLoop::TYPE_JAVA) {
- java_thread_.reset(new android::JavaHandlerThread("target"));
- java_thread_->Start();
- } else
-#endif
- {
- target_.reset(new Thread("target"));
- target_->StartWithOptions(Thread::Options(target_type, 0u));
-
- // Without this, it's possible for the scheduling threads to start and run
- // before the target thread. In this case, the scheduling threads will
- // call target_message_loop()->ScheduleWork(), which dereferences the
- // loop's message pump, which is only created after the target thread has
- // finished starting.
- target_->WaitUntilThreadStarted();
- }
-
- std::vector<std::unique_ptr<Thread>> scheduling_threads;
- scheduling_times_.reset(new base::TimeDelta[num_scheduling_threads]);
- scheduling_thread_times_.reset(new base::TimeDelta[num_scheduling_threads]);
- min_batch_times_.reset(new base::TimeDelta[num_scheduling_threads]);
- max_batch_times_.reset(new base::TimeDelta[num_scheduling_threads]);
-
- for (int i = 0; i < num_scheduling_threads; ++i) {
- scheduling_threads.push_back(std::make_unique<Thread>("posting thread"));
- scheduling_threads[i]->Start();
- }
-
- for (int i = 0; i < num_scheduling_threads; ++i) {
- scheduling_threads[i]->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ScheduleWorkTest::Schedule,
- base::Unretained(this), i));
- }
-
- for (int i = 0; i < num_scheduling_threads; ++i) {
- scheduling_threads[i]->Stop();
- }
-#if defined(OS_ANDROID)
- if (target_type == MessageLoop::TYPE_JAVA) {
- java_thread_->Stop();
- java_thread_.reset();
- } else
-#endif
- {
- target_->Stop();
- target_.reset();
- }
- base::TimeDelta total_time;
- base::TimeDelta total_thread_time;
- base::TimeDelta min_batch_time = base::TimeDelta::Max();
- base::TimeDelta max_batch_time = base::TimeDelta();
- for (int i = 0; i < num_scheduling_threads; ++i) {
- total_time += scheduling_times_[i];
- total_thread_time += scheduling_thread_times_[i];
- min_batch_time = std::min(min_batch_time, min_batch_times_[i]);
- max_batch_time = std::max(max_batch_time, max_batch_times_[i]);
- }
- std::string trace = StringPrintf(
- "%d_threads_scheduling_to_%s_pump",
- num_scheduling_threads,
- target_type == MessageLoop::TYPE_IO
- ? "io"
- : (target_type == MessageLoop::TYPE_UI ? "ui" : "default"));
- perf_test::PrintResult(
- "task",
- "",
- trace,
- total_time.InMicroseconds() / static_cast<double>(counter_),
- "us/task",
- true);
- perf_test::PrintResult(
- "task",
- "_min_batch_time",
- trace,
- min_batch_time.InMicroseconds() / static_cast<double>(kBatchSize),
- "us/task",
- false);
- perf_test::PrintResult(
- "task",
- "_max_batch_time",
- trace,
- max_batch_time.InMicroseconds() / static_cast<double>(kBatchSize),
- "us/task",
- false);
- if (ThreadTicks::IsSupported()) {
- perf_test::PrintResult(
- "task",
- "_thread_time",
- trace,
- total_thread_time.InMicroseconds() / static_cast<double>(counter_),
- "us/task",
- true);
- }
- }
-
- MessageLoop* target_message_loop() {
-#if defined(OS_ANDROID)
- if (java_thread_)
- return java_thread_->message_loop();
-#endif
- return target_->message_loop();
- }
-
- private:
- std::unique_ptr<Thread> target_;
-#if defined(OS_ANDROID)
- std::unique_ptr<android::JavaHandlerThread> java_thread_;
-#endif
- std::unique_ptr<base::TimeDelta[]> scheduling_times_;
- std::unique_ptr<base::TimeDelta[]> scheduling_thread_times_;
- std::unique_ptr<base::TimeDelta[]> min_batch_times_;
- std::unique_ptr<base::TimeDelta[]> max_batch_times_;
- uint64_t counter_;
-
- static const size_t kTargetTimeSec = 5;
- static const size_t kBatchSize = 1000;
-};
-
-TEST_F(ScheduleWorkTest, ThreadTimeToIOFromOneThread) {
- ScheduleWork(MessageLoop::TYPE_IO, 1);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToIOFromTwoThreads) {
- ScheduleWork(MessageLoop::TYPE_IO, 2);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToIOFromFourThreads) {
- ScheduleWork(MessageLoop::TYPE_IO, 4);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToUIFromOneThread) {
- ScheduleWork(MessageLoop::TYPE_UI, 1);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToUIFromTwoThreads) {
- ScheduleWork(MessageLoop::TYPE_UI, 2);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToUIFromFourThreads) {
- ScheduleWork(MessageLoop::TYPE_UI, 4);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToDefaultFromOneThread) {
- ScheduleWork(MessageLoop::TYPE_DEFAULT, 1);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToDefaultFromTwoThreads) {
- ScheduleWork(MessageLoop::TYPE_DEFAULT, 2);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToDefaultFromFourThreads) {
- ScheduleWork(MessageLoop::TYPE_DEFAULT, 4);
-}
-
-#if defined(OS_ANDROID)
-TEST_F(ScheduleWorkTest, ThreadTimeToJavaFromOneThread) {
- ScheduleWork(MessageLoop::TYPE_JAVA, 1);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToJavaFromTwoThreads) {
- ScheduleWork(MessageLoop::TYPE_JAVA, 2);
-}
-
-TEST_F(ScheduleWorkTest, ThreadTimeToJavaFromFourThreads) {
- ScheduleWork(MessageLoop::TYPE_JAVA, 4);
-}
-#endif
-
-} // namespace base
diff --git a/base/metrics/field_trial_params_unittest.cc b/base/metrics/field_trial_params_unittest.cc
deleted file mode 100644
index d310c0d4f5..0000000000
--- a/base/metrics/field_trial_params_unittest.cc
+++ /dev/null
@@ -1,458 +0,0 @@
-// Copyright 2017 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/metrics/field_trial_params.h"
-
-#include "base/feature_list.h"
-#include "base/macros.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_param_associator.h"
-#include "base/test/scoped_feature_list.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// Call FieldTrialList::FactoryGetFieldTrial() with a future expiry date.
-scoped_refptr<FieldTrial> CreateFieldTrial(
- const std::string& trial_name,
- int total_probability,
- const std::string& default_group_name,
- int* default_group_number) {
- return FieldTrialList::FactoryGetFieldTrial(
- trial_name, total_probability, default_group_name,
- FieldTrialList::kNoExpirationYear, 1, 1, FieldTrial::SESSION_RANDOMIZED,
- default_group_number);
-}
-
-} // namespace
-
-class FieldTrialParamsTest : public ::testing::Test {
- public:
- FieldTrialParamsTest() : field_trial_list_(nullptr) {}
-
- ~FieldTrialParamsTest() override {
- // Ensure that the maps are cleared between tests, since they are stored as
- // process singletons.
- FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
- }
-
- void CreateFeatureWithTrial(const Feature& feature,
- FeatureList::OverrideState override_state,
- FieldTrial* trial) {
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->RegisterFieldTrialOverride(feature.name, override_state,
- trial);
- scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
- }
-
- private:
- FieldTrialList field_trial_list_;
- test::ScopedFeatureList scoped_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(FieldTrialParamsTest);
-};
-
-TEST_F(FieldTrialParamsTest, AssociateFieldTrialParams) {
- const std::string kTrialName = "AssociateFieldTrialParams";
-
- {
- std::map<std::string, std::string> params;
- params["a"] = "10";
- params["b"] = "test";
- ASSERT_TRUE(AssociateFieldTrialParams(kTrialName, "A", params));
- }
- {
- std::map<std::string, std::string> params;
- params["a"] = "5";
- ASSERT_TRUE(AssociateFieldTrialParams(kTrialName, "B", params));
- }
-
- FieldTrialList::CreateFieldTrial(kTrialName, "B");
- EXPECT_EQ("5", GetFieldTrialParamValue(kTrialName, "a"));
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "b"));
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "x"));
-
- std::map<std::string, std::string> params;
- EXPECT_TRUE(GetFieldTrialParams(kTrialName, &params));
- EXPECT_EQ(1U, params.size());
- EXPECT_EQ("5", params["a"]);
-}
-
-TEST_F(FieldTrialParamsTest, AssociateFieldTrialParams_Fail) {
- const std::string kTrialName = "AssociateFieldTrialParams_Fail";
- const std::string kGroupName = "A";
-
- std::map<std::string, std::string> params;
- params["a"] = "10";
- ASSERT_TRUE(AssociateFieldTrialParams(kTrialName, kGroupName, params));
- params["a"] = "1";
- params["b"] = "2";
- ASSERT_FALSE(AssociateFieldTrialParams(kTrialName, kGroupName, params));
-
- FieldTrialList::CreateFieldTrial(kTrialName, kGroupName);
- EXPECT_EQ("10", GetFieldTrialParamValue(kTrialName, "a"));
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "b"));
-}
-
-TEST_F(FieldTrialParamsTest, AssociateFieldTrialParams_TrialActiveFail) {
- const std::string kTrialName = "AssociateFieldTrialParams_TrialActiveFail";
- FieldTrialList::CreateFieldTrial(kTrialName, "A");
- ASSERT_EQ("A", FieldTrialList::FindFullName(kTrialName));
-
- std::map<std::string, std::string> params;
- params["a"] = "10";
- EXPECT_FALSE(AssociateFieldTrialParams(kTrialName, "B", params));
- EXPECT_FALSE(AssociateFieldTrialParams(kTrialName, "A", params));
-}
-
-TEST_F(FieldTrialParamsTest, AssociateFieldTrialParams_DoesntActivateTrial) {
- const std::string kTrialName =
- "AssociateFieldTrialParams_DoesntActivateTrial";
-
- ASSERT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
- ASSERT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
-
- std::map<std::string, std::string> params;
- params["a"] = "10";
- EXPECT_TRUE(AssociateFieldTrialParams(kTrialName, "A", params));
- ASSERT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParams_NoTrial) {
- const std::string kTrialName = "GetFieldTrialParams_NoParams";
-
- std::map<std::string, std::string> params;
- EXPECT_FALSE(GetFieldTrialParams(kTrialName, &params));
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "x"));
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "y"));
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParams_NoParams) {
- const std::string kTrialName = "GetFieldTrialParams_NoParams";
-
- FieldTrialList::CreateFieldTrial(kTrialName, "A");
-
- std::map<std::string, std::string> params;
- EXPECT_FALSE(GetFieldTrialParams(kTrialName, &params));
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "x"));
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "y"));
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParams_ActivatesTrial) {
- const std::string kTrialName = "GetFieldTrialParams_ActivatesTrial";
-
- ASSERT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
- ASSERT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
-
- std::map<std::string, std::string> params;
- EXPECT_FALSE(GetFieldTrialParams(kTrialName, &params));
- ASSERT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParamValue_ActivatesTrial) {
- const std::string kTrialName = "GetFieldTrialParamValue_ActivatesTrial";
-
- ASSERT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
- ASSERT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
-
- std::map<std::string, std::string> params;
- EXPECT_EQ(std::string(), GetFieldTrialParamValue(kTrialName, "x"));
- ASSERT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParamsByFeature) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
- const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
-
- std::map<std::string, std::string> params;
- params["x"] = "1";
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- std::map<std::string, std::string> actualParams;
- EXPECT_TRUE(GetFieldTrialParamsByFeature(kFeature, &actualParams));
- EXPECT_EQ(params, actualParams);
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParamValueByFeature) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
- const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
-
- std::map<std::string, std::string> params;
- params["x"] = "1";
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- std::map<std::string, std::string> actualParams;
- EXPECT_EQ(params["x"], GetFieldTrialParamValueByFeature(kFeature, "x"));
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParamsByFeature_Disable) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
- const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
-
- std::map<std::string, std::string> params;
- params["x"] = "1";
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_DISABLE_FEATURE,
- trial.get());
-
- std::map<std::string, std::string> actualParams;
- EXPECT_FALSE(GetFieldTrialParamsByFeature(kFeature, &actualParams));
-}
-
-TEST_F(FieldTrialParamsTest, GetFieldTrialParamValueByFeature_Disable) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
- const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
-
- std::map<std::string, std::string> params;
- params["x"] = "1";
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_DISABLE_FEATURE,
- trial.get());
-
- std::map<std::string, std::string> actualParams;
- EXPECT_EQ(std::string(), GetFieldTrialParamValueByFeature(kFeature, "x"));
-}
-
-TEST_F(FieldTrialParamsTest, FeatureParamString) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
-
- static const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
- static const FeatureParam<std::string> a{&kFeature, "a", "default"};
- static const FeatureParam<std::string> b{&kFeature, "b", ""};
- static const FeatureParam<std::string> c{&kFeature, "c", "default"};
- static const FeatureParam<std::string> d{&kFeature, "d", ""};
- static const FeatureParam<std::string> e{&kFeature, "e", "default"};
- static const FeatureParam<std::string> f{&kFeature, "f", ""};
-
- std::map<std::string, std::string> params;
- params["a"] = "";
- params["b"] = "non-default";
- params["c"] = "non-default";
- params["d"] = "";
- // "e" is not registered
- // "f" is not registered
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- EXPECT_EQ("default", a.Get()); // empty
- EXPECT_EQ("non-default", b.Get());
- EXPECT_EQ("non-default", c.Get());
- EXPECT_EQ("", d.Get()); // empty
- EXPECT_EQ("default", e.Get()); // not registered
- EXPECT_EQ("", f.Get()); // not registered
-}
-
-TEST_F(FieldTrialParamsTest, FeatureParamInt) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
-
- static const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
- static const FeatureParam<int> a{&kFeature, "a", 0};
- static const FeatureParam<int> b{&kFeature, "b", 0};
- static const FeatureParam<int> c{&kFeature, "c", 0};
- static const FeatureParam<int> d{&kFeature, "d", 0};
- static const FeatureParam<int> e{&kFeature, "e", 0};
-
- std::map<std::string, std::string> params;
- params["a"] = "1";
- params["b"] = "1.5";
- params["c"] = "foo";
- params["d"] = "";
- // "e" is not registered
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- EXPECT_EQ(1, GetFieldTrialParamByFeatureAsInt(kFeature, "a", 0));
- EXPECT_EQ(0, GetFieldTrialParamByFeatureAsInt(kFeature, "b", 0)); // invalid
- EXPECT_EQ(0, GetFieldTrialParamByFeatureAsInt(kFeature, "c", 0)); // invalid
- EXPECT_EQ(0, GetFieldTrialParamByFeatureAsInt(kFeature, "d", 0)); // empty
- EXPECT_EQ(0, GetFieldTrialParamByFeatureAsInt(kFeature, "e", 0)); // empty
-
- EXPECT_EQ(1, a.Get());
- EXPECT_EQ(0, b.Get()); // invalid
- EXPECT_EQ(0, c.Get()); // invalid
- EXPECT_EQ(0, d.Get()); // empty
- EXPECT_EQ(0, e.Get()); // empty
-}
-
-TEST_F(FieldTrialParamsTest, FeatureParamDouble) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
-
- static const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
- static const FeatureParam<double> a{&kFeature, "a", 0.0};
- static const FeatureParam<double> b{&kFeature, "b", 0.0};
- static const FeatureParam<double> c{&kFeature, "c", 0.0};
- static const FeatureParam<double> d{&kFeature, "d", 0.0};
- static const FeatureParam<double> e{&kFeature, "e", 0.0};
- static const FeatureParam<double> f{&kFeature, "f", 0.0};
-
- std::map<std::string, std::string> params;
- params["a"] = "1";
- params["b"] = "1.5";
- params["c"] = "1.0e-10";
- params["d"] = "foo";
- params["e"] = "";
- // "f" is not registered
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- EXPECT_EQ(1, GetFieldTrialParamByFeatureAsDouble(kFeature, "a", 0));
- EXPECT_EQ(1.5, GetFieldTrialParamByFeatureAsDouble(kFeature, "b", 0));
- EXPECT_EQ(1.0e-10, GetFieldTrialParamByFeatureAsDouble(kFeature, "c", 0));
- EXPECT_EQ(0,
- GetFieldTrialParamByFeatureAsDouble(kFeature, "d", 0)); // invalid
- EXPECT_EQ(0, GetFieldTrialParamByFeatureAsDouble(kFeature, "e", 0)); // empty
- EXPECT_EQ(0, GetFieldTrialParamByFeatureAsDouble(kFeature, "f", 0)); // empty
-
- EXPECT_EQ(1, a.Get());
- EXPECT_EQ(1.5, b.Get());
- EXPECT_EQ(1.0e-10, c.Get());
- EXPECT_EQ(0, d.Get()); // invalid
- EXPECT_EQ(0, e.Get()); // empty
- EXPECT_EQ(0, f.Get()); // empty
-}
-
-TEST_F(FieldTrialParamsTest, FeatureParamBool) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
-
- static const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
- static const FeatureParam<bool> a{&kFeature, "a", false};
- static const FeatureParam<bool> b{&kFeature, "b", true};
- static const FeatureParam<bool> c{&kFeature, "c", false};
- static const FeatureParam<bool> d{&kFeature, "d", true};
- static const FeatureParam<bool> e{&kFeature, "e", true};
- static const FeatureParam<bool> f{&kFeature, "f", true};
-
- std::map<std::string, std::string> params;
- params["a"] = "true";
- params["b"] = "false";
- params["c"] = "1";
- params["d"] = "False";
- params["e"] = "";
- // "f" is not registered
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- EXPECT_TRUE(a.Get());
- EXPECT_FALSE(b.Get());
- EXPECT_FALSE(c.Get()); // invalid
- EXPECT_TRUE(d.Get()); // invalid
- EXPECT_TRUE(e.Get()); // empty
- EXPECT_TRUE(f.Get()); // empty
-}
-
-enum Hand { ROCK, PAPER, SCISSORS };
-
-TEST_F(FieldTrialParamsTest, FeatureParamEnum) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
-
- static const FeatureParam<Hand>::Option hands[] = {
- {ROCK, "rock"}, {PAPER, "paper"}, {SCISSORS, "scissors"}};
- static const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
- static const FeatureParam<Hand> a{&kFeature, "a", ROCK, &hands};
- static const FeatureParam<Hand> b{&kFeature, "b", ROCK, &hands};
- static const FeatureParam<Hand> c{&kFeature, "c", ROCK, &hands};
- static const FeatureParam<Hand> d{&kFeature, "d", ROCK, &hands};
- static const FeatureParam<Hand> e{&kFeature, "e", PAPER, &hands};
- static const FeatureParam<Hand> f{&kFeature, "f", SCISSORS, &hands};
-
- std::map<std::string, std::string> params;
- params["a"] = "rock";
- params["b"] = "paper";
- params["c"] = "scissors";
- params["d"] = "lizard";
- params["e"] = "";
- // "f" is not registered
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- EXPECT_EQ(ROCK, a.Get());
- EXPECT_EQ(PAPER, b.Get());
- EXPECT_EQ(SCISSORS, c.Get());
- EXPECT_EQ(ROCK, d.Get()); // invalid
- EXPECT_EQ(PAPER, e.Get()); // invalid/empty
- EXPECT_EQ(SCISSORS, f.Get()); // not registered
-}
-
-enum class UI { ONE_D, TWO_D, THREE_D };
-
-TEST_F(FieldTrialParamsTest, FeatureParamEnumClass) {
- const std::string kTrialName = "GetFieldTrialParamsByFeature";
-
- static const FeatureParam<UI>::Option uis[] = {
- {UI::ONE_D, "1d"}, {UI::TWO_D, "2d"}, {UI::THREE_D, "3d"}};
- static const Feature kFeature{"TestFeature", FEATURE_DISABLED_BY_DEFAULT};
- static const FeatureParam<UI> a{&kFeature, "a", UI::ONE_D, &uis};
- static const FeatureParam<UI> b{&kFeature, "b", UI::ONE_D, &uis};
- static const FeatureParam<UI> c{&kFeature, "c", UI::ONE_D, &uis};
- static const FeatureParam<UI> d{&kFeature, "d", UI::ONE_D, &uis};
- static const FeatureParam<UI> e{&kFeature, "e", UI::TWO_D, &uis};
- static const FeatureParam<UI> f{&kFeature, "f", UI::THREE_D, &uis};
-
- std::map<std::string, std::string> params;
- params["a"] = "1d";
- params["b"] = "2d";
- params["c"] = "3d";
- params["d"] = "4d";
- params["e"] = "";
- // "f" is not registered
- AssociateFieldTrialParams(kTrialName, "A", params);
- scoped_refptr<FieldTrial> trial(
- CreateFieldTrial(kTrialName, 100, "A", nullptr));
-
- CreateFeatureWithTrial(kFeature, FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial.get());
-
- EXPECT_EQ(UI::ONE_D, a.Get());
- EXPECT_EQ(UI::TWO_D, b.Get());
- EXPECT_EQ(UI::THREE_D, c.Get());
- EXPECT_EQ(UI::ONE_D, d.Get()); // invalid
- EXPECT_EQ(UI::TWO_D, e.Get()); // invalid/empty
- EXPECT_EQ(UI::THREE_D, f.Get()); // not registered
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_functions_unittest.cc b/base/metrics/histogram_functions_unittest.cc
deleted file mode 100644
index 32f439469b..0000000000
--- a/base/metrics/histogram_functions_unittest.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2016 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/metrics/histogram_functions.h"
-
-#include "base/metrics/histogram_macros.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/time/time.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-enum UmaHistogramTestingEnum {
- UMA_HISTOGRAM_TESTING_ENUM_FIRST,
- UMA_HISTOGRAM_TESTING_ENUM_SECOND,
- UMA_HISTOGRAM_TESTING_ENUM_THIRD
-};
-
-TEST(HistogramFunctionsTest, ExactLinear) {
- std::string histogram("Testing.UMA.HistogramExactLinear");
- HistogramTester tester;
- UmaHistogramExactLinear(histogram, 10, 100);
- tester.ExpectUniqueSample(histogram, 10, 1);
- UmaHistogramExactLinear(histogram, 20, 100);
- UmaHistogramExactLinear(histogram, 10, 100);
- tester.ExpectBucketCount(histogram, 10, 2);
- tester.ExpectBucketCount(histogram, 20, 1);
- tester.ExpectTotalCount(histogram, 3);
- // Test linear buckets overflow.
- UmaHistogramExactLinear(histogram, 200, 100);
- tester.ExpectBucketCount(histogram, 101, 1);
- tester.ExpectTotalCount(histogram, 4);
- // Test linear buckets underflow.
- UmaHistogramExactLinear(histogram, 0, 100);
- tester.ExpectBucketCount(histogram, 0, 1);
- tester.ExpectTotalCount(histogram, 5);
-}
-
-TEST(HistogramFunctionsTest, Enumeration) {
- std::string histogram("Testing.UMA.HistogramEnumeration");
- HistogramTester tester;
- UmaHistogramEnumeration(histogram, UMA_HISTOGRAM_TESTING_ENUM_FIRST,
- UMA_HISTOGRAM_TESTING_ENUM_THIRD);
- tester.ExpectUniqueSample(histogram, UMA_HISTOGRAM_TESTING_ENUM_FIRST, 1);
-
- // Verify the overflow & underflow bucket exists.
- UMA_HISTOGRAM_ENUMERATION(
- histogram, static_cast<int>(UMA_HISTOGRAM_TESTING_ENUM_THIRD) + 10,
- static_cast<int>(UMA_HISTOGRAM_TESTING_ENUM_THIRD));
- tester.ExpectBucketCount(
- histogram, static_cast<int>(UMA_HISTOGRAM_TESTING_ENUM_THIRD) + 1, 1);
- tester.ExpectTotalCount(histogram, 2);
-}
-
-TEST(HistogramFunctionsTest, Boolean) {
- std::string histogram("Testing.UMA.HistogramBoolean");
- HistogramTester tester;
- UmaHistogramBoolean(histogram, true);
- tester.ExpectUniqueSample(histogram, 1, 1);
- UmaHistogramBoolean(histogram, false);
- tester.ExpectBucketCount(histogram, 0, 1);
- tester.ExpectTotalCount(histogram, 2);
-}
-
-TEST(HistogramFunctionsTest, Percentage) {
- std::string histogram("Testing.UMA.HistogramPercentage");
- HistogramTester tester;
- UmaHistogramPercentage(histogram, 50);
- tester.ExpectUniqueSample(histogram, 50, 1);
- // Test overflows.
- UmaHistogramPercentage(histogram, 110);
- tester.ExpectBucketCount(histogram, 101, 1);
- tester.ExpectTotalCount(histogram, 2);
-}
-
-TEST(HistogramFunctionsTest, Counts) {
- std::string histogram("Testing.UMA.HistogramCount.Custom");
- HistogramTester tester;
- UmaHistogramCustomCounts(histogram, 10, 1, 100, 10);
- tester.ExpectUniqueSample(histogram, 10, 1);
- UmaHistogramCustomCounts(histogram, 20, 1, 100, 10);
- UmaHistogramCustomCounts(histogram, 20, 1, 100, 10);
- UmaHistogramCustomCounts(histogram, 20, 1, 100, 10);
- tester.ExpectBucketCount(histogram, 20, 3);
- tester.ExpectTotalCount(histogram, 4);
- UmaHistogramCustomCounts(histogram, 110, 1, 100, 10);
- tester.ExpectBucketCount(histogram, 101, 1);
- tester.ExpectTotalCount(histogram, 5);
-}
-
-TEST(HistogramFunctionsTest, Times) {
- std::string histogram("Testing.UMA.HistogramTimes");
- HistogramTester tester;
- UmaHistogramTimes(histogram, TimeDelta::FromSeconds(1));
- tester.ExpectTimeBucketCount(histogram, TimeDelta::FromSeconds(1), 1);
- tester.ExpectTotalCount(histogram, 1);
- UmaHistogramTimes(histogram, TimeDelta::FromSeconds(9));
- tester.ExpectTimeBucketCount(histogram, TimeDelta::FromSeconds(9), 1);
- tester.ExpectTotalCount(histogram, 2);
- UmaHistogramTimes(histogram, TimeDelta::FromSeconds(10)); // Overflows
- tester.ExpectTimeBucketCount(histogram, TimeDelta::FromSeconds(10), 1);
- UmaHistogramTimes(histogram, TimeDelta::FromSeconds(20)); // Overflows.
- // Check the value by picking any overflow time.
- tester.ExpectTimeBucketCount(histogram, TimeDelta::FromSeconds(11), 2);
- tester.ExpectTotalCount(histogram, 4);
-}
-
-TEST(HistogramFunctionsTest, Sparse_SupportsLargeRange) {
- std::string histogram("Testing.UMA.HistogramSparse");
- HistogramTester tester;
- UmaHistogramSparse(histogram, 0);
- UmaHistogramSparse(histogram, 123456789);
- UmaHistogramSparse(histogram, 123456789);
- EXPECT_THAT(tester.GetAllSamples(histogram),
- testing::ElementsAre(Bucket(0, 1), Bucket(123456789, 2)));
-}
-
-TEST(HistogramFunctionsTest, Sparse_SupportsNegativeValues) {
- std::string histogram("Testing.UMA.HistogramSparse");
- HistogramTester tester;
- UmaHistogramSparse(histogram, -1);
- tester.ExpectUniqueSample(histogram, -1, 1);
-}
-
-} // namespace base.
diff --git a/base/metrics/histogram_unittest.nc b/base/metrics/histogram_unittest.nc
deleted file mode 100644
index c9c2657997..0000000000
--- a/base/metrics/histogram_unittest.nc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2016 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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
-
-namespace base {
-
-#if defined(NCTEST_DIFFERENT_ENUM) // [r"\|sample\| and \|boundary\| shouldn't be of different enums"]
-
-void WontCompile() {
- enum TypeA { A };
- enum TypeB { B };
- UMA_HISTOGRAM_ENUMERATION("", A, B);
-}
-
-#elif defined(NCTEST_DIFFERENT_ENUM_CLASS) // [r"\|sample\| and \|boundary\| shouldn't be of different enums"]
-
-void WontCompile() {
- enum class TypeA { A };
- enum class TypeB { B };
- UMA_HISTOGRAM_ENUMERATION("", TypeA::A, TypeB::B);
-}
-
-#elif defined(NCTEST_DIFFERENT_ENUM_MIXED) // [r"\|sample\| and \|boundary\| shouldn't be of different enums"]
-
-void WontCompile() {
- enum class TypeA { A };
- enum TypeB { B };
- UMA_HISTOGRAM_ENUMERATION("", TypeA::A, B);
-}
-
-#elif defined(NCTEST_NEGATIVE_ENUM_MAX) // [r'static_assert failed "\|boundary\| is out of range of HistogramBase::Sample"']
-
-void WontCompile() {
- // Buckets for enumeration start from 0, so a boundary < 0 is illegal.
- enum class TypeA { A = -1 };
- UMA_HISTOGRAM_ENUMERATION("", TypeA::A, TypeA::A);
-}
-
-#elif defined(NCTEST_ENUM_MAX_OUT_OF_RANGE) // [r'static_assert failed "\|boundary\| is out of range of HistogramBase::Sample"']
-
-void WontCompile() {
- // HistogramBase::Sample is an int and can't hold larger values.
- enum class TypeA : uint32_t { A = 0xffffffff };
- UMA_HISTOGRAM_ENUMERATION("", TypeA::A, TypeA::A);
-}
-
-#elif defined(NCTEST_SAMPLE_NOT_ENUM) // [r'static_assert failed "Unexpected: \|boundary\| is enum, but \|sample\| is not."']
-
-void WontCompile() {
- enum TypeA { A };
- UMA_HISTOGRAM_ENUMERATION("", 0, TypeA::A);
-}
-
-#elif defined(NCTEST_FUNCTION_INT) // [r"Non enum passed to UmaHistogramEnumeration"]
-
-void WontCompile() {
- UmaHistogramEnumeration("", 1, 2);
-}
-
-#elif defined(NCTEST_FUNCTION_DIFFERENT_ENUM) // [r"no matching function for call to 'UmaHistogramEnumeration'"]
-
-void WontCompile() {
- enum TypeA { A };
- enum TypeB { B };
- UmaHistogramEnumeration("", A, B);
-}
-
-#elif defined(NCTEST_FUNCTION_FIRST_NOT_ENUM) // [r"no matching function for call to 'UmaHistogramEnumeration'"]
-
-void WontCompile() {
- enum TypeB { B };
- UmaHistogramEnumeration("", 1, B);
-}
-
-#elif defined(NCTEST_FUNCTION_SECOND_NOT_ENUM) // [r"no matching function for call to 'UmaHistogramEnumeration'"]
-
-void WontCompile() {
- enum TypeA { A };
- UmaHistogramEnumeration("", A, 2);
-}
-
-#endif
-
-} // namespace base
diff --git a/base/native_library_unittest.cc b/base/native_library_unittest.cc
deleted file mode 100644
index 2bfb9ec946..0000000000
--- a/base/native_library_unittest.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2015 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/files/file_path.h"
-#include "base/macros.h"
-#include "base/native_library.h"
-#include "base/path_service.h"
-#include "base/test/native_library_test_utils.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-const FilePath::CharType kDummyLibraryPath[] =
- FILE_PATH_LITERAL("dummy_library");
-
-TEST(NativeLibraryTest, LoadFailure) {
- NativeLibraryLoadError error;
- EXPECT_FALSE(LoadNativeLibrary(FilePath(kDummyLibraryPath), &error));
- EXPECT_FALSE(error.ToString().empty());
-}
-
-// |error| is optional and can be null.
-TEST(NativeLibraryTest, LoadFailureWithNullError) {
- EXPECT_FALSE(LoadNativeLibrary(FilePath(kDummyLibraryPath), nullptr));
-}
-
-TEST(NativeLibraryTest, GetNativeLibraryName) {
- const char kExpectedName[] =
-#if defined(OS_WIN)
- "mylib.dll";
-#elif defined(OS_IOS)
- "mylib";
-#elif defined(OS_MACOSX)
- "libmylib.dylib";
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- "libmylib.so";
-#endif
- EXPECT_EQ(kExpectedName, GetNativeLibraryName("mylib"));
-}
-
-TEST(NativeLibraryTest, GetLoadableModuleName) {
- const char kExpectedName[] =
-#if defined(OS_WIN)
- "mylib.dll";
-#elif defined(OS_IOS)
- "mylib";
-#elif defined(OS_MACOSX)
- "mylib.so";
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- "libmylib.so";
-#endif
- EXPECT_EQ(kExpectedName, GetLoadableModuleName("mylib"));
-}
-
-// We don't support dynamic loading on iOS, and ASAN will complain about our
-// intentional ODR violation because of |g_native_library_exported_value| being
-// defined globally both here and in the shared library.
-#if !defined(OS_IOS) && !defined(ADDRESS_SANITIZER)
-
-const char kTestLibraryName[] =
-#if defined(OS_WIN)
- "test_shared_library.dll";
-#elif defined(OS_MACOSX)
- "libtest_shared_library.dylib";
-#elif defined(OS_ANDROID) && defined(COMPONENT_BUILD)
- "libtest_shared_library.cr.so";
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- "libtest_shared_library.so";
-#endif
-
-class TestLibrary {
- public:
- TestLibrary() : TestLibrary(NativeLibraryOptions()) {}
-
- explicit TestLibrary(const NativeLibraryOptions& options)
- : library_(nullptr) {
- base::FilePath exe_path;
-
-#if !defined(OS_FUCHSIA)
- // Libraries do not sit alongside the executable in Fuchsia. NativeLibrary
- // is aware of this and is able to resolve library paths correctly.
- CHECK(base::PathService::Get(base::DIR_EXE, &exe_path));
-#endif
-
- library_ = LoadNativeLibraryWithOptions(
- exe_path.AppendASCII(kTestLibraryName), options, nullptr);
- CHECK(library_);
- }
-
- ~TestLibrary() {
- UnloadNativeLibrary(library_);
- }
-
- template <typename ReturnType, typename... Args>
- ReturnType Call(const char* function_name, Args... args) {
- return reinterpret_cast<ReturnType(*)(Args...)>(
- GetFunctionPointerFromNativeLibrary(library_, function_name))(args...);
- }
-
- private:
- NativeLibrary library_;
-
- DISALLOW_COPY_AND_ASSIGN(TestLibrary);
-};
-
-// NativeLibraaryTest.LoadLibrary is failing on M tablets only.
-// crbug/641309
-#if !defined(OS_ANDROID)
-
-// Verifies that we can load a native library and resolve its exported symbols.
-TEST(NativeLibraryTest, LoadLibrary) {
- TestLibrary library;
- EXPECT_EQ(5, library.Call<int>("GetSimpleTestValue"));
-}
-
-#endif // !defined(OS_ANDROID)
-
-// Android dlopen() requires further investigation, as it might vary across
-// versions with respect to symbol resolution scope.
-// TSan and MSan error out on RTLD_DEEPBIND, https://crbug.com/705255
-#if !defined(OS_ANDROID) && !defined(THREAD_SANITIZER) && \
- !defined(MEMORY_SANITIZER)
-
-// Verifies that the |prefer_own_symbols| option satisfies its guarantee that
-// a loaded library will always prefer local symbol resolution before
-// considering global symbols.
-TEST(NativeLibraryTest, LoadLibraryPreferOwnSymbols) {
- NativeLibraryOptions options;
- options.prefer_own_symbols = true;
- TestLibrary library(options);
-
- // Verify that this binary and the DSO use different storage for
- // |g_native_library_exported_value|.
- g_native_library_exported_value = 1;
- library.Call<void>("SetExportedValue", 2);
- EXPECT_EQ(1, g_native_library_exported_value);
- g_native_library_exported_value = 3;
- EXPECT_EQ(2, library.Call<int>("GetExportedValue"));
-
- // Both this binary and the library link against the
- // native_library_test_utils source library, which in turn exports the
- // NativeLibraryTestIncrement() function whose return value depends on some
- // static internal state.
- //
- // The DSO's GetIncrementValue() forwards to that function inside the DSO.
- //
- // Here we verify that direct calls to NativeLibraryTestIncrement() in this
- // binary return a sequence of values independent from the sequence returned
- // by GetIncrementValue(), ensuring that the DSO is calling its own local
- // definition of NativeLibraryTestIncrement().
- EXPECT_EQ(1, library.Call<int>("GetIncrementValue"));
- EXPECT_EQ(1, NativeLibraryTestIncrement());
- EXPECT_EQ(2, library.Call<int>("GetIncrementValue"));
- EXPECT_EQ(3, library.Call<int>("GetIncrementValue"));
- EXPECT_EQ(4, library.Call<int>("NativeLibraryTestIncrement"));
- EXPECT_EQ(2, NativeLibraryTestIncrement());
- EXPECT_EQ(3, NativeLibraryTestIncrement());
-}
-
-#endif // !defined(OS_ANDROID)
-
-#endif // !defined(OS_IOS) && !defined(ADDRESS_SANITIZER)
-
-} // namespace base
diff --git a/base/nix/mime_util_xdg.cc b/base/nix/mime_util_xdg.cc
deleted file mode 100644
index 6b5b11d639..0000000000
--- a/base/nix/mime_util_xdg.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/nix/mime_util_xdg.h"
-
-#include "base/files/file_path.h"
-#include "base/lazy_instance.h"
-#include "base/synchronization/lock.h"
-#include "base/third_party/xdg_mime/xdgmime.h"
-#include "base/threading/thread_restrictions.h"
-
-namespace base {
-namespace nix {
-
-namespace {
-
-// None of the XDG stuff is thread-safe, so serialize all access under
-// this lock.
-LazyInstance<Lock>::Leaky g_mime_util_xdg_lock = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-std::string GetFileMimeType(const FilePath& filepath) {
- if (filepath.empty())
- return std::string();
- AssertBlockingAllowed();
- AutoLock scoped_lock(g_mime_util_xdg_lock.Get());
- return xdg_mime_get_mime_type_from_file_name(filepath.value().c_str());
-}
-
-} // namespace nix
-} // namespace base
diff --git a/base/nix/mime_util_xdg.h b/base/nix/mime_util_xdg.h
deleted file mode 100644
index e0f264a565..0000000000
--- a/base/nix/mime_util_xdg.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_NIX_MIME_UTIL_XDG_H_
-#define BASE_NIX_MIME_UTIL_XDG_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "build/build_config.h"
-
-namespace base {
-
-class FilePath;
-
-namespace nix {
-
-// Gets the mime type for a file at |filepath|.
-//
-// The mime type is calculated based only on the file name of |filepath|. In
-// particular |filepath| will not be touched on disk and |filepath| doesn't even
-// have to exist. This means that the function does not work for directories
-// (i.e. |filepath| is assumed to be a path to a file).
-//
-// Note that this function might need to read from disk the mime-types data
-// provided by the OS. Therefore this function should not be called from
-// threads that disallow IO via base::ThreadRestrictions::SetIOAllowed(false).
-//
-// If the mime type is unknown, this will return application/octet-stream.
-BASE_EXPORT std::string GetFileMimeType(const FilePath& filepath);
-
-} // namespace nix
-} // namespace base
-
-#endif // BASE_NIX_MIME_UTIL_XDG_H_
diff --git a/base/nix/xdg_util.cc b/base/nix/xdg_util.cc
deleted file mode 100644
index 9ff4d88e83..0000000000
--- a/base/nix/xdg_util.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/nix/xdg_util.h"
-
-#include <string>
-
-#include "base/base_paths.h"
-#include "base/environment.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "base/third_party/xdg_user_dirs/xdg_user_dir_lookup.h"
-
-namespace {
-
-// The KDE session version environment variable introduced in KDE 4.
-const char kKDESessionEnvVar[] = "KDE_SESSION_VERSION";
-
-} // namespace
-
-namespace base {
-namespace nix {
-
-const char kDotConfigDir[] = ".config";
-const char kXdgConfigHomeEnvVar[] = "XDG_CONFIG_HOME";
-
-FilePath GetXDGDirectory(Environment* env, const char* env_name,
- const char* fallback_dir) {
- FilePath path;
- std::string env_value;
- if (env->GetVar(env_name, &env_value) && !env_value.empty()) {
- path = FilePath(env_value);
- } else {
- PathService::Get(DIR_HOME, &path);
- path = path.Append(fallback_dir);
- }
- return path.StripTrailingSeparators();
-}
-
-FilePath GetXDGUserDirectory(const char* dir_name, const char* fallback_dir) {
- FilePath path;
- char* xdg_dir = xdg_user_dir_lookup(dir_name);
- if (xdg_dir) {
- path = FilePath(xdg_dir);
- free(xdg_dir);
- } else {
- PathService::Get(DIR_HOME, &path);
- path = path.Append(fallback_dir);
- }
- return path.StripTrailingSeparators();
-}
-
-DesktopEnvironment GetDesktopEnvironment(Environment* env) {
- // XDG_CURRENT_DESKTOP is the newest standard circa 2012.
- std::string xdg_current_desktop;
- if (env->GetVar("XDG_CURRENT_DESKTOP", &xdg_current_desktop)) {
- // Not all desktop environments set this env var as of this writing.
- if (base::StartsWith(xdg_current_desktop, "Unity",
- base::CompareCase::SENSITIVE)) {
- // gnome-fallback sessions set XDG_CURRENT_DESKTOP to Unity
- // DESKTOP_SESSION can be gnome-fallback or gnome-fallback-compiz
- std::string desktop_session;
- if (env->GetVar("DESKTOP_SESSION", &desktop_session) &&
- desktop_session.find("gnome-fallback") != std::string::npos) {
- return DESKTOP_ENVIRONMENT_GNOME;
- }
- return DESKTOP_ENVIRONMENT_UNITY;
- }
- if (xdg_current_desktop == "GNOME")
- return DESKTOP_ENVIRONMENT_GNOME;
- if (xdg_current_desktop == "X-Cinnamon")
- return DESKTOP_ENVIRONMENT_CINNAMON;
- if (xdg_current_desktop == "KDE") {
- std::string kde_session;
- if (env->GetVar(kKDESessionEnvVar, &kde_session)) {
- if (kde_session == "5") {
- return DESKTOP_ENVIRONMENT_KDE5;
- }
- }
- return DESKTOP_ENVIRONMENT_KDE4;
- }
- if (xdg_current_desktop == "Pantheon")
- return DESKTOP_ENVIRONMENT_PANTHEON;
- if (xdg_current_desktop == "XFCE")
- return DESKTOP_ENVIRONMENT_XFCE;
- }
-
- // DESKTOP_SESSION was what everyone used in 2010.
- std::string desktop_session;
- if (env->GetVar("DESKTOP_SESSION", &desktop_session)) {
- if (desktop_session == "gnome" || desktop_session == "mate")
- return DESKTOP_ENVIRONMENT_GNOME;
- if (desktop_session == "kde4" || desktop_session == "kde-plasma")
- return DESKTOP_ENVIRONMENT_KDE4;
- if (desktop_session == "kde") {
- // This may mean KDE4 on newer systems, so we have to check.
- if (env->HasVar(kKDESessionEnvVar))
- return DESKTOP_ENVIRONMENT_KDE4;
- return DESKTOP_ENVIRONMENT_KDE3;
- }
- if (desktop_session.find("xfce") != std::string::npos ||
- desktop_session == "xubuntu") {
- return DESKTOP_ENVIRONMENT_XFCE;
- }
- }
-
- // Fall back on some older environment variables.
- // Useful particularly in the DESKTOP_SESSION=default case.
- if (env->HasVar("GNOME_DESKTOP_SESSION_ID"))
- return DESKTOP_ENVIRONMENT_GNOME;
- if (env->HasVar("KDE_FULL_SESSION")) {
- if (env->HasVar(kKDESessionEnvVar))
- return DESKTOP_ENVIRONMENT_KDE4;
- return DESKTOP_ENVIRONMENT_KDE3;
- }
-
- return DESKTOP_ENVIRONMENT_OTHER;
-}
-
-const char* GetDesktopEnvironmentName(DesktopEnvironment env) {
- switch (env) {
- case DESKTOP_ENVIRONMENT_OTHER:
- return nullptr;
- case DESKTOP_ENVIRONMENT_CINNAMON:
- return "CINNAMON";
- case DESKTOP_ENVIRONMENT_GNOME:
- return "GNOME";
- case DESKTOP_ENVIRONMENT_KDE3:
- return "KDE3";
- case DESKTOP_ENVIRONMENT_KDE4:
- return "KDE4";
- case DESKTOP_ENVIRONMENT_KDE5:
- return "KDE5";
- case DESKTOP_ENVIRONMENT_PANTHEON:
- return "PANTHEON";
- case DESKTOP_ENVIRONMENT_UNITY:
- return "UNITY";
- case DESKTOP_ENVIRONMENT_XFCE:
- return "XFCE";
- }
- return nullptr;
-}
-
-const char* GetDesktopEnvironmentName(Environment* env) {
- return GetDesktopEnvironmentName(GetDesktopEnvironment(env));
-}
-
-} // namespace nix
-} // namespace base
diff --git a/base/nix/xdg_util.h b/base/nix/xdg_util.h
deleted file mode 100644
index 65f7d15705..0000000000
--- a/base/nix/xdg_util.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_NIX_XDG_UTIL_H_
-#define BASE_NIX_XDG_UTIL_H_
-
-// XDG refers to http://en.wikipedia.org/wiki/Freedesktop.org .
-// This file contains utilities found across free desktop environments.
-//
-// TODO(brettw) this file should be in app/x11, but is currently used by
-// net. We should have a net API to allow the embedder to specify the behavior
-// that it uses XDG for, and then move this file.
-
-#include "base/base_export.h"
-
-#ifdef nix
-#error asdf
-#endif
-
-namespace base {
-
-class Environment;
-class FilePath;
-
-namespace nix {
-
-// The default XDG config directory name.
-BASE_EXPORT extern const char kDotConfigDir[];
-
-// The XDG config directory environment variable.
-BASE_EXPORT extern const char kXdgConfigHomeEnvVar[];
-
-// Utility function for getting XDG directories.
-// |env_name| is the name of an environment variable that we want to use to get
-// a directory path. |fallback_dir| is the directory relative to $HOME that we
-// use if |env_name| cannot be found or is empty. |fallback_dir| may be NULL.
-// Examples of |env_name| are XDG_CONFIG_HOME and XDG_DATA_HOME.
-BASE_EXPORT FilePath GetXDGDirectory(Environment* env, const char* env_name,
- const char* fallback_dir);
-
-// Wrapper around xdg_user_dir_lookup() from src/base/third_party/xdg-user-dirs
-// This looks up "well known" user directories like the desktop and music
-// folder. Examples of |dir_name| are DESKTOP and MUSIC.
-BASE_EXPORT FilePath GetXDGUserDirectory(const char* dir_name,
- const char* fallback_dir);
-
-enum DesktopEnvironment {
- DESKTOP_ENVIRONMENT_OTHER,
- DESKTOP_ENVIRONMENT_CINNAMON,
- DESKTOP_ENVIRONMENT_GNOME,
- // KDE3, KDE4 and KDE5 are sufficiently different that we count
- // them as different desktop environments here.
- DESKTOP_ENVIRONMENT_KDE3,
- DESKTOP_ENVIRONMENT_KDE4,
- DESKTOP_ENVIRONMENT_KDE5,
- DESKTOP_ENVIRONMENT_PANTHEON,
- DESKTOP_ENVIRONMENT_UNITY,
- DESKTOP_ENVIRONMENT_XFCE,
-};
-
-// Return an entry from the DesktopEnvironment enum with a best guess
-// of which desktop environment we're using. We use this to know when
-// to attempt to use preferences from the desktop environment --
-// proxy settings, password manager, etc.
-BASE_EXPORT DesktopEnvironment GetDesktopEnvironment(Environment* env);
-
-// Return a string representation of the given desktop environment.
-// May return NULL in the case of DESKTOP_ENVIRONMENT_OTHER.
-BASE_EXPORT const char* GetDesktopEnvironmentName(DesktopEnvironment env);
-// Convenience wrapper that calls GetDesktopEnvironment() first.
-BASE_EXPORT const char* GetDesktopEnvironmentName(Environment* env);
-
-} // namespace nix
-} // namespace base
-
-#endif // BASE_NIX_XDG_UTIL_H_
diff --git a/base/nix/xdg_util_unittest.cc b/base/nix/xdg_util_unittest.cc
deleted file mode 100644
index e195303ca3..0000000000
--- a/base/nix/xdg_util_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2010 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/nix/xdg_util.h"
-
-#include "base/environment.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::Eq;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-
-namespace base {
-namespace nix {
-
-namespace {
-
-class MockEnvironment : public Environment {
- public:
- MOCK_METHOD2(GetVar, bool(StringPiece, std::string* result));
- MOCK_METHOD2(SetVar, bool(StringPiece, const std::string& new_value));
- MOCK_METHOD1(UnSetVar, bool(StringPiece));
-};
-
-// Needs to be const char* to make gmock happy.
-const char* const kDesktopGnome = "gnome";
-const char* const kDesktopGnomeFallback = "gnome-fallback";
-const char* const kDesktopMATE = "mate";
-const char* const kDesktopKDE4 = "kde4";
-const char* const kDesktopKDE = "kde";
-const char* const kDesktopXFCE = "xfce";
-const char* const kXdgDesktopCinnamon = "X-Cinnamon";
-const char* const kXdgDesktopGNOME = "GNOME";
-const char* const kXdgDesktopKDE = "KDE";
-const char* const kXdgDesktopPantheon = "Pantheon";
-const char* const kXdgDesktopUnity = "Unity";
-const char* const kXdgDesktopUnity7 = "Unity:Unity7";
-const char* const kXdgDesktopUnity8 = "Unity:Unity8";
-const char* const kKDESessionKDE5 = "5";
-
-const char kDesktopSession[] = "DESKTOP_SESSION";
-const char kKDESession[] = "KDE_SESSION_VERSION";
-const char kXdgDesktop[] = "XDG_CURRENT_DESKTOP";
-
-} // namespace
-
-TEST(XDGUtilTest, GetDesktopEnvironmentGnome) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kDesktopSession), _))
- .WillOnce(DoAll(SetArgPointee<1>(kDesktopGnome), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_GNOME, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetDesktopEnvironmentMATE) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kDesktopSession), _))
- .WillOnce(DoAll(SetArgPointee<1>(kDesktopMATE), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_GNOME, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetDesktopEnvironmentKDE4) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kDesktopSession), _))
- .WillOnce(DoAll(SetArgPointee<1>(kDesktopKDE4), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_KDE4, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetDesktopEnvironmentKDE3) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kDesktopSession), _))
- .WillOnce(DoAll(SetArgPointee<1>(kDesktopKDE), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_KDE3, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetDesktopEnvironmentXFCE) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kDesktopSession), _))
- .WillOnce(DoAll(SetArgPointee<1>(kDesktopXFCE), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_XFCE, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopCinnamon) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopCinnamon), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_CINNAMON, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopGnome) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopGNOME), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_GNOME, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopGnomeFallback) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopUnity), Return(true)));
- EXPECT_CALL(getter, GetVar(Eq(kDesktopSession), _))
- .WillOnce(DoAll(SetArgPointee<1>(kDesktopGnomeFallback), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_GNOME, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopKDE5) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopKDE), Return(true)));
- EXPECT_CALL(getter, GetVar(Eq(kKDESession), _))
- .WillOnce(DoAll(SetArgPointee<1>(kKDESessionKDE5), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_KDE5, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopKDE4) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopKDE), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_KDE4, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopPantheon) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopPantheon), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_PANTHEON, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopUnity) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopUnity), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_UNITY, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopUnity7) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopUnity7), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_UNITY, GetDesktopEnvironment(&getter));
-}
-
-TEST(XDGUtilTest, GetXdgDesktopUnity8) {
- MockEnvironment getter;
- EXPECT_CALL(getter, GetVar(_, _)).WillRepeatedly(Return(false));
- EXPECT_CALL(getter, GetVar(Eq(kXdgDesktop), _))
- .WillOnce(DoAll(SetArgPointee<1>(kXdgDesktopUnity8), Return(true)));
-
- EXPECT_EQ(DESKTOP_ENVIRONMENT_UNITY, GetDesktopEnvironment(&getter));
-}
-
-} // namespace nix
-} // namespace base
diff --git a/base/numerics/BUILD.gn b/base/numerics/BUILD.gn
new file mode 100644
index 0000000000..0bb8dd1036
--- /dev/null
+++ b/base/numerics/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2017 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.
+
+# This is a dependency-free, header-only, library, and it needs to stay that
+# way to facilitate pulling it into various third-party projects. So, this
+# file is here to protect against accidentally introducing external
+# dependencies or depending on internal implementation details.
+source_set("base_numerics") {
+ visibility = [ "//base/*" ]
+ sources = [
+ "checked_math_impl.h",
+ "clamped_math_impl.h",
+ "safe_conversions_arm_impl.h",
+ "safe_conversions_impl.h",
+ "safe_math_arm_impl.h",
+ "safe_math_clang_gcc_impl.h",
+ "safe_math_shared_impl.h",
+ ]
+ public = [
+ "checked_math.h",
+ "clamped_math.h",
+ "math_constants.h",
+ "ranges.h",
+ "safe_conversions.h",
+ "safe_math.h",
+ ]
+}
diff --git a/base/os_compat_android.cc b/base/os_compat_android.cc
deleted file mode 100644
index c1a2ac86dd..0000000000
--- a/base/os_compat_android.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/os_compat_android.h"
-
-#include <asm/unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <unistd.h>
-
-#if !defined(__LP64__)
-#include <time64.h>
-#endif
-
-#include "base/rand_util.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-
-extern "C" {
-// There is no futimes() avaiable in Bionic, so we provide our own
-// implementation until it is there.
-int futimes(int fd, const struct timeval tv[2]) {
- if (tv == NULL)
- return syscall(__NR_utimensat, fd, NULL, NULL, 0);
-
- if (tv[0].tv_usec < 0 || tv[0].tv_usec >= 1000000 ||
- tv[1].tv_usec < 0 || tv[1].tv_usec >= 1000000) {
- errno = EINVAL;
- return -1;
- }
-
- // Convert timeval to timespec.
- struct timespec ts[2];
- ts[0].tv_sec = tv[0].tv_sec;
- ts[0].tv_nsec = tv[0].tv_usec * 1000;
- ts[1].tv_sec = tv[1].tv_sec;
- ts[1].tv_nsec = tv[1].tv_usec * 1000;
- return syscall(__NR_utimensat, fd, NULL, ts, 0);
-}
-
-#if !defined(__LP64__)
-// 32-bit Android has only timegm64() and not timegm().
-// We replicate the behaviour of timegm() when the result overflows time_t.
-time_t timegm(struct tm* const t) {
- // time_t is signed on Android.
- static const time_t kTimeMax = ~(1L << (sizeof(time_t) * CHAR_BIT - 1));
- static const time_t kTimeMin = (1L << (sizeof(time_t) * CHAR_BIT - 1));
- time64_t result = timegm64(t);
- if (result < kTimeMin || result > kTimeMax)
- return -1;
- return result;
-}
-#endif
-
-// The following is only needed when building with GCC 4.6 or higher
-// (i.e. not with Android GCC 4.4.3, nor with Clang).
-//
-// GCC is now capable of optimizing successive calls to sin() and cos() into
-// a single call to sincos(). This means that source code that looks like:
-//
-// double c, s;
-// c = cos(angle);
-// s = sin(angle);
-//
-// Will generate machine code that looks like:
-//
-// double c, s;
-// sincos(angle, &s, &c);
-//
-// Unfortunately, sincos() and friends are not part of the Android libm.so
-// library provided by the NDK for API level 9. When the optimization kicks
-// in, it makes the final build fail with a puzzling message (puzzling
-// because 'sincos' doesn't appear anywhere in the sources!).
-//
-// To solve this, we provide our own implementation of the sincos() function
-// and related friends. Note that we must also explicitely tell GCC to disable
-// optimizations when generating these. Otherwise, the generated machine code
-// for each function would simply end up calling itself, resulting in a
-// runtime crash due to stack overflow.
-//
-#if defined(__GNUC__) && !defined(__clang__) && \
- !defined(ANDROID_SINCOS_PROVIDED)
-
-// For the record, Clang does not support the 'optimize' attribute.
-// In the unlikely event that it begins performing this optimization too,
-// we'll have to find a different way to achieve this. NOTE: Tested with O1
-// which still performs the optimization.
-//
-#define GCC_NO_OPTIMIZE __attribute__((optimize("O0")))
-
-GCC_NO_OPTIMIZE
-void sincos(double angle, double* s, double *c) {
- *c = cos(angle);
- *s = sin(angle);
-}
-
-GCC_NO_OPTIMIZE
-void sincosf(float angle, float* s, float* c) {
- *c = cosf(angle);
- *s = sinf(angle);
-}
-
-#endif // __GNUC__ && !__clang__
-
-// An implementation of mkdtemp, since it is not exposed by the NDK
-// for native API level 9 that we target.
-//
-// For any changes in the mkdtemp function, you should manually run the unittest
-// OsCompatAndroidTest.DISABLED_TestMkdTemp in your local machine to check if it
-// passes. Please don't enable it, since it creates a directory and may be
-// source of flakyness.
-char* mkdtemp(char* path) {
- if (path == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- const int path_len = strlen(path);
-
- // The last six characters of 'path' must be XXXXXX.
- const base::StringPiece kSuffix("XXXXXX");
- const int kSuffixLen = kSuffix.length();
- if (!base::StringPiece(path, path_len).ends_with(kSuffix)) {
- errno = EINVAL;
- return NULL;
- }
-
- // If the path contains a directory, as in /tmp/foo/XXXXXXXX, make sure
- // that /tmp/foo exists, otherwise we're going to loop a really long
- // time for nothing below
- char* dirsep = strrchr(path, '/');
- if (dirsep != NULL) {
- struct stat st;
- int ret;
-
- *dirsep = '\0'; // Terminating directory path temporarily
-
- ret = stat(path, &st);
-
- *dirsep = '/'; // Restoring directory separator
- if (ret < 0) // Directory probably does not exist
- return NULL;
- if (!S_ISDIR(st.st_mode)) { // Not a directory
- errno = ENOTDIR;
- return NULL;
- }
- }
-
- // Max number of tries using different random suffixes.
- const int kMaxTries = 100;
-
- // Now loop until we CAN create a directory by that name or we reach the max
- // number of tries.
- for (int i = 0; i < kMaxTries; ++i) {
- // Fill the suffix XXXXXX with a random string composed of a-z chars.
- for (int pos = 0; pos < kSuffixLen; ++pos) {
- char rand_char = static_cast<char>(base::RandInt('a', 'z'));
- path[path_len - kSuffixLen + pos] = rand_char;
- }
- if (mkdir(path, 0700) == 0) {
- // We just created the directory succesfully.
- return path;
- }
- if (errno != EEXIST) {
- // The directory doesn't exist, but an error occured
- return NULL;
- }
- }
-
- // We reached the max number of tries.
- return NULL;
-}
-
-} // extern "C"
diff --git a/base/os_compat_android.h b/base/os_compat_android.h
deleted file mode 100644
index e33b1f7ac3..0000000000
--- a/base/os_compat_android.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_OS_COMPAT_ANDROID_H_
-#define BASE_OS_COMPAT_ANDROID_H_
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <utime.h>
-
-// Not implemented in Bionic.
-extern "C" int futimes(int fd, const struct timeval tv[2]);
-
-// Not exposed or implemented in Bionic.
-extern "C" char* mkdtemp(char* path);
-
-// Android has no timegm().
-extern "C" time_t timegm(struct tm* const t);
-
-#endif // BASE_OS_COMPAT_ANDROID_H_
diff --git a/base/os_compat_android_unittest.cc b/base/os_compat_android_unittest.cc
deleted file mode 100644
index 7fbdc6dace..0000000000
--- a/base/os_compat_android_unittest.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/os_compat_android.h"
-
-#include "base/files/file_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-typedef testing::Test OsCompatAndroidTest;
-
-// Keep this Unittest DISABLED_ , because it actually creates a directory in the
-// device and it may be source of flakyness. For any changes in the mkdtemp
-// function, you should run this unittest in your local machine to check if it
-// passes.
-TEST_F(OsCompatAndroidTest, DISABLED_TestMkdTemp) {
- FilePath tmp_dir;
- EXPECT_TRUE(base::GetTempDir(&tmp_dir));
-
- // Not six XXXXXX at the suffix of the path.
- FilePath sub_dir = tmp_dir.Append("XX");
- std::string sub_dir_string = sub_dir.value();
- // this should be OK since mkdtemp just replaces characters in place
- char* buffer = const_cast<char*>(sub_dir_string.c_str());
- EXPECT_EQ(NULL, mkdtemp(buffer));
-
- // Directory does not exist
- char invalid_path2[] = "doesntoexist/foobarXXXXXX";
- EXPECT_EQ(NULL, mkdtemp(invalid_path2));
-
- // Successfully create a tmp dir.
- FilePath sub_dir2 = tmp_dir.Append("XXXXXX");
- std::string sub_dir2_string = sub_dir2.value();
- // this should be OK since mkdtemp just replaces characters in place
- char* buffer2 = const_cast<char*>(sub_dir2_string.c_str());
- EXPECT_TRUE(mkdtemp(buffer2) != NULL);
-}
-
-} // namespace base
diff --git a/base/path_service_unittest.cc b/base/path_service_unittest.cc
deleted file mode 100644
index cf69ef111c..0000000000
--- a/base/path_service_unittest.cc
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/path_service.h"
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest-spi.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
-namespace base {
-
-namespace {
-
-// Returns true if PathService::Get returns true and sets the path parameter
-// to non-empty for the given PathService::DirType enumeration value.
-bool ReturnsValidPath(int dir_type) {
- FilePath path;
- bool result = PathService::Get(dir_type, &path);
-
- // Some paths might not exist on some platforms in which case confirming
- // |result| is true and !path.empty() is the best we can do.
- bool check_path_exists = true;
-#if defined(OS_POSIX)
- // If chromium has never been started on this account, the cache path may not
- // exist.
- if (dir_type == DIR_CACHE)
- check_path_exists = false;
-#endif
-#if defined(OS_LINUX)
- // On the linux try-bots: a path is returned (e.g. /home/chrome-bot/Desktop),
- // but it doesn't exist.
- if (dir_type == DIR_USER_DESKTOP)
- check_path_exists = false;
-#endif
-#if defined(OS_IOS)
- // Bundled unittests on iOS may not have Resources directory in the bundle.
- if (dir_type == DIR_ASSETS)
- check_path_exists = false;
-#endif
-#if defined(OS_MACOSX)
- if (dir_type != DIR_EXE && dir_type != DIR_MODULE && dir_type != FILE_EXE &&
- dir_type != FILE_MODULE) {
- if (path.ReferencesParent())
- return false;
- }
-#else
- if (path.ReferencesParent())
- return false;
-#endif
- return result && !path.empty() && (!check_path_exists || PathExists(path));
-}
-
-#if defined(OS_WIN)
-// Function to test any directory keys that are not supported on some versions
-// of Windows. Checks that the function fails and that the returned path is
-// empty.
-bool ReturnsInvalidPath(int dir_type) {
- FilePath path;
- bool result = PathService::Get(dir_type, &path);
- return !result && path.empty();
-}
-#endif
-
-} // namespace
-
-// On the Mac this winds up using some autoreleased objects, so we need to
-// be a PlatformTest.
-typedef PlatformTest PathServiceTest;
-
-// Test that all PathService::Get calls return a value and a true result
-// in the development environment. (This test was created because a few
-// later changes to Get broke the semantics of the function and yielded the
-// correct value while returning false.)
-TEST_F(PathServiceTest, Get) {
- for (int key = PATH_START + 1; key < PATH_END; ++key) {
-#if defined(OS_ANDROID)
- if (key == FILE_MODULE || key == DIR_USER_DESKTOP ||
- key == DIR_HOME)
- continue; // Android doesn't implement these.
-#elif defined(OS_IOS)
- if (key == DIR_USER_DESKTOP)
- continue; // iOS doesn't implement DIR_USER_DESKTOP.
-#elif defined(OS_FUCHSIA)
- if (key == DIR_USER_DESKTOP || key == FILE_MODULE || key == DIR_MODULE)
- continue; // Fuchsia doesn't implement DIR_USER_DESKTOP, FILE_MODULE and
- // DIR_MODULE.
-#endif
- EXPECT_PRED1(ReturnsValidPath, key);
- }
-#if defined(OS_WIN)
- for (int key = PATH_WIN_START + 1; key < PATH_WIN_END; ++key) {
- bool valid = true;
- if (key == DIR_APP_SHORTCUTS)
- valid = base::win::GetVersion() >= base::win::VERSION_WIN8;
-
- if (valid)
- EXPECT_TRUE(ReturnsValidPath(key)) << key;
- else
- EXPECT_TRUE(ReturnsInvalidPath(key)) << key;
- }
-#elif defined(OS_MACOSX)
- for (int key = PATH_MAC_START + 1; key < PATH_MAC_END; ++key) {
- EXPECT_PRED1(ReturnsValidPath, key);
- }
-#elif defined(OS_ANDROID)
- for (int key = PATH_ANDROID_START + 1; key < PATH_ANDROID_END;
- ++key) {
- EXPECT_PRED1(ReturnsValidPath, key);
- }
-#elif defined(OS_POSIX)
- for (int key = PATH_POSIX_START + 1; key < PATH_POSIX_END;
- ++key) {
- EXPECT_PRED1(ReturnsValidPath, key);
- }
-#endif
-}
-
-// Test that all versions of the Override function of PathService do what they
-// are supposed to do.
-TEST_F(PathServiceTest, Override) {
- int my_special_key = 666;
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath fake_cache_dir(temp_dir.GetPath().AppendASCII("cache"));
- // PathService::Override should always create the path provided if it doesn't
- // exist.
- EXPECT_TRUE(PathService::Override(my_special_key, fake_cache_dir));
- EXPECT_TRUE(PathExists(fake_cache_dir));
-
- FilePath fake_cache_dir2(temp_dir.GetPath().AppendASCII("cache2"));
- // PathService::OverrideAndCreateIfNeeded should obey the |create| parameter.
- PathService::OverrideAndCreateIfNeeded(my_special_key,
- fake_cache_dir2,
- false,
- false);
- EXPECT_FALSE(PathExists(fake_cache_dir2));
- EXPECT_TRUE(PathService::OverrideAndCreateIfNeeded(my_special_key,
- fake_cache_dir2,
- false,
- true));
- EXPECT_TRUE(PathExists(fake_cache_dir2));
-
-#if defined(OS_POSIX)
- FilePath non_existent(
- MakeAbsoluteFilePath(temp_dir.GetPath()).AppendASCII("non_existent"));
- EXPECT_TRUE(non_existent.IsAbsolute());
- EXPECT_FALSE(PathExists(non_existent));
-#if !defined(OS_ANDROID)
- // This fails because MakeAbsoluteFilePath fails for non-existent files.
- // Earlier versions of Bionic libc don't fail for non-existent files, so
- // skip this check on Android.
- EXPECT_FALSE(PathService::OverrideAndCreateIfNeeded(my_special_key,
- non_existent,
- false,
- false));
-#endif
- // This works because indicating that |non_existent| is absolute skips the
- // internal MakeAbsoluteFilePath call.
- EXPECT_TRUE(PathService::OverrideAndCreateIfNeeded(my_special_key,
- non_existent,
- true,
- false));
- // Check that the path has been overridden and no directory was created.
- EXPECT_FALSE(PathExists(non_existent));
- FilePath path;
- EXPECT_TRUE(PathService::Get(my_special_key, &path));
- EXPECT_EQ(non_existent, path);
-#endif
-}
-
-// Check if multiple overrides can co-exist.
-TEST_F(PathServiceTest, OverrideMultiple) {
- int my_special_key = 666;
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath fake_cache_dir1(temp_dir.GetPath().AppendASCII("1"));
- EXPECT_TRUE(PathService::Override(my_special_key, fake_cache_dir1));
- EXPECT_TRUE(PathExists(fake_cache_dir1));
- ASSERT_EQ(1, WriteFile(fake_cache_dir1.AppendASCII("t1"), ".", 1));
-
- FilePath fake_cache_dir2(temp_dir.GetPath().AppendASCII("2"));
- EXPECT_TRUE(PathService::Override(my_special_key + 1, fake_cache_dir2));
- EXPECT_TRUE(PathExists(fake_cache_dir2));
- ASSERT_EQ(1, WriteFile(fake_cache_dir2.AppendASCII("t2"), ".", 1));
-
- FilePath result;
- EXPECT_TRUE(PathService::Get(my_special_key, &result));
- // Override might have changed the path representation but our test file
- // should be still there.
- EXPECT_TRUE(PathExists(result.AppendASCII("t1")));
- EXPECT_TRUE(PathService::Get(my_special_key + 1, &result));
- EXPECT_TRUE(PathExists(result.AppendASCII("t2")));
-}
-
-TEST_F(PathServiceTest, RemoveOverride) {
- // Before we start the test we have to call RemoveOverride at least once to
- // clear any overrides that might have been left from other tests.
- PathService::RemoveOverride(DIR_TEMP);
-
- FilePath original_user_data_dir;
- EXPECT_TRUE(PathService::Get(DIR_TEMP, &original_user_data_dir));
- EXPECT_FALSE(PathService::RemoveOverride(DIR_TEMP));
-
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- EXPECT_TRUE(PathService::Override(DIR_TEMP, temp_dir.GetPath()));
- FilePath new_user_data_dir;
- EXPECT_TRUE(PathService::Get(DIR_TEMP, &new_user_data_dir));
- EXPECT_NE(original_user_data_dir, new_user_data_dir);
-
- EXPECT_TRUE(PathService::RemoveOverride(DIR_TEMP));
- EXPECT_TRUE(PathService::Get(DIR_TEMP, &new_user_data_dir));
- EXPECT_EQ(original_user_data_dir, new_user_data_dir);
-}
-
-#if defined(OS_WIN)
-TEST_F(PathServiceTest, GetProgramFiles) {
- FilePath programfiles_dir;
-#if defined(_WIN64)
- // 64-bit on 64-bit.
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files"));
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILESX86,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files (x86)"));
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES6432,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files"));
-#else
- if (base::win::OSInfo::GetInstance()->wow64_status() ==
- base::win::OSInfo::WOW64_ENABLED) {
- // 32-bit on 64-bit.
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files (x86)"));
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILESX86,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files (x86)"));
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES6432,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files"));
- } else {
- // 32-bit on 32-bit.
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files"));
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILESX86,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files"));
- EXPECT_TRUE(PathService::Get(DIR_PROGRAM_FILES6432,
- &programfiles_dir));
- EXPECT_EQ(programfiles_dir.value(),
- FILE_PATH_LITERAL("C:\\Program Files"));
- }
-#endif
-}
-#endif
-
-} // namespace base
diff --git a/base/posix/safe_strerror.cc b/base/posix/safe_strerror.cc
index aab8b87921..aef5742d33 100644
--- a/base/posix/safe_strerror.cc
+++ b/base/posix/safe_strerror.cc
@@ -2,6 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#if defined(__ANDROID__)
+// Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE
+// is defined, but the symbol is renamed to __gnu_strerror_r which only exists
+// on those later versions. To preserve ABI compatibility with older versions,
+// undefine _GNU_SOURCE and use the POSIX version.
+#undef _GNU_SOURCE
+#endif
+
#include "base/posix/safe_strerror.h"
#include <errno.h>
@@ -14,11 +22,6 @@ namespace base {
#if defined(__GLIBC__) || defined(OS_NACL)
#define USE_HISTORICAL_STRERRO_R 1
-// Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE
-// is defined, but the symbol is renamed to __gnu_strerror_r which only exists
-// on those later versions. For parity, add the same condition as bionic.
-#elif defined(__BIONIC__) && defined(_GNU_SOURCE) && __ANDROID_API__ >= 23
-#define USE_HISTORICAL_STRERRO_R 1
#else
#define USE_HISTORICAL_STRERRO_R 0
#endif
diff --git a/base/power_monitor/power_monitor.cc b/base/power_monitor/power_monitor.cc
deleted file mode 100644
index ba0ef6bdfc..0000000000
--- a/base/power_monitor/power_monitor.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 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/power_monitor/power_monitor.h"
-
-#include <utility>
-
-#include "base/power_monitor/power_monitor_source.h"
-
-namespace base {
-
-static PowerMonitor* g_power_monitor = nullptr;
-
-PowerMonitor::PowerMonitor(std::unique_ptr<PowerMonitorSource> source)
- : observers_(new ObserverListThreadSafe<PowerObserver>()),
- source_(std::move(source)) {
- DCHECK(!g_power_monitor);
- g_power_monitor = this;
-}
-
-PowerMonitor::~PowerMonitor() {
- source_->Shutdown();
- DCHECK_EQ(this, g_power_monitor);
- g_power_monitor = nullptr;
-}
-
-// static
-PowerMonitor* PowerMonitor::Get() {
- return g_power_monitor;
-}
-
-void PowerMonitor::AddObserver(PowerObserver* obs) {
- observers_->AddObserver(obs);
-}
-
-void PowerMonitor::RemoveObserver(PowerObserver* obs) {
- observers_->RemoveObserver(obs);
-}
-
-PowerMonitorSource* PowerMonitor::Source() {
- return source_.get();
-}
-
-bool PowerMonitor::IsOnBatteryPower() {
- return source_->IsOnBatteryPower();
-}
-
-void PowerMonitor::NotifyPowerStateChange(bool battery_in_use) {
- DVLOG(1) << "PowerStateChange: " << (battery_in_use ? "On" : "Off")
- << " battery";
- observers_->Notify(FROM_HERE, &PowerObserver::OnPowerStateChange,
- battery_in_use);
-}
-
-void PowerMonitor::NotifySuspend() {
- DVLOG(1) << "Power Suspending";
- observers_->Notify(FROM_HERE, &PowerObserver::OnSuspend);
-}
-
-void PowerMonitor::NotifyResume() {
- DVLOG(1) << "Power Resuming";
- observers_->Notify(FROM_HERE, &PowerObserver::OnResume);
-}
-
-} // namespace base
diff --git a/base/power_monitor/power_monitor_device_source.cc b/base/power_monitor/power_monitor_device_source.cc
deleted file mode 100644
index f42065499f..0000000000
--- a/base/power_monitor/power_monitor_device_source.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 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/power_monitor/power_monitor_device_source.h"
-
-namespace base {
-
-PowerMonitorDeviceSource::PowerMonitorDeviceSource() {
-#if defined(OS_MACOSX)
- PlatformInit();
-#endif
-
-#if defined(OS_WIN) || defined(OS_MACOSX)
- // Provide the correct battery status if possible. Others platforms, such as
- // Android and ChromeOS, will update their status once their backends are
- // actually initialized.
- SetInitialOnBatteryPowerState(IsOnBatteryPowerImpl());
-#endif
-}
-
-PowerMonitorDeviceSource::~PowerMonitorDeviceSource() {
-#if defined(OS_MACOSX)
- PlatformDestroy();
-#endif
-}
-
-// PowerMonitorDeviceSource does not need to take any special action to ensure
-// that it doesn't callback into PowerMonitor after this phase of shutdown has
-// completed.
-void PowerMonitorDeviceSource::Shutdown() {}
-
-} // namespace base
diff --git a/base/power_monitor/power_monitor_device_source_android.cc b/base/power_monitor/power_monitor_device_source_android.cc
deleted file mode 100644
index 7688513501..0000000000
--- a/base/power_monitor/power_monitor_device_source_android.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2013 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/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_device_source.h"
-#include "base/power_monitor/power_monitor_source.h"
-#include "jni/PowerMonitor_jni.h"
-
-namespace base {
-
-// A helper function which is a friend of PowerMonitorSource.
-void ProcessPowerEventHelper(PowerMonitorSource::PowerEvent event) {
- PowerMonitorSource::ProcessPowerEvent(event);
-}
-
-namespace android {
-
-// Native implementation of PowerMonitor.java. Note: This will be invoked by
-// PowerMonitor.java shortly after startup to set the correct initial value for
-// "is on battery power."
-void JNI_PowerMonitor_OnBatteryChargingChanged(
- JNIEnv* env,
- const JavaParamRef<jclass>& clazz) {
- ProcessPowerEventHelper(PowerMonitorSource::POWER_STATE_EVENT);
-}
-
-// Note: Android does not have the concept of suspend / resume as it's known by
-// other platforms. Thus we do not send Suspend/Resume notifications. See
-// http://crbug.com/644515
-
-} // namespace android
-
-bool PowerMonitorDeviceSource::IsOnBatteryPowerImpl() {
- JNIEnv* env = base::android::AttachCurrentThread();
- return base::android::Java_PowerMonitor_isBatteryPower(env);
-}
-
-} // namespace base
diff --git a/base/power_monitor/power_monitor_device_source_chromeos.cc b/base/power_monitor/power_monitor_device_source_chromeos.cc
deleted file mode 100644
index c3466ee15a..0000000000
--- a/base/power_monitor/power_monitor_device_source_chromeos.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_device_source.h"
-#include "base/power_monitor/power_monitor_source.h"
-
-namespace base {
-
-namespace {
-
-// The most-recently-seen power source.
-bool g_on_battery = false;
-
-} // namespace
-
-// static
-void PowerMonitorDeviceSource::SetPowerSource(bool on_battery) {
- if (on_battery != g_on_battery) {
- g_on_battery = on_battery;
- ProcessPowerEvent(POWER_STATE_EVENT);
- }
-}
-
-// static
-void PowerMonitorDeviceSource::HandleSystemSuspending() {
- ProcessPowerEvent(SUSPEND_EVENT);
-}
-
-// static
-void PowerMonitorDeviceSource::HandleSystemResumed() {
- ProcessPowerEvent(RESUME_EVENT);
-}
-
-bool PowerMonitorDeviceSource::IsOnBatteryPowerImpl() {
- return g_on_battery;
-}
-
-} // namespace base
diff --git a/base/power_monitor/power_monitor_device_source_stub.cc b/base/power_monitor/power_monitor_device_source_stub.cc
deleted file mode 100644
index f24e5b23f0..0000000000
--- a/base/power_monitor/power_monitor_device_source_stub.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2013 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/power_monitor/power_monitor_device_source.h"
-
-namespace base {
-
-bool PowerMonitorDeviceSource::IsOnBatteryPowerImpl() {
- NOTIMPLEMENTED();
- return false;
-}
-
-} // namespace base
diff --git a/base/power_monitor/power_monitor_source.cc b/base/power_monitor/power_monitor_source.cc
deleted file mode 100644
index d4757b0629..0000000000
--- a/base/power_monitor/power_monitor_source.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2013 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/power_monitor/power_monitor_source.h"
-
-#include "base/power_monitor/power_monitor.h"
-#include "build/build_config.h"
-
-namespace base {
-
-PowerMonitorSource::PowerMonitorSource() = default;
-PowerMonitorSource::~PowerMonitorSource() = default;
-
-bool PowerMonitorSource::IsOnBatteryPower() {
- AutoLock auto_lock(battery_lock_);
- return on_battery_power_;
-}
-
-void PowerMonitorSource::ProcessPowerEvent(PowerEvent event_id) {
- PowerMonitor* monitor = PowerMonitor::Get();
- if (!monitor)
- return;
-
- PowerMonitorSource* source = monitor->Source();
-
- // Suppress duplicate notifications. Some platforms may
- // send multiple notifications of the same event.
- switch (event_id) {
- case POWER_STATE_EVENT:
- {
- bool new_on_battery_power = source->IsOnBatteryPowerImpl();
- bool changed = false;
-
- {
- AutoLock auto_lock(source->battery_lock_);
- if (source->on_battery_power_ != new_on_battery_power) {
- changed = true;
- source->on_battery_power_ = new_on_battery_power;
- }
- }
-
- if (changed)
- monitor->NotifyPowerStateChange(new_on_battery_power);
- }
- break;
- case RESUME_EVENT:
- if (source->suspended_) {
- source->suspended_ = false;
- monitor->NotifyResume();
- }
- break;
- case SUSPEND_EVENT:
- if (!source->suspended_) {
- source->suspended_ = true;
- monitor->NotifySuspend();
- }
- break;
- }
-}
-
-void PowerMonitorSource::SetInitialOnBatteryPowerState(bool on_battery_power) {
- // Must only be called before a monitor exists, otherwise the caller should
- // have just used a normal ProcessPowerEvent(POWER_STATE_EVENT) call.
- DCHECK(!PowerMonitor::Get());
- on_battery_power_ = on_battery_power;
-}
-
-} // namespace base
diff --git a/base/power_monitor/power_monitor_unittest.cc b/base/power_monitor/power_monitor_unittest.cc
deleted file mode 100644
index 7f2a84b774..0000000000
--- a/base/power_monitor/power_monitor_unittest.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2013 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/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/power_monitor/power_monitor.h"
-#include "base/test/power_monitor_test_base.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class PowerMonitorTest : public testing::Test {
- protected:
- PowerMonitorTest() {
- power_monitor_source_ = new PowerMonitorTestSource();
- power_monitor_.reset(new PowerMonitor(
- std::unique_ptr<PowerMonitorSource>(power_monitor_source_)));
- }
- ~PowerMonitorTest() override = default;
-
- PowerMonitorTestSource* source() { return power_monitor_source_; }
- PowerMonitor* monitor() { return power_monitor_.get(); }
-
- private:
- base::MessageLoop message_loop_;
- PowerMonitorTestSource* power_monitor_source_;
- std::unique_ptr<PowerMonitor> power_monitor_;
-
- DISALLOW_COPY_AND_ASSIGN(PowerMonitorTest);
-};
-
-// PowerMonitorSource is tightly coupled with the PowerMonitor, so this test
-// Will cover both classes
-TEST_F(PowerMonitorTest, PowerNotifications) {
- const int kObservers = 5;
-
- PowerMonitorTestObserver observers[kObservers];
- for (int index = 0; index < kObservers; ++index)
- monitor()->AddObserver(&observers[index]);
-
- // Sending resume when not suspended should have no effect.
- source()->GenerateResumeEvent();
- EXPECT_EQ(observers[0].resumes(), 0);
-
- // Pretend we suspended.
- source()->GenerateSuspendEvent();
- // Ensure all observers were notified of the event
- for (int index = 0; index < kObservers; ++index)
- EXPECT_EQ(observers[index].suspends(), 1);
-
- // Send a second suspend notification. This should be suppressed.
- source()->GenerateSuspendEvent();
- EXPECT_EQ(observers[0].suspends(), 1);
-
- // Pretend we were awakened.
- source()->GenerateResumeEvent();
- EXPECT_EQ(observers[0].resumes(), 1);
-
- // Send a duplicate resume notification. This should be suppressed.
- source()->GenerateResumeEvent();
- EXPECT_EQ(observers[0].resumes(), 1);
-
- // Pretend the device has gone on battery power
- source()->GeneratePowerStateEvent(true);
- EXPECT_EQ(observers[0].power_state_changes(), 1);
- EXPECT_EQ(observers[0].last_power_state(), true);
-
- // Repeated indications the device is on battery power should be suppressed.
- source()->GeneratePowerStateEvent(true);
- EXPECT_EQ(observers[0].power_state_changes(), 1);
-
- // Pretend the device has gone off battery power
- source()->GeneratePowerStateEvent(false);
- EXPECT_EQ(observers[0].power_state_changes(), 2);
- EXPECT_EQ(observers[0].last_power_state(), false);
-
- // Repeated indications the device is off battery power should be suppressed.
- source()->GeneratePowerStateEvent(false);
- EXPECT_EQ(observers[0].power_state_changes(), 2);
-}
-
-} // namespace base
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc
deleted file mode 100644
index 835cf7e485..0000000000
--- a/base/process/memory_unittest.cc
+++ /dev/null
@@ -1,533 +0,0 @@
-// Copyright (c) 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.
-
-#define _CRT_SECURE_NO_WARNINGS
-
-#include "base/process/memory.h"
-
-#include <stddef.h>
-
-#include <limits>
-
-#include "base/allocator/allocator_check.h"
-#include "base/allocator/buildflags.h"
-#include "base/compiler_specific.h"
-#include "base/debug/alias.h"
-#include "base/memory/aligned_memory.h"
-#include "base/strings/stringprintf.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-#if defined(OS_POSIX)
-#include <errno.h>
-#endif
-#if defined(OS_MACOSX)
-#include <malloc/malloc.h>
-#include "base/allocator/allocator_interception_mac.h"
-#include "base/allocator/allocator_shim.h"
-#include "base/process/memory_unittest_mac.h"
-#endif
-#if defined(OS_LINUX)
-#include <malloc.h>
-#include "base/test/malloc_wrapper.h"
-#endif
-
-#if defined(OS_WIN)
-
-#if defined(COMPILER_MSVC)
-// ssize_t needed for OutOfMemoryTest.
-#if defined(_WIN64)
-typedef __int64 ssize_t;
-#else
-typedef long ssize_t;
-#endif
-#endif
-
-// HeapQueryInformation function pointer.
-typedef BOOL (WINAPI* HeapQueryFn) \
- (HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
-
-#endif // defined(OS_WIN)
-
-#if defined(OS_MACOSX)
-
-// For the following Mac tests:
-// Note that base::EnableTerminationOnHeapCorruption() is called as part of
-// test suite setup and does not need to be done again, else mach_override
-// will fail.
-
-TEST(ProcessMemoryTest, MacTerminateOnHeapCorruption) {
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
- base::allocator::InitializeAllocatorShim();
-#endif
- // Assert that freeing an unallocated pointer will crash the process.
- char buf[9];
- asm("" : "=r" (buf)); // Prevent clang from being too smart.
-#if ARCH_CPU_64_BITS
- // On 64 bit Macs, the malloc system automatically abort()s on heap corruption
- // but does not output anything.
- ASSERT_DEATH(free(buf), "");
-#elif defined(ADDRESS_SANITIZER)
- // AddressSanitizer replaces malloc() and prints a different error message on
- // heap corruption.
- ASSERT_DEATH(free(buf), "attempting free on address which "
- "was not malloc\\(\\)-ed");
-#else
- ADD_FAILURE() << "This test is not supported in this build configuration.";
-#endif
-
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
- base::allocator::UninterceptMallocZonesForTesting();
-#endif
-}
-
-#endif // defined(OS_MACOSX)
-
-TEST(MemoryTest, AllocatorShimWorking) {
-#if defined(OS_MACOSX)
-#if BUILDFLAG(USE_ALLOCATOR_SHIM)
- base::allocator::InitializeAllocatorShim();
-#endif
- base::allocator::InterceptAllocationsMac();
-#endif
- ASSERT_TRUE(base::allocator::IsAllocatorInitialized());
-
-#if defined(OS_MACOSX)
- base::allocator::UninterceptMallocZonesForTesting();
-#endif
-}
-
-// OpenBSD does not support these tests. Don't test these on ASan/TSan/MSan
-// configurations: only test the real allocator.
-// Windows only supports these tests with the allocator shim in place.
-#if !defined(OS_OPENBSD) && BUILDFLAG(USE_ALLOCATOR_SHIM) && \
- !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-
-namespace {
-#if defined(OS_WIN)
-// Windows raises an exception rather than using LOG(FATAL) in order to make the
-// exit code unique to OOM.
-const char* kOomRegex = "";
-const int kExitCode = base::win::kOomExceptionCode;
-#else
-const char* kOomRegex = "Out of memory";
-const int kExitCode = 1;
-#endif
-} // namespace
-
-class OutOfMemoryTest : public testing::Test {
- public:
- OutOfMemoryTest()
- : value_(nullptr),
- // Make test size as large as possible minus a few pages so
- // that alignment or other rounding doesn't make it wrap.
- test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024),
- // A test size that is > 2Gb and will cause the allocators to reject
- // the allocation due to security restrictions. See crbug.com/169327.
- insecure_test_size_(std::numeric_limits<int>::max()),
- signed_test_size_(std::numeric_limits<ssize_t>::max()) {}
-
- protected:
- void* value_;
- size_t test_size_;
- size_t insecure_test_size_;
- ssize_t signed_test_size_;
-};
-
-class OutOfMemoryDeathTest : public OutOfMemoryTest {
- public:
- void SetUpInDeathAssert() {
-#if defined(OS_MACOSX) && BUILDFLAG(USE_ALLOCATOR_SHIM)
- base::allocator::InitializeAllocatorShim();
-#endif
-
- // Must call EnableTerminationOnOutOfMemory() because that is called from
- // chrome's main function and therefore hasn't been called yet.
- // Since this call may result in another thread being created and death
- // tests shouldn't be started in a multithread environment, this call
- // should be done inside of the ASSERT_DEATH.
- base::EnableTerminationOnOutOfMemory();
- }
-
-#if defined(OS_MACOSX)
- void TearDown() override {
- base::allocator::UninterceptMallocZonesForTesting();
- }
-#endif
-};
-
-TEST_F(OutOfMemoryDeathTest, New) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = operator new(test_size_);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, NewArray) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = new char[test_size_];
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, Malloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = malloc(test_size_);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, Realloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = realloc(nullptr, test_size_);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, Calloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = calloc(1024, test_size_ / 1024L);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, AlignedAlloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = base::AlignedAlloc(test_size_, 8);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-// POSIX does not define an aligned realloc function.
-#if defined(OS_WIN)
-TEST_F(OutOfMemoryDeathTest, AlignedRealloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = _aligned_realloc(NULL, test_size_, 8);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-namespace {
-
-constexpr uint32_t kUnhandledExceptionExitCode = 0xBADA55;
-
-// This unhandled exception filter exits the process with an exit code distinct
-// from the exception code. This is to verify that the out of memory new handler
-// causes an unhandled exception.
-LONG WINAPI ExitingUnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) {
- _exit(kUnhandledExceptionExitCode);
-}
-
-} // namespace
-
-TEST_F(OutOfMemoryDeathTest, NewHandlerGeneratesUnhandledException) {
- ASSERT_EXIT(
- {
- SetUpInDeathAssert();
- SetUnhandledExceptionFilter(&ExitingUnhandledExceptionFilter);
- value_ = new char[test_size_];
- },
- testing::ExitedWithCode(kUnhandledExceptionExitCode), kOomRegex);
-}
-#endif // defined(OS_WIN)
-
-// OS X and Android have no 2Gb allocation limit.
-// See https://crbug.com/169327.
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
-TEST_F(OutOfMemoryDeathTest, SecurityNew) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = operator new(insecure_test_size_);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, SecurityNewArray) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = new char[insecure_test_size_];
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, SecurityMalloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = malloc(insecure_test_size_);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, SecurityRealloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = realloc(nullptr, insecure_test_size_);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, SecurityCalloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = calloc(1024, insecure_test_size_ / 1024L);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, SecurityAlignedAlloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = base::AlignedAlloc(insecure_test_size_, 8);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-
-// POSIX does not define an aligned realloc function.
-#if defined(OS_WIN)
-TEST_F(OutOfMemoryDeathTest, SecurityAlignedRealloc) {
- ASSERT_EXIT({
- SetUpInDeathAssert();
- value_ = _aligned_realloc(NULL, insecure_test_size_, 8);
- }, testing::ExitedWithCode(kExitCode), kOomRegex);
-}
-#endif // defined(OS_WIN)
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
-
-#if defined(OS_LINUX)
-
-TEST_F(OutOfMemoryDeathTest, Valloc) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = valloc(test_size_);
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, SecurityValloc) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = valloc(insecure_test_size_);
- }, kOomRegex);
-}
-
-#if PVALLOC_AVAILABLE == 1
-TEST_F(OutOfMemoryDeathTest, Pvalloc) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = pvalloc(test_size_);
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, SecurityPvalloc) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = pvalloc(insecure_test_size_);
- }, kOomRegex);
-}
-#endif // PVALLOC_AVAILABLE == 1
-
-TEST_F(OutOfMemoryDeathTest, Memalign) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = memalign(4, test_size_);
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, ViaSharedLibraries) {
- // This tests that the run-time symbol resolution is overriding malloc for
- // shared libraries as well as for our code.
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = MallocWrapper(test_size_);
- }, kOomRegex);
-}
-#endif // OS_LINUX
-
-// Android doesn't implement posix_memalign().
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
-TEST_F(OutOfMemoryDeathTest, Posix_memalign) {
- // Grab the return value of posix_memalign to silence a compiler warning
- // about unused return values. We don't actually care about the return
- // value, since we're asserting death.
- ASSERT_DEATH({
- SetUpInDeathAssert();
- EXPECT_EQ(ENOMEM, posix_memalign(&value_, 8, test_size_));
- }, kOomRegex);
-}
-#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
-
-#if defined(OS_MACOSX)
-
-// Purgeable zone tests
-
-TEST_F(OutOfMemoryDeathTest, MallocPurgeable) {
- malloc_zone_t* zone = malloc_default_purgeable_zone();
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = malloc_zone_malloc(zone, test_size_);
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, ReallocPurgeable) {
- malloc_zone_t* zone = malloc_default_purgeable_zone();
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = malloc_zone_realloc(zone, NULL, test_size_);
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, CallocPurgeable) {
- malloc_zone_t* zone = malloc_default_purgeable_zone();
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = malloc_zone_calloc(zone, 1024, test_size_ / 1024L);
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, VallocPurgeable) {
- malloc_zone_t* zone = malloc_default_purgeable_zone();
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = malloc_zone_valloc(zone, test_size_);
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, PosixMemalignPurgeable) {
- malloc_zone_t* zone = malloc_default_purgeable_zone();
- ASSERT_DEATH({
- SetUpInDeathAssert();
- value_ = malloc_zone_memalign(zone, 8, test_size_);
- }, kOomRegex);
-}
-
-// Since these allocation functions take a signed size, it's possible that
-// calling them just once won't be enough to exhaust memory. In the 32-bit
-// environment, it's likely that these allocation attempts will fail because
-// not enough contiguous address space is available. In the 64-bit environment,
-// it's likely that they'll fail because they would require a preposterous
-// amount of (virtual) memory.
-
-TEST_F(OutOfMemoryDeathTest, CFAllocatorSystemDefault) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- while ((value_ =
- base::AllocateViaCFAllocatorSystemDefault(signed_test_size_))) {}
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, CFAllocatorMalloc) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- while ((value_ =
- base::AllocateViaCFAllocatorMalloc(signed_test_size_))) {}
- }, kOomRegex);
-}
-
-TEST_F(OutOfMemoryDeathTest, CFAllocatorMallocZone) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- while ((value_ =
- base::AllocateViaCFAllocatorMallocZone(signed_test_size_))) {}
- }, kOomRegex);
-}
-
-#if !defined(ARCH_CPU_64_BITS)
-
-// See process_util_unittest_mac.mm for an explanation of why this test isn't
-// run in the 64-bit environment.
-
-TEST_F(OutOfMemoryDeathTest, PsychoticallyBigObjCObject) {
- ASSERT_DEATH({
- SetUpInDeathAssert();
- while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {}
- }, kOomRegex);
-}
-
-#endif // !ARCH_CPU_64_BITS
-#endif // OS_MACOSX
-
-class OutOfMemoryHandledTest : public OutOfMemoryTest {
- public:
- static const size_t kSafeMallocSize = 512;
- static const size_t kSafeCallocSize = 128;
- static const size_t kSafeCallocItems = 4;
-
- void SetUp() override {
- OutOfMemoryTest::SetUp();
-
- // We enable termination on OOM - just as Chrome does at early
- // initialization - and test that UncheckedMalloc and UncheckedCalloc
- // properly by-pass this in order to allow the caller to handle OOM.
- base::EnableTerminationOnOutOfMemory();
- }
-
- void TearDown() override {
-#if defined(OS_MACOSX)
- base::allocator::UninterceptMallocZonesForTesting();
-#endif
- }
-};
-
-#if defined(OS_WIN)
-
-namespace {
-
-DWORD HandleOutOfMemoryException(EXCEPTION_POINTERS* exception_ptrs,
- size_t expected_size) {
- EXPECT_EQ(base::win::kOomExceptionCode,
- exception_ptrs->ExceptionRecord->ExceptionCode);
- EXPECT_LE(1U, exception_ptrs->ExceptionRecord->NumberParameters);
- EXPECT_EQ(expected_size,
- exception_ptrs->ExceptionRecord->ExceptionInformation[0]);
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-} // namespace
-
-TEST_F(OutOfMemoryTest, TerminateBecauseOutOfMemoryReportsAllocSize) {
-// On Windows, TerminateBecauseOutOfMemory reports the attempted allocation
-// size in the exception raised.
-#if defined(ARCH_CPU_64_BITS)
- // Test with a size larger than 32 bits on 64 bit machines.
- const size_t kAttemptedAllocationSize = 0xBADA55F00DULL;
-#else
- const size_t kAttemptedAllocationSize = 0xBADA55;
-#endif
-
- __try {
- base::TerminateBecauseOutOfMemory(kAttemptedAllocationSize);
- } __except (HandleOutOfMemoryException(GetExceptionInformation(),
- kAttemptedAllocationSize)) {
- }
-}
-#endif // OS_WIN
-
-// TODO(b.kelemen): make UncheckedMalloc and UncheckedCalloc work
-// on Windows as well.
-TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) {
- EXPECT_TRUE(base::UncheckedMalloc(kSafeMallocSize, &value_));
- EXPECT_TRUE(value_ != nullptr);
- free(value_);
-
- EXPECT_FALSE(base::UncheckedMalloc(test_size_, &value_));
- EXPECT_TRUE(value_ == nullptr);
-}
-
-TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) {
- EXPECT_TRUE(base::UncheckedCalloc(1, kSafeMallocSize, &value_));
- EXPECT_TRUE(value_ != nullptr);
- const char* bytes = static_cast<const char*>(value_);
- for (size_t i = 0; i < kSafeMallocSize; ++i)
- EXPECT_EQ(0, bytes[i]);
- free(value_);
-
- EXPECT_TRUE(
- base::UncheckedCalloc(kSafeCallocItems, kSafeCallocSize, &value_));
- EXPECT_TRUE(value_ != nullptr);
- bytes = static_cast<const char*>(value_);
- for (size_t i = 0; i < (kSafeCallocItems * kSafeCallocSize); ++i)
- EXPECT_EQ(0, bytes[i]);
- free(value_);
-
- EXPECT_FALSE(base::UncheckedCalloc(1, test_size_, &value_));
- EXPECT_TRUE(value_ == nullptr);
-}
-#endif // !defined(OS_OPENBSD) && BUILDFLAG(ENABLE_WIN_ALLOCATOR_SHIM_TESTS) &&
- // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
diff --git a/base/process/process_linux.cc b/base/process/process_linux.cc
deleted file mode 100644
index faf39afd4b..0000000000
--- a/base/process/process_linux.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (c) 2011 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/process/process.h"
-
-#include <errno.h>
-#include <sys/resource.h>
-
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_restrictions.h"
-#include "build/build_config.h"
-
-// Not defined on AIX by default.
-#if defined(OS_AIX)
-#define RLIMIT_NICE 20
-#endif
-
-namespace base {
-
-namespace {
-
-const int kForegroundPriority = 0;
-
-#if defined(OS_CHROMEOS)
-// We are more aggressive in our lowering of background process priority
-// for chromeos as we have much more control over other processes running
-// on the machine.
-//
-// TODO(davemoore) Refactor this by adding support for higher levels to set
-// the foregrounding / backgrounding process so we don't have to keep
-// chrome / chromeos specific logic here.
-const int kBackgroundPriority = 19;
-const char kControlPath[] = "/sys/fs/cgroup/cpu%s/cgroup.procs";
-const char kForeground[] = "/chrome_renderers/foreground";
-const char kBackground[] = "/chrome_renderers/background";
-const char kProcPath[] = "/proc/%d/cgroup";
-
-struct CGroups {
- // Check for cgroups files. ChromeOS supports these by default. It creates
- // a cgroup mount in /sys/fs/cgroup and then configures two cpu task groups,
- // one contains at most a single foreground renderer and the other contains
- // all background renderers. This allows us to limit the impact of background
- // renderers on foreground ones to a greater level than simple renicing.
- bool enabled;
- base::FilePath foreground_file;
- base::FilePath background_file;
-
- CGroups() {
- foreground_file =
- base::FilePath(base::StringPrintf(kControlPath, kForeground));
- background_file =
- base::FilePath(base::StringPrintf(kControlPath, kBackground));
- base::FileSystemType foreground_type;
- base::FileSystemType background_type;
- enabled =
- base::GetFileSystemType(foreground_file, &foreground_type) &&
- base::GetFileSystemType(background_file, &background_type) &&
- foreground_type == FILE_SYSTEM_CGROUP &&
- background_type == FILE_SYSTEM_CGROUP;
- }
-
- static CGroups& Get() {
- static auto& groups = *new CGroups;
- return groups;
- }
-};
-#else
-const int kBackgroundPriority = 5;
-#endif // defined(OS_CHROMEOS)
-
-bool CanReraisePriority() {
- // We won't be able to raise the priority if we don't have the right rlimit.
- // The limit may be adjusted in /etc/security/limits.conf for PAM systems.
- struct rlimit rlim;
- return (getrlimit(RLIMIT_NICE, &rlim) == 0) &&
- (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur);
-}
-
-} // namespace
-
-// static
-bool Process::CanBackgroundProcesses() {
-#if defined(OS_CHROMEOS)
- if (CGroups::Get().enabled)
- return true;
-#endif // defined(OS_CHROMEOS)
-
- static const bool can_reraise_priority = CanReraisePriority();
- return can_reraise_priority;
-}
-
-bool Process::IsProcessBackgrounded() const {
- DCHECK(IsValid());
-
-#if defined(OS_CHROMEOS)
- if (CGroups::Get().enabled) {
- // Used to allow reading the process priority from proc on thread launch.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- std::string proc;
- if (base::ReadFileToString(
- base::FilePath(StringPrintf(kProcPath, process_)), &proc)) {
- return IsProcessBackgroundedCGroup(proc);
- }
- return false;
- }
-#endif // defined(OS_CHROMEOS)
-
- return GetPriority() == kBackgroundPriority;
-}
-
-bool Process::SetProcessBackgrounded(bool background) {
- DCHECK(IsValid());
-
-#if defined(OS_CHROMEOS)
- if (CGroups::Get().enabled) {
- std::string pid = IntToString(process_);
- const base::FilePath file = background ? CGroups::Get().background_file
- : CGroups::Get().foreground_file;
- return base::WriteFile(file, pid.c_str(), pid.size()) > 0;
- }
-#endif // defined(OS_CHROMEOS)
-
- if (!CanBackgroundProcesses())
- return false;
-
- int priority = background ? kBackgroundPriority : kForegroundPriority;
- int result = setpriority(PRIO_PROCESS, process_, priority);
- DPCHECK(result == 0);
- return result == 0;
-}
-
-#if defined(OS_CHROMEOS)
-bool IsProcessBackgroundedCGroup(const StringPiece& cgroup_contents) {
- // The process can be part of multiple control groups, and for each cgroup
- // hierarchy there's an entry in the file. We look for a control group
- // named "/chrome_renderers/background" to determine if the process is
- // backgrounded. crbug.com/548818.
- std::vector<StringPiece> lines = SplitStringPiece(
- cgroup_contents, "\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
- for (const auto& line : lines) {
- std::vector<StringPiece> fields =
- SplitStringPiece(line, ":", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- if (fields.size() != 3U) {
- NOTREACHED();
- continue;
- }
- if (fields[2] == kBackground)
- return true;
- }
-
- return false;
-}
-#endif // defined(OS_CHROMEOS)
-
-#if defined(OS_CHROMEOS)
-// Reads /proc/<pid>/status and returns the PID in its PID namespace.
-// If the process is not in a PID namespace or /proc/<pid>/status does not
-// report NSpid, kNullProcessId is returned.
-ProcessId Process::GetPidInNamespace() const {
- std::string status;
- {
- // Synchronously reading files in /proc does not hit the disk.
- ThreadRestrictions::ScopedAllowIO allow_io;
- FilePath status_file =
- FilePath("/proc").Append(IntToString(process_)).Append("status");
- if (!ReadFileToString(status_file, &status)) {
- return kNullProcessId;
- }
- }
-
- StringPairs pairs;
- SplitStringIntoKeyValuePairs(status, ':', '\n', &pairs);
- for (const auto& pair : pairs) {
- const std::string& key = pair.first;
- const std::string& value_str = pair.second;
- if (key == "NSpid") {
- std::vector<StringPiece> split_value_str = SplitStringPiece(
- value_str, "\t", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
- if (split_value_str.size() <= 1) {
- return kNullProcessId;
- }
- int value;
- // The last value in the list is the PID in the namespace.
- if (!StringToInt(split_value_str.back(), &value)) {
- NOTREACHED();
- return kNullProcessId;
- }
- return value;
- }
- }
- return kNullProcessId;
-}
-#endif // defined(OS_CHROMEOS)
-
-} // namespace base
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
index b33b599618..ad741f8f13 100644
--- a/base/process/process_metrics_unittest.cc
+++ b/base/process/process_metrics_unittest.cc
@@ -571,7 +571,7 @@ MULTIPROCESS_TEST_MAIN(ChildMain) {
// ARC note: don't compile as SpawnMultiProcessTestChild brings in a lot of
// extra dependency.
-#if !defined(OS_ANDROID) && !defined(__ANDROID_HOST__)
+#if !defined(OS_ANDROID) && !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
TEST(ProcessMetricsTest, GetChildOpenFdCount) {
ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
@@ -600,7 +600,7 @@ TEST(ProcessMetricsTest, GetChildOpenFdCount) {
EXPECT_EQ(0, open_fds);
ASSERT_TRUE(child.Terminate(0, true));
}
-#endif // !defined(OS_ANDROID) && !defined(__ANDROID_HOST__)
+#endif // !defined(__ANDROID__)
#endif // defined(OS_LINUX)
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc
deleted file mode 100644
index 219944df7a..0000000000
--- a/base/process/process_unittest.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-// 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/process/process.h"
-
-#include <utility>
-
-#include "base/at_exit.h"
-#include "base/process/kill.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace {
-
-#if defined(OS_WIN)
-const int kExpectedStillRunningExitCode = 0x102;
-#else
-const int kExpectedStillRunningExitCode = 0;
-#endif
-
-#if defined(OS_MACOSX)
-// Fake port provider that returns the calling process's
-// task port, ignoring its argument.
-class FakePortProvider : public base::PortProvider {
- mach_port_t TaskForPid(base::ProcessHandle process) const override {
- return mach_task_self();
- }
-};
-#endif
-
-} // namespace
-
-namespace base {
-
-class ProcessTest : public MultiProcessTest {
-};
-
-TEST_F(ProcessTest, Create) {
- Process process(SpawnChild("SimpleChildProcess"));
- ASSERT_TRUE(process.IsValid());
- ASSERT_FALSE(process.is_current());
- EXPECT_NE(process.Pid(), kNullProcessId);
- process.Close();
- ASSERT_FALSE(process.IsValid());
-}
-
-TEST_F(ProcessTest, CreateCurrent) {
- Process process = Process::Current();
- ASSERT_TRUE(process.IsValid());
- ASSERT_TRUE(process.is_current());
- EXPECT_NE(process.Pid(), kNullProcessId);
- process.Close();
- ASSERT_FALSE(process.IsValid());
-}
-
-TEST_F(ProcessTest, Move) {
- Process process1(SpawnChild("SimpleChildProcess"));
- EXPECT_TRUE(process1.IsValid());
-
- Process process2;
- EXPECT_FALSE(process2.IsValid());
-
- process2 = std::move(process1);
- EXPECT_TRUE(process2.IsValid());
- EXPECT_FALSE(process1.IsValid());
- EXPECT_FALSE(process2.is_current());
-
- Process process3 = Process::Current();
- process2 = std::move(process3);
- EXPECT_TRUE(process2.is_current());
- EXPECT_TRUE(process2.IsValid());
- EXPECT_FALSE(process3.IsValid());
-}
-
-TEST_F(ProcessTest, Duplicate) {
- Process process1(SpawnChild("SimpleChildProcess"));
- ASSERT_TRUE(process1.IsValid());
-
- Process process2 = process1.Duplicate();
- ASSERT_TRUE(process1.IsValid());
- ASSERT_TRUE(process2.IsValid());
- EXPECT_EQ(process1.Pid(), process2.Pid());
- EXPECT_FALSE(process1.is_current());
- EXPECT_FALSE(process2.is_current());
-
- process1.Close();
- ASSERT_TRUE(process2.IsValid());
-}
-
-TEST_F(ProcessTest, DuplicateCurrent) {
- Process process1 = Process::Current();
- ASSERT_TRUE(process1.IsValid());
-
- Process process2 = process1.Duplicate();
- ASSERT_TRUE(process1.IsValid());
- ASSERT_TRUE(process2.IsValid());
- EXPECT_EQ(process1.Pid(), process2.Pid());
- EXPECT_TRUE(process1.is_current());
- EXPECT_TRUE(process2.is_current());
-
- process1.Close();
- ASSERT_TRUE(process2.IsValid());
-}
-
-TEST_F(ProcessTest, DeprecatedGetProcessFromHandle) {
- Process process1(SpawnChild("SimpleChildProcess"));
- ASSERT_TRUE(process1.IsValid());
-
- Process process2 = Process::DeprecatedGetProcessFromHandle(process1.Handle());
- ASSERT_TRUE(process1.IsValid());
- ASSERT_TRUE(process2.IsValid());
- EXPECT_EQ(process1.Pid(), process2.Pid());
- EXPECT_FALSE(process1.is_current());
- EXPECT_FALSE(process2.is_current());
-
- process1.Close();
- ASSERT_TRUE(process2.IsValid());
-}
-
-MULTIPROCESS_TEST_MAIN(SleepyChildProcess) {
- PlatformThread::Sleep(TestTimeouts::action_max_timeout());
- return 0;
-}
-
-TEST_F(ProcessTest, Terminate) {
- Process process(SpawnChild("SleepyChildProcess"));
- ASSERT_TRUE(process.IsValid());
-
- const int kDummyExitCode = 42;
- int exit_code = kDummyExitCode;
- EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
- GetTerminationStatus(process.Handle(), &exit_code));
- EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
-
- exit_code = kDummyExitCode;
- int kExpectedExitCode = 250;
- process.Terminate(kExpectedExitCode, false);
- process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
- &exit_code);
-
- EXPECT_NE(TERMINATION_STATUS_STILL_RUNNING,
- GetTerminationStatus(process.Handle(), &exit_code));
-#if !defined(OS_POSIX) && !defined(OS_FUCHSIA)
- // The POSIX & Fuchsia implementations actually ignore the exit_code.
- EXPECT_EQ(kExpectedExitCode, exit_code);
-#endif
-}
-
-void AtExitHandler(void*) {
- // At-exit handler should not be called at
- // Process::TerminateCurrentProcessImmediately.
- DCHECK(false);
-}
-
-class ThreadLocalObject {
- ~ThreadLocalObject() {
- // Thread-local storage should not be destructed at
- // Process::TerminateCurrentProcessImmediately.
- DCHECK(false);
- }
-};
-
-MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode0) {
- base::ThreadLocalPointer<ThreadLocalObject> object;
- base::AtExitManager::RegisterCallback(&AtExitHandler, nullptr);
- Process::TerminateCurrentProcessImmediately(0);
-}
-
-TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithZeroExitCode) {
- Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode0"));
- ASSERT_TRUE(process.IsValid());
- int exit_code = 42;
- ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
- &exit_code));
- EXPECT_EQ(0, exit_code);
-}
-
-MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode250) {
- Process::TerminateCurrentProcessImmediately(250);
-}
-
-TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithNonZeroExitCode) {
- Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode250"));
- ASSERT_TRUE(process.IsValid());
- int exit_code = 42;
- ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
- &exit_code));
- EXPECT_EQ(250, exit_code);
-}
-
-MULTIPROCESS_TEST_MAIN(FastSleepyChildProcess) {
- PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 10);
- return 0;
-}
-
-TEST_F(ProcessTest, WaitForExit) {
- Process process(SpawnChild("FastSleepyChildProcess"));
- ASSERT_TRUE(process.IsValid());
-
- const int kDummyExitCode = 42;
- int exit_code = kDummyExitCode;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(0, exit_code);
-}
-
-TEST_F(ProcessTest, WaitForExitWithTimeout) {
- Process process(SpawnChild("SleepyChildProcess"));
- ASSERT_TRUE(process.IsValid());
-
- const int kDummyExitCode = 42;
- int exit_code = kDummyExitCode;
- TimeDelta timeout = TestTimeouts::tiny_timeout();
- EXPECT_FALSE(process.WaitForExitWithTimeout(timeout, &exit_code));
- EXPECT_EQ(kDummyExitCode, exit_code);
-
- process.Terminate(kDummyExitCode, false);
-}
-
-// Ensure that the priority of a process is restored correctly after
-// backgrounding and restoring.
-// Note: a platform may not be willing or able to lower the priority of
-// a process. The calls to SetProcessBackground should be noops then.
-TEST_F(ProcessTest, SetProcessBackgrounded) {
- if (!Process::CanBackgroundProcesses())
- return;
- Process process(SpawnChild("SimpleChildProcess"));
- int old_priority = process.GetPriority();
-#if defined(OS_WIN)
- EXPECT_TRUE(process.SetProcessBackgrounded(true));
- EXPECT_TRUE(process.IsProcessBackgrounded());
- EXPECT_TRUE(process.SetProcessBackgrounded(false));
- EXPECT_FALSE(process.IsProcessBackgrounded());
-#elif defined(OS_MACOSX)
- // On the Mac, backgrounding a process requires a port to that process.
- // In the browser it's available through the MachBroker class, which is not
- // part of base. Additionally, there is an indefinite amount of time between
- // spawning a process and receiving its port. Because this test just checks
- // the ability to background/foreground a process, we can use the current
- // process's port instead.
- FakePortProvider provider;
- EXPECT_TRUE(process.SetProcessBackgrounded(&provider, true));
- EXPECT_TRUE(process.IsProcessBackgrounded(&provider));
- EXPECT_TRUE(process.SetProcessBackgrounded(&provider, false));
- EXPECT_FALSE(process.IsProcessBackgrounded(&provider));
-
-#else
- process.SetProcessBackgrounded(true);
- process.SetProcessBackgrounded(false);
-#endif
- int new_priority = process.GetPriority();
- EXPECT_EQ(old_priority, new_priority);
-}
-
-// Same as SetProcessBackgrounded but to this very process. It uses
-// a different code path at least for Windows.
-TEST_F(ProcessTest, SetProcessBackgroundedSelf) {
- if (!Process::CanBackgroundProcesses())
- return;
- Process process = Process::Current();
- int old_priority = process.GetPriority();
-#if defined(OS_WIN)
- EXPECT_TRUE(process.SetProcessBackgrounded(true));
- EXPECT_TRUE(process.IsProcessBackgrounded());
- EXPECT_TRUE(process.SetProcessBackgrounded(false));
- EXPECT_FALSE(process.IsProcessBackgrounded());
-#elif defined(OS_MACOSX)
- FakePortProvider provider;
- EXPECT_TRUE(process.SetProcessBackgrounded(&provider, true));
- EXPECT_TRUE(process.IsProcessBackgrounded(&provider));
- EXPECT_TRUE(process.SetProcessBackgrounded(&provider, false));
- EXPECT_FALSE(process.IsProcessBackgrounded(&provider));
-#else
- process.SetProcessBackgrounded(true);
- process.SetProcessBackgrounded(false);
-#endif
- int new_priority = process.GetPriority();
- EXPECT_EQ(old_priority, new_priority);
-}
-
-// Consumers can use WaitForExitWithTimeout(base::TimeDelta(), nullptr) to check
-// whether the process is still running. This may not be safe because of the
-// potential reusing of the process id. So we won't export Process::IsRunning()
-// on all platforms. But for the controllable scenario in the test cases, the
-// behavior should be guaranteed.
-TEST_F(ProcessTest, CurrentProcessIsRunning) {
- EXPECT_FALSE(Process::Current().WaitForExitWithTimeout(
- base::TimeDelta(), nullptr));
-}
-
-#if defined(OS_MACOSX)
-// On Mac OSX, we can detect whether a non-child process is running.
-TEST_F(ProcessTest, PredefinedProcessIsRunning) {
- // Process 1 is the /sbin/launchd, it should be always running.
- EXPECT_FALSE(Process::Open(1).WaitForExitWithTimeout(
- base::TimeDelta(), nullptr));
-}
-#endif
-
-TEST_F(ProcessTest, ChildProcessIsRunning) {
- Process process(SpawnChild("SleepyChildProcess"));
- EXPECT_FALSE(process.WaitForExitWithTimeout(
- base::TimeDelta(), nullptr));
- process.Terminate(0, true);
- EXPECT_TRUE(process.WaitForExitWithTimeout(
- base::TimeDelta(), nullptr));
-}
-
-#if defined(OS_CHROMEOS)
-
-// Tests that the function IsProcessBackgroundedCGroup() can parse the contents
-// of the /proc/<pid>/cgroup file successfully.
-TEST_F(ProcessTest, TestIsProcessBackgroundedCGroup) {
- const char kNotBackgrounded[] = "5:cpuacct,cpu,cpuset:/daemons\n";
- const char kBackgrounded[] =
- "2:freezer:/chrome_renderers/to_be_frozen\n"
- "1:cpu:/chrome_renderers/background\n";
-
- EXPECT_FALSE(IsProcessBackgroundedCGroup(kNotBackgrounded));
- EXPECT_TRUE(IsProcessBackgroundedCGroup(kBackgrounded));
-}
-
-#endif // defined(OS_CHROMEOS)
-
-} // namespace base
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
deleted file mode 100644
index 4e788b78a8..0000000000
--- a/base/process/process_util_unittest.cc
+++ /dev/null
@@ -1,1357 +0,0 @@
-// Copyright (c) 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.
-
-#define _CRT_SECURE_NO_WARNINGS
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/command_line.h"
-#include "base/debug/alias.h"
-#include "base/debug/stack_trace.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/process/memory.h"
-#include "base/process/process.h"
-#include "base/process/process_metrics.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-#if defined(OS_LINUX)
-#include <malloc.h>
-#include <sched.h>
-#include <sys/syscall.h>
-#endif
-#if defined(OS_POSIX)
-#include <sys/resource.h>
-#endif
-#if defined(OS_POSIX)
-#include <dlfcn.h>
-#include <errno.h>
-#include <sched.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#endif
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#endif
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-#if defined(OS_MACOSX)
-#include <mach/vm_param.h>
-#include <malloc/malloc.h>
-#endif
-#if defined(OS_ANDROID)
-#include "third_party/lss/linux_syscall_support.h"
-#endif
-#if defined(OS_FUCHSIA)
-#include <lib/fdio/limits.h>
-#include <zircon/process.h>
-#include <zircon/processargs.h>
-#include <zircon/syscalls.h>
-#include "base/base_paths_fuchsia.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/fuchsia/file_utils.h"
-#include "base/fuchsia/fuchsia_logging.h"
-#endif
-
-namespace base {
-
-namespace {
-
-const char kSignalFileSlow[] = "SlowChildProcess.die";
-const char kSignalFileKill[] = "KilledChildProcess.die";
-const char kTestHelper[] = "test_child_process";
-
-#if defined(OS_POSIX)
-const char kSignalFileTerm[] = "TerminatedChildProcess.die";
-#endif
-
-#if defined(OS_FUCHSIA)
-const char kSignalFileClone[] = "ClonedTmpDir.die";
-const char kDataDirHasStaged[] = "DataDirHasStaged.die";
-const char kFooDirHasStaged[] = "FooDirHasStaged.die";
-const char kFooDirDoesNotHaveStaged[] = "FooDirDoesNotHaveStaged.die";
-#endif
-
-#if defined(OS_WIN)
-const int kExpectedStillRunningExitCode = 0x102;
-const int kExpectedKilledExitCode = 1;
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
-const int kExpectedStillRunningExitCode = 0;
-#endif
-
-// Sleeps until file filename is created.
-void WaitToDie(const char* filename) {
- FILE* fp;
- do {
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
- fp = fopen(filename, "r");
- } while (!fp);
- fclose(fp);
-}
-
-// Signals children they should die now.
-void SignalChildren(const char* filename) {
- FILE* fp = fopen(filename, "w");
- fclose(fp);
-}
-
-// Using a pipe to the child to wait for an event was considered, but
-// there were cases in the past where pipes caused problems (other
-// libraries closing the fds, child deadlocking). This is a simple
-// case, so it's not worth the risk. Using wait loops is discouraged
-// in most instances.
-TerminationStatus WaitForChildTermination(ProcessHandle handle,
- int* exit_code) {
- // Now we wait until the result is something other than STILL_RUNNING.
- TerminationStatus status = TERMINATION_STATUS_STILL_RUNNING;
- const TimeDelta kInterval = TimeDelta::FromMilliseconds(20);
- TimeDelta waited;
- do {
- status = GetTerminationStatus(handle, exit_code);
- PlatformThread::Sleep(kInterval);
- waited += kInterval;
- } while (status == TERMINATION_STATUS_STILL_RUNNING &&
- waited < TestTimeouts::action_max_timeout());
-
- return status;
-}
-
-} // namespace
-
-const int kSuccess = 0;
-
-class ProcessUtilTest : public MultiProcessTest {
- public:
- void SetUp() override {
- ASSERT_TRUE(PathService::Get(DIR_ASSETS, &test_helper_path_));
- test_helper_path_ = test_helper_path_.AppendASCII(kTestHelper);
- }
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
- // Spawn a child process that counts how many file descriptors are open.
- int CountOpenFDsInChild();
-#endif
- // Converts the filename to a platform specific filepath.
- // On Android files can not be created in arbitrary directories.
- static std::string GetSignalFilePath(const char* filename);
-
- protected:
- base::FilePath test_helper_path_;
-};
-
-std::string ProcessUtilTest::GetSignalFilePath(const char* filename) {
-#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
- FilePath tmp_dir;
- PathService::Get(DIR_TEMP, &tmp_dir);
- tmp_dir = tmp_dir.Append(filename);
- return tmp_dir.value();
-#else
- return filename;
-#endif
-}
-
-MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
- return kSuccess;
-}
-
-// TODO(viettrungluu): This should be in a "MultiProcessTestTest".
-TEST_F(ProcessUtilTest, SpawnChild) {
- Process process = SpawnChild("SimpleChildProcess");
- ASSERT_TRUE(process.IsValid());
- int exit_code;
- EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
- &exit_code));
-}
-
-MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
- WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileSlow).c_str());
- return kSuccess;
-}
-
-TEST_F(ProcessUtilTest, KillSlowChild) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
- remove(signal_file.c_str());
- Process process = SpawnChild("SlowChildProcess");
- ASSERT_TRUE(process.IsValid());
- SignalChildren(signal_file.c_str());
- int exit_code;
- EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
- &exit_code));
- remove(signal_file.c_str());
-}
-
-// Times out on Linux and Win, flakes on other platforms, http://crbug.com/95058
-TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
- remove(signal_file.c_str());
- Process process = SpawnChild("SlowChildProcess");
- ASSERT_TRUE(process.IsValid());
-
- int exit_code = 42;
- EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
- GetTerminationStatus(process.Handle(), &exit_code));
- EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
-
- SignalChildren(signal_file.c_str());
- exit_code = 42;
- TerminationStatus status =
- WaitForChildTermination(process.Handle(), &exit_code);
- EXPECT_EQ(TERMINATION_STATUS_NORMAL_TERMINATION, status);
- EXPECT_EQ(kSuccess, exit_code);
- remove(signal_file.c_str());
-}
-
-#if defined(OS_FUCHSIA)
-
-MULTIPROCESS_TEST_MAIN(CheckDataDirHasStaged) {
- if (!PathExists(base::FilePath("/data/staged"))) {
- return 1;
- }
- WaitToDie(ProcessUtilTest::GetSignalFilePath(kDataDirHasStaged).c_str());
- return kSuccess;
-}
-
-// Test transferred paths override cloned paths.
-TEST_F(ProcessUtilTest, HandleTransfersOverrideClones) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kDataDirHasStaged);
- remove(signal_file.c_str());
-
- // Create a tempdir with "staged" as its contents.
- ScopedTempDir tmpdir_with_staged;
- ASSERT_TRUE(tmpdir_with_staged.CreateUniqueTempDir());
- {
- base::FilePath staged_file_path =
- tmpdir_with_staged.GetPath().Append("staged");
- base::File staged_file(staged_file_path,
- base::File::FLAG_CREATE | base::File::FLAG_WRITE);
- ASSERT_TRUE(staged_file.created());
- staged_file.Close();
- }
-
- base::LaunchOptions options;
- options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
-
- // Attach the tempdir to "data", but also try to duplicate the existing "data"
- // directory.
- options.paths_to_clone.push_back(base::FilePath("/data"));
- options.paths_to_clone.push_back(base::FilePath("/tmp"));
- options.paths_to_transfer.push_back(
- {FilePath("/data"),
- fuchsia::GetHandleFromFile(
- base::File(base::FilePath(tmpdir_with_staged.GetPath()),
- base::File::FLAG_OPEN | base::File::FLAG_READ))
- .release()});
-
- // Verify from that "/data/staged" exists from the child process' perspective.
- Process process(SpawnChildWithOptions("CheckDataDirHasStaged", options));
- ASSERT_TRUE(process.IsValid());
- SignalChildren(signal_file.c_str());
-
- int exit_code = 42;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(kSuccess, exit_code);
-}
-
-MULTIPROCESS_TEST_MAIN(CheckMountedDir) {
- if (!PathExists(base::FilePath("/foo/staged"))) {
- return 1;
- }
- WaitToDie(ProcessUtilTest::GetSignalFilePath(kFooDirHasStaged).c_str());
- return kSuccess;
-}
-
-// Test that we can install an opaque handle in the child process' namespace.
-TEST_F(ProcessUtilTest, TransferHandleToPath) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kFooDirHasStaged);
- remove(signal_file.c_str());
-
- // Create a tempdir with "staged" as its contents.
- ScopedTempDir new_tmpdir;
- ASSERT_TRUE(new_tmpdir.CreateUniqueTempDir());
- base::FilePath staged_file_path = new_tmpdir.GetPath().Append("staged");
- base::File staged_file(staged_file_path,
- base::File::FLAG_CREATE | base::File::FLAG_WRITE);
- ASSERT_TRUE(staged_file.created());
- staged_file.Close();
-
- // Mount the tempdir to "/foo".
- zx::handle tmp_handle = fuchsia::GetHandleFromFile(
- base::File(base::FilePath(new_tmpdir.GetPath()),
- base::File::FLAG_OPEN | base::File::FLAG_READ));
- ASSERT_TRUE(tmp_handle.is_valid());
- LaunchOptions options;
- options.paths_to_clone.push_back(base::FilePath("/tmp"));
- options.paths_to_transfer.push_back(
- {base::FilePath("/foo"), tmp_handle.release()});
- options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
-
- // Verify from that "/foo/staged" exists from the child process' perspective.
- Process process(SpawnChildWithOptions("CheckMountedDir", options));
- ASSERT_TRUE(process.IsValid());
- SignalChildren(signal_file.c_str());
-
- int exit_code = 42;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(kSuccess, exit_code);
-}
-
-MULTIPROCESS_TEST_MAIN(CheckTmpFileExists) {
- // Look through the filesystem to ensure that no other directories
- // besides "tmp" are in the namespace.
- base::FileEnumerator enumerator(
- base::FilePath("/"), false,
- base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
- base::FilePath next_path;
- while (!(next_path = enumerator.Next()).empty()) {
- if (next_path != base::FilePath("/tmp")) {
- LOG(ERROR) << "Clone policy violation: found non-tmp directory "
- << next_path.MaybeAsASCII();
- return 1;
- }
- }
- WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileClone).c_str());
- return kSuccess;
-}
-
-TEST_F(ProcessUtilTest, CloneTmp) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
- remove(signal_file.c_str());
-
- LaunchOptions options;
- options.paths_to_clone.push_back(base::FilePath("/tmp"));
- options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
-
- Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
- ASSERT_TRUE(process.IsValid());
-
- SignalChildren(signal_file.c_str());
-
- int exit_code = 42;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(kSuccess, exit_code);
-}
-
-MULTIPROCESS_TEST_MAIN(CheckMountedDirDoesNotExist) {
- if (PathExists(base::FilePath("/foo"))) {
- return 1;
- }
- WaitToDie(
- ProcessUtilTest::GetSignalFilePath(kFooDirDoesNotHaveStaged).c_str());
- return kSuccess;
-}
-
-TEST_F(ProcessUtilTest, TransferInvalidHandleFails) {
- LaunchOptions options;
- options.paths_to_clone.push_back(base::FilePath("/tmp"));
- options.paths_to_transfer.push_back(
- {base::FilePath("/foo"), ZX_HANDLE_INVALID});
- options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
-
- // Verify that the process is never constructed.
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kFooDirDoesNotHaveStaged);
- remove(signal_file.c_str());
- Process process(
- SpawnChildWithOptions("CheckMountedDirDoesNotExist", options));
- ASSERT_FALSE(process.IsValid());
-}
-
-TEST_F(ProcessUtilTest, CloneInvalidDirFails) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
- remove(signal_file.c_str());
-
- LaunchOptions options;
- options.paths_to_clone.push_back(base::FilePath("/tmp"));
- options.paths_to_clone.push_back(base::FilePath("/definitely_not_a_dir"));
- options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
-
- Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
- ASSERT_FALSE(process.IsValid());
-}
-
-// Test that we can clone other directories. CheckTmpFileExists will return an
-// error code if it detects a directory other than "/tmp", so we can use that as
-// a signal that it successfully detected another entry in the root namespace.
-TEST_F(ProcessUtilTest, CloneAlternateDir) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
- remove(signal_file.c_str());
-
- LaunchOptions options;
- options.paths_to_clone.push_back(base::FilePath("/tmp"));
- options.paths_to_clone.push_back(base::FilePath("/data"));
- options.spawn_flags = FDIO_SPAWN_CLONE_STDIO;
-
- Process process(SpawnChildWithOptions("CheckTmpFileExists", options));
- ASSERT_TRUE(process.IsValid());
-
- SignalChildren(signal_file.c_str());
-
- int exit_code = 42;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(1, exit_code);
-}
-
-TEST_F(ProcessUtilTest, HandlesToTransferClosedOnSpawnFailure) {
- zx::handle handles[2];
- zx_status_t result = zx_channel_create(0, handles[0].reset_and_get_address(),
- handles[1].reset_and_get_address());
- ZX_CHECK(ZX_OK == result, result) << "zx_channel_create";
-
- LaunchOptions options;
- options.handles_to_transfer.push_back({0, handles[0].get()});
-
- // Launch a non-existent binary, causing fdio_spawn() to fail.
- CommandLine command_line(FilePath(
- FILE_PATH_LITERAL("💩magical_filename_that_will_never_exist_ever")));
- Process process(LaunchProcess(command_line, options));
- ASSERT_FALSE(process.IsValid());
-
- // If LaunchProcess did its job then handles[0] is no longer valid, and
- // handles[1] should observe a channel-closed signal.
- EXPECT_EQ(
- zx_object_wait_one(handles[1].get(), ZX_CHANNEL_PEER_CLOSED, 0, nullptr),
- ZX_OK);
- EXPECT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(handles[0].get()));
- ignore_result(handles[0].release());
-}
-
-TEST_F(ProcessUtilTest, HandlesToTransferClosedOnBadPathToMapFailure) {
- zx::handle handles[2];
- zx_status_t result = zx_channel_create(0, handles[0].reset_and_get_address(),
- handles[1].reset_and_get_address());
- ZX_CHECK(ZX_OK == result, result) << "zx_channel_create";
-
- LaunchOptions options;
- options.handles_to_transfer.push_back({0, handles[0].get()});
- options.spawn_flags = options.spawn_flags & ~FDIO_SPAWN_CLONE_NAMESPACE;
- options.paths_to_clone.emplace_back(
- "💩magical_path_that_will_never_exist_ever");
-
- // LaunchProces should fail to open() the path_to_map, and fail before
- // fdio_spawn().
- Process process(LaunchProcess(CommandLine(FilePath()), options));
- ASSERT_FALSE(process.IsValid());
-
- // If LaunchProcess did its job then handles[0] is no longer valid, and
- // handles[1] should observe a channel-closed signal.
- EXPECT_EQ(
- zx_object_wait_one(handles[1].get(), ZX_CHANNEL_PEER_CLOSED, 0, nullptr),
- ZX_OK);
- EXPECT_EQ(ZX_ERR_BAD_HANDLE, zx_handle_close(handles[0].get()));
- ignore_result(handles[0].release());
-}
-#endif // defined(OS_FUCHSIA)
-
-// On Android SpawnProcess() doesn't use LaunchProcess() and doesn't support
-// LaunchOptions::current_directory.
-#if !defined(OS_ANDROID)
-MULTIPROCESS_TEST_MAIN(CheckCwdProcess) {
- FilePath expected;
- CHECK(GetTempDir(&expected));
- expected = MakeAbsoluteFilePath(expected);
- CHECK(!expected.empty());
-
- FilePath actual;
- CHECK(GetCurrentDirectory(&actual));
- actual = MakeAbsoluteFilePath(actual);
- CHECK(!actual.empty());
-
- CHECK(expected == actual) << "Expected: " << expected.value()
- << " Actual: " << actual.value();
- return kSuccess;
-}
-
-TEST_F(ProcessUtilTest, CurrentDirectory) {
- // TODO(rickyz): Add support for passing arguments to multiprocess children,
- // then create a special directory for this test.
- FilePath tmp_dir;
- ASSERT_TRUE(GetTempDir(&tmp_dir));
-
- LaunchOptions options;
- options.current_directory = tmp_dir;
-
- Process process(SpawnChildWithOptions("CheckCwdProcess", options));
- ASSERT_TRUE(process.IsValid());
-
- int exit_code = 42;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(kSuccess, exit_code);
-}
-#endif // !defined(OS_ANDROID)
-
-#if defined(OS_WIN)
-// TODO(cpu): figure out how to test this in other platforms.
-TEST_F(ProcessUtilTest, GetProcId) {
- ProcessId id1 = GetProcId(GetCurrentProcess());
- EXPECT_NE(0ul, id1);
- Process process = SpawnChild("SimpleChildProcess");
- ASSERT_TRUE(process.IsValid());
- ProcessId id2 = process.Pid();
- EXPECT_NE(0ul, id2);
- EXPECT_NE(id1, id2);
-}
-#endif // defined(OS_WIN)
-
-#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
-// This test is disabled on Mac, since it's flaky due to ReportCrash
-// taking a variable amount of time to parse and load the debug and
-// symbol data for this unit test's executable before firing the
-// signal handler.
-//
-// TODO(gspencer): turn this test process into a very small program
-// with no symbols (instead of using the multiprocess testing
-// framework) to reduce the ReportCrash overhead.
-//
-// It is disabled on Android as MultiprocessTests are started as services that
-// the framework restarts on crashes.
-const char kSignalFileCrash[] = "CrashingChildProcess.die";
-
-MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
- WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
-#if defined(OS_POSIX)
- // Have to disable to signal handler for segv so we can get a crash
- // instead of an abnormal termination through the crash dump handler.
- ::signal(SIGSEGV, SIG_DFL);
-#endif
- // Make this process have a segmentation fault.
- volatile int* oops = nullptr;
- *oops = 0xDEAD;
- return 1;
-}
-
-// This test intentionally crashes, so we don't need to run it under
-// AddressSanitizer.
-#if defined(ADDRESS_SANITIZER) || defined(OS_FUCHSIA)
-// TODO(crbug.com/753490): Access to the process termination reason is not
-// implemented in Fuchsia.
-#define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash
-#else
-#define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash
-#endif
-TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileCrash);
- remove(signal_file.c_str());
- Process process = SpawnChild("CrashingChildProcess");
- ASSERT_TRUE(process.IsValid());
-
- int exit_code = 42;
- EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
- GetTerminationStatus(process.Handle(), &exit_code));
- EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
-
- SignalChildren(signal_file.c_str());
- exit_code = 42;
- TerminationStatus status =
- WaitForChildTermination(process.Handle(), &exit_code);
- EXPECT_EQ(TERMINATION_STATUS_PROCESS_CRASHED, status);
-
-#if defined(OS_WIN)
- EXPECT_EQ(static_cast<int>(0xc0000005), exit_code);
-#elif defined(OS_POSIX)
- int signaled = WIFSIGNALED(exit_code);
- EXPECT_NE(0, signaled);
- int signal = WTERMSIG(exit_code);
- EXPECT_EQ(SIGSEGV, signal);
-#endif
-
- // Reset signal handlers back to "normal".
- debug::EnableInProcessStackDumping();
- remove(signal_file.c_str());
-}
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
-
-MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
- WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileKill).c_str());
-#if defined(OS_WIN)
- // Kill ourselves.
- HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId());
- ::TerminateProcess(handle, kExpectedKilledExitCode);
-#elif defined(OS_POSIX)
- // Send a SIGKILL to this process, just like the OOM killer would.
- ::kill(getpid(), SIGKILL);
-#elif defined(OS_FUCHSIA)
- zx_task_kill(zx_process_self());
-#endif
- return 1;
-}
-
-#if defined(OS_POSIX)
-MULTIPROCESS_TEST_MAIN(TerminatedChildProcess) {
- WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileTerm).c_str());
- // Send a SIGTERM to this process.
- ::kill(getpid(), SIGTERM);
- return 1;
-}
-#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-#if defined(OS_FUCHSIA)
-// TODO(crbug.com/753490): Access to the process termination reason is not
-// implemented in Fuchsia.
-#define MAYBE_GetTerminationStatusSigKill DISABLED_GetTerminationStatusSigKill
-#else
-#define MAYBE_GetTerminationStatusSigKill GetTerminationStatusSigKill
-#endif
-TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusSigKill) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileKill);
- remove(signal_file.c_str());
- Process process = SpawnChild("KilledChildProcess");
- ASSERT_TRUE(process.IsValid());
-
- int exit_code = 42;
- EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
- GetTerminationStatus(process.Handle(), &exit_code));
- EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
-
- SignalChildren(signal_file.c_str());
- exit_code = 42;
- TerminationStatus status =
- WaitForChildTermination(process.Handle(), &exit_code);
-#if defined(OS_CHROMEOS)
- EXPECT_EQ(TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM, status);
-#else
- EXPECT_EQ(TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
-#endif
-
-#if defined(OS_WIN)
- EXPECT_EQ(kExpectedKilledExitCode, exit_code);
-#elif defined(OS_POSIX)
- int signaled = WIFSIGNALED(exit_code);
- EXPECT_NE(0, signaled);
- int signal = WTERMSIG(exit_code);
- EXPECT_EQ(SIGKILL, signal);
-#endif
- remove(signal_file.c_str());
-}
-
-#if defined(OS_POSIX)
-// TODO(crbug.com/753490): Access to the process termination reason is not
-// implemented in Fuchsia. Unix signals are not implemented in Fuchsia so this
-// test might not be relevant anyway.
-TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileTerm);
- remove(signal_file.c_str());
- Process process = SpawnChild("TerminatedChildProcess");
- ASSERT_TRUE(process.IsValid());
-
- int exit_code = 42;
- EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
- GetTerminationStatus(process.Handle(), &exit_code));
- EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
-
- SignalChildren(signal_file.c_str());
- exit_code = 42;
- TerminationStatus status =
- WaitForChildTermination(process.Handle(), &exit_code);
- EXPECT_EQ(TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
-
- int signaled = WIFSIGNALED(exit_code);
- EXPECT_NE(0, signaled);
- int signal = WTERMSIG(exit_code);
- EXPECT_EQ(SIGTERM, signal);
- remove(signal_file.c_str());
-}
-#endif // defined(OS_POSIX)
-
-TEST_F(ProcessUtilTest, EnsureTerminationUndying) {
- test::ScopedTaskEnvironment task_environment;
-
- Process child_process = SpawnChild("process_util_test_never_die");
- ASSERT_TRUE(child_process.IsValid());
-
- EnsureProcessTerminated(child_process.Duplicate());
-
-#if defined(OS_POSIX)
- errno = 0;
-#endif // defined(OS_POSIX)
-
- // Allow a generous timeout, to cope with slow/loaded test bots.
- bool did_exit = child_process.WaitForExitWithTimeout(
- TestTimeouts::action_max_timeout(), nullptr);
-
-#if defined(OS_POSIX)
- // Both EnsureProcessTerminated() and WaitForExitWithTimeout() will call
- // waitpid(). One will succeed, and the other will fail with ECHILD. If our
- // wait failed then check for ECHILD, and assumed |did_exit| in that case.
- did_exit = did_exit || (errno == ECHILD);
-#endif // defined(OS_POSIX)
-
- EXPECT_TRUE(did_exit);
-}
-
-MULTIPROCESS_TEST_MAIN(process_util_test_never_die) {
- while (1) {
- PlatformThread::Sleep(TimeDelta::FromSeconds(500));
- }
- return kSuccess;
-}
-
-TEST_F(ProcessUtilTest, EnsureTerminationGracefulExit) {
- test::ScopedTaskEnvironment task_environment;
-
- Process child_process = SpawnChild("process_util_test_die_immediately");
- ASSERT_TRUE(child_process.IsValid());
-
- // Wait for the child process to actually exit.
- child_process.Duplicate().WaitForExitWithTimeout(
- TestTimeouts::action_max_timeout(), nullptr);
-
- EnsureProcessTerminated(child_process.Duplicate());
-
- // Verify that the process is really, truly gone.
- EXPECT_TRUE(child_process.WaitForExitWithTimeout(
- TestTimeouts::action_max_timeout(), nullptr));
-}
-
-MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) {
- return kSuccess;
-}
-
-#if defined(OS_WIN)
-// TODO(estade): if possible, port this test.
-TEST_F(ProcessUtilTest, LaunchAsUser) {
- UserTokenHandle token;
- ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
- LaunchOptions options;
- options.as_user = token;
- EXPECT_TRUE(
- LaunchProcess(MakeCmdLine("SimpleChildProcess"), options).IsValid());
-}
-
-static const char kEventToTriggerHandleSwitch[] = "event-to-trigger-handle";
-
-MULTIPROCESS_TEST_MAIN(TriggerEventChildProcess) {
- std::string handle_value_string =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- kEventToTriggerHandleSwitch);
- CHECK(!handle_value_string.empty());
-
- uint64_t handle_value_uint64;
- CHECK(StringToUint64(handle_value_string, &handle_value_uint64));
- // Give ownership of the handle to |event|.
- WaitableEvent event(
- win::ScopedHandle(reinterpret_cast<HANDLE>(handle_value_uint64)));
-
- event.Signal();
-
- return 0;
-}
-
-TEST_F(ProcessUtilTest, InheritSpecifiedHandles) {
- // Manually create the event, so that it can be inheritable.
- SECURITY_ATTRIBUTES security_attributes = {};
- security_attributes.nLength = static_cast<DWORD>(sizeof(security_attributes));
- security_attributes.lpSecurityDescriptor = NULL;
- security_attributes.bInheritHandle = true;
-
- // Takes ownership of the event handle.
- WaitableEvent event(
- win::ScopedHandle(CreateEvent(&security_attributes, true, false, NULL)));
- LaunchOptions options;
- options.handles_to_inherit.emplace_back(event.handle());
-
- CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess");
- cmd_line.AppendSwitchASCII(
- kEventToTriggerHandleSwitch,
- NumberToString(reinterpret_cast<uint64_t>(event.handle())));
-
- // Launch the process and wait for it to trigger the event.
- ASSERT_TRUE(LaunchProcess(cmd_line, options).IsValid());
- EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
-}
-#endif // defined(OS_WIN)
-
-TEST_F(ProcessUtilTest, GetAppOutput) {
- base::CommandLine command(test_helper_path_);
- command.AppendArg("hello");
- command.AppendArg("there");
- command.AppendArg("good");
- command.AppendArg("people");
- std::string output;
- EXPECT_TRUE(GetAppOutput(command, &output));
- EXPECT_EQ("hello there good people", output);
- output.clear();
-
- const char* kEchoMessage = "blah";
- command = base::CommandLine(test_helper_path_);
- command.AppendArg("-x");
- command.AppendArg("28");
- command.AppendArg(kEchoMessage);
- EXPECT_FALSE(GetAppOutput(command, &output));
- EXPECT_EQ(kEchoMessage, output);
-}
-
-TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) {
- const char* kEchoMessage1 = "doge";
- int exit_code = -1;
- base::CommandLine command(test_helper_path_);
- command.AppendArg(kEchoMessage1);
- std::string output;
- EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code));
- EXPECT_EQ(kEchoMessage1, output);
- EXPECT_EQ(0, exit_code);
- output.clear();
-
- const char* kEchoMessage2 = "pupper";
- const int kExpectedExitCode = 42;
- command = base::CommandLine(test_helper_path_);
- command.AppendArg("-x");
- command.AppendArg(base::IntToString(kExpectedExitCode));
- command.AppendArg(kEchoMessage2);
-#if defined(OS_WIN)
- // On Windows, anything that quits with a nonzero status code is handled as a
- // "crash", so just ignore GetAppOutputWithExitCode's return value.
- GetAppOutputWithExitCode(command, &output, &exit_code);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- EXPECT_TRUE(GetAppOutputWithExitCode(command, &output, &exit_code));
-#endif
- EXPECT_EQ(kEchoMessage2, output);
- EXPECT_EQ(kExpectedExitCode, exit_code);
-}
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-namespace {
-
-// Returns the maximum number of files that a process can have open.
-// Returns 0 on error.
-int GetMaxFilesOpenInProcess() {
-#if defined(OS_FUCHSIA)
- return FDIO_MAX_FD;
-#else
- struct rlimit rlim;
- if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
- return 0;
- }
-
- // rlim_t is a uint64_t - clip to maxint. We do this since FD #s are ints
- // which are all 32 bits on the supported platforms.
- rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32_t>::max());
- if (rlim.rlim_cur > max_int) {
- return max_int;
- }
-
- return rlim.rlim_cur;
-#endif // defined(OS_FUCHSIA)
-}
-
-const int kChildPipe = 20; // FD # for write end of pipe in child process.
-
-#if defined(OS_MACOSX)
-
-// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
-#if !defined(_GUARDID_T)
-#define _GUARDID_T
-typedef __uint64_t guardid_t;
-#endif // _GUARDID_T
-
-// From .../MacOSX10.9.sdk/usr/include/sys/syscall.h
-#if !defined(SYS_change_fdguard_np)
-#define SYS_change_fdguard_np 444
-#endif
-
-// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
-#if !defined(GUARD_DUP)
-#define GUARD_DUP (1u << 1)
-#endif
-
-// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_guarded.c?txt>
-//
-// Atomically replaces |guard|/|guardflags| with |nguard|/|nguardflags| on |fd|.
-int change_fdguard_np(int fd,
- const guardid_t *guard, u_int guardflags,
- const guardid_t *nguard, u_int nguardflags,
- int *fdflagsp) {
- return syscall(SYS_change_fdguard_np, fd, guard, guardflags,
- nguard, nguardflags, fdflagsp);
-}
-
-// Attempt to set a file-descriptor guard on |fd|. In case of success, remove
-// it and return |true| to indicate that it can be guarded. Returning |false|
-// means either that |fd| is guarded by some other code, or more likely EBADF.
-//
-// Starting with 10.9, libdispatch began setting GUARD_DUP on a file descriptor.
-// Unfortunately, it is spun up as part of +[NSApplication initialize], which is
-// not really something that Chromium can avoid using on OSX. See
-// <http://crbug.com/338157>. This function allows querying whether the file
-// descriptor is guarded before attempting to close it.
-bool CanGuardFd(int fd) {
- // Saves the original flags to reset later.
- int original_fdflags = 0;
-
- // This can be any value at all, it just has to match up between the two
- // calls.
- const guardid_t kGuard = 15;
-
- // Attempt to change the guard. This can fail with EBADF if the file
- // descriptor is bad, or EINVAL if the fd already has a guard set.
- int ret =
- change_fdguard_np(fd, NULL, 0, &kGuard, GUARD_DUP, &original_fdflags);
- if (ret == -1)
- return false;
-
- // Remove the guard. It should not be possible to fail in removing the guard
- // just added.
- ret = change_fdguard_np(fd, &kGuard, GUARD_DUP, NULL, 0, &original_fdflags);
- DPCHECK(ret == 0);
-
- return true;
-}
-#endif // defined(OS_MACOSX)
-
-} // namespace
-
-MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) {
- // This child process counts the number of open FDs, it then writes that
- // number out to a pipe connected to the parent.
- int num_open_files = 0;
- int write_pipe = kChildPipe;
- int max_files = GetMaxFilesOpenInProcess();
- for (int i = STDERR_FILENO + 1; i < max_files; i++) {
-#if defined(OS_MACOSX)
- // Ignore guarded or invalid file descriptors.
- if (!CanGuardFd(i))
- continue;
-#endif
-
- if (i != kChildPipe) {
- int fd;
- if ((fd = HANDLE_EINTR(dup(i))) != -1) {
- close(fd);
- num_open_files += 1;
- }
- }
- }
-
- int written = HANDLE_EINTR(write(write_pipe, &num_open_files,
- sizeof(num_open_files)));
- DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files));
- int ret = IGNORE_EINTR(close(write_pipe));
- DPCHECK(ret == 0);
-
- return 0;
-}
-
-int ProcessUtilTest::CountOpenFDsInChild() {
- int fds[2];
- if (pipe(fds) < 0)
- NOTREACHED();
-
- LaunchOptions options;
- options.fds_to_remap.emplace_back(fds[1], kChildPipe);
- Process process =
- SpawnChildWithOptions("ProcessUtilsLeakFDChildProcess", options);
- CHECK(process.IsValid());
- int ret = IGNORE_EINTR(close(fds[1]));
- DPCHECK(ret == 0);
-
- // Read number of open files in client process from pipe;
- int num_open_files = -1;
- ssize_t bytes_read =
- HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files)));
- CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files)));
-
-#if defined(THREAD_SANITIZER)
- // Compiler-based ThreadSanitizer makes this test slow.
- TimeDelta timeout = TimeDelta::FromSeconds(3);
-#else
- TimeDelta timeout = TimeDelta::FromSeconds(1);
-#endif
- int exit_code;
- CHECK(process.WaitForExitWithTimeout(timeout, &exit_code));
- ret = IGNORE_EINTR(close(fds[0]));
- DPCHECK(ret == 0);
-
- return num_open_files;
-}
-
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
-// ProcessUtilTest.FDRemapping is flaky when ran under xvfb-run on Precise.
-// The problem is 100% reproducible with both ASan and TSan.
-// See http://crbug.com/136720.
-#define MAYBE_FDRemapping DISABLED_FDRemapping
-#else
-#define MAYBE_FDRemapping FDRemapping
-#endif // defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
-TEST_F(ProcessUtilTest, MAYBE_FDRemapping) {
- int fds_before = CountOpenFDsInChild();
-
- // open some dummy fds to make sure they don't propagate over to the
- // child process.
- int dev_null = open("/dev/null", O_RDONLY);
- DPCHECK(dev_null != -1);
- int sockets[2];
- int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
- DPCHECK(ret == 0);
-
- int fds_after = CountOpenFDsInChild();
-
- ASSERT_EQ(fds_after, fds_before);
-
- ret = IGNORE_EINTR(close(sockets[0]));
- DPCHECK(ret == 0);
- ret = IGNORE_EINTR(close(sockets[1]));
- DPCHECK(ret == 0);
- ret = IGNORE_EINTR(close(dev_null));
- DPCHECK(ret == 0);
-}
-
-const char kPipeValue = '\xcc';
-MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyStdio) {
- // Write to stdio so the parent process can observe output.
- CHECK_EQ(1, HANDLE_EINTR(write(STDOUT_FILENO, &kPipeValue, 1)));
-
- // Close all of the handles, to verify they are valid.
- CHECK_EQ(0, IGNORE_EINTR(close(STDIN_FILENO)));
- CHECK_EQ(0, IGNORE_EINTR(close(STDOUT_FILENO)));
- CHECK_EQ(0, IGNORE_EINTR(close(STDERR_FILENO)));
- return 0;
-}
-
-TEST_F(ProcessUtilTest, FDRemappingIncludesStdio) {
- int dev_null = open("/dev/null", O_RDONLY);
- ASSERT_LT(2, dev_null);
-
- // Backup stdio and replace it with the write end of a pipe, for our
- // child process to inherit.
- int pipe_fds[2];
- int result = pipe(pipe_fds);
- ASSERT_EQ(0, result);
- int backup_stdio = HANDLE_EINTR(dup(STDOUT_FILENO));
- ASSERT_LE(0, backup_stdio);
- result = dup2(pipe_fds[1], STDOUT_FILENO);
- ASSERT_EQ(STDOUT_FILENO, result);
-
- // Launch the test process, which should inherit our pipe stdio.
- LaunchOptions options;
- options.fds_to_remap.emplace_back(dev_null, dev_null);
- Process process = SpawnChildWithOptions("ProcessUtilsVerifyStdio", options);
- ASSERT_TRUE(process.IsValid());
-
- // Restore stdio, so we can output stuff.
- result = dup2(backup_stdio, STDOUT_FILENO);
- ASSERT_EQ(STDOUT_FILENO, result);
-
- // Close our copy of the write end of the pipe, so that the read()
- // from the other end will see EOF if it wasn't copied to the child.
- result = IGNORE_EINTR(close(pipe_fds[1]));
- ASSERT_EQ(0, result);
-
- result = IGNORE_EINTR(close(backup_stdio));
- ASSERT_EQ(0, result);
- result = IGNORE_EINTR(close(dev_null));
- ASSERT_EQ(0, result);
-
- // Read from the pipe to verify that it is connected to the child
- // process' stdio.
- char buf[16] = {};
- EXPECT_EQ(1, HANDLE_EINTR(read(pipe_fds[0], buf, sizeof(buf))));
- EXPECT_EQ(kPipeValue, buf[0]);
-
- result = IGNORE_EINTR(close(pipe_fds[0]));
- ASSERT_EQ(0, result);
-
- int exit_code;
- ASSERT_TRUE(
- process.WaitForExitWithTimeout(TimeDelta::FromSeconds(5), &exit_code));
- EXPECT_EQ(0, exit_code);
-}
-
-#if defined(OS_FUCHSIA)
-
-const uint16_t kStartupHandleId = 43;
-MULTIPROCESS_TEST_MAIN(ProcessUtilsVerifyHandle) {
- zx_handle_t handle =
- zx_take_startup_handle(PA_HND(PA_USER0, kStartupHandleId));
- CHECK_NE(ZX_HANDLE_INVALID, handle);
-
- // Write to the pipe so the parent process can observe output.
- size_t bytes_written = 0;
- zx_status_t result = zx_socket_write(handle, 0, &kPipeValue,
- sizeof(kPipeValue), &bytes_written);
- CHECK_EQ(ZX_OK, result);
- CHECK_EQ(1u, bytes_written);
-
- CHECK_EQ(ZX_OK, zx_handle_close(handle));
- return 0;
-}
-
-TEST_F(ProcessUtilTest, LaunchWithHandleTransfer) {
- // Create a pipe to pass to the child process.
- zx_handle_t handles[2];
- zx_status_t result =
- zx_socket_create(ZX_SOCKET_STREAM, &handles[0], &handles[1]);
- ASSERT_EQ(ZX_OK, result);
-
- // Launch the test process, and pass it one end of the pipe.
- LaunchOptions options;
- options.handles_to_transfer.push_back(
- {PA_HND(PA_USER0, kStartupHandleId), handles[0]});
- Process process = SpawnChildWithOptions("ProcessUtilsVerifyHandle", options);
- ASSERT_TRUE(process.IsValid());
-
- // Read from the pipe to verify that the child received it.
- zx_signals_t signals = 0;
- result = zx_object_wait_one(
- handles[1], ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
- (base::TimeTicks::Now() + TestTimeouts::action_timeout()).ToZxTime(),
- &signals);
- ASSERT_EQ(ZX_OK, result);
- ASSERT_TRUE(signals & ZX_SOCKET_READABLE);
-
- size_t bytes_read = 0;
- char buf[16] = {0};
- result = zx_socket_read(handles[1], 0, buf, sizeof(buf), &bytes_read);
- EXPECT_EQ(ZX_OK, result);
- EXPECT_EQ(1u, bytes_read);
- EXPECT_EQ(kPipeValue, buf[0]);
-
- CHECK_EQ(ZX_OK, zx_handle_close(handles[1]));
-
- int exit_code;
- ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_timeout(),
- &exit_code));
- EXPECT_EQ(0, exit_code);
-}
-
-#endif // defined(OS_FUCHSIA)
-
-namespace {
-
-std::string TestLaunchProcess(const std::vector<std::string>& args,
- const EnvironmentMap& env_changes,
- const bool clear_environ,
- const int clone_flags) {
- int fds[2];
- PCHECK(pipe(fds) == 0);
-
- LaunchOptions options;
- options.wait = true;
- options.environ = env_changes;
- options.clear_environ = clear_environ;
- options.fds_to_remap.emplace_back(fds[1], 1);
-#if defined(OS_LINUX)
- options.clone_flags = clone_flags;
-#else
- CHECK_EQ(0, clone_flags);
-#endif // defined(OS_LINUX)
- EXPECT_TRUE(LaunchProcess(args, options).IsValid());
- PCHECK(IGNORE_EINTR(close(fds[1])) == 0);
-
- char buf[512];
- const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
-
- PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
-
- return std::string(buf, n);
-}
-
-const char kLargeString[] =
- "0123456789012345678901234567890123456789012345678901234567890123456789"
- "0123456789012345678901234567890123456789012345678901234567890123456789"
- "0123456789012345678901234567890123456789012345678901234567890123456789"
- "0123456789012345678901234567890123456789012345678901234567890123456789"
- "0123456789012345678901234567890123456789012345678901234567890123456789"
- "0123456789012345678901234567890123456789012345678901234567890123456789"
- "0123456789012345678901234567890123456789012345678901234567890123456789";
-
-} // namespace
-
-TEST_F(ProcessUtilTest, LaunchProcess) {
- const int no_clone_flags = 0;
- const bool no_clear_environ = false;
- const char kBaseTest[] = "BASE_TEST";
- const std::vector<std::string> kPrintEnvCommand = {test_helper_path_.value(),
- "-e", kBaseTest};
-
- EnvironmentMap env_changes;
- env_changes[kBaseTest] = "bar";
- EXPECT_EQ("bar", TestLaunchProcess(kPrintEnvCommand, env_changes,
- no_clear_environ, no_clone_flags));
- env_changes.clear();
-
- EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */));
- EXPECT_EQ("testing", TestLaunchProcess(kPrintEnvCommand, env_changes,
- no_clear_environ, no_clone_flags));
-
- env_changes[kBaseTest] = std::string();
- EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
- no_clear_environ, no_clone_flags));
-
- env_changes[kBaseTest] = "foo";
- EXPECT_EQ("foo", TestLaunchProcess(kPrintEnvCommand, env_changes,
- no_clear_environ, no_clone_flags));
-
- env_changes.clear();
- EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */));
- EXPECT_EQ(std::string(kLargeString),
- TestLaunchProcess(kPrintEnvCommand, env_changes, no_clear_environ,
- no_clone_flags));
-
- env_changes[kBaseTest] = "wibble";
- EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
- no_clear_environ, no_clone_flags));
-
-#if defined(OS_LINUX)
- // Test a non-trival value for clone_flags.
- EXPECT_EQ("wibble", TestLaunchProcess(kPrintEnvCommand, env_changes,
- no_clear_environ, CLONE_FS));
-
- EXPECT_EQ("wibble",
- TestLaunchProcess(kPrintEnvCommand, env_changes,
- true /* clear_environ */, no_clone_flags));
- env_changes.clear();
- EXPECT_EQ("", TestLaunchProcess(kPrintEnvCommand, env_changes,
- true /* clear_environ */, no_clone_flags));
-#endif // defined(OS_LINUX)
-}
-
-// There's no such thing as a parent process id on Fuchsia.
-#if !defined(OS_FUCHSIA)
-TEST_F(ProcessUtilTest, GetParentProcessId) {
- ProcessId ppid = GetParentProcessId(GetCurrentProcessHandle());
- EXPECT_EQ(ppid, static_cast<ProcessId>(getppid()));
-}
-#endif // !defined(OS_FUCHSIA)
-
-#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
-class WriteToPipeDelegate : public LaunchOptions::PreExecDelegate {
- public:
- explicit WriteToPipeDelegate(int fd) : fd_(fd) {}
- ~WriteToPipeDelegate() override = default;
- void RunAsyncSafe() override {
- RAW_CHECK(HANDLE_EINTR(write(fd_, &kPipeValue, 1)) == 1);
- RAW_CHECK(IGNORE_EINTR(close(fd_)) == 0);
- }
-
- private:
- int fd_;
- DISALLOW_COPY_AND_ASSIGN(WriteToPipeDelegate);
-};
-
-TEST_F(ProcessUtilTest, PreExecHook) {
- int pipe_fds[2];
- ASSERT_EQ(0, pipe(pipe_fds));
-
- ScopedFD read_fd(pipe_fds[0]);
- ScopedFD write_fd(pipe_fds[1]);
-
- WriteToPipeDelegate write_to_pipe_delegate(write_fd.get());
- LaunchOptions options;
- options.fds_to_remap.emplace_back(write_fd.get(), write_fd.get());
- options.pre_exec_delegate = &write_to_pipe_delegate;
- Process process(SpawnChildWithOptions("SimpleChildProcess", options));
- ASSERT_TRUE(process.IsValid());
-
- write_fd.reset();
- char c;
- ASSERT_EQ(1, HANDLE_EINTR(read(read_fd.get(), &c, 1)));
- EXPECT_EQ(c, kPipeValue);
-
- int exit_code = 42;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(0, exit_code);
-}
-#endif // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
-
-#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
-
-#if defined(OS_LINUX)
-MULTIPROCESS_TEST_MAIN(CheckPidProcess) {
- const pid_t kInitPid = 1;
- const pid_t pid = syscall(__NR_getpid);
- CHECK(pid == kInitPid);
- CHECK(getpid() == pid);
- return kSuccess;
-}
-
-#if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
-TEST_F(ProcessUtilTest, CloneFlags) {
- if (!PathExists(FilePath("/proc/self/ns/user")) ||
- !PathExists(FilePath("/proc/self/ns/pid"))) {
- // User or PID namespaces are not supported.
- return;
- }
-
- LaunchOptions options;
- options.clone_flags = CLONE_NEWUSER | CLONE_NEWPID;
-
- Process process(SpawnChildWithOptions("CheckPidProcess", options));
- ASSERT_TRUE(process.IsValid());
-
- int exit_code = 42;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_EQ(kSuccess, exit_code);
-}
-#endif // defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
-
-TEST(ForkWithFlagsTest, UpdatesPidCache) {
- // Warm up the libc pid cache, if there is one.
- ASSERT_EQ(syscall(__NR_getpid), getpid());
-
- pid_t ctid = 0;
- const pid_t pid = ForkWithFlags(SIGCHLD | CLONE_CHILD_SETTID, nullptr, &ctid);
- if (pid == 0) {
- // In child. Check both the raw getpid syscall and the libc getpid wrapper
- // (which may rely on a pid cache).
- RAW_CHECK(syscall(__NR_getpid) == ctid);
- RAW_CHECK(getpid() == ctid);
- _exit(kSuccess);
- }
-
- ASSERT_NE(-1, pid);
- int status = 42;
- ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
- ASSERT_TRUE(WIFEXITED(status));
- EXPECT_EQ(kSuccess, WEXITSTATUS(status));
-}
-
-TEST_F(ProcessUtilTest, InvalidCurrentDirectory) {
- LaunchOptions options;
- options.current_directory = FilePath("/dev/null");
-
- Process process(SpawnChildWithOptions("SimpleChildProcess", options));
- ASSERT_TRUE(process.IsValid());
-
- int exit_code = kSuccess;
- EXPECT_TRUE(process.WaitForExit(&exit_code));
- EXPECT_NE(kSuccess, exit_code);
-}
-#endif // defined(OS_LINUX)
-
-} // namespace base
diff --git a/base/profiler/native_stack_sampler.cc b/base/profiler/native_stack_sampler.cc
deleted file mode 100644
index 6eed54f046..0000000000
--- a/base/profiler/native_stack_sampler.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 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/profiler/native_stack_sampler.h"
-
-#include "base/memory/ptr_util.h"
-
-namespace base {
-
-NativeStackSampler::StackBuffer::StackBuffer(size_t buffer_size)
- : buffer_(new uintptr_t[(buffer_size + sizeof(uintptr_t) - 1) /
- sizeof(uintptr_t)]),
- size_(buffer_size) {}
-
-NativeStackSampler::StackBuffer::~StackBuffer() = default;
-
-NativeStackSampler::NativeStackSampler() = default;
-
-NativeStackSampler::~NativeStackSampler() = default;
-
-std::unique_ptr<NativeStackSampler::StackBuffer>
-NativeStackSampler::CreateStackBuffer() {
- size_t size = GetStackBufferSize();
- if (size == 0)
- return nullptr;
- return std::make_unique<StackBuffer>(size);
-}
-
-NativeStackSamplerTestDelegate::~NativeStackSamplerTestDelegate() = default;
-
-NativeStackSamplerTestDelegate::NativeStackSamplerTestDelegate() = default;
-
-} // namespace base
diff --git a/base/profiler/native_stack_sampler.h b/base/profiler/native_stack_sampler.h
deleted file mode 100644
index 5d7e9b0771..0000000000
--- a/base/profiler/native_stack_sampler.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
-#define BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
-
-#include <memory>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/profiler/stack_sampling_profiler.h"
-#include "base/threading/platform_thread.h"
-
-namespace base {
-
-class NativeStackSamplerTestDelegate;
-
-// NativeStackSampler is an implementation detail of StackSamplingProfiler. It
-// abstracts the native implementation required to record a set of stack frames
-// for a given thread.
-class NativeStackSampler {
- public:
- // This class contains a buffer for stack copies that can be shared across
- // multiple instances of NativeStackSampler.
- class StackBuffer {
- public:
- StackBuffer(size_t buffer_size);
- ~StackBuffer();
-
- void* buffer() const { return buffer_.get(); }
- size_t size() const { return size_; }
-
- private:
- // The word-aligned buffer.
- const std::unique_ptr<uintptr_t[]> buffer_;
-
- // The size of the buffer.
- const size_t size_;
-
- DISALLOW_COPY_AND_ASSIGN(StackBuffer);
- };
-
- virtual ~NativeStackSampler();
-
- // Creates a stack sampler that records samples for thread with |thread_id|.
- // Returns null if this platform does not support stack sampling.
- static std::unique_ptr<NativeStackSampler> Create(
- PlatformThreadId thread_id,
- NativeStackSamplerTestDelegate* test_delegate);
-
- // Gets the required size of the stack buffer.
- static size_t GetStackBufferSize();
-
- // Creates an instance of the a stack buffer that can be used for calls to
- // any NativeStackSampler object.
- static std::unique_ptr<StackBuffer> CreateStackBuffer();
-
- // The following functions are all called on the SamplingThread (not the
- // thread being sampled).
-
- // Notifies the sampler that we're starting to record a new profile.
- virtual void ProfileRecordingStarting() = 0;
-
- // Records a set of internal frames and returns them.
- virtual std::vector<StackSamplingProfiler::InternalFrame> RecordStackFrames(
- StackBuffer* stackbuffer,
- StackSamplingProfiler::ProfileBuilder* profile_builder) = 0;
-
- protected:
- NativeStackSampler();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NativeStackSampler);
-};
-
-// NativeStackSamplerTestDelegate provides seams for test code to execute during
-// stack collection.
-class BASE_EXPORT NativeStackSamplerTestDelegate {
- public:
- virtual ~NativeStackSamplerTestDelegate();
-
- // Called after copying the stack and resuming the target thread, but prior to
- // walking the stack. Invoked on the SamplingThread.
- virtual void OnPreStackWalk() = 0;
-
- protected:
- NativeStackSamplerTestDelegate();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerTestDelegate);
-};
-
-} // namespace base
-
-#endif // BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
-
diff --git a/base/profiler/native_stack_sampler_posix.cc b/base/profiler/native_stack_sampler_posix.cc
deleted file mode 100644
index fdc18e017f..0000000000
--- a/base/profiler/native_stack_sampler_posix.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 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/profiler/native_stack_sampler.h"
-
-namespace base {
-
-std::unique_ptr<NativeStackSampler> NativeStackSampler::Create(
- PlatformThreadId thread_id,
- NativeStackSamplerTestDelegate* test_delegate) {
- return std::unique_ptr<NativeStackSampler>();
-}
-
-size_t NativeStackSampler::GetStackBufferSize() {
- return 0;
-}
-
-} // namespace base
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
deleted file mode 100644
index 02df814f8c..0000000000
--- a/base/profiler/stack_sampling_profiler.cc
+++ /dev/null
@@ -1,808 +0,0 @@
-// Copyright 2015 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/profiler/stack_sampling_profiler.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/atomic_sequence_num.h"
-#include "base/atomicops.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/singleton.h"
-#include "base/profiler/native_stack_sampler.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/timer/elapsed_timer.h"
-
-namespace base {
-
-const size_t kUnknownModuleIndex = static_cast<size_t>(-1);
-
-namespace {
-
-// This value is used to initialize the WaitableEvent object. This MUST BE set
-// to MANUAL for correct operation of the IsSignaled() call in Start(). See the
-// comment there for why.
-constexpr WaitableEvent::ResetPolicy kResetPolicy =
- WaitableEvent::ResetPolicy::MANUAL;
-
-// This value is used when there is no collection in progress and thus no ID
-// for referencing the active collection to the SamplingThread.
-const int kNullProfilerId = -1;
-
-} // namespace
-
-// StackSamplingProfiler::Module ----------------------------------------------
-
-StackSamplingProfiler::Module::Module() : base_address(0u) {}
-
-StackSamplingProfiler::Module::Module(uintptr_t base_address,
- const std::string& id,
- const FilePath& filename)
- : base_address(base_address), id(id), filename(filename) {}
-
-StackSamplingProfiler::Module::~Module() = default;
-
-// StackSamplingProfiler::InternalModule --------------------------------------
-
-StackSamplingProfiler::InternalModule::InternalModule() : is_valid(false) {}
-
-StackSamplingProfiler::InternalModule::InternalModule(uintptr_t base_address,
- const std::string& id,
- const FilePath& filename)
- : base_address(base_address), id(id), filename(filename), is_valid(true) {}
-
-StackSamplingProfiler::InternalModule::~InternalModule() = default;
-
-// StackSamplingProfiler::Frame -----------------------------------------------
-
-StackSamplingProfiler::Frame::Frame(uintptr_t instruction_pointer,
- size_t module_index)
- : instruction_pointer(instruction_pointer), module_index(module_index) {}
-
-StackSamplingProfiler::Frame::~Frame() = default;
-
-StackSamplingProfiler::Frame::Frame()
- : instruction_pointer(0), module_index(kUnknownModuleIndex) {}
-
-// StackSamplingProfiler::InternalFrame -------------------------------------
-
-StackSamplingProfiler::InternalFrame::InternalFrame(
- uintptr_t instruction_pointer,
- InternalModule internal_module)
- : instruction_pointer(instruction_pointer),
- internal_module(std::move(internal_module)) {}
-
-StackSamplingProfiler::InternalFrame::~InternalFrame() = default;
-
-// StackSamplingProfiler::Sample ----------------------------------------------
-
-StackSamplingProfiler::Sample::Sample() = default;
-
-StackSamplingProfiler::Sample::Sample(const Sample& sample) = default;
-
-StackSamplingProfiler::Sample::~Sample() = default;
-
-StackSamplingProfiler::Sample::Sample(const Frame& frame) {
- frames.push_back(std::move(frame));
-}
-
-StackSamplingProfiler::Sample::Sample(const std::vector<Frame>& frames)
- : frames(frames) {}
-
-// StackSamplingProfiler::CallStackProfile ------------------------------------
-
-StackSamplingProfiler::CallStackProfile::CallStackProfile() = default;
-
-StackSamplingProfiler::CallStackProfile::CallStackProfile(
- CallStackProfile&& other) = default;
-
-StackSamplingProfiler::CallStackProfile::~CallStackProfile() = default;
-
-StackSamplingProfiler::CallStackProfile&
-StackSamplingProfiler::CallStackProfile::operator=(CallStackProfile&& other) =
- default;
-
-StackSamplingProfiler::CallStackProfile
-StackSamplingProfiler::CallStackProfile::CopyForTesting() const {
- return CallStackProfile(*this);
-}
-
-StackSamplingProfiler::CallStackProfile::CallStackProfile(
- const CallStackProfile& other) = default;
-
-// StackSamplingProfiler::SamplingThread --------------------------------------
-
-class StackSamplingProfiler::SamplingThread : public Thread {
- public:
- class TestAPI {
- public:
- // Reset the existing sampler. This will unfortunately create the object
- // unnecessarily if it doesn't already exist but there's no way around that.
- static void Reset();
-
- // Disables inherent idle-shutdown behavior.
- static void DisableIdleShutdown();
-
- // Begins an idle shutdown as if the idle-timer had expired and wait for
- // it to execute. Since the timer would have only been started at a time
- // when the sampling thread actually was idle, this must be called only
- // when it is known that there are no active sampling threads. If
- // |simulate_intervening_add| is true then, when executed, the shutdown
- // task will believe that a new collection has been added since it was
- // posted.
- static void ShutdownAssumingIdle(bool simulate_intervening_add);
-
- private:
- // Calls the sampling threads ShutdownTask and then signals an event.
- static void ShutdownTaskAndSignalEvent(SamplingThread* sampler,
- int add_events,
- WaitableEvent* event);
- };
-
- struct CollectionContext {
- CollectionContext(PlatformThreadId target,
- const SamplingParams& params,
- WaitableEvent* finished,
- std::unique_ptr<NativeStackSampler> sampler,
- std::unique_ptr<ProfileBuilder> profile_builder)
- : collection_id(next_collection_id.GetNext()),
- target(target),
- params(params),
- finished(finished),
- native_sampler(std::move(sampler)),
- profile_builder(std::move(profile_builder)) {}
- ~CollectionContext() = default;
-
- // An identifier for this collection, used to uniquely identify the
- // collection to outside interests.
- const int collection_id;
-
- const PlatformThreadId target; // ID of The thread being sampled.
- const SamplingParams params; // Information about how to sample.
- WaitableEvent* const finished; // Signaled when all sampling complete.
-
- // Platform-specific module that does the actual sampling.
- std::unique_ptr<NativeStackSampler> native_sampler;
-
- // Receives the sampling data and builds a CallStackProfile.
- std::unique_ptr<ProfileBuilder> profile_builder;
-
- // The absolute time for the next sample.
- Time next_sample_time;
-
- // The time that a profile was started, for calculating the total duration.
- Time profile_start_time;
-
- // Counter that indicates the current sample position along the acquisition.
- int sample_count = 0;
-
- // Sequence number for generating new collection ids.
- static AtomicSequenceNumber next_collection_id;
- };
-
- // Gets the single instance of this class.
- static SamplingThread* GetInstance();
-
- // Adds a new CollectionContext to the thread. This can be called externally
- // from any thread. This returns a collection id that can later be used to
- // stop the sampling.
- int Add(std::unique_ptr<CollectionContext> collection);
-
- // Removes an active collection based on its collection id, forcing it to run
- // its callback if any data has been collected. This can be called externally
- // from any thread.
- void Remove(int collection_id);
-
- private:
- friend class TestAPI;
- friend struct DefaultSingletonTraits<SamplingThread>;
-
- // The different states in which the sampling-thread can be.
- enum ThreadExecutionState {
- // The thread is not running because it has never been started. It will be
- // started when a sampling request is received.
- NOT_STARTED,
-
- // The thread is running and processing tasks. This is the state when any
- // sampling requests are active and during the "idle" period afterward
- // before the thread is stopped.
- RUNNING,
-
- // Once all sampling requests have finished and the "idle" period has
- // expired, the thread will be set to this state and its shutdown
- // initiated. A call to Stop() must be made to ensure the previous thread
- // has completely exited before calling Start() and moving back to the
- // RUNNING state.
- EXITING,
- };
-
- SamplingThread();
- ~SamplingThread() override;
-
- // Get task runner that is usable from the outside.
- scoped_refptr<SingleThreadTaskRunner> GetOrCreateTaskRunnerForAdd();
- scoped_refptr<SingleThreadTaskRunner> GetTaskRunner(
- ThreadExecutionState* out_state);
-
- // Get task runner that is usable from the sampling thread itself.
- scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread();
-
- // Finishes a collection. The collection's |finished| waitable event will be
- // signalled. The |collection| should already have been removed from
- // |active_collections_| by the caller, as this is needed to avoid flakiness
- // in unit tests.
- void FinishCollection(CollectionContext* collection);
-
- // Check if the sampling thread is idle and begin a shutdown if it is.
- void ScheduleShutdownIfIdle();
-
- // These methods are tasks that get posted to the internal message queue.
- void AddCollectionTask(std::unique_ptr<CollectionContext> collection);
- void RemoveCollectionTask(int collection_id);
- void RecordSampleTask(int collection_id);
- void ShutdownTask(int add_events);
-
- // Thread:
- void CleanUp() override;
-
- // A stack-buffer used by the native sampler for its work. This buffer can
- // be re-used for multiple native sampler objects so long as the API calls
- // that take it are not called concurrently.
- std::unique_ptr<NativeStackSampler::StackBuffer> stack_buffer_;
-
- // A map of collection ids to collection contexts. Because this class is a
- // singleton that is never destroyed, context objects will never be destructed
- // except by explicit action. Thus, it's acceptable to pass unretained
- // pointers to these objects when posting tasks.
- std::map<int, std::unique_ptr<CollectionContext>> active_collections_;
-
- // State maintained about the current execution (or non-execution) of
- // the thread. This state must always be accessed while holding the
- // lock. A copy of the task-runner is maintained here for use by any
- // calling thread; this is necessary because Thread's accessor for it is
- // not itself thread-safe. The lock is also used to order calls to the
- // Thread API (Start, Stop, StopSoon, & DetachFromSequence) so that
- // multiple threads may make those calls.
- Lock thread_execution_state_lock_; // Protects all thread_execution_state_*
- ThreadExecutionState thread_execution_state_ = NOT_STARTED;
- scoped_refptr<SingleThreadTaskRunner> thread_execution_state_task_runner_;
- bool thread_execution_state_disable_idle_shutdown_for_testing_ = false;
-
- // A counter that notes adds of new collection requests. It is incremented
- // when changes occur so that delayed shutdown tasks are able to detect if
- // something new has happened while it was waiting. Like all "execution_state"
- // vars, this must be accessed while holding |thread_execution_state_lock_|.
- int thread_execution_state_add_events_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(SamplingThread);
-};
-
-// static
-void StackSamplingProfiler::SamplingThread::TestAPI::Reset() {
- SamplingThread* sampler = SamplingThread::GetInstance();
-
- ThreadExecutionState state;
- {
- AutoLock lock(sampler->thread_execution_state_lock_);
- state = sampler->thread_execution_state_;
- DCHECK(sampler->active_collections_.empty());
- }
-
- // Stop the thread and wait for it to exit. This has to be done through by
- // the thread itself because it has taken ownership of its own lifetime.
- if (state == RUNNING) {
- ShutdownAssumingIdle(false);
- state = EXITING;
- }
- // Make sure thread is cleaned up since state will be reset to NOT_STARTED.
- if (state == EXITING)
- sampler->Stop();
-
- // Reset internal variables to the just-initialized state.
- {
- AutoLock lock(sampler->thread_execution_state_lock_);
- sampler->thread_execution_state_ = NOT_STARTED;
- sampler->thread_execution_state_task_runner_ = nullptr;
- sampler->thread_execution_state_disable_idle_shutdown_for_testing_ = false;
- sampler->thread_execution_state_add_events_ = 0;
- }
-}
-
-// static
-void StackSamplingProfiler::SamplingThread::TestAPI::DisableIdleShutdown() {
- SamplingThread* sampler = SamplingThread::GetInstance();
-
- {
- AutoLock lock(sampler->thread_execution_state_lock_);
- sampler->thread_execution_state_disable_idle_shutdown_for_testing_ = true;
- }
-}
-
-// static
-void StackSamplingProfiler::SamplingThread::TestAPI::ShutdownAssumingIdle(
- bool simulate_intervening_add) {
- SamplingThread* sampler = SamplingThread::GetInstance();
-
- ThreadExecutionState state;
- scoped_refptr<SingleThreadTaskRunner> task_runner =
- sampler->GetTaskRunner(&state);
- DCHECK_EQ(RUNNING, state);
- DCHECK(task_runner);
-
- int add_events;
- {
- AutoLock lock(sampler->thread_execution_state_lock_);
- add_events = sampler->thread_execution_state_add_events_;
- if (simulate_intervening_add)
- ++sampler->thread_execution_state_add_events_;
- }
-
- WaitableEvent executed(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- // PostTaskAndReply won't work because thread and associated message-loop may
- // be shut down.
- task_runner->PostTask(
- FROM_HERE, BindOnce(&ShutdownTaskAndSignalEvent, Unretained(sampler),
- add_events, Unretained(&executed)));
- executed.Wait();
-}
-
-// static
-void StackSamplingProfiler::SamplingThread::TestAPI::ShutdownTaskAndSignalEvent(
- SamplingThread* sampler,
- int add_events,
- WaitableEvent* event) {
- sampler->ShutdownTask(add_events);
- event->Signal();
-}
-
-AtomicSequenceNumber StackSamplingProfiler::SamplingThread::CollectionContext::
- next_collection_id;
-
-StackSamplingProfiler::SamplingThread::SamplingThread()
- : Thread("StackSamplingProfiler") {}
-
-StackSamplingProfiler::SamplingThread::~SamplingThread() = default;
-
-StackSamplingProfiler::SamplingThread*
-StackSamplingProfiler::SamplingThread::GetInstance() {
- return Singleton<SamplingThread, LeakySingletonTraits<SamplingThread>>::get();
-}
-
-int StackSamplingProfiler::SamplingThread::Add(
- std::unique_ptr<CollectionContext> collection) {
- // This is not to be run on the sampling thread.
-
- int collection_id = collection->collection_id;
- scoped_refptr<SingleThreadTaskRunner> task_runner =
- GetOrCreateTaskRunnerForAdd();
-
- task_runner->PostTask(
- FROM_HERE, BindOnce(&SamplingThread::AddCollectionTask, Unretained(this),
- std::move(collection)));
-
- return collection_id;
-}
-
-void StackSamplingProfiler::SamplingThread::Remove(int collection_id) {
- // This is not to be run on the sampling thread.
-
- ThreadExecutionState state;
- scoped_refptr<SingleThreadTaskRunner> task_runner = GetTaskRunner(&state);
- if (state != RUNNING)
- return;
- DCHECK(task_runner);
-
- // This can fail if the thread were to exit between acquisition of the task
- // runner above and the call below. In that case, however, everything has
- // stopped so there's no need to try to stop it.
- task_runner->PostTask(FROM_HERE,
- BindOnce(&SamplingThread::RemoveCollectionTask,
- Unretained(this), collection_id));
-}
-
-scoped_refptr<SingleThreadTaskRunner>
-StackSamplingProfiler::SamplingThread::GetOrCreateTaskRunnerForAdd() {
- AutoLock lock(thread_execution_state_lock_);
-
- // The increment of the "add events" count is why this method is to be only
- // called from "add".
- ++thread_execution_state_add_events_;
-
- if (thread_execution_state_ == RUNNING) {
- DCHECK(thread_execution_state_task_runner_);
- // This shouldn't be called from the sampling thread as it's inefficient.
- // Use GetTaskRunnerOnSamplingThread() instead.
- DCHECK_NE(GetThreadId(), PlatformThread::CurrentId());
- return thread_execution_state_task_runner_;
- }
-
- if (thread_execution_state_ == EXITING) {
- // StopSoon() was previously called to shut down the thread
- // asynchonously. Stop() must now be called before calling Start() again to
- // reset the thread state.
- //
- // We must allow blocking here to satisfy the Thread implementation, but in
- // practice the Stop() call is unlikely to actually block. For this to
- // happen a new profiling request would have to be made within the narrow
- // window between StopSoon() and thread exit following the end of the 60
- // second idle period.
- ScopedAllowBlocking allow_blocking;
- Stop();
- }
-
- DCHECK(!stack_buffer_);
- stack_buffer_ = NativeStackSampler::CreateStackBuffer();
-
- // The thread is not running. Start it and get associated runner. The task-
- // runner has to be saved for future use because though it can be used from
- // any thread, it can be acquired via task_runner() only on the created
- // thread and the thread that creates it (i.e. this thread) for thread-safety
- // reasons which are alleviated in SamplingThread by gating access to it with
- // the |thread_execution_state_lock_|.
- Start();
- thread_execution_state_ = RUNNING;
- thread_execution_state_task_runner_ = Thread::task_runner();
-
- // Detach the sampling thread from the "sequence" (i.e. thread) that
- // started it so that it can be self-managed or stopped by another thread.
- DetachFromSequence();
-
- return thread_execution_state_task_runner_;
-}
-
-scoped_refptr<SingleThreadTaskRunner>
-StackSamplingProfiler::SamplingThread::GetTaskRunner(
- ThreadExecutionState* out_state) {
- AutoLock lock(thread_execution_state_lock_);
- if (out_state)
- *out_state = thread_execution_state_;
- if (thread_execution_state_ == RUNNING) {
- // This shouldn't be called from the sampling thread as it's inefficient.
- // Use GetTaskRunnerOnSamplingThread() instead.
- DCHECK_NE(GetThreadId(), PlatformThread::CurrentId());
- DCHECK(thread_execution_state_task_runner_);
- } else {
- DCHECK(!thread_execution_state_task_runner_);
- }
-
- return thread_execution_state_task_runner_;
-}
-
-scoped_refptr<SingleThreadTaskRunner>
-StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() {
- // This should be called only from the sampling thread as it has limited
- // accessibility.
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
-
- return Thread::task_runner();
-}
-
-void StackSamplingProfiler::SamplingThread::FinishCollection(
- CollectionContext* collection) {
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
- DCHECK_EQ(0u, active_collections_.count(collection->collection_id));
-
- TimeDelta profile_duration = Time::Now() - collection->profile_start_time +
- collection->params.sampling_interval;
-
- collection->profile_builder->OnProfileCompleted(
- profile_duration, collection->params.sampling_interval);
-
- // Signal that this collection is finished.
- collection->finished->Signal();
-
- ScheduleShutdownIfIdle();
-}
-
-void StackSamplingProfiler::SamplingThread::ScheduleShutdownIfIdle() {
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
-
- if (!active_collections_.empty())
- return;
-
- int add_events;
- {
- AutoLock lock(thread_execution_state_lock_);
- if (thread_execution_state_disable_idle_shutdown_for_testing_)
- return;
- add_events = thread_execution_state_add_events_;
- }
-
- GetTaskRunnerOnSamplingThread()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&SamplingThread::ShutdownTask, Unretained(this), add_events),
- TimeDelta::FromSeconds(60));
-}
-
-void StackSamplingProfiler::SamplingThread::AddCollectionTask(
- std::unique_ptr<CollectionContext> collection) {
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
-
- const int collection_id = collection->collection_id;
- const TimeDelta initial_delay = collection->params.initial_delay;
-
- active_collections_.insert(
- std::make_pair(collection_id, std::move(collection)));
-
- GetTaskRunnerOnSamplingThread()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&SamplingThread::RecordSampleTask, Unretained(this),
- collection_id),
- initial_delay);
-
- // Another increment of "add events" serves to invalidate any pending
- // shutdown tasks that may have been initiated between the Add() and this
- // task running.
- {
- AutoLock lock(thread_execution_state_lock_);
- ++thread_execution_state_add_events_;
- }
-}
-
-void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(
- int collection_id) {
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
-
- auto found = active_collections_.find(collection_id);
- if (found == active_collections_.end())
- return;
-
- // Remove |collection| from |active_collections_|.
- std::unique_ptr<CollectionContext> collection = std::move(found->second);
- size_t count = active_collections_.erase(collection_id);
- DCHECK_EQ(1U, count);
-
- FinishCollection(collection.get());
-}
-
-void StackSamplingProfiler::SamplingThread::RecordSampleTask(
- int collection_id) {
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
-
- auto found = active_collections_.find(collection_id);
-
- // The task won't be found if it has been stopped.
- if (found == active_collections_.end())
- return;
-
- CollectionContext* collection = found->second.get();
-
- // If this is the first sample, the collection params need to be filled.
- if (collection->sample_count == 0) {
- collection->profile_start_time = Time::Now();
- collection->next_sample_time = Time::Now();
- collection->native_sampler->ProfileRecordingStarting();
- }
-
- // Record a single sample.
- collection->profile_builder->OnSampleCompleted(
- collection->native_sampler->RecordStackFrames(
- stack_buffer_.get(), collection->profile_builder.get()));
-
- // Schedule the next sample recording if there is one.
- if (++collection->sample_count < collection->params.samples_per_profile) {
- // This will keep a consistent average interval between samples but will
- // result in constant series of acquisitions, thus nearly locking out the
- // target thread, if the interval is smaller than the time it takes to
- // actually acquire the sample. Anything sampling that quickly is going
- // to be a problem anyway so don't worry about it.
- collection->next_sample_time += collection->params.sampling_interval;
- bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&SamplingThread::RecordSampleTask, Unretained(this),
- collection_id),
- std::max(collection->next_sample_time - Time::Now(), TimeDelta()));
- DCHECK(success);
- return;
- }
-
- // Take ownership of |collection| and remove it from the map.
- std::unique_ptr<CollectionContext> owned_collection =
- std::move(found->second);
- size_t count = active_collections_.erase(collection_id);
- DCHECK_EQ(1U, count);
-
- // All capturing has completed so finish the collection.
- FinishCollection(collection);
-}
-
-void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) {
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
-
- // Holding this lock ensures that any attempt to start another job will
- // get postponed until |thread_execution_state_| is updated, thus eliminating
- // the race in starting a new thread while the previous one is exiting.
- AutoLock lock(thread_execution_state_lock_);
-
- // If the current count of creation requests doesn't match the passed count
- // then other tasks have been created since this was posted. Abort shutdown.
- if (thread_execution_state_add_events_ != add_events)
- return;
-
- // There can be no new AddCollectionTasks at this point because creating
- // those always increments "add events". There may be other requests, like
- // Remove, but it's okay to schedule the thread to stop once they've been
- // executed (i.e. "soon").
- DCHECK(active_collections_.empty());
- StopSoon();
-
- // StopSoon will have set the owning sequence (again) so it must be detached
- // (again) in order for Stop/Start to be called (again) should more work
- // come in. Holding the |thread_execution_state_lock_| ensures the necessary
- // happens-after with regard to this detach and future Thread API calls.
- DetachFromSequence();
-
- // Set the thread_state variable so the thread will be restarted when new
- // work comes in. Remove the |thread_execution_state_task_runner_| to avoid
- // confusion.
- thread_execution_state_ = EXITING;
- thread_execution_state_task_runner_ = nullptr;
- stack_buffer_.reset();
-}
-
-void StackSamplingProfiler::SamplingThread::CleanUp() {
- DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
-
- // There should be no collections remaining when the thread stops.
- DCHECK(active_collections_.empty());
-
- // Let the parent clean up.
- Thread::CleanUp();
-}
-
-// StackSamplingProfiler ------------------------------------------------------
-
-// static
-void StackSamplingProfiler::TestAPI::Reset() {
- SamplingThread::TestAPI::Reset();
-}
-
-// static
-bool StackSamplingProfiler::TestAPI::IsSamplingThreadRunning() {
- return SamplingThread::GetInstance()->IsRunning();
-}
-
-// static
-void StackSamplingProfiler::TestAPI::DisableIdleShutdown() {
- SamplingThread::TestAPI::DisableIdleShutdown();
-}
-
-// static
-void StackSamplingProfiler::TestAPI::PerformSamplingThreadIdleShutdown(
- bool simulate_intervening_start) {
- SamplingThread::TestAPI::ShutdownAssumingIdle(simulate_intervening_start);
-}
-
-StackSamplingProfiler::StackSamplingProfiler(
- const SamplingParams& params,
- std::unique_ptr<ProfileBuilder> profile_builder,
- NativeStackSamplerTestDelegate* test_delegate)
- : StackSamplingProfiler(PlatformThread::CurrentId(),
- params,
- std::move(profile_builder),
- test_delegate) {}
-
-StackSamplingProfiler::StackSamplingProfiler(
- PlatformThreadId thread_id,
- const SamplingParams& params,
- std::unique_ptr<ProfileBuilder> profile_builder,
- NativeStackSamplerTestDelegate* test_delegate)
- : thread_id_(thread_id),
- params_(params),
- profile_builder_(std::move(profile_builder)),
- // The event starts "signaled" so code knows it's safe to start thread
- // and "manual" so that it can be waited in multiple places.
- profiling_inactive_(kResetPolicy, WaitableEvent::InitialState::SIGNALED),
- profiler_id_(kNullProfilerId),
- test_delegate_(test_delegate) {
- DCHECK(profile_builder_);
-}
-
-StackSamplingProfiler::~StackSamplingProfiler() {
- // Stop returns immediately but the shutdown runs asynchronously. There is a
- // non-zero probability that one more sample will be taken after this call
- // returns.
- Stop();
-
- // The behavior of sampling a thread that has exited is undefined and could
- // cause Bad Things(tm) to occur. The safety model provided by this class is
- // that an instance of this object is expected to live at least as long as
- // the thread it is sampling. However, because the sampling is performed
- // asynchronously by the SamplingThread, there is no way to guarantee this
- // is true without waiting for it to signal that it has finished.
- //
- // The wait time should, at most, be only as long as it takes to collect one
- // sample (~200us) or none at all if sampling has already completed.
- ThreadRestrictions::ScopedAllowWait allow_wait;
- profiling_inactive_.Wait();
-}
-
-void StackSamplingProfiler::Start() {
- // Multiple calls to Start() for a single StackSamplingProfiler object is not
- // allowed. If profile_builder_ is nullptr, then Start() has been called
- // already.
- DCHECK(profile_builder_);
-
- std::unique_ptr<NativeStackSampler> native_sampler =
- NativeStackSampler::Create(thread_id_, test_delegate_);
-
- if (!native_sampler)
- return;
-
- // The IsSignaled() check below requires that the WaitableEvent be manually
- // reset, to avoid signaling the event in IsSignaled() itself.
- static_assert(kResetPolicy == WaitableEvent::ResetPolicy::MANUAL,
- "The reset policy must be set to MANUAL");
-
- // If a previous profiling phase is still winding down, wait for it to
- // complete. We can't use task posting for this coordination because the
- // thread owning the profiler may not have a message loop.
- if (!profiling_inactive_.IsSignaled())
- profiling_inactive_.Wait();
- profiling_inactive_.Reset();
-
- DCHECK_EQ(kNullProfilerId, profiler_id_);
- profiler_id_ = SamplingThread::GetInstance()->Add(
- std::make_unique<SamplingThread::CollectionContext>(
- thread_id_, params_, &profiling_inactive_, std::move(native_sampler),
- std::move(profile_builder_)));
- DCHECK_NE(kNullProfilerId, profiler_id_);
-}
-
-void StackSamplingProfiler::Stop() {
- SamplingThread::GetInstance()->Remove(profiler_id_);
- profiler_id_ = kNullProfilerId;
-}
-
-// StackSamplingProfiler::Frame global functions ------------------------------
-
-bool operator==(const StackSamplingProfiler::Module& a,
- const StackSamplingProfiler::Module& b) {
- return a.base_address == b.base_address && a.id == b.id &&
- a.filename == b.filename;
-}
-
-bool operator==(const StackSamplingProfiler::Sample& a,
- const StackSamplingProfiler::Sample& b) {
- return a.process_milestones == b.process_milestones && a.frames == b.frames;
-}
-
-bool operator!=(const StackSamplingProfiler::Sample& a,
- const StackSamplingProfiler::Sample& b) {
- return !(a == b);
-}
-
-bool operator<(const StackSamplingProfiler::Sample& a,
- const StackSamplingProfiler::Sample& b) {
- if (a.process_milestones != b.process_milestones)
- return a.process_milestones < b.process_milestones;
-
- return a.frames < b.frames;
-}
-
-bool operator==(const StackSamplingProfiler::Frame& a,
- const StackSamplingProfiler::Frame& b) {
- return a.instruction_pointer == b.instruction_pointer &&
- a.module_index == b.module_index;
-}
-
-bool operator<(const StackSamplingProfiler::Frame& a,
- const StackSamplingProfiler::Frame& b) {
- if (a.module_index != b.module_index)
- return a.module_index < b.module_index;
-
- return a.instruction_pointer < b.instruction_pointer;
-}
-
-} // namespace base
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h
deleted file mode 100644
index e43349a8fe..0000000000
--- a/base/profiler/stack_sampling_profiler.h
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_PROFILER_STACK_SAMPLING_PROFILER_H_
-#define BASE_PROFILER_STACK_SAMPLING_PROFILER_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-
-namespace base {
-
-// Identifies an unknown module.
-BASE_EXPORT extern const size_t kUnknownModuleIndex;
-
-class NativeStackSamplerTestDelegate;
-
-// StackSamplingProfiler periodically stops a thread to sample its stack, for
-// the purpose of collecting information about which code paths are
-// executing. This information is used in aggregate by UMA to identify hot
-// and/or janky code paths.
-//
-// Sample StackSamplingProfiler usage:
-//
-// // Create and customize params as desired.
-// base::StackStackSamplingProfiler::SamplingParams params;
-//
-// // To process the profiles, use a custom ProfileBuilder subclass:
-// class SubProfileBuilder :
-// public base::StackSamplingProfiler::ProfileBuilder{...}
-// base::StackSamplingProfiler profiler(base::PlatformThread::CurrentId()),
-// params, std::make_unique<SubProfileBuilder>(...));
-//
-// profiler.Start();
-// // ... work being done on the target thread here ...
-// profiler.Stop(); // optional, stops collection before complete per params
-//
-// The default SamplingParams causes stacks to be recorded in a single profile
-// at a 10Hz interval for a total of 30 seconds. All of these parameters may be
-// altered as desired.
-//
-// When a call stack profile is complete, or the profiler is stopped,
-// ProfileBuilder's OnProfileCompleted function is called from a thread created
-// by the profiler.
-class BASE_EXPORT StackSamplingProfiler {
- public:
- // Module represents the module (DLL or exe) corresponding to a stack frame.
- struct BASE_EXPORT Module {
- Module();
- Module(uintptr_t base_address,
- const std::string& id,
- const FilePath& filename);
- ~Module();
-
- // Points to the base address of the module.
- uintptr_t base_address;
-
- // An opaque binary string that uniquely identifies a particular program
- // version with high probability. This is parsed from headers of the loaded
- // module.
- // For binaries generated by GNU tools:
- // Contents of the .note.gnu.build-id field.
- // On Windows:
- // GUID + AGE in the debug image headers of a module.
- std::string id;
-
- // The filename of the module.
- FilePath filename;
- };
-
- // InternalModule represents the module (DLL or exe) and its validness state.
- // Different from Module, it has an additional field "is_valid".
- //
- // This struct is only used for sampling data transfer from NativeStackSampler
- // to ProfileBuilder.
- struct BASE_EXPORT InternalModule {
- InternalModule();
- InternalModule(uintptr_t base_address,
- const std::string& id,
- const FilePath& filename);
- ~InternalModule();
-
- // Points to the base address of the module.
- uintptr_t base_address;
-
- // An opaque binary string that uniquely identifies a particular program
- // version with high probability. This is parsed from headers of the loaded
- // module.
- // For binaries generated by GNU tools:
- // Contents of the .note.gnu.build-id field.
- // On Windows:
- // GUID + AGE in the debug image headers of a module.
- std::string id;
-
- // The filename of the module.
- FilePath filename;
-
- // The validness of the module.
- bool is_valid;
- };
-
- // Frame represents an individual sampled stack frame with module information.
- struct BASE_EXPORT Frame {
- Frame(uintptr_t instruction_pointer, size_t module_index);
- ~Frame();
-
- // Default constructor to satisfy IPC macros. Do not use explicitly.
- Frame();
-
- // The sampled instruction pointer within the function.
- uintptr_t instruction_pointer;
-
- // Index of the module in CallStackProfile::modules. We don't represent
- // module state directly here to save space.
- size_t module_index;
- };
-
- // InternalFrame represents an individual sampled stack frame with full module
- // information. This is different from Frame which only contains module index.
- //
- // This struct is only used for sampling data transfer from NativeStackSampler
- // to ProfileBuilder.
- struct BASE_EXPORT InternalFrame {
- InternalFrame(uintptr_t instruction_pointer,
- InternalModule internal_module);
- ~InternalFrame();
-
- // The sampled instruction pointer within the function.
- uintptr_t instruction_pointer;
-
- // The module information.
- InternalModule internal_module;
- };
-
- // Sample represents a set of stack frames with some extra information.
- struct BASE_EXPORT Sample {
- Sample();
- Sample(const Sample& sample);
- ~Sample();
-
- // These constructors are used only during testing.
- Sample(const Frame& frame);
- Sample(const std::vector<Frame>& frames);
-
- // The entire stack frame when the sample is taken.
- std::vector<Frame> frames;
-
- // A bit-field indicating which process milestones have passed. This can be
- // used to tell where in the process lifetime the samples are taken. Just
- // as a "lifetime" can only move forward, these bits mark the milestones of
- // the processes life as they occur. Bits can be set but never reset. The
- // actual definition of the individual bits is left to the user of this
- // module.
- uint32_t process_milestones = 0;
- };
-
- // CallStackProfile represents a set of samples.
- struct BASE_EXPORT CallStackProfile {
- CallStackProfile();
- CallStackProfile(CallStackProfile&& other);
- ~CallStackProfile();
-
- CallStackProfile& operator=(CallStackProfile&& other);
-
- CallStackProfile CopyForTesting() const;
-
- std::vector<Module> modules;
- std::vector<Sample> samples;
-
- // Duration of this profile.
- TimeDelta profile_duration;
-
- // Time between samples.
- TimeDelta sampling_period;
-
- private:
- // Copying is possible but expensive so disallow it except for internal use
- // (i.e. CopyForTesting); use std::move instead.
- CallStackProfile(const CallStackProfile& other);
-
- DISALLOW_ASSIGN(CallStackProfile);
- };
-
- // Represents parameters that configure the sampling.
- struct BASE_EXPORT SamplingParams {
- // Time to delay before first samples are taken.
- TimeDelta initial_delay = TimeDelta::FromMilliseconds(0);
-
- // Number of samples to record per profile.
- int samples_per_profile = 300;
-
- // Interval between samples during a sampling profile. This is the desired
- // duration from the start of one sample to the start of the next sample.
- TimeDelta sampling_interval = TimeDelta::FromMilliseconds(100);
- };
-
- // Testing support. These methods are static beause they interact with the
- // sampling thread, a singleton used by all StackSamplingProfiler objects.
- // These methods can only be called by the same thread that started the
- // sampling.
- class BASE_EXPORT TestAPI {
- public:
- // Resets the internal state to that of a fresh start. This is necessary
- // so that tests don't inherit state from previous tests.
- static void Reset();
-
- // Returns whether the sampling thread is currently running or not.
- static bool IsSamplingThreadRunning();
-
- // Disables inherent idle-shutdown behavior.
- static void DisableIdleShutdown();
-
- // Initiates an idle shutdown task, as though the idle timer had expired,
- // causing the thread to exit. There is no "idle" check so this must be
- // called only when all sampling tasks have completed. This blocks until
- // the task has been executed, though the actual stopping of the thread
- // still happens asynchronously. Watch IsSamplingThreadRunning() to know
- // when the thread has exited. If |simulate_intervening_start| is true then
- // this method will make it appear to the shutdown task that a new profiler
- // was started between when the idle-shutdown was initiated and when it
- // runs.
- static void PerformSamplingThreadIdleShutdown(
- bool simulate_intervening_start);
- };
-
- // The ProfileBuilder interface allows the user to record profile information
- // on the fly in whatever format is desired. Functions are invoked by the
- // profiler on its own thread so must not block or perform expensive
- // operations.
- class BASE_EXPORT ProfileBuilder {
- public:
- ProfileBuilder() = default;
- virtual ~ProfileBuilder() = default;
-
- // Metadata associated with the sample to be saved off.
- // The code implementing this method must not do anything that could acquire
- // a mutex, including allocating memory (which includes LOG messages)
- // because that mutex could be held by a stopped thread, thus resulting in
- // deadlock.
- virtual void RecordAnnotations() = 0;
-
- // Records a new set of internal frames. Invoked when sampling a sample
- // completes.
- virtual void OnSampleCompleted(
- std::vector<InternalFrame> internal_frames) = 0;
-
- // Finishes the profile construction with |profile_duration| and
- // |sampling_period|. Invoked when sampling a profile completes.
- virtual void OnProfileCompleted(TimeDelta profile_duration,
- TimeDelta sampling_period) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ProfileBuilder);
- };
-
- // Creates a profiler for the CURRENT thread. An optional |test_delegate| can
- // be supplied by tests. The caller must ensure that this object gets
- // destroyed before the current thread exits.
- StackSamplingProfiler(
- const SamplingParams& params,
- std::unique_ptr<ProfileBuilder> profile_builder,
- NativeStackSamplerTestDelegate* test_delegate = nullptr);
-
- // Creates a profiler for ANOTHER thread. An optional |test_delegate| can be
- // supplied by tests.
- //
- // IMPORTANT: The caller must ensure that the thread being sampled does not
- // exit before this object gets destructed or Bad Things(tm) may occur.
- StackSamplingProfiler(
- PlatformThreadId thread_id,
- const SamplingParams& params,
- std::unique_ptr<ProfileBuilder> profile_builder,
- NativeStackSamplerTestDelegate* test_delegate = nullptr);
-
- // Stops any profiling currently taking place before destroying the profiler.
- // This will block until profile_builder_'s OnProfileCompleted function has
- // executed if profiling has started but not already finished.
- ~StackSamplingProfiler();
-
- // Initializes the profiler and starts sampling. Might block on a
- // WaitableEvent if this StackSamplingProfiler was previously started and
- // recently stopped, while the previous profiling phase winds down.
- void Start();
-
- // Stops the profiler and any ongoing sampling. This method will return
- // immediately with the profile_builder_'s OnProfileCompleted function being
- // run asynchronously. At most one more stack sample will be taken after this
- // method returns. Calling this function is optional; if not invoked profiling
- // terminates when all the profiling samples specified in the SamplingParams
- // are completed or the profiler object is destroyed, whichever occurs first.
- void Stop();
-
- private:
- friend class TestAPI;
-
- // SamplingThread is a separate thread used to suspend and sample stacks from
- // the target thread.
- class SamplingThread;
-
- // The thread whose stack will be sampled.
- PlatformThreadId thread_id_;
-
- const SamplingParams params_;
-
- // Receives the sampling data and builds a CallStackProfile. The ownership of
- // this object will be transferred to the sampling thread when thread sampling
- // starts.
- std::unique_ptr<ProfileBuilder> profile_builder_;
-
- // This starts "signaled", is reset when sampling begins, and is signaled
- // when that sampling is complete and the profile_builder_'s
- // OnProfileCompleted function has executed.
- WaitableEvent profiling_inactive_;
-
- // An ID uniquely identifying this profiler to the sampling thread. This
- // will be an internal "null" value when no collection has been started.
- int profiler_id_;
-
- // Stored until it can be passed to the NativeStackSampler created in Start().
- NativeStackSamplerTestDelegate* const test_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(StackSamplingProfiler);
-};
-
-// These operators permit types to be compared and used in a map of Samples, as
-// done in tests and by the metrics provider code.
-BASE_EXPORT bool operator==(const StackSamplingProfiler::Module& a,
- const StackSamplingProfiler::Module& b);
-BASE_EXPORT bool operator==(const StackSamplingProfiler::Sample& a,
- const StackSamplingProfiler::Sample& b);
-BASE_EXPORT bool operator!=(const StackSamplingProfiler::Sample& a,
- const StackSamplingProfiler::Sample& b);
-BASE_EXPORT bool operator<(const StackSamplingProfiler::Sample& a,
- const StackSamplingProfiler::Sample& b);
-BASE_EXPORT bool operator==(const StackSamplingProfiler::Frame& a,
- const StackSamplingProfiler::Frame& b);
-BASE_EXPORT bool operator<(const StackSamplingProfiler::Frame& a,
- const StackSamplingProfiler::Frame& b);
-
-} // namespace base
-
-#endif // BASE_PROFILER_STACK_SAMPLING_PROFILER_H_
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc
deleted file mode 100644
index b0f883624f..0000000000
--- a/base/profiler/stack_sampling_profiler_unittest.cc
+++ /dev/null
@@ -1,1522 +0,0 @@
-// Copyright 2015 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 <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <cstdlib>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/native_library.h"
-#include "base/path_service.h"
-#include "base/profiler/native_stack_sampler.h"
-#include "base/profiler/stack_sampling_profiler.h"
-#include "base/run_loop.h"
-#include "base/scoped_native_library.h"
-#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/bind_test_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include <intrin.h>
-#include <malloc.h>
-#include <windows.h>
-#else
-#include <alloca.h>
-#endif
-
-// STACK_SAMPLING_PROFILER_SUPPORTED is used to conditionally enable the tests
-// below for supported platforms (currently Win x64 and Mac x64).
-#if defined(_WIN64) || (defined(OS_MACOSX) && !defined(OS_IOS))
-#define STACK_SAMPLING_PROFILER_SUPPORTED 1
-#endif
-
-#if defined(OS_WIN)
-#pragma intrinsic(_ReturnAddress)
-#endif
-
-namespace base {
-
-#if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
-#define PROFILER_TEST_F(TestClass, TestName) TEST_F(TestClass, TestName)
-#else
-#define PROFILER_TEST_F(TestClass, TestName) \
- TEST_F(TestClass, DISABLED_##TestName)
-#endif
-
-using SamplingParams = StackSamplingProfiler::SamplingParams;
-using Frame = StackSamplingProfiler::Frame;
-using Frames = std::vector<Frame>;
-using InternalFrame = StackSamplingProfiler::InternalFrame;
-using InternalFrames = std::vector<InternalFrame>;
-using InternalFrameSets = std::vector<std::vector<InternalFrame>>;
-using Module = StackSamplingProfiler::Module;
-using InternalModule = StackSamplingProfiler::InternalModule;
-using Sample = StackSamplingProfiler::Sample;
-
-namespace {
-
-// Configuration for the frames that appear on the stack.
-struct StackConfiguration {
- enum Config { NORMAL, WITH_ALLOCA, WITH_OTHER_LIBRARY };
-
- explicit StackConfiguration(Config config)
- : StackConfiguration(config, nullptr) {
- EXPECT_NE(config, WITH_OTHER_LIBRARY);
- }
-
- StackConfiguration(Config config, NativeLibrary library)
- : config(config), library(library) {
- EXPECT_TRUE(config != WITH_OTHER_LIBRARY || library);
- }
-
- Config config;
-
- // Only used if config == WITH_OTHER_LIBRARY.
- NativeLibrary library;
-};
-
-// Signature for a target function that is expected to appear in the stack. See
-// SignalAndWaitUntilSignaled() below. The return value should be a program
-// counter pointer near the end of the function.
-using TargetFunction = const void* (*)(WaitableEvent*,
- WaitableEvent*,
- const StackConfiguration*);
-
-// A thread to target for profiling, whose stack is guaranteed to contain
-// SignalAndWaitUntilSignaled() when coordinated with the main thread.
-class TargetThread : public PlatformThread::Delegate {
- public:
- explicit TargetThread(const StackConfiguration& stack_config);
-
- // PlatformThread::Delegate:
- void ThreadMain() override;
-
- // Waits for the thread to have started and be executing in
- // SignalAndWaitUntilSignaled().
- void WaitForThreadStart();
-
- // Allows the thread to return from SignalAndWaitUntilSignaled() and finish
- // execution.
- void SignalThreadToFinish();
-
- // This function is guaranteed to be executing between calls to
- // WaitForThreadStart() and SignalThreadToFinish() when invoked with
- // |thread_started_event_| and |finish_event_|. Returns a program counter
- // value near the end of the function. May be invoked with null WaitableEvents
- // to just return the program counter.
- //
- // This function is static so that we can get a straightforward address
- // for it in one of the tests below, rather than dealing with the complexity
- // of a member function pointer representation.
- static const void* SignalAndWaitUntilSignaled(
- WaitableEvent* thread_started_event,
- WaitableEvent* finish_event,
- const StackConfiguration* stack_config);
-
- // Calls into SignalAndWaitUntilSignaled() after allocating memory on the
- // stack with alloca.
- static const void* CallWithAlloca(WaitableEvent* thread_started_event,
- WaitableEvent* finish_event,
- const StackConfiguration* stack_config);
-
- // Calls into SignalAndWaitUntilSignaled() via a function in
- // base_profiler_test_support_library.
- static const void* CallThroughOtherLibrary(
- WaitableEvent* thread_started_event,
- WaitableEvent* finish_event,
- const StackConfiguration* stack_config);
-
- PlatformThreadId id() const { return id_; }
-
- private:
- struct TargetFunctionArgs {
- WaitableEvent* thread_started_event;
- WaitableEvent* finish_event;
- const StackConfiguration* stack_config;
- };
-
- // Callback function to be provided when calling through the other library.
- static void OtherLibraryCallback(void* arg);
-
- // Returns the current program counter, or a value very close to it.
- static const void* GetProgramCounter();
-
- WaitableEvent thread_started_event_;
- WaitableEvent finish_event_;
- PlatformThreadId id_;
- const StackConfiguration stack_config_;
-
- DISALLOW_COPY_AND_ASSIGN(TargetThread);
-};
-
-TargetThread::TargetThread(const StackConfiguration& stack_config)
- : thread_started_event_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED),
- finish_event_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED),
- id_(0),
- stack_config_(stack_config) {}
-
-void TargetThread::ThreadMain() {
- id_ = PlatformThread::CurrentId();
- switch (stack_config_.config) {
- case StackConfiguration::NORMAL:
- SignalAndWaitUntilSignaled(&thread_started_event_, &finish_event_,
- &stack_config_);
- break;
-
- case StackConfiguration::WITH_ALLOCA:
- CallWithAlloca(&thread_started_event_, &finish_event_, &stack_config_);
- break;
-
- case StackConfiguration::WITH_OTHER_LIBRARY:
- CallThroughOtherLibrary(&thread_started_event_, &finish_event_,
- &stack_config_);
- break;
- }
-}
-
-void TargetThread::WaitForThreadStart() {
- thread_started_event_.Wait();
-}
-
-void TargetThread::SignalThreadToFinish() {
- finish_event_.Signal();
-}
-
-// static
-// Disable inlining for this function so that it gets its own stack frame.
-NOINLINE const void* TargetThread::SignalAndWaitUntilSignaled(
- WaitableEvent* thread_started_event,
- WaitableEvent* finish_event,
- const StackConfiguration* stack_config) {
- if (thread_started_event && finish_event) {
- thread_started_event->Signal();
- finish_event->Wait();
- }
-
- // Volatile to prevent a tail call to GetProgramCounter().
- const void* volatile program_counter = GetProgramCounter();
- return program_counter;
-}
-
-// static
-// Disable inlining for this function so that it gets its own stack frame.
-NOINLINE const void* TargetThread::CallWithAlloca(
- WaitableEvent* thread_started_event,
- WaitableEvent* finish_event,
- const StackConfiguration* stack_config) {
- const size_t alloca_size = 100;
- // Memset to 0 to generate a clean failure.
- std::memset(alloca(alloca_size), 0, alloca_size);
-
- SignalAndWaitUntilSignaled(thread_started_event, finish_event, stack_config);
-
- // Volatile to prevent a tail call to GetProgramCounter().
- const void* volatile program_counter = GetProgramCounter();
- return program_counter;
-}
-
-// static
-NOINLINE const void* TargetThread::CallThroughOtherLibrary(
- WaitableEvent* thread_started_event,
- WaitableEvent* finish_event,
- const StackConfiguration* stack_config) {
- if (stack_config) {
- // A function whose arguments are a function accepting void*, and a void*.
- using InvokeCallbackFunction = void (*)(void (*)(void*), void*);
- EXPECT_TRUE(stack_config->library);
- InvokeCallbackFunction function = reinterpret_cast<InvokeCallbackFunction>(
- GetFunctionPointerFromNativeLibrary(stack_config->library,
- "InvokeCallbackFunction"));
- EXPECT_TRUE(function);
-
- TargetFunctionArgs args = {thread_started_event, finish_event,
- stack_config};
- (*function)(&OtherLibraryCallback, &args);
- }
-
- // Volatile to prevent a tail call to GetProgramCounter().
- const void* volatile program_counter = GetProgramCounter();
- return program_counter;
-}
-
-// static
-void TargetThread::OtherLibraryCallback(void* arg) {
- const TargetFunctionArgs* args = static_cast<TargetFunctionArgs*>(arg);
- SignalAndWaitUntilSignaled(args->thread_started_event, args->finish_event,
- args->stack_config);
- // Prevent tail call.
- volatile int i = 0;
- ALLOW_UNUSED_LOCAL(i);
-}
-
-// static
-// Disable inlining for this function so that it gets its own stack frame.
-NOINLINE const void* TargetThread::GetProgramCounter() {
-#if defined(OS_WIN)
- return _ReturnAddress();
-#else
- return __builtin_return_address(0);
-#endif
-}
-
-// Profile consists of a set of internal frame sets and other sampling
-// information.
-struct Profile {
- Profile() = default;
- Profile(Profile&& other) = default;
- Profile(const InternalFrameSets& frame_sets,
- int annotation_count,
- TimeDelta profile_duration,
- TimeDelta sampling_period);
-
- ~Profile() = default;
-
- Profile& operator=(Profile&& other) = default;
-
- // The collected internal frame sets.
- InternalFrameSets frame_sets;
-
- // The number of invocations of RecordAnnotations().
- int annotation_count;
-
- // Duration of this profile.
- TimeDelta profile_duration;
-
- // Time between samples.
- TimeDelta sampling_period;
-};
-
-Profile::Profile(const InternalFrameSets& frame_sets,
- int annotation_count,
- TimeDelta profile_duration,
- TimeDelta sampling_period)
- : frame_sets(frame_sets),
- annotation_count(annotation_count),
- profile_duration(profile_duration),
- sampling_period(sampling_period) {}
-
-// The callback type used to collect a profile. The passed Profile is move-only.
-// Other threads, including the UI thread, may block on callback completion so
-// this should run as quickly as possible.
-using ProfileCompletedCallback = Callback<void(Profile)>;
-
-// TestProfileBuilder collects internal frames produced by the profiler.
-class TestProfileBuilder : public StackSamplingProfiler::ProfileBuilder {
- public:
- TestProfileBuilder(const ProfileCompletedCallback& callback);
-
- ~TestProfileBuilder() override;
-
- // StackSamplingProfiler::ProfileBuilder:
- void RecordAnnotations() override;
- void OnSampleCompleted(InternalFrames internal_frames) override;
- void OnProfileCompleted(TimeDelta profile_duration,
- TimeDelta sampling_period) override;
-
- private:
- // The sets of internal frames recorded.
- std::vector<InternalFrames> frame_sets_;
-
- // The number of invocations of RecordAnnotations().
- int annotation_count_ = 0;
-
- // Callback made when sampling a profile completes.
- const ProfileCompletedCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(TestProfileBuilder);
-};
-
-TestProfileBuilder::TestProfileBuilder(const ProfileCompletedCallback& callback)
- : callback_(callback) {}
-
-TestProfileBuilder::~TestProfileBuilder() = default;
-
-void TestProfileBuilder::RecordAnnotations() {
- ++annotation_count_;
-}
-
-void TestProfileBuilder::OnSampleCompleted(InternalFrames internal_frames) {
- frame_sets_.push_back(std::move(internal_frames));
-}
-
-void TestProfileBuilder::OnProfileCompleted(TimeDelta profile_duration,
- TimeDelta sampling_period) {
- callback_.Run(Profile(frame_sets_, annotation_count_, profile_duration,
- sampling_period));
-}
-
-// Loads the other library, which defines a function to be called in the
-// WITH_OTHER_LIBRARY configuration.
-NativeLibrary LoadOtherLibrary() {
- // The lambda gymnastics works around the fact that we can't use ASSERT_*
- // macros in a function returning non-null.
- const auto load = [](NativeLibrary* library) {
- FilePath other_library_path;
- ASSERT_TRUE(PathService::Get(DIR_EXE, &other_library_path));
- other_library_path = other_library_path.AppendASCII(
- GetNativeLibraryName("base_profiler_test_support_library"));
- NativeLibraryLoadError load_error;
- *library = LoadNativeLibrary(other_library_path, &load_error);
- ASSERT_TRUE(*library) << "error loading " << other_library_path.value()
- << ": " << load_error.ToString();
- };
-
- NativeLibrary library = nullptr;
- load(&library);
- return library;
-}
-
-// Unloads |library| and returns when it has completed unloading. Unloading a
-// library is asynchronous on Windows, so simply calling UnloadNativeLibrary()
-// is insufficient to ensure it's been unloaded.
-void SynchronousUnloadNativeLibrary(NativeLibrary library) {
- UnloadNativeLibrary(library);
-#if defined(OS_WIN)
- // NativeLibrary is a typedef for HMODULE, which is actually the base address
- // of the module.
- uintptr_t module_base_address = reinterpret_cast<uintptr_t>(library);
- HMODULE module_handle;
- // Keep trying to get the module handle until the call fails.
- while (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
- GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
- reinterpret_cast<LPCTSTR>(module_base_address),
- &module_handle) ||
- ::GetLastError() != ERROR_MOD_NOT_FOUND) {
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
- }
-#elif defined(OS_MACOSX)
-// Unloading a library on the Mac is synchronous.
-#else
- NOTIMPLEMENTED();
-#endif
-}
-
-// Executes the function with the target thread running and executing within
-// SignalAndWaitUntilSignaled(). Performs all necessary target thread startup
-// and shutdown work before and afterward.
-template <class Function>
-void WithTargetThread(Function function,
- const StackConfiguration& stack_config) {
- TargetThread target_thread(stack_config);
- PlatformThreadHandle target_thread_handle;
- EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle));
-
- target_thread.WaitForThreadStart();
-
- function(target_thread.id());
-
- target_thread.SignalThreadToFinish();
-
- PlatformThread::Join(target_thread_handle);
-}
-
-template <class Function>
-void WithTargetThread(Function function) {
- WithTargetThread(function, StackConfiguration(StackConfiguration::NORMAL));
-}
-
-struct TestProfilerInfo {
- TestProfilerInfo(PlatformThreadId thread_id,
- const SamplingParams& params,
- NativeStackSamplerTestDelegate* delegate = nullptr)
- : completed(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- profiler(thread_id,
- params,
- std::make_unique<TestProfileBuilder>(
- BindLambdaForTesting([this](Profile result_profile) {
- profile = std::move(result_profile);
- completed.Signal();
- })),
- delegate) {}
-
- // The order here is important to ensure objects being referenced don't get
- // destructed until after the objects referencing them.
- Profile profile;
- WaitableEvent completed;
- StackSamplingProfiler profiler;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestProfilerInfo);
-};
-
-// Creates multiple profilers based on a vector of parameters.
-std::vector<std::unique_ptr<TestProfilerInfo>> CreateProfilers(
- PlatformThreadId target_thread_id,
- const std::vector<SamplingParams>& params) {
- DCHECK(!params.empty());
-
- std::vector<std::unique_ptr<TestProfilerInfo>> profilers;
- for (size_t i = 0; i < params.size(); ++i) {
- profilers.push_back(
- std::make_unique<TestProfilerInfo>(target_thread_id, params[i]));
- }
-
- return profilers;
-}
-
-// Captures internal frames as specified by |params| on the TargetThread, and
-// returns them. Waits up to |profiler_wait_time| for the profiler to complete.
-InternalFrameSets CaptureFrameSets(const SamplingParams& params,
- TimeDelta profiler_wait_time) {
- InternalFrameSets frame_sets;
- WithTargetThread([&params, &frame_sets,
- profiler_wait_time](PlatformThreadId target_thread_id) {
- TestProfilerInfo info(target_thread_id, params);
- info.profiler.Start();
- info.completed.TimedWait(profiler_wait_time);
- info.profiler.Stop();
- info.completed.Wait();
- frame_sets = std::move(info.profile.frame_sets);
- });
-
- return frame_sets;
-}
-
-// Waits for one of multiple samplings to complete.
-size_t WaitForSamplingComplete(
- const std::vector<std::unique_ptr<TestProfilerInfo>>& infos) {
- // Map unique_ptrs to something that WaitMany can accept.
- std::vector<WaitableEvent*> sampling_completed_rawptrs(infos.size());
- std::transform(infos.begin(), infos.end(), sampling_completed_rawptrs.begin(),
- [](const std::unique_ptr<TestProfilerInfo>& info) {
- return &info.get()->completed;
- });
- // Wait for one profiler to finish.
- return WaitableEvent::WaitMany(sampling_completed_rawptrs.data(),
- sampling_completed_rawptrs.size());
-}
-
-// If this executable was linked with /INCREMENTAL (the default for non-official
-// debug and release builds on Windows), function addresses do not correspond to
-// function code itself, but instead to instructions in the Incremental Link
-// Table that jump to the functions. Checks for a jump instruction and if
-// present does a little decompilation to find the function's actual starting
-// address.
-const void* MaybeFixupFunctionAddressForILT(const void* function_address) {
-#if defined(_WIN64)
- const unsigned char* opcode =
- reinterpret_cast<const unsigned char*>(function_address);
- if (*opcode == 0xe9) {
- // This is a relative jump instruction. Assume we're in the ILT and compute
- // the function start address from the instruction offset.
- const int32_t* offset = reinterpret_cast<const int32_t*>(opcode + 1);
- const unsigned char* next_instruction =
- reinterpret_cast<const unsigned char*>(offset + 1);
- return next_instruction + *offset;
- }
-#endif
- return function_address;
-}
-
-// Searches through the frames in |sample|, returning an iterator to the first
-// frame that has an instruction pointer within |target_function|. Returns
-// sample.end() if no such frames are found.
-InternalFrames::const_iterator FindFirstFrameWithinFunction(
- const InternalFrames& frames,
- TargetFunction target_function) {
- uintptr_t function_start =
- reinterpret_cast<uintptr_t>(MaybeFixupFunctionAddressForILT(
- reinterpret_cast<const void*>(target_function)));
- uintptr_t function_end =
- reinterpret_cast<uintptr_t>(target_function(nullptr, nullptr, nullptr));
- for (auto it = frames.begin(); it != frames.end(); ++it) {
- if (it->instruction_pointer >= function_start &&
- it->instruction_pointer <= function_end) {
- return it;
- }
- }
- return frames.end();
-}
-
-// Formats a sample into a string that can be output for test diagnostics.
-std::string FormatSampleForDiagnosticOutput(const InternalFrames& frames) {
- std::string output;
- for (const auto& frame : frames) {
- output += StringPrintf(
- "0x%p %s\n", reinterpret_cast<const void*>(frame.instruction_pointer),
- frame.internal_module.filename.AsUTF8Unsafe().c_str());
- }
- return output;
-}
-
-// Returns a duration that is longer than the test timeout. We would use
-// TimeDelta::Max() but https://crbug.com/465948.
-TimeDelta AVeryLongTimeDelta() {
- return TimeDelta::FromDays(1);
-}
-
-// Tests the scenario where the library is unloaded after copying the stack, but
-// before walking it. If |wait_until_unloaded| is true, ensures that the
-// asynchronous library loading has completed before walking the stack. If
-// false, the unloading may still be occurring during the stack walk.
-void TestLibraryUnload(bool wait_until_unloaded) {
- // Test delegate that supports intervening between the copying of the stack
- // and the walking of the stack.
- class StackCopiedSignaler : public NativeStackSamplerTestDelegate {
- public:
- StackCopiedSignaler(WaitableEvent* stack_copied,
- WaitableEvent* start_stack_walk,
- bool wait_to_walk_stack)
- : stack_copied_(stack_copied),
- start_stack_walk_(start_stack_walk),
- wait_to_walk_stack_(wait_to_walk_stack) {}
-
- void OnPreStackWalk() override {
- stack_copied_->Signal();
- if (wait_to_walk_stack_)
- start_stack_walk_->Wait();
- }
-
- private:
- WaitableEvent* const stack_copied_;
- WaitableEvent* const start_stack_walk_;
- const bool wait_to_walk_stack_;
- };
-
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- NativeLibrary other_library = LoadOtherLibrary();
- TargetThread target_thread(StackConfiguration(
- StackConfiguration::WITH_OTHER_LIBRARY, other_library));
-
- PlatformThreadHandle target_thread_handle;
- EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle));
-
- target_thread.WaitForThreadStart();
-
- WaitableEvent sampling_thread_completed(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- Profile profile;
-
- WaitableEvent stack_copied(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent start_stack_walk(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- StackCopiedSignaler test_delegate(&stack_copied, &start_stack_walk,
- wait_until_unloaded);
- StackSamplingProfiler profiler(
- target_thread.id(), params,
- std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
- [&profile, &sampling_thread_completed](Profile result_profile) {
- profile = std::move(result_profile);
- sampling_thread_completed.Signal();
- })),
- &test_delegate);
-
- profiler.Start();
-
- // Wait for the stack to be copied and the target thread to be resumed.
- stack_copied.Wait();
-
- // Cause the target thread to finish, so that it's no longer executing code in
- // the library we're about to unload.
- target_thread.SignalThreadToFinish();
- PlatformThread::Join(target_thread_handle);
-
- // Unload the library now that it's not being used.
- if (wait_until_unloaded)
- SynchronousUnloadNativeLibrary(other_library);
- else
- UnloadNativeLibrary(other_library);
-
- // Let the stack walk commence after unloading the library, if we're waiting
- // on that event.
- start_stack_walk.Signal();
-
- // Wait for the sampling thread to complete and fill out |profile|.
- sampling_thread_completed.Wait();
-
- // Look up the frames.
- ASSERT_EQ(1u, profile.frame_sets.size());
- const InternalFrames& frames = profile.frame_sets[0];
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled().
- InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction(
- frames, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(end_frame != frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-
- if (wait_until_unloaded) {
- // The stack should look like this, resulting one frame after
- // SignalAndWaitUntilSignaled. The frame in the now-unloaded library is
- // not recorded since we can't get module information.
- //
- // ... WaitableEvent and system frames ...
- // TargetThread::SignalAndWaitUntilSignaled
- // TargetThread::OtherLibraryCallback
- EXPECT_EQ(2, frames.end() - end_frame)
- << "Stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
- } else {
- // We didn't wait for the asynchronous unloading to complete, so the results
- // are non-deterministic: if the library finished unloading we should have
- // the same stack as |wait_until_unloaded|, if not we should have the full
- // stack. The important thing is that we should not crash.
-
- if (frames.end() - end_frame == 2) {
- // This is the same case as |wait_until_unloaded|.
- return;
- }
-
- // Check that the stack contains a frame for
- // TargetThread::CallThroughOtherLibrary().
- InternalFrames::const_iterator other_library_frame =
- FindFirstFrameWithinFunction(frames,
- &TargetThread::CallThroughOtherLibrary);
- ASSERT_TRUE(other_library_frame != frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::CallThroughOtherLibrary))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-
- // The stack should look like this, resulting in three frames between
- // SignalAndWaitUntilSignaled and CallThroughOtherLibrary:
- //
- // ... WaitableEvent and system frames ...
- // TargetThread::SignalAndWaitUntilSignaled
- // TargetThread::OtherLibraryCallback
- // InvokeCallbackFunction (in other library)
- // TargetThread::CallThroughOtherLibrary
- EXPECT_EQ(3, other_library_frame - end_frame)
- << "Stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
- }
-}
-
-// Provide a suitable (and clean) environment for the tests below. All tests
-// must use this class to ensure that proper clean-up is done and thus be
-// usable in a later test.
-class StackSamplingProfilerTest : public testing::Test {
- public:
- void SetUp() override {
- // The idle-shutdown time is too long for convenient (and accurate) testing.
- // That behavior is checked instead by artificially triggering it through
- // the TestAPI.
- StackSamplingProfiler::TestAPI::DisableIdleShutdown();
- }
-
- void TearDown() override {
- // Be a good citizen and clean up after ourselves. This also re-enables the
- // idle-shutdown behavior.
- StackSamplingProfiler::TestAPI::Reset();
- }
-};
-
-} // namespace
-
-// Checks that the basic expected information is present in sampled internal
-// frames.
-//
-// macOS ASAN is not yet supported - crbug.com/718628.
-#if !(defined(ADDRESS_SANITIZER) && defined(OS_MACOSX))
-#define MAYBE_Basic Basic
-#else
-#define MAYBE_Basic DISABLED_Basic
-#endif
-PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Basic) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
-
- // Check that the size of the frame sets are correct.
- ASSERT_EQ(1u, frame_sets.size());
- const InternalFrames& frames = frame_sets[0];
-
- // Check that all the modules are valid.
- for (const auto& frame : frames)
- EXPECT_TRUE(frame.internal_module.is_valid);
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled().
- InternalFrames::const_iterator loc = FindFirstFrameWithinFunction(
- frames, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(loc != frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-}
-
-// Checks that the profiler handles stacks containing dynamically-allocated
-// stack memory.
-// macOS ASAN is not yet supported - crbug.com/718628.
-#if !(defined(ADDRESS_SANITIZER) && defined(OS_MACOSX))
-#define MAYBE_Alloca Alloca
-#else
-#define MAYBE_Alloca DISABLED_Alloca
-#endif
-PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Alloca) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- Profile profile;
- WithTargetThread(
- [&params, &profile](PlatformThreadId target_thread_id) {
- WaitableEvent sampling_thread_completed(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- StackSamplingProfiler profiler(
- target_thread_id, params,
- std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
- [&profile, &sampling_thread_completed](Profile result_profile) {
- profile = std::move(result_profile);
- sampling_thread_completed.Signal();
- })));
- profiler.Start();
- sampling_thread_completed.Wait();
- },
- StackConfiguration(StackConfiguration::WITH_ALLOCA));
-
- // Look up the frames.
- ASSERT_EQ(1u, profile.frame_sets.size());
- const InternalFrames& frames = profile.frame_sets[0];
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled().
- InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction(
- frames, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(end_frame != frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-
- // Check that the stack contains a frame for TargetThread::CallWithAlloca().
- InternalFrames::const_iterator alloca_frame =
- FindFirstFrameWithinFunction(frames, &TargetThread::CallWithAlloca);
- ASSERT_TRUE(alloca_frame != frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(
- reinterpret_cast<const void*>(&TargetThread::CallWithAlloca))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-
- // These frames should be adjacent on the stack.
- EXPECT_EQ(1, alloca_frame - end_frame)
- << "Stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-}
-
-// Checks that a profiler can stop/destruct without ever having started.
-PROFILER_TEST_F(StackSamplingProfilerTest, StopWithoutStarting) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- Profile profile;
- WaitableEvent sampling_completed(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- StackSamplingProfiler profiler(
- target_thread_id, params,
- std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
- [&profile, &sampling_completed](Profile result_profile) {
- profile = std::move(result_profile);
- sampling_completed.Signal();
- })));
-
- profiler.Stop(); // Constructed but never started.
- EXPECT_FALSE(sampling_completed.IsSignaled());
- });
-}
-
-// Checks that its okay to stop a profiler before it finishes even when the
-// sampling thread continues to run.
-PROFILER_TEST_F(StackSamplingProfilerTest, StopSafely) {
- // Test delegate that counts samples.
- class SampleRecordedCounter : public NativeStackSamplerTestDelegate {
- public:
- SampleRecordedCounter() = default;
-
- void OnPreStackWalk() override {
- AutoLock lock(lock_);
- ++count_;
- }
-
- size_t Get() {
- AutoLock lock(lock_);
- return count_;
- }
-
- private:
- Lock lock_;
- size_t count_ = 0;
- };
-
- WithTargetThread([](PlatformThreadId target_thread_id) {
- SamplingParams params[2];
-
- // Providing an initial delay makes it more likely that both will be
- // scheduled before either starts to run. Once started, samples will
- // run ordered by their scheduled, interleaved times regardless of
- // whatever interval the thread wakes up.
- params[0].initial_delay = TimeDelta::FromMilliseconds(10);
- params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[0].samples_per_profile = 100000;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(10);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_profile = 100000;
-
- SampleRecordedCounter samples_recorded[size(params)];
-
- TestProfilerInfo profiler_info0(target_thread_id, params[0],
- &samples_recorded[0]);
- TestProfilerInfo profiler_info1(target_thread_id, params[1],
- &samples_recorded[1]);
-
- profiler_info0.profiler.Start();
- profiler_info1.profiler.Start();
-
- // Wait for both to start accumulating samples. Using a WaitableEvent is
- // possible but gets complicated later on because there's no way of knowing
- // if 0 or 1 additional sample will be taken after Stop() and thus no way
- // of knowing how many Wait() calls to make on it.
- while (samples_recorded[0].Get() == 0 || samples_recorded[1].Get() == 0)
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
-
- // Ensure that the first sampler can be safely stopped while the second
- // continues to run. The stopped first profiler will still have a
- // RecordSampleTask pending that will do nothing when executed because the
- // collection will have been removed by Stop().
- profiler_info0.profiler.Stop();
- profiler_info0.completed.Wait();
- size_t count0 = samples_recorded[0].Get();
- size_t count1 = samples_recorded[1].Get();
-
- // Waiting for the second sampler to collect a couple samples ensures that
- // the pending RecordSampleTask for the first has executed because tasks are
- // always ordered by their next scheduled time.
- while (samples_recorded[1].Get() < count1 + 2)
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
-
- // Ensure that the first profiler didn't do anything since it was stopped.
- EXPECT_EQ(count0, samples_recorded[0].Get());
- });
-}
-
-// Checks that no internal frames are captured if the profiling is stopped
-// during the initial delay.
-PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInitialDelay) {
- SamplingParams params;
- params.initial_delay = TimeDelta::FromSeconds(60);
-
- InternalFrameSets frame_sets =
- CaptureFrameSets(params, TimeDelta::FromMilliseconds(0));
-
- EXPECT_TRUE(frame_sets.empty());
-}
-
-// Checks that tasks can be stopped before completion and incomplete internal
-// frames are captured.
-PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterSampleInterval) {
- // Test delegate that counts samples.
- class SampleRecordedEvent : public NativeStackSamplerTestDelegate {
- public:
- SampleRecordedEvent()
- : sample_recorded_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- void OnPreStackWalk() override { sample_recorded_.Signal(); }
-
- void WaitForSample() { sample_recorded_.Wait(); }
-
- private:
- WaitableEvent sample_recorded_;
- };
-
- WithTargetThread([](PlatformThreadId target_thread_id) {
- SamplingParams params;
-
- params.sampling_interval = AVeryLongTimeDelta();
- params.samples_per_profile = 2;
-
- SampleRecordedEvent samples_recorded;
- TestProfilerInfo profiler_info(target_thread_id, params, &samples_recorded);
-
- profiler_info.profiler.Start();
-
- // Wait for profiler to start accumulating samples.
- samples_recorded.WaitForSample();
-
- // Ensure that it can stop safely.
- profiler_info.profiler.Stop();
- profiler_info.completed.Wait();
-
- EXPECT_EQ(1u, profiler_info.profile.frame_sets.size());
- });
-}
-
-// Checks that we can destroy the profiler while profiling.
-PROFILER_TEST_F(StackSamplingProfilerTest, DestroyProfilerWhileProfiling) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(10);
-
- Profile profile;
- WithTargetThread([&params, &profile](PlatformThreadId target_thread_id) {
- std::unique_ptr<StackSamplingProfiler> profiler;
- auto profile_builder = std::make_unique<TestProfileBuilder>(
- BindLambdaForTesting([&profile](Profile result_profile) {
- profile = std::move(result_profile);
- }));
- profiler.reset(new StackSamplingProfiler(target_thread_id, params,
- std::move(profile_builder)));
- profiler->Start();
- profiler.reset();
-
- // Wait longer than a sample interval to catch any use-after-free actions by
- // the profiler thread.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
- });
-}
-
-// Checks that the different profilers may be run.
-PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleProfilers) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
- ASSERT_EQ(1u, frame_sets.size());
-
- frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
- ASSERT_EQ(1u, frame_sets.size());
-}
-
-// Checks that a sampler can be started while another is running.
-PROFILER_TEST_F(StackSamplingProfilerTest, MultipleStart) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- std::vector<SamplingParams> params(2);
-
- params[0].initial_delay = AVeryLongTimeDelta();
- params[0].samples_per_profile = 1;
-
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_profile = 1;
-
- std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
- CreateProfilers(target_thread_id, params);
-
- profiler_infos[0]->profiler.Start();
- profiler_infos[1]->profiler.Start();
- profiler_infos[1]->completed.Wait();
- EXPECT_EQ(1u, profiler_infos[1]->profile.frame_sets.size());
- });
-}
-
-// Checks that the profile duration and the sampling interval are calculated
-// correctly. Also checks that RecordAnnotations() is invoked each time a sample
-// is recorded.
-PROFILER_TEST_F(StackSamplingProfilerTest, ProfileGeneralInfo) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(1);
- params.samples_per_profile = 3;
-
- TestProfilerInfo profiler_info(target_thread_id, params);
-
- profiler_info.profiler.Start();
- profiler_info.completed.Wait();
- EXPECT_EQ(3u, profiler_info.profile.frame_sets.size());
-
- // The profile duration should be greater than the total sampling intervals.
- EXPECT_GT(profiler_info.profile.profile_duration,
- profiler_info.profile.sampling_period * 3);
-
- EXPECT_EQ(TimeDelta::FromMilliseconds(1),
- profiler_info.profile.sampling_period);
-
- // The number of invocations of RecordAnnotations() should be equal to the
- // number of samples recorded.
- EXPECT_EQ(3, profiler_info.profile.annotation_count);
- });
-}
-
-// Checks that the sampling thread can shut down.
-PROFILER_TEST_F(StackSamplingProfilerTest, SamplerIdleShutdown) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
- ASSERT_EQ(1u, frame_sets.size());
-
- // Capture thread should still be running at this point.
- ASSERT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
-
- // Initiate an "idle" shutdown and ensure it happens. Idle-shutdown was
- // disabled by the test fixture so the test will fail due to a timeout if
- // it does not exit.
- StackSamplingProfiler::TestAPI::PerformSamplingThreadIdleShutdown(false);
-
- // While the shutdown has been initiated, the actual exit of the thread still
- // happens asynchronously. Watch until the thread actually exits. This test
- // will time-out in the case of failure.
- while (StackSamplingProfiler::TestAPI::IsSamplingThreadRunning())
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
-}
-
-// Checks that additional requests will restart a stopped profiler.
-PROFILER_TEST_F(StackSamplingProfilerTest,
- WillRestartSamplerAfterIdleShutdown) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- InternalFrameSets frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
- ASSERT_EQ(1u, frame_sets.size());
-
- // Capture thread should still be running at this point.
- ASSERT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
-
- // Post a ShutdownTask on the sampling thread which, when executed, will
- // mark the thread as EXITING and begin shut down of the thread.
- StackSamplingProfiler::TestAPI::PerformSamplingThreadIdleShutdown(false);
-
- // Ensure another capture will start the sampling thread and run.
- frame_sets = CaptureFrameSets(params, AVeryLongTimeDelta());
- ASSERT_EQ(1u, frame_sets.size());
- EXPECT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
-}
-
-// Checks that it's safe to stop a task after it's completed and the sampling
-// thread has shut-down for being idle.
-PROFILER_TEST_F(StackSamplingProfilerTest, StopAfterIdleShutdown) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- SamplingParams params;
-
- params.sampling_interval = TimeDelta::FromMilliseconds(1);
- params.samples_per_profile = 1;
-
- TestProfilerInfo profiler_info(target_thread_id, params);
-
- profiler_info.profiler.Start();
- profiler_info.completed.Wait();
-
- // Capture thread should still be running at this point.
- ASSERT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
-
- // Perform an idle shutdown.
- StackSamplingProfiler::TestAPI::PerformSamplingThreadIdleShutdown(false);
-
- // Stop should be safe though its impossible to know at this moment if the
- // sampling thread has completely exited or will just "stop soon".
- profiler_info.profiler.Stop();
- });
-}
-
-// Checks that profilers can run both before and after the sampling thread has
-// started.
-PROFILER_TEST_F(StackSamplingProfilerTest,
- ProfileBeforeAndAfterSamplingThreadRunning) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- std::vector<SamplingParams> params(2);
-
- params[0].initial_delay = AVeryLongTimeDelta();
- params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[0].samples_per_profile = 1;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(0);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_profile = 1;
-
- std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
- CreateProfilers(target_thread_id, params);
-
- // First profiler is started when there has never been a sampling thread.
- EXPECT_FALSE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
- profiler_infos[0]->profiler.Start();
- // Second profiler is started when sampling thread is already running.
- EXPECT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
- profiler_infos[1]->profiler.Start();
-
- // Only the second profiler should finish before test times out.
- size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
- EXPECT_EQ(1U, completed_profiler);
- });
-}
-
-// Checks that an idle-shutdown task will abort if a new profiler starts
-// between when it was posted and when it runs.
-PROFILER_TEST_F(StackSamplingProfilerTest, IdleShutdownAbort) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- SamplingParams params;
-
- params.sampling_interval = TimeDelta::FromMilliseconds(1);
- params.samples_per_profile = 1;
-
- TestProfilerInfo profiler_info(target_thread_id, params);
-
- profiler_info.profiler.Start();
- profiler_info.completed.Wait();
- EXPECT_EQ(1u, profiler_info.profile.frame_sets.size());
-
- // Perform an idle shutdown but simulate that a new capture is started
- // before it can actually run.
- StackSamplingProfiler::TestAPI::PerformSamplingThreadIdleShutdown(true);
-
- // Though the shutdown-task has been executed, any actual exit of the
- // thread is asynchronous so there is no way to detect that *didn't* exit
- // except to wait a reasonable amount of time and then check. Since the
- // thread was just running ("perform" blocked until it was), it should
- // finish almost immediately and without any waiting for tasks or events.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(200));
- EXPECT_TRUE(StackSamplingProfiler::TestAPI::IsSamplingThreadRunning());
-
- // Ensure that it's still possible to run another sampler.
- TestProfilerInfo another_info(target_thread_id, params);
- another_info.profiler.Start();
- another_info.completed.Wait();
- EXPECT_EQ(1u, another_info.profile.frame_sets.size());
- });
-}
-
-// Checks that synchronized multiple sampling requests execute in parallel.
-PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_InSync) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- std::vector<SamplingParams> params(2);
-
- // Providing an initial delay makes it more likely that both will be
- // scheduled before either starts to run. Once started, samples will
- // run ordered by their scheduled, interleaved times regardless of
- // whatever interval the thread wakes up. Thus, total execution time
- // will be 10ms (delay) + 10x1ms (sampling) + 1/2 timer minimum interval.
- params[0].initial_delay = TimeDelta::FromMilliseconds(10);
- params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[0].samples_per_profile = 9;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(11);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_profile = 8;
-
- std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
- CreateProfilers(target_thread_id, params);
-
- profiler_infos[0]->profiler.Start();
- profiler_infos[1]->profiler.Start();
-
- // Wait for one profiler to finish.
- size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
-
- size_t other_profiler = 1 - completed_profiler;
- // Wait for the other profiler to finish.
- profiler_infos[other_profiler]->completed.Wait();
-
- // Ensure each got the correct number of frame sets.
- EXPECT_EQ(9u, profiler_infos[0]->profile.frame_sets.size());
- EXPECT_EQ(8u, profiler_infos[1]->profile.frame_sets.size());
- });
-}
-
-// Checks that several mixed sampling requests execute in parallel.
-PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_Mixed) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- std::vector<SamplingParams> params(3);
-
- params[0].initial_delay = TimeDelta::FromMilliseconds(8);
- params[0].sampling_interval = TimeDelta::FromMilliseconds(4);
- params[0].samples_per_profile = 10;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(9);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(3);
- params[1].samples_per_profile = 10;
-
- params[2].initial_delay = TimeDelta::FromMilliseconds(10);
- params[2].sampling_interval = TimeDelta::FromMilliseconds(2);
- params[2].samples_per_profile = 10;
-
- std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
- CreateProfilers(target_thread_id, params);
-
- for (size_t i = 0; i < profiler_infos.size(); ++i)
- profiler_infos[i]->profiler.Start();
-
- // Wait for one profiler to finish.
- size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
- EXPECT_EQ(10u,
- profiler_infos[completed_profiler]->profile.frame_sets.size());
- // Stop and destroy all profilers, always in the same order. Don't crash.
- for (size_t i = 0; i < profiler_infos.size(); ++i)
- profiler_infos[i]->profiler.Stop();
- for (size_t i = 0; i < profiler_infos.size(); ++i)
- profiler_infos[i].reset();
- });
-}
-
-// Checks that a stack that runs through another library produces a stack with
-// the expected functions.
-// macOS ASAN is not yet supported - crbug.com/718628.
-#if !(defined(ADDRESS_SANITIZER) && defined(OS_MACOSX))
-#define MAYBE_OtherLibrary OtherLibrary
-#else
-#define MAYBE_OtherLibrary DISABLED_OtherLibrary
-#endif
-PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_OtherLibrary) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_profile = 1;
-
- Profile profile;
- {
- ScopedNativeLibrary other_library(LoadOtherLibrary());
- WithTargetThread(
- [&params, &profile](PlatformThreadId target_thread_id) {
- WaitableEvent sampling_thread_completed(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- StackSamplingProfiler profiler(
- target_thread_id, params,
- std::make_unique<TestProfileBuilder>(
- BindLambdaForTesting([&profile, &sampling_thread_completed](
- Profile result_profile) {
- profile = std::move(result_profile);
- sampling_thread_completed.Signal();
- })));
- profiler.Start();
- sampling_thread_completed.Wait();
- },
- StackConfiguration(StackConfiguration::WITH_OTHER_LIBRARY,
- other_library.get()));
- }
-
- // Look up the frames.
- ASSERT_EQ(1u, profile.frame_sets.size());
- const InternalFrames& frames = profile.frame_sets[0];
-
- // Check that the stack contains a frame for
- // TargetThread::CallThroughOtherLibrary().
- InternalFrames::const_iterator other_library_frame =
- FindFirstFrameWithinFunction(frames,
- &TargetThread::CallThroughOtherLibrary);
- ASSERT_TRUE(other_library_frame != frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::CallThroughOtherLibrary))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled().
- InternalFrames::const_iterator end_frame = FindFirstFrameWithinFunction(
- frames, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(end_frame != frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-
- // The stack should look like this, resulting in three frames between
- // SignalAndWaitUntilSignaled and CallThroughOtherLibrary:
- //
- // ... WaitableEvent and system frames ...
- // TargetThread::SignalAndWaitUntilSignaled
- // TargetThread::OtherLibraryCallback
- // InvokeCallbackFunction (in other library)
- // TargetThread::CallThroughOtherLibrary
- EXPECT_EQ(3, other_library_frame - end_frame)
- << "Stack:\n"
- << FormatSampleForDiagnosticOutput(frames);
-}
-
-// Checks that a stack that runs through a library that is unloading produces a
-// stack, and doesn't crash.
-// Unloading is synchronous on the Mac, so this test is inapplicable.
-#if !defined(OS_MACOSX)
-#define MAYBE_UnloadingLibrary UnloadingLibrary
-#else
-#define MAYBE_UnloadingLibrary DISABLED_UnloadingLibrary
-#endif
-PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadingLibrary) {
- TestLibraryUnload(false);
-}
-
-// Checks that a stack that runs through a library that has been unloaded
-// produces a stack, and doesn't crash.
-// macOS ASAN is not yet supported - crbug.com/718628.
-#if !(defined(ADDRESS_SANITIZER) && defined(OS_MACOSX))
-#define MAYBE_UnloadedLibrary UnloadedLibrary
-#else
-#define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary
-#endif
-PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) {
- TestLibraryUnload(true);
-}
-
-// Checks that different threads can be sampled in parallel.
-PROFILER_TEST_F(StackSamplingProfilerTest, MultipleSampledThreads) {
- // Create target threads. The extra parethesis around the StackConfiguration
- // call are to avoid the most-vexing-parse problem.
- TargetThread target_thread1((StackConfiguration(StackConfiguration::NORMAL)));
- TargetThread target_thread2((StackConfiguration(StackConfiguration::NORMAL)));
- PlatformThreadHandle target_thread_handle1, target_thread_handle2;
- EXPECT_TRUE(
- PlatformThread::Create(0, &target_thread1, &target_thread_handle1));
- EXPECT_TRUE(
- PlatformThread::Create(0, &target_thread2, &target_thread_handle2));
- target_thread1.WaitForThreadStart();
- target_thread2.WaitForThreadStart();
-
- // Providing an initial delay makes it more likely that both will be
- // scheduled before either starts to run. Once started, samples will
- // run ordered by their scheduled, interleaved times regardless of
- // whatever interval the thread wakes up.
- SamplingParams params1, params2;
- params1.initial_delay = TimeDelta::FromMilliseconds(10);
- params1.sampling_interval = TimeDelta::FromMilliseconds(1);
- params1.samples_per_profile = 9;
- params2.initial_delay = TimeDelta::FromMilliseconds(10);
- params2.sampling_interval = TimeDelta::FromMilliseconds(1);
- params2.samples_per_profile = 8;
-
- Profile profile1, profile2;
-
- WaitableEvent sampling_thread_completed1(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- StackSamplingProfiler profiler1(
- target_thread1.id(), params1,
- std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
- [&profile1, &sampling_thread_completed1](Profile result_profile) {
- profile1 = std::move(result_profile);
- sampling_thread_completed1.Signal();
- })));
-
- WaitableEvent sampling_thread_completed2(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- StackSamplingProfiler profiler2(
- target_thread2.id(), params2,
- std::make_unique<TestProfileBuilder>(BindLambdaForTesting(
- [&profile2, &sampling_thread_completed2](Profile result_profile) {
- profile2 = std::move(result_profile);
- sampling_thread_completed2.Signal();
- })));
-
- // Finally the real work.
- profiler1.Start();
- profiler2.Start();
- sampling_thread_completed1.Wait();
- sampling_thread_completed2.Wait();
- EXPECT_EQ(9u, profile1.frame_sets.size());
- EXPECT_EQ(8u, profile2.frame_sets.size());
-
- target_thread1.SignalThreadToFinish();
- target_thread2.SignalThreadToFinish();
- PlatformThread::Join(target_thread_handle1);
- PlatformThread::Join(target_thread_handle2);
-}
-
-// A simple thread that runs a profiler on another thread.
-class ProfilerThread : public SimpleThread {
- public:
- ProfilerThread(const std::string& name,
- PlatformThreadId thread_id,
- const SamplingParams& params)
- : SimpleThread(name, Options()),
- run_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- completed_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- profiler_(thread_id,
- params,
- std::make_unique<TestProfileBuilder>(
- BindLambdaForTesting([this](Profile result_profile) {
- profile_ = std::move(result_profile);
- completed_.Signal();
- }))) {}
-
- void Run() override {
- run_.Wait();
- profiler_.Start();
- }
-
- void Go() { run_.Signal(); }
-
- void Wait() { completed_.Wait(); }
-
- Profile& profile() { return profile_; }
-
- private:
- WaitableEvent run_;
-
- Profile profile_;
- WaitableEvent completed_;
- StackSamplingProfiler profiler_;
-};
-
-// Checks that different threads can run samplers in parallel.
-PROFILER_TEST_F(StackSamplingProfilerTest, MultipleProfilerThreads) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- // Providing an initial delay makes it more likely that both will be
- // scheduled before either starts to run. Once started, samples will
- // run ordered by their scheduled, interleaved times regardless of
- // whatever interval the thread wakes up.
- SamplingParams params1, params2;
- params1.initial_delay = TimeDelta::FromMilliseconds(10);
- params1.sampling_interval = TimeDelta::FromMilliseconds(1);
- params1.samples_per_profile = 9;
- params2.initial_delay = TimeDelta::FromMilliseconds(10);
- params2.sampling_interval = TimeDelta::FromMilliseconds(1);
- params2.samples_per_profile = 8;
-
- // Start the profiler threads and give them a moment to get going.
- ProfilerThread profiler_thread1("profiler1", target_thread_id, params1);
- ProfilerThread profiler_thread2("profiler2", target_thread_id, params2);
- profiler_thread1.Start();
- profiler_thread2.Start();
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
-
- // This will (approximately) synchronize the two threads.
- profiler_thread1.Go();
- profiler_thread2.Go();
-
- // Wait for them both to finish and validate collection.
- profiler_thread1.Wait();
- profiler_thread2.Wait();
- EXPECT_EQ(9u, profiler_thread1.profile().frame_sets.size());
- EXPECT_EQ(8u, profiler_thread2.profile().frame_sets.size());
-
- profiler_thread1.Join();
- profiler_thread2.Join();
- });
-}
-
-} // namespace base
diff --git a/base/profiler/test_support_library.cc b/base/profiler/test_support_library.cc
deleted file mode 100644
index 035f8f70c0..0000000000
--- a/base/profiler/test_support_library.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 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.
-
-// Note: there is intentionally no header file associated with this library so
-// we don't risk implicitly demand loading it by accessing a symbol.
-
-#if defined(WIN32)
-#define BASE_PROFILER_TEST_SUPPORT_LIBRARY_EXPORT __declspec(dllexport)
-#else // defined(WIN32)
-#define BASE_PROFILER_TEST_SUPPORT_LIBRARY_EXPORT __attribute__((visibility("default")))
-#endif
-
-namespace base {
-
-// Must be defined in an extern "C" block so we can look up the unmangled name.
-extern "C" {
-
-BASE_PROFILER_TEST_SUPPORT_LIBRARY_EXPORT void InvokeCallbackFunction(
- void (*function)(void*),
- void* arg) {
- function(arg);
- // Prevent tail call.
- volatile int i = 0;
- i = 1;
-}
-
-} // extern "C"
-
-} // namespace base
diff --git a/base/profiler/win32_stack_frame_unwinder.cc b/base/profiler/win32_stack_frame_unwinder.cc
deleted file mode 100644
index a3f5f74b85..0000000000
--- a/base/profiler/win32_stack_frame_unwinder.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2015 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/profiler/win32_stack_frame_unwinder.h"
-
-#include <windows.h>
-
-#include <utility>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-
-namespace base {
-
-// Win32UnwindFunctions -------------------------------------------------------
-
-const HMODULE ModuleHandleTraits::kNonNullModuleForTesting =
- reinterpret_cast<HMODULE>(static_cast<uintptr_t>(-1));
-
-// static
-bool ModuleHandleTraits::CloseHandle(HMODULE handle) {
- if (handle == kNonNullModuleForTesting)
- return true;
-
- return ::FreeLibrary(handle) != 0;
-}
-
-// static
-bool ModuleHandleTraits::IsHandleValid(HMODULE handle) {
- return handle != nullptr;
-}
-
-// static
-HMODULE ModuleHandleTraits::NullHandle() {
- return nullptr;
-}
-
-namespace {
-
-// Implements the UnwindFunctions interface for the corresponding Win32
-// functions.
-class Win32UnwindFunctions : public Win32StackFrameUnwinder::UnwindFunctions {
-public:
- Win32UnwindFunctions();
- ~Win32UnwindFunctions() override;
-
- PRUNTIME_FUNCTION LookupFunctionEntry(DWORD64 program_counter,
- PDWORD64 image_base) override;
-
- void VirtualUnwind(DWORD64 image_base,
- DWORD64 program_counter,
- PRUNTIME_FUNCTION runtime_function,
- CONTEXT* context) override;
-
- ScopedModuleHandle GetModuleForProgramCounter(
- DWORD64 program_counter) override;
-
-private:
- DISALLOW_COPY_AND_ASSIGN(Win32UnwindFunctions);
-};
-
-Win32UnwindFunctions::Win32UnwindFunctions() {}
-Win32UnwindFunctions::~Win32UnwindFunctions() {}
-
-PRUNTIME_FUNCTION Win32UnwindFunctions::LookupFunctionEntry(
- DWORD64 program_counter,
- PDWORD64 image_base) {
-#ifdef _WIN64
- return ::RtlLookupFunctionEntry(program_counter, image_base, nullptr);
-#else
- NOTREACHED();
- return nullptr;
-#endif
-}
-
-void Win32UnwindFunctions::VirtualUnwind(DWORD64 image_base,
- DWORD64 program_counter,
- PRUNTIME_FUNCTION runtime_function,
- CONTEXT* context) {
-#ifdef _WIN64
- void* handler_data;
- ULONG64 establisher_frame;
- KNONVOLATILE_CONTEXT_POINTERS nvcontext = {};
- ::RtlVirtualUnwind(UNW_FLAG_NHANDLER, image_base, program_counter,
- runtime_function, context, &handler_data,
- &establisher_frame, &nvcontext);
-#else
- NOTREACHED();
-#endif
-}
-
-ScopedModuleHandle Win32UnwindFunctions::GetModuleForProgramCounter(
- DWORD64 program_counter) {
- HMODULE module_handle = nullptr;
- // GetModuleHandleEx() increments the module reference count, which is then
- // managed and ultimately decremented by ScopedModuleHandle.
- if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
- reinterpret_cast<LPCTSTR>(program_counter),
- &module_handle)) {
- const DWORD error = ::GetLastError();
- DCHECK_EQ(ERROR_MOD_NOT_FOUND, static_cast<int>(error));
- }
- return ScopedModuleHandle(module_handle);
-}
-
-} // namespace
-
-// Win32StackFrameUnwinder ----------------------------------------------------
-
-Win32StackFrameUnwinder::UnwindFunctions::~UnwindFunctions() {}
-Win32StackFrameUnwinder::UnwindFunctions::UnwindFunctions() {}
-
-Win32StackFrameUnwinder::Win32StackFrameUnwinder()
- : Win32StackFrameUnwinder(WrapUnique(new Win32UnwindFunctions)) {}
-
-Win32StackFrameUnwinder::~Win32StackFrameUnwinder() {}
-
-bool Win32StackFrameUnwinder::TryUnwind(CONTEXT* context,
- ScopedModuleHandle* module) {
-#ifdef _WIN64
- ScopedModuleHandle frame_module =
- unwind_functions_->GetModuleForProgramCounter(context->Rip);
- if (!frame_module.IsValid()) {
- // There's no loaded module containing the instruction pointer. This can be
- // due to executing code that is not in a module. In particular,
- // runtime-generated code associated with third-party injected DLLs
- // typically is not in a module. It can also be due to the the module having
- // been unloaded since we recorded the stack. In the latter case the
- // function unwind information was part of the unloaded module, so it's not
- // possible to unwind further.
- //
- // If a module was found, it's still theoretically possible for the detected
- // module module to be different than the one that was loaded when the stack
- // was copied (i.e. if the module was unloaded and a different module loaded
- // in overlapping memory). This likely would cause a crash, but has not been
- // observed in practice.
- return false;
- }
-
- ULONG64 image_base;
- // Try to look up unwind metadata for the current function.
- PRUNTIME_FUNCTION runtime_function =
- unwind_functions_->LookupFunctionEntry(context->Rip, &image_base);
-
- if (runtime_function) {
- unwind_functions_->VirtualUnwind(image_base, context->Rip, runtime_function,
- context);
- at_top_frame_ = false;
- } else {
- if (at_top_frame_) {
- at_top_frame_ = false;
-
- // This is a leaf function (i.e. a function that neither calls a function,
- // nor allocates any stack space itself) so the return address is at RSP.
- context->Rip = *reinterpret_cast<DWORD64*>(context->Rsp);
- context->Rsp += 8;
- } else {
- // In theory we shouldn't get here, as it means we've encountered a
- // function without unwind information below the top of the stack, which
- // is forbidden by the Microsoft x64 calling convention.
- //
- // The one known case in Chrome code that executes this path occurs
- // because of BoringSSL unwind information inconsistent with the actual
- // function code. See https://crbug.com/542919.
- //
- // Note that dodgy third-party generated code that otherwise would enter
- // this path should be caught by the module check above, since the code
- // typically is located outside of a module.
- return false;
- }
- }
-
- module->Set(frame_module.Take());
- return true;
-#else
- NOTREACHED();
- return false;
-#endif
-}
-
-Win32StackFrameUnwinder::Win32StackFrameUnwinder(
- std::unique_ptr<UnwindFunctions> unwind_functions)
- : at_top_frame_(true), unwind_functions_(std::move(unwind_functions)) {}
-
-} // namespace base
diff --git a/base/profiler/win32_stack_frame_unwinder.h b/base/profiler/win32_stack_frame_unwinder.h
deleted file mode 100644
index c92d50cd2b..0000000000
--- a/base/profiler/win32_stack_frame_unwinder.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_PROFILER_WIN32_STACK_FRAME_UNWINDER_H_
-#define BASE_PROFILER_WIN32_STACK_FRAME_UNWINDER_H_
-
-#include <windows.h>
-
-#include <memory>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/win/scoped_handle.h"
-
-namespace base {
-
-#if !defined(_WIN64)
-// Allows code to compile for x86. Actual support for x86 will require either
-// refactoring these interfaces or separate architecture-specific interfaces.
-struct RUNTIME_FUNCTION {
- DWORD BeginAddress;
- DWORD EndAddress;
-};
-using PRUNTIME_FUNCTION = RUNTIME_FUNCTION*;
-#endif // !defined(_WIN64)
-
-// Traits class to adapt GenericScopedHandle for HMODULES.
-class ModuleHandleTraits : public win::HandleTraits {
- public:
- using Handle = HMODULE;
-
- static bool BASE_EXPORT CloseHandle(HMODULE handle);
- static bool BASE_EXPORT IsHandleValid(HMODULE handle);
- static HMODULE BASE_EXPORT NullHandle();
-
- BASE_EXPORT static const HMODULE kNonNullModuleForTesting;
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ModuleHandleTraits);
-};
-
-// HMODULE is not really a handle, and has reference count semantics, so the
-// standard VerifierTraits does not apply.
-using ScopedModuleHandle =
- win::GenericScopedHandle<ModuleHandleTraits, win::DummyVerifierTraits>;
-
-// Instances of this class are expected to be created and destroyed for each
-// stack unwinding. This class is not used while the target thread is suspended,
-// so may allocate from the default heap.
-class BASE_EXPORT Win32StackFrameUnwinder {
- public:
- // Interface for Win32 unwind-related functionality this class depends
- // on. Provides a seam for testing.
- class BASE_EXPORT UnwindFunctions {
- public:
- virtual ~UnwindFunctions();
-
- virtual PRUNTIME_FUNCTION LookupFunctionEntry(DWORD64 program_counter,
- PDWORD64 image_base) = 0;
- virtual void VirtualUnwind(DWORD64 image_base,
- DWORD64 program_counter,
- PRUNTIME_FUNCTION runtime_function,
- CONTEXT* context) = 0;
-
- // Returns the module containing |program_counter|. Can return null if the
- // module has been unloaded.
- virtual ScopedModuleHandle GetModuleForProgramCounter(
- DWORD64 program_counter) = 0;
-
- protected:
- UnwindFunctions();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(UnwindFunctions);
- };
-
- Win32StackFrameUnwinder();
- ~Win32StackFrameUnwinder();
-
- // Attempts to unwind the frame represented by the stack and instruction
- // pointers in |context|. If successful, updates |context| and provides the
- // module associated with the frame in |module|.
- bool TryUnwind(CONTEXT* context, ScopedModuleHandle* module);
-
- private:
- // This function is for internal and test purposes only.
- Win32StackFrameUnwinder(std::unique_ptr<UnwindFunctions> unwind_functions);
- friend class Win32StackFrameUnwinderTest;
-
- // State associated with each stack unwinding.
- bool at_top_frame_;
- bool unwind_info_present_for_all_frames_;
-
- std::unique_ptr<UnwindFunctions> unwind_functions_;
-
- DISALLOW_COPY_AND_ASSIGN(Win32StackFrameUnwinder);
-};
-
-} // namespace base
-
-#endif // BASE_PROFILER_WIN32_STACK_FRAME_UNWINDER_H_
diff --git a/base/profiler/win32_stack_frame_unwinder_unittest.cc b/base/profiler/win32_stack_frame_unwinder_unittest.cc
deleted file mode 100644
index cecfe224ec..0000000000
--- a/base/profiler/win32_stack_frame_unwinder_unittest.cc
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2015 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/profiler/win32_stack_frame_unwinder.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class TestUnwindFunctions : public Win32StackFrameUnwinder::UnwindFunctions {
- public:
- TestUnwindFunctions();
-
- PRUNTIME_FUNCTION LookupFunctionEntry(DWORD64 program_counter,
- PDWORD64 image_base) override;
- void VirtualUnwind(DWORD64 image_base,
- DWORD64 program_counter,
- PRUNTIME_FUNCTION runtime_function,
- CONTEXT* context) override;
- ScopedModuleHandle GetModuleForProgramCounter(
- DWORD64 program_counter) override;
-
- // Instructs GetModuleForProgramCounter to return null on the next call.
- void SetUnloadedModule();
-
- // These functions set whether the next frame will have a RUNTIME_FUNCTION.
- void SetHasRuntimeFunction(CONTEXT* context);
- void SetNoRuntimeFunction(CONTEXT* context);
-
- private:
- enum { kImageBaseIncrement = 1 << 20 };
-
- static RUNTIME_FUNCTION* const kInvalidRuntimeFunction;
-
- bool module_is_loaded_;
- DWORD64 expected_program_counter_;
- DWORD64 next_image_base_;
- DWORD64 expected_image_base_;
- RUNTIME_FUNCTION* next_runtime_function_;
- std::vector<RUNTIME_FUNCTION> runtime_functions_;
-
- DISALLOW_COPY_AND_ASSIGN(TestUnwindFunctions);
-};
-
-RUNTIME_FUNCTION* const TestUnwindFunctions::kInvalidRuntimeFunction =
- reinterpret_cast<RUNTIME_FUNCTION*>(static_cast<uintptr_t>(-1));
-
-TestUnwindFunctions::TestUnwindFunctions()
- : module_is_loaded_(true),
- expected_program_counter_(0),
- next_image_base_(kImageBaseIncrement),
- expected_image_base_(0),
- next_runtime_function_(kInvalidRuntimeFunction) {
-}
-
-PRUNTIME_FUNCTION TestUnwindFunctions::LookupFunctionEntry(
- DWORD64 program_counter,
- PDWORD64 image_base) {
- EXPECT_EQ(expected_program_counter_, program_counter);
- *image_base = expected_image_base_ = next_image_base_;
- next_image_base_ += kImageBaseIncrement;
- RUNTIME_FUNCTION* return_value = next_runtime_function_;
- next_runtime_function_ = kInvalidRuntimeFunction;
- return return_value;
-}
-
-void TestUnwindFunctions::VirtualUnwind(DWORD64 image_base,
- DWORD64 program_counter,
- PRUNTIME_FUNCTION runtime_function,
- CONTEXT* context) {
- ASSERT_NE(kInvalidRuntimeFunction, runtime_function)
- << "expected call to SetHasRuntimeFunction() or SetNoRuntimeFunction() "
- << "before invoking TryUnwind()";
- EXPECT_EQ(expected_image_base_, image_base);
- expected_image_base_ = 0;
- EXPECT_EQ(expected_program_counter_, program_counter);
- expected_program_counter_ = 0;
- // This function should only be called when LookupFunctionEntry returns
- // a RUNTIME_FUNCTION.
- EXPECT_EQ(&runtime_functions_.back(), runtime_function);
-}
-
-ScopedModuleHandle TestUnwindFunctions::GetModuleForProgramCounter(
- DWORD64 program_counter) {
- bool return_non_null_value = module_is_loaded_;
- module_is_loaded_ = true;
- return ScopedModuleHandle(return_non_null_value ?
- ModuleHandleTraits::kNonNullModuleForTesting :
- nullptr);
-}
-
-void TestUnwindFunctions::SetUnloadedModule() {
- module_is_loaded_ = false;
-}
-
-void TestUnwindFunctions::SetHasRuntimeFunction(CONTEXT* context) {
- RUNTIME_FUNCTION runtime_function = {};
- runtime_function.BeginAddress = 16;
- runtime_function.EndAddress = runtime_function.BeginAddress + 256;
- runtime_functions_.push_back(runtime_function);
- next_runtime_function_ = &runtime_functions_.back();
-
- expected_program_counter_ = context->Rip =
- next_image_base_ + runtime_function.BeginAddress + 8;
-}
-
-void TestUnwindFunctions::SetNoRuntimeFunction(CONTEXT* context) {
- expected_program_counter_ = context->Rip = 100;
- next_runtime_function_ = nullptr;
-}
-
-} // namespace
-
-class Win32StackFrameUnwinderTest : public testing::Test {
- protected:
- Win32StackFrameUnwinderTest() {}
-
- // This exists so that Win32StackFrameUnwinder's constructor can be private
- // with a single friend declaration of this test fixture.
- std::unique_ptr<Win32StackFrameUnwinder> CreateUnwinder();
-
- // Weak pointer to the unwind functions used by last created unwinder.
- TestUnwindFunctions* unwind_functions_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Win32StackFrameUnwinderTest);
-};
-
-std::unique_ptr<Win32StackFrameUnwinder>
-Win32StackFrameUnwinderTest::CreateUnwinder() {
- std::unique_ptr<TestUnwindFunctions> unwind_functions(
- new TestUnwindFunctions);
- unwind_functions_ = unwind_functions.get();
- return WrapUnique(
- new Win32StackFrameUnwinder(std::move(unwind_functions)));
-}
-
-// Checks the case where all frames have unwind information.
-TEST_F(Win32StackFrameUnwinderTest, FramesWithUnwindInfo) {
- std::unique_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
- CONTEXT context = {0};
- ScopedModuleHandle module;
-
- unwind_functions_->SetHasRuntimeFunction(&context);
- EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
- EXPECT_TRUE(module.IsValid());
-
- unwind_functions_->SetHasRuntimeFunction(&context);
- module.Set(nullptr);
- EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
- EXPECT_TRUE(module.IsValid());
-
- unwind_functions_->SetHasRuntimeFunction(&context);
- module.Set(nullptr);
- EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
- EXPECT_TRUE(module.IsValid());
-}
-
-// Checks that an instruction pointer in an unloaded module fails to unwind.
-TEST_F(Win32StackFrameUnwinderTest, UnloadedModule) {
- std::unique_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
- CONTEXT context = {0};
- ScopedModuleHandle module;
-
- unwind_functions_->SetUnloadedModule();
- EXPECT_FALSE(unwinder->TryUnwind(&context, &module));
-}
-
-// Checks that the CONTEXT's stack pointer gets popped when the top frame has no
-// unwind information.
-TEST_F(Win32StackFrameUnwinderTest, FrameAtTopWithoutUnwindInfo) {
- std::unique_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
- CONTEXT context = {0};
- ScopedModuleHandle module;
- DWORD64 next_ip = 0x0123456789abcdef;
- DWORD64 original_rsp = reinterpret_cast<DWORD64>(&next_ip);
- context.Rsp = original_rsp;
-
- unwind_functions_->SetNoRuntimeFunction(&context);
- EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
- EXPECT_EQ(next_ip, context.Rip);
- EXPECT_EQ(original_rsp + 8, context.Rsp);
- EXPECT_TRUE(module.IsValid());
-
- unwind_functions_->SetHasRuntimeFunction(&context);
- module.Set(nullptr);
- EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
- EXPECT_TRUE(module.IsValid());
-
- unwind_functions_->SetHasRuntimeFunction(&context);
- module.Set(nullptr);
- EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
- EXPECT_TRUE(module.IsValid());
-}
-
-// Checks that a frame below the top of the stack with missing unwind info
-// terminates the unwinding.
-TEST_F(Win32StackFrameUnwinderTest, FrameBelowTopWithoutUnwindInfo) {
- {
- // First stack, with a bad function below the top of the stack.
- std::unique_ptr<Win32StackFrameUnwinder> unwinder = CreateUnwinder();
- CONTEXT context = {0};
- ScopedModuleHandle module;
- unwind_functions_->SetHasRuntimeFunction(&context);
- EXPECT_TRUE(unwinder->TryUnwind(&context, &module));
- EXPECT_TRUE(module.IsValid());
-
- unwind_functions_->SetNoRuntimeFunction(&context);
- EXPECT_FALSE(unwinder->TryUnwind(&context, &module));
- }
-}
-
-} // namespace base
diff --git a/base/run_loop.h b/base/run_loop.h
index 8f5e0099d0..2582a69f1d 100644
--- a/base/run_loop.h
+++ b/base/run_loop.h
@@ -250,7 +250,7 @@ class BASE_EXPORT RunLoop {
private:
FRIEND_TEST_ALL_PREFIXES(MessageLoopTypedTest, RunLoopQuitOrderAfter);
-#if defined(OS_ANDROID) && 0
+#if defined(OS_ANDROID)
// Android doesn't support the blocking RunLoop::Run, so it calls
// BeforeRun and AfterRun directly.
friend class base::MessagePumpForUI;
diff --git a/base/run_loop_unittest.cc b/base/run_loop_unittest.cc
deleted file mode 100644
index c7db14aa3d..0000000000
--- a/base/run_loop_unittest.cc
+++ /dev/null
@@ -1,636 +0,0 @@
-// Copyright 2016 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/run_loop.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/containers/queue.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/gtest_util.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker_impl.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-void QuitWhenIdleTask(RunLoop* run_loop, int* counter) {
- run_loop->QuitWhenIdle();
- ++(*counter);
-}
-
-void ShouldRunTask(int* counter) {
- ++(*counter);
-}
-
-void ShouldNotRunTask() {
- ADD_FAILURE() << "Ran a task that shouldn't run.";
-}
-
-void RunNestedLoopTask(int* counter) {
- RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
-
- // This task should quit |nested_run_loop| but not the main RunLoop.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&nested_run_loop),
- Unretained(counter)));
-
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
-
- nested_run_loop.Run();
-
- ++(*counter);
-}
-
-// A simple SingleThreadTaskRunner that just queues undelayed tasks (and ignores
-// delayed tasks). Tasks can then be processed one by one by ProcessTask() which
-// will return true if it processed a task and false otherwise.
-class SimpleSingleThreadTaskRunner : public SingleThreadTaskRunner {
- public:
- SimpleSingleThreadTaskRunner() = default;
-
- bool PostDelayedTask(const Location& from_here,
- OnceClosure task,
- base::TimeDelta delay) override {
- if (delay > base::TimeDelta())
- return false;
- AutoLock auto_lock(tasks_lock_);
- pending_tasks_.push(std::move(task));
- return true;
- }
-
- bool PostNonNestableDelayedTask(const Location& from_here,
- OnceClosure task,
- base::TimeDelta delay) override {
- return PostDelayedTask(from_here, std::move(task), delay);
- }
-
- bool RunsTasksInCurrentSequence() const override {
- return origin_thread_checker_.CalledOnValidThread();
- }
-
- bool ProcessSingleTask() {
- OnceClosure task;
- {
- AutoLock auto_lock(tasks_lock_);
- if (pending_tasks_.empty())
- return false;
- task = std::move(pending_tasks_.front());
- pending_tasks_.pop();
- }
- // It's important to Run() after pop() and outside the lock as |task| may
- // run a nested loop which will re-enter ProcessSingleTask().
- std::move(task).Run();
- return true;
- }
-
- private:
- ~SimpleSingleThreadTaskRunner() override = default;
-
- Lock tasks_lock_;
- base::queue<OnceClosure> pending_tasks_;
-
- // RunLoop relies on RunsTasksInCurrentSequence() signal. Use a
- // ThreadCheckerImpl to be able to reliably provide that signal even in
- // non-dcheck builds.
- ThreadCheckerImpl origin_thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleSingleThreadTaskRunner);
-};
-
-// The basis of all TestDelegates, allows safely injecting a OnceClosure to be
-// run in the next idle phase of this delegate's Run() implementation. This can
-// be used to have code run on a thread that is otherwise livelocked in an idle
-// phase (sometimes a simple PostTask() won't do it -- e.g. when processing
-// application tasks is disallowed).
-class InjectableTestDelegate : public RunLoop::Delegate {
- public:
- void InjectClosureOnDelegate(OnceClosure closure) {
- AutoLock auto_lock(closure_lock_);
- closure_ = std::move(closure);
- }
-
- bool RunInjectedClosure() {
- AutoLock auto_lock(closure_lock_);
- if (closure_.is_null())
- return false;
- std::move(closure_).Run();
- return true;
- }
-
- private:
- Lock closure_lock_;
- OnceClosure closure_;
-};
-
-// A simple test RunLoop::Delegate to exercise Runloop logic independent of any
-// other base constructs. BindToCurrentThread() must be called before this
-// TestBoundDelegate is operational.
-class TestBoundDelegate final : public InjectableTestDelegate {
- public:
- TestBoundDelegate() = default;
-
- // Makes this TestBoundDelegate become the RunLoop::Delegate and
- // ThreadTaskRunnerHandle for this thread.
- void BindToCurrentThread() {
- thread_task_runner_handle_ =
- std::make_unique<ThreadTaskRunnerHandle>(simple_task_runner_);
- RunLoop::RegisterDelegateForCurrentThread(this);
- }
-
- private:
- void Run(bool application_tasks_allowed) override {
- if (nested_run_allowing_tasks_incoming_) {
- EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
- EXPECT_TRUE(application_tasks_allowed);
- } else if (RunLoop::IsNestedOnCurrentThread()) {
- EXPECT_FALSE(application_tasks_allowed);
- }
- nested_run_allowing_tasks_incoming_ = false;
-
- while (!should_quit_) {
- if (application_tasks_allowed && simple_task_runner_->ProcessSingleTask())
- continue;
-
- if (ShouldQuitWhenIdle())
- break;
-
- if (RunInjectedClosure())
- continue;
-
- PlatformThread::YieldCurrentThread();
- }
- should_quit_ = false;
- }
-
- void Quit() override { should_quit_ = true; }
-
- void EnsureWorkScheduled() override {
- nested_run_allowing_tasks_incoming_ = true;
- }
-
- // True if the next invocation of Run() is expected to be from a
- // kNestableTasksAllowed RunLoop.
- bool nested_run_allowing_tasks_incoming_ = false;
-
- scoped_refptr<SimpleSingleThreadTaskRunner> simple_task_runner_ =
- MakeRefCounted<SimpleSingleThreadTaskRunner>();
-
- std::unique_ptr<ThreadTaskRunnerHandle> thread_task_runner_handle_;
-
- bool should_quit_ = false;
-};
-
-enum class RunLoopTestType {
- // Runs all RunLoopTests under a ScopedTaskEnvironment to make sure real world
- // scenarios work.
- kRealEnvironment,
-
- // Runs all RunLoopTests under a test RunLoop::Delegate to make sure the
- // delegate interface fully works standalone.
- kTestDelegate,
-};
-
-// The task environment for the RunLoopTest of a given type. A separate class
-// so it can be instantiated on the stack in the RunLoopTest fixture.
-class RunLoopTestEnvironment {
- public:
- RunLoopTestEnvironment(RunLoopTestType type) {
- switch (type) {
- case RunLoopTestType::kRealEnvironment: {
- task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
- break;
- }
- case RunLoopTestType::kTestDelegate: {
- auto test_delegate = std::make_unique<TestBoundDelegate>();
- test_delegate->BindToCurrentThread();
- test_delegate_ = std::move(test_delegate);
- break;
- }
- }
- }
-
- private:
- // Instantiates one or the other based on the RunLoopTestType.
- std::unique_ptr<test::ScopedTaskEnvironment> task_environment_;
- std::unique_ptr<InjectableTestDelegate> test_delegate_;
-};
-
-class RunLoopTest : public testing::TestWithParam<RunLoopTestType> {
- protected:
- RunLoopTest() : test_environment_(GetParam()) {}
-
- RunLoopTestEnvironment test_environment_;
- RunLoop run_loop_;
- int counter_ = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
-};
-
-} // namespace
-
-TEST_P(RunLoopTest, QuitWhenIdle) {
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
- Unretained(&counter_)));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
-
- run_loop_.Run();
- EXPECT_EQ(2, counter_);
-}
-
-TEST_P(RunLoopTest, QuitWhenIdleNestedLoop) {
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RunNestedLoopTask, Unretained(&counter_)));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&QuitWhenIdleTask, Unretained(&run_loop_),
- Unretained(&counter_)));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
-
- run_loop_.Run();
- EXPECT_EQ(4, counter_);
-}
-
-TEST_P(RunLoopTest, QuitWhenIdleClosure) {
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- run_loop_.QuitWhenIdleClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&ShouldRunTask, Unretained(&counter_)));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
-
- run_loop_.Run();
- EXPECT_EQ(1, counter_);
-}
-
-// Verify that the QuitWhenIdleClosure() can run after the RunLoop has been
-// deleted. It should have no effect.
-TEST_P(RunLoopTest, QuitWhenIdleClosureAfterRunLoopScope) {
- Closure quit_when_idle_closure;
- {
- RunLoop run_loop;
- quit_when_idle_closure = run_loop.QuitWhenIdleClosure();
- run_loop.RunUntilIdle();
- }
- quit_when_idle_closure.Run();
-}
-
-// Verify that Quit can be executed from another sequence.
-TEST_P(RunLoopTest, QuitFromOtherSequence) {
- Thread other_thread("test");
- other_thread.Start();
- scoped_refptr<SequencedTaskRunner> other_sequence =
- other_thread.task_runner();
-
- // Always expected to run before asynchronous Quit() kicks in.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- other_sequence->PostTask(
- FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
- Unretained(&run_loop_)));
- other_sequence->PostTask(
- FROM_HERE,
- base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
-
- // Anything that's posted after the Quit closure was posted back to this
- // sequence shouldn't get a chance to run.
- loop_was_quit.Wait();
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::BindOnce(&ShouldNotRunTask));
-
- run_loop_.Run();
-
- EXPECT_EQ(1, counter_);
-}
-
-// Verify that QuitClosure can be executed from another sequence.
-TEST_P(RunLoopTest, QuitFromOtherSequenceWithClosure) {
- Thread other_thread("test");
- other_thread.Start();
- scoped_refptr<SequencedTaskRunner> other_sequence =
- other_thread.task_runner();
-
- // Always expected to run before asynchronous Quit() kicks in.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- WaitableEvent loop_was_quit(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
- other_sequence->PostTask(
- FROM_HERE,
- base::BindOnce(&WaitableEvent::Signal, base::Unretained(&loop_was_quit)));
-
- // Anything that's posted after the Quit closure was posted back to this
- // sequence shouldn't get a chance to run.
- loop_was_quit.Wait();
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::BindOnce(&ShouldNotRunTask));
-
- run_loop_.Run();
-
- EXPECT_EQ(1, counter_);
-}
-
-// Verify that Quit can be executed from another sequence even when the
-// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
-TEST_P(RunLoopTest, QuitFromOtherSequenceRacy) {
- Thread other_thread("test");
- other_thread.Start();
- scoped_refptr<SequencedTaskRunner> other_sequence =
- other_thread.task_runner();
-
- // Always expected to run before asynchronous Quit() kicks in.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- other_sequence->PostTask(
- FROM_HERE, base::BindOnce([](RunLoop* run_loop) { run_loop->Quit(); },
- Unretained(&run_loop_)));
-
- run_loop_.Run();
-
- EXPECT_EQ(1, counter_);
-}
-
-// Verify that QuitClosure can be executed from another sequence even when the
-// Quit is racing with Run() -- i.e. forgo the WaitableEvent used above.
-TEST_P(RunLoopTest, QuitFromOtherSequenceRacyWithClosure) {
- Thread other_thread("test");
- other_thread.Start();
- scoped_refptr<SequencedTaskRunner> other_sequence =
- other_thread.task_runner();
-
- // Always expected to run before asynchronous Quit() kicks in.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- other_sequence->PostTask(FROM_HERE, run_loop_.QuitClosure());
-
- run_loop_.Run();
-
- EXPECT_EQ(1, counter_);
-}
-
-// Verify that QuitWhenIdle can be executed from another sequence.
-TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequence) {
- Thread other_thread("test");
- other_thread.Start();
- scoped_refptr<SequencedTaskRunner> other_sequence =
- other_thread.task_runner();
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- other_sequence->PostTask(
- FROM_HERE,
- base::BindOnce([](RunLoop* run_loop) { run_loop->QuitWhenIdle(); },
- Unretained(&run_loop_)));
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- run_loop_.Run();
-
- // Regardless of the outcome of the race this thread shouldn't have been idle
- // until the counter was ticked twice.
- EXPECT_EQ(2, counter_);
-}
-
-// Verify that QuitWhenIdleClosure can be executed from another sequence.
-TEST_P(RunLoopTest, QuitWhenIdleFromOtherSequenceWithClosure) {
- Thread other_thread("test");
- other_thread.Start();
- scoped_refptr<SequencedTaskRunner> other_sequence =
- other_thread.task_runner();
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- other_sequence->PostTask(FROM_HERE, run_loop_.QuitWhenIdleClosure());
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&ShouldRunTask, Unretained(&counter_)));
-
- run_loop_.Run();
-
- // Regardless of the outcome of the race this thread shouldn't have been idle
- // until the counter was ticked twice.
- EXPECT_EQ(2, counter_);
-}
-
-TEST_P(RunLoopTest, IsRunningOnCurrentThread) {
- EXPECT_FALSE(RunLoop::IsRunningOnCurrentThread());
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce([]() { EXPECT_TRUE(RunLoop::IsRunningOnCurrentThread()); }));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
- run_loop_.Run();
-}
-
-TEST_P(RunLoopTest, IsNestedOnCurrentThread) {
- EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce([]() {
- EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
-
- RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce([]() {
- EXPECT_TRUE(RunLoop::IsNestedOnCurrentThread());
- }));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_run_loop.QuitClosure());
-
- EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
- nested_run_loop.Run();
- EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
- }));
-
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure());
- run_loop_.Run();
-}
-
-namespace {
-
-class MockNestingObserver : public RunLoop::NestingObserver {
- public:
- MockNestingObserver() = default;
-
- // RunLoop::NestingObserver:
- MOCK_METHOD0(OnBeginNestedRunLoop, void());
- MOCK_METHOD0(OnExitNestedRunLoop, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockNestingObserver);
-};
-
-class MockTask {
- public:
- MockTask() = default;
- MOCK_METHOD0(Task, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockTask);
-};
-
-} // namespace
-
-TEST_P(RunLoopTest, NestingObservers) {
- testing::StrictMock<MockNestingObserver> nesting_observer;
- testing::StrictMock<MockTask> mock_task_a;
- testing::StrictMock<MockTask> mock_task_b;
-
- RunLoop::AddNestingObserverOnCurrentThread(&nesting_observer);
-
- const RepeatingClosure run_nested_loop = Bind([]() {
- RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_run_loop.QuitClosure());
- nested_run_loop.Run();
- });
-
- // Generate a stack of nested RunLoops. OnBeginNestedRunLoop() is expected
- // when beginning each nesting depth and OnExitNestedRunLoop() is expected
- // when exiting each nesting depth. Each one of these tasks is ahead of the
- // QuitClosures as those are only posted at the end of the queue when
- // |run_nested_loop| is executed.
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_a)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_nested_loop);
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&MockTask::Task, base::Unretained(&mock_task_b)));
-
- {
- testing::InSequence in_sequence;
- EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
- EXPECT_CALL(mock_task_a, Task());
- EXPECT_CALL(nesting_observer, OnBeginNestedRunLoop());
- EXPECT_CALL(mock_task_b, Task());
- EXPECT_CALL(nesting_observer, OnExitNestedRunLoop()).Times(2);
- }
- run_loop_.RunUntilIdle();
-
- RunLoop::RemoveNestingObserverOnCurrentThread(&nesting_observer);
-}
-
-TEST_P(RunLoopTest, DisallowRunningForTesting) {
- RunLoop::ScopedDisallowRunningForTesting disallow_running;
- EXPECT_DCHECK_DEATH({ run_loop_.RunUntilIdle(); });
-}
-
-TEST_P(RunLoopTest, ExpiredDisallowRunningForTesting) {
- { RunLoop::ScopedDisallowRunningForTesting disallow_running; }
- // Running should be fine after |disallow_running| goes out of scope.
- run_loop_.RunUntilIdle();
-}
-
-INSTANTIATE_TEST_CASE_P(Real,
- RunLoopTest,
- testing::Values(RunLoopTestType::kRealEnvironment));
-INSTANTIATE_TEST_CASE_P(Mock,
- RunLoopTest,
- testing::Values(RunLoopTestType::kTestDelegate));
-
-TEST(RunLoopDeathTest, MustRegisterBeforeInstantiating) {
- TestBoundDelegate unbound_test_delegate_;
- // RunLoop::RunLoop() should CHECK fetching the ThreadTaskRunnerHandle.
- EXPECT_DEATH_IF_SUPPORTED({ RunLoop(); }, "");
-}
-
-TEST(RunLoopDelegateTest, NestableTasksDontRunInDefaultNestedLoops) {
- TestBoundDelegate test_delegate;
- test_delegate.BindToCurrentThread();
-
- base::Thread other_thread("test");
- other_thread.Start();
-
- RunLoop main_loop;
- // A nested run loop which isn't kNestableTasksAllowed.
- RunLoop nested_run_loop(RunLoop::Type::kDefault);
-
- bool nested_run_loop_ended = false;
-
- // The first task on the main loop will result in a nested run loop. Since
- // it's not kNestableTasksAllowed, no further task should be processed until
- // it's quit.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce([](RunLoop* nested_run_loop) { nested_run_loop->Run(); },
- Unretained(&nested_run_loop)));
-
- // Post a task that will fail if it runs inside the nested run loop.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(
- [](const bool& nested_run_loop_ended,
- OnceClosure continuation_callback) {
- EXPECT_TRUE(nested_run_loop_ended);
- EXPECT_FALSE(RunLoop::IsNestedOnCurrentThread());
- std::move(continuation_callback).Run();
- },
- ConstRef(nested_run_loop_ended), main_loop.QuitClosure()));
-
- // Post a task flipping the boolean bit for extra verification right before
- // quitting |nested_run_loop|.
- other_thread.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(
- [](bool* nested_run_loop_ended) {
- EXPECT_FALSE(*nested_run_loop_ended);
- *nested_run_loop_ended = true;
- },
- Unretained(&nested_run_loop_ended)),
- TestTimeouts::tiny_timeout());
- // Post an async delayed task to exit the run loop when idle. This confirms
- // that (1) the test task only ran in the main loop after the nested loop
- // exited and (2) the nested run loop actually considers itself idle while
- // spinning. Note: The quit closure needs to be injected directly on the
- // delegate as invoking QuitWhenIdle() off-thread results in a thread bounce
- // which will not processed because of the very logic under test (nestable
- // tasks don't run in |nested_run_loop|).
- other_thread.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(
- [](TestBoundDelegate* test_delegate, OnceClosure injected_closure) {
- test_delegate->InjectClosureOnDelegate(std::move(injected_closure));
- },
- Unretained(&test_delegate), nested_run_loop.QuitWhenIdleClosure()),
- TestTimeouts::tiny_timeout());
-
- main_loop.Run();
-}
-
-} // namespace base
diff --git a/base/safe_numerics_unittest.cc b/base/safe_numerics_unittest.cc
deleted file mode 100644
index 44675cf72c..0000000000
--- a/base/safe_numerics_unittest.cc
+++ /dev/null
@@ -1,1640 +0,0 @@
-// Copyright 2013 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 <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-#include <type_traits>
-
-#include "base/compiler_specific.h"
-
-// WARNING: This block must come before the base/numerics headers are included.
-// These tests deliberately cause arithmetic boundary errors. If the compiler is
-// aggressive enough, it can const detect these errors, so we disable warnings.
-#if defined(OS_WIN)
-#pragma warning(disable : 4756) // Arithmetic overflow.
-#pragma warning(disable : 4293) // Invalid shift.
-#endif
-
-// This may not need to come before the base/numerics headers, but let's keep
-// it close to the MSVC equivalent.
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Winteger-overflow"
-#endif
-
-#include "base/logging.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/numerics/safe_math.h"
-#include "base/test/gtest_util.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(COMPILER_MSVC) && defined(ARCH_CPU_32_BITS)
-#include <mmintrin.h>
-#endif
-
-namespace base {
-namespace internal {
-
-using std::numeric_limits;
-
-// This is a helper function for finding the maximum value in Src that can be
-// wholy represented as the destination floating-point type.
-template <typename Dst, typename Src>
-Dst GetMaxConvertibleToFloat() {
- using DstLimits = numeric_limits<Dst>;
- using SrcLimits = numeric_limits<Src>;
- static_assert(SrcLimits::is_specialized, "Source must be numeric.");
- static_assert(DstLimits::is_specialized, "Destination must be numeric.");
- CHECK(DstLimits::is_iec559);
-
- if (SrcLimits::digits <= DstLimits::digits &&
- MaxExponent<Src>::value <= MaxExponent<Dst>::value)
- return SrcLimits::max();
- Src max = SrcLimits::max() / 2 + (SrcLimits::is_integer ? 1 : 0);
- while (max != static_cast<Src>(static_cast<Dst>(max))) {
- max /= 2;
- }
- return static_cast<Dst>(max);
-}
-
-// Test corner case promotions used
-static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int8_t>::value, "");
-static_assert(IsIntegerArithmeticSafe<int32_t, int16_t, int8_t>::value, "");
-static_assert(IsIntegerArithmeticSafe<int32_t, int8_t, int16_t>::value, "");
-static_assert(!IsIntegerArithmeticSafe<int32_t, int32_t, int8_t>::value, "");
-static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
-static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
-static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
-static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
-static_assert(
- std::is_same<BigEnoughPromotion<int16_t, int8_t>::type, int16_t>::value,
- "");
-static_assert(
- std::is_same<BigEnoughPromotion<int32_t, uint32_t>::type, int64_t>::value,
- "");
-static_assert(
- std::is_same<BigEnoughPromotion<intmax_t, int8_t>::type, intmax_t>::value,
- "");
-static_assert(
- std::is_same<BigEnoughPromotion<uintmax_t, int8_t>::type, uintmax_t>::value,
- "");
-static_assert(BigEnoughPromotion<int16_t, int8_t>::is_contained, "");
-static_assert(BigEnoughPromotion<int32_t, uint32_t>::is_contained, "");
-static_assert(BigEnoughPromotion<intmax_t, int8_t>::is_contained, "");
-static_assert(!BigEnoughPromotion<uintmax_t, int8_t>::is_contained, "");
-static_assert(
- std::is_same<FastIntegerArithmeticPromotion<int16_t, int8_t>::type,
- int32_t>::value,
- "");
-static_assert(
- std::is_same<FastIntegerArithmeticPromotion<int32_t, uint32_t>::type,
- int64_t>::value,
- "");
-static_assert(
- std::is_same<FastIntegerArithmeticPromotion<intmax_t, int8_t>::type,
- intmax_t>::value,
- "");
-static_assert(
- std::is_same<FastIntegerArithmeticPromotion<uintmax_t, int8_t>::type,
- uintmax_t>::value,
- "");
-static_assert(FastIntegerArithmeticPromotion<int16_t, int8_t>::is_contained,
- "");
-static_assert(FastIntegerArithmeticPromotion<int32_t, uint32_t>::is_contained,
- "");
-static_assert(!FastIntegerArithmeticPromotion<intmax_t, int8_t>::is_contained,
- "");
-static_assert(!FastIntegerArithmeticPromotion<uintmax_t, int8_t>::is_contained,
- "");
-
-template <typename U>
-U GetNumericValueForTest(const CheckedNumeric<U>& src) {
- return src.state_.value();
-}
-
-template <typename U>
-U GetNumericValueForTest(const ClampedNumeric<U>& src) {
- return static_cast<U>(src);
-}
-
-template <typename U>
-U GetNumericValueForTest(const U& src) {
- return src;
-}
-
-// Logs the ValueOrDie() failure instead of crashing.
-struct LogOnFailure {
- template <typename T>
- static T HandleFailure() {
- LOG(WARNING) << "ValueOrDie() failed unexpectedly.";
- return T();
- }
-};
-
-template <typename T>
-constexpr T GetValue(const T& src) {
- return src;
-}
-
-template <typename T, typename U>
-constexpr T GetValueAsDest(const U& src) {
- return static_cast<T>(src);
-}
-
-template <typename T>
-constexpr T GetValue(const CheckedNumeric<T>& src) {
- return src.template ValueOrDie<T, LogOnFailure>();
-}
-
-template <typename T, typename U>
-constexpr T GetValueAsDest(const CheckedNumeric<U>& src) {
- return src.template ValueOrDie<T, LogOnFailure>();
-}
-
-template <typename T>
-constexpr T GetValue(const ClampedNumeric<T>& src) {
- return static_cast<T>(src);
-}
-
-template <typename T, typename U>
-constexpr T GetValueAsDest(const ClampedNumeric<U>& src) {
- return static_cast<T>(src);
-}
-
-// Helper macros to wrap displaying the conversion types and line numbers.
-#define TEST_EXPECTED_VALIDITY(expected, actual) \
- EXPECT_EQ(expected, (actual).template Cast<Dst>().IsValid()) \
- << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
- << dst << " on line " << line
-
-#define TEST_EXPECTED_SUCCESS(actual) TEST_EXPECTED_VALIDITY(true, actual)
-#define TEST_EXPECTED_FAILURE(actual) TEST_EXPECTED_VALIDITY(false, actual)
-
-// We have to handle promotions, so infer the underlying type below from actual.
-#define TEST_EXPECTED_VALUE(expected, actual) \
- EXPECT_EQ(GetValue(expected), GetValueAsDest<decltype(expected)>(actual)) \
- << "Result test: Value " << GetNumericValueForTest(actual) << " as " \
- << dst << " on line " << line
-
-// Test the simple pointer arithmetic overrides.
-template <typename Dst>
-void TestStrictPointerMath() {
- Dst dummy_value = 0;
- Dst* dummy_ptr = &dummy_value;
- static const Dst kDummyOffset = 2; // Don't want to go too far.
- EXPECT_EQ(dummy_ptr + kDummyOffset,
- dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
- EXPECT_EQ(dummy_ptr - kDummyOffset,
- dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
- EXPECT_NE(dummy_ptr, dummy_ptr + StrictNumeric<Dst>(kDummyOffset));
- EXPECT_NE(dummy_ptr, dummy_ptr - StrictNumeric<Dst>(kDummyOffset));
- EXPECT_DEATH_IF_SUPPORTED(
- dummy_ptr + StrictNumeric<size_t>(std::numeric_limits<size_t>::max()),
- "");
-}
-
-// Signed integer arithmetic.
-template <typename Dst>
-static void TestSpecializedArithmetic(
- const char* dst,
- int line,
- typename std::enable_if<numeric_limits<Dst>::is_integer &&
- numeric_limits<Dst>::is_signed,
- int>::type = 0) {
- using DstLimits = SaturationDefaultLimits<Dst>;
- TEST_EXPECTED_FAILURE(-CheckedNumeric<Dst>(DstLimits::lowest()));
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- MakeCheckedNum(-DstLimits::max()).Abs());
-
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- -ClampedNumeric<Dst>(DstLimits::lowest()));
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- MakeClampedNum(-DstLimits::max()).Abs());
-
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
- DstLimits::lowest());
-
- TEST_EXPECTED_VALUE(DstLimits::max() - 1,
- ClampedNumeric<Dst>(DstLimits::max()) + -1);
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
- TEST_EXPECTED_VALUE(
- DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) - -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
- DstLimits::lowest());
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
- DstLimits::max());
-
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
- TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
- ClampedNumeric<Dst>(DstLimits::lowest()) - -1);
- TEST_EXPECTED_VALUE(
- DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
- TEST_EXPECTED_VALUE(
- DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) / -1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(-1) / 2);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * -1);
- TEST_EXPECTED_VALUE(DstLimits::max(),
- CheckedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
- TEST_EXPECTED_VALUE(DstLimits::max(),
- CheckedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
- TEST_EXPECTED_VALUE(DstLimits::lowest(),
- CheckedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
- TEST_EXPECTED_VALUE(DstLimits::lowest(),
- CheckedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
- TEST_EXPECTED_VALUE(
- typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
- MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- MakeCheckedNum(DstLimits::max()).UnsignedAbs());
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).UnsignedAbs());
-
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) / -1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(-1) / 2);
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) * -1);
- TEST_EXPECTED_VALUE(DstLimits::max(),
- ClampedNumeric<Dst>(DstLimits::lowest() + 1) * Dst(-1));
- TEST_EXPECTED_VALUE(DstLimits::max(),
- ClampedNumeric<Dst>(-1) * Dst(DstLimits::lowest() + 1));
- TEST_EXPECTED_VALUE(DstLimits::lowest(),
- ClampedNumeric<Dst>(DstLimits::lowest()) * Dst(1));
- TEST_EXPECTED_VALUE(DstLimits::lowest(),
- ClampedNumeric<Dst>(1) * Dst(DstLimits::lowest()));
- TEST_EXPECTED_VALUE(
- typename std::make_unsigned<Dst>::type(0) - DstLimits::lowest(),
- MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- MakeClampedNum(DstLimits::max()).UnsignedAbs());
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).UnsignedAbs());
-
- // Modulus is legal only for integers.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % 2);
- TEST_EXPECTED_VALUE(-1, CheckedNumeric<Dst>(-1) % -2);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
- // Test all the different modulus combinations.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- CheckedNumeric<Dst> checked_dst = 1;
- TEST_EXPECTED_VALUE(0, checked_dst %= 1);
- // Test that div by 0 is avoided but returns invalid result.
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
- // Test bit shifts.
- volatile Dst negative_one = -1;
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
- << (IntegerBitsPlusSign<Dst>::value - 1));
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
- << IntegerBitsPlusSign<Dst>::value);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
- TEST_EXPECTED_VALUE(
- static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2),
- CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0)
- << (IntegerBitsPlusSign<Dst>::value - 1));
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
- TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
- IntegerBitsPlusSign<Dst>::value);
- TEST_EXPECTED_VALUE(
- 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
-
- // Modulus is legal only for integers.
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
- TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % 2);
- TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(-1) % -2);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
- // Test all the different modulus combinations.
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
- ClampedNumeric<Dst> clamped_dst = 1;
- TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
- TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
- // Test bit shifts.
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(1)
- << (IntegerBitsPlusSign<Dst>::value - 1U));
- TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0)
- << (IntegerBitsPlusSign<Dst>::value + 0U));
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::max()) << 1U);
- TEST_EXPECTED_VALUE(
- static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U),
- ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 2U));
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0)
- << (IntegerBitsPlusSign<Dst>::value - 1U));
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
- TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
- TEST_EXPECTED_VALUE(
- 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value + 0U));
- TEST_EXPECTED_VALUE(
- 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
- TEST_EXPECTED_VALUE(
- -1, ClampedNumeric<Dst>(-1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
- TEST_EXPECTED_VALUE(-1, ClampedNumeric<Dst>(DstLimits::lowest()) >>
- (IntegerBitsPlusSign<Dst>::value - 0U));
-
- TestStrictPointerMath<Dst>();
-}
-
-// Unsigned integer arithmetic.
-template <typename Dst>
-static void TestSpecializedArithmetic(
- const char* dst,
- int line,
- typename std::enable_if<numeric_limits<Dst>::is_integer &&
- !numeric_limits<Dst>::is_signed,
- int>::type = 0) {
- using DstLimits = SaturationDefaultLimits<Dst>;
- TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) - 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) / 2);
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
- TEST_EXPECTED_SUCCESS(
- CheckedNumeric<typename std::make_signed<Dst>::type>(
- std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
- .UnsignedAbs());
- TEST_EXPECTED_VALUE(DstLimits::lowest(),
- MakeCheckedNum(DstLimits::lowest()).UnsignedAbs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- MakeCheckedNum(DstLimits::max()).UnsignedAbs());
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0).UnsignedAbs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).UnsignedAbs());
-
- TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>(DstLimits::lowest()));
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) - 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) / 2);
- TEST_EXPECTED_VALUE(0,
- ClampedNumeric<Dst>(DstLimits::lowest()).UnsignedAbs());
- TEST_EXPECTED_VALUE(
- as_unsigned(
- std::numeric_limits<typename std::make_signed<Dst>::type>::lowest()),
- ClampedNumeric<typename std::make_signed<Dst>::type>(
- std::numeric_limits<typename std::make_signed<Dst>::type>::lowest())
- .UnsignedAbs());
- TEST_EXPECTED_VALUE(DstLimits::lowest(),
- MakeClampedNum(DstLimits::lowest()).UnsignedAbs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- MakeClampedNum(DstLimits::max()).UnsignedAbs());
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0).UnsignedAbs());
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).UnsignedAbs());
-
- // Modulus is legal only for integers.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() % 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) % 2);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(DstLimits::lowest()) % 2);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(DstLimits::max()) % 2);
- // Test all the different modulus combinations.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 % CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) % 1);
- CheckedNumeric<Dst> checked_dst = 1;
- TEST_EXPECTED_VALUE(0, checked_dst %= 1);
- // Test that div by 0 is avoided but returns invalid result.
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) % 0);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
- << IntegerBitsPlusSign<Dst>::value);
- // Test bit shifts.
- volatile int negative_one = -1;
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) << negative_one);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1)
- << IntegerBitsPlusSign<Dst>::value);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(0)
- << IntegerBitsPlusSign<Dst>::value);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) << 1);
- TEST_EXPECTED_VALUE(
- static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1),
- CheckedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1));
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) << 0);
- TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) << 1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >>
- IntegerBitsPlusSign<Dst>::value);
- TEST_EXPECTED_VALUE(
- 0, CheckedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1));
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) >> negative_one);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) & 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) & 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) & 0);
- TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
- MakeCheckedNum(DstLimits::max()) & -1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) | 0);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) | 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) | 0);
- TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
- CheckedNumeric<Dst>(0) | static_cast<Dst>(-1));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) ^ 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) ^ 0);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(0) ^ 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(0) ^ 0);
- TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
- CheckedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
- TEST_EXPECTED_VALUE(DstLimits::max(), ~CheckedNumeric<Dst>(0));
-
- // Modulus is legal only for integers.
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() % 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) % 2);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::lowest()) % 2);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(DstLimits::max()) % 2);
- // Test all the different modulus combinations.
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 % ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) % 1);
- ClampedNumeric<Dst> clamped_dst = 1;
- TEST_EXPECTED_VALUE(0, clamped_dst %= 1);
- // Test that div by 0 is avoided but returns invalid result.
- TEST_EXPECTED_VALUE(Dst(1), ClampedNumeric<Dst>(1) % 0);
- // Test bit shifts.
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(1)
- << as_unsigned(IntegerBitsPlusSign<Dst>::value));
- TEST_EXPECTED_VALUE(Dst(0), ClampedNumeric<Dst>(0) << as_unsigned(
- IntegerBitsPlusSign<Dst>::value));
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::max()) << 1U);
- TEST_EXPECTED_VALUE(
- static_cast<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U),
- ClampedNumeric<Dst>(1) << (IntegerBitsPlusSign<Dst>::value - 1U));
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) << 0U);
- TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) << 1U);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) >>
- as_unsigned(IntegerBitsPlusSign<Dst>::value));
- TEST_EXPECTED_VALUE(
- 0, ClampedNumeric<Dst>(1) >> (IntegerBitsPlusSign<Dst>::value - 1U));
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) & 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) & 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) & 0);
- TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
- MakeClampedNum(DstLimits::max()) & -1);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 1);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) | 0);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) | 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) | 0);
- TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
- ClampedNumeric<Dst>(0) | static_cast<Dst>(-1));
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) ^ 1);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) ^ 0);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(0) ^ 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) ^ 0);
- TEST_EXPECTED_VALUE(std::numeric_limits<Dst>::max(),
- ClampedNumeric<Dst>(0) ^ static_cast<Dst>(-1));
- TEST_EXPECTED_VALUE(DstLimits::max(), ~ClampedNumeric<Dst>(0));
-
- TestStrictPointerMath<Dst>();
-}
-
-// Floating point arithmetic.
-template <typename Dst>
-void TestSpecializedArithmetic(
- const char* dst,
- int line,
- typename std::enable_if<numeric_limits<Dst>::is_iec559, int>::type = 0) {
- using DstLimits = SaturationDefaultLimits<Dst>;
- TEST_EXPECTED_SUCCESS(-CheckedNumeric<Dst>(DstLimits::lowest()));
-
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()).Abs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(-1).Abs());
-
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + -1);
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) + 1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) +
- DstLimits::lowest());
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) -
- DstLimits::lowest());
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) -
- DstLimits::max());
-
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::lowest()) * 2);
-
- TEST_EXPECTED_VALUE(-0.5, CheckedNumeric<Dst>(-1.0) / 2);
-
- TEST_EXPECTED_VALUE(DstLimits::max(),
- -ClampedNumeric<Dst>(DstLimits::lowest()));
-
- TEST_EXPECTED_VALUE(DstLimits::max(),
- ClampedNumeric<Dst>(DstLimits::lowest()).Abs());
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(-1).Abs());
-
- TEST_EXPECTED_VALUE(DstLimits::lowest() - 1,
- ClampedNumeric<Dst>(DstLimits::lowest()) + -1);
- TEST_EXPECTED_VALUE(DstLimits::max() + 1,
- ClampedNumeric<Dst>(DstLimits::max()) + 1);
- TEST_EXPECTED_VALUE(
- DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) + DstLimits::lowest());
-
- TEST_EXPECTED_VALUE(
- DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::max()) - DstLimits::lowest());
- TEST_EXPECTED_VALUE(
- DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) - DstLimits::max());
-
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::lowest()) * 2);
-
- TEST_EXPECTED_VALUE(-0.5, ClampedNumeric<Dst>(-1.0) / 2);
-}
-
-// Generic arithmetic tests.
-template <typename Dst>
-static void TestArithmetic(const char* dst, int line) {
- using DstLimits = SaturationDefaultLimits<Dst>;
-
- EXPECT_EQ(true, CheckedNumeric<Dst>().IsValid());
- EXPECT_EQ(false, CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
- DstLimits::max())
- .IsValid());
- EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDie());
- EXPECT_EQ(static_cast<Dst>(0), CheckedNumeric<Dst>().ValueOrDefault(1));
- EXPECT_EQ(static_cast<Dst>(1),
- CheckedNumeric<Dst>(CheckedNumeric<Dst>(DstLimits::max()) *
- DstLimits::max())
- .ValueOrDefault(1));
-
- // Test the operator combinations.
- TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(2, 1 + CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 - CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, 1 * CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, 1 / CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(2, CheckedNumeric<Dst>(1) + 1);
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>(1) - 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) * 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
- CheckedNumeric<Dst> checked_dst = 1;
- TEST_EXPECTED_VALUE(2, checked_dst += 1);
- checked_dst = 1;
- TEST_EXPECTED_VALUE(0, checked_dst -= 1);
- checked_dst = 1;
- TEST_EXPECTED_VALUE(1, checked_dst *= 1);
- checked_dst = 1;
- TEST_EXPECTED_VALUE(1, checked_dst /= 1);
-
- TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(2, 1 + ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(0, 1 - ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, 1 * ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, 1 / ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(2, ClampedNumeric<Dst>(1) + 1);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(1) - 1);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) * 1);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
- ClampedNumeric<Dst> clamped_dst = 1;
- TEST_EXPECTED_VALUE(2, clamped_dst += 1);
- clamped_dst = 1;
- TEST_EXPECTED_VALUE(0, clamped_dst -= 1);
- clamped_dst = 1;
- TEST_EXPECTED_VALUE(1, clamped_dst *= 1);
- clamped_dst = 1;
- TEST_EXPECTED_VALUE(1, clamped_dst /= 1);
-
- // Generic negation.
- if (DstLimits::is_signed) {
- TEST_EXPECTED_VALUE(0, -CheckedNumeric<Dst>());
- TEST_EXPECTED_VALUE(-1, -CheckedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, -CheckedNumeric<Dst>(-1));
- TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
- -CheckedNumeric<Dst>(DstLimits::max()));
-
- TEST_EXPECTED_VALUE(0, -ClampedNumeric<Dst>());
- TEST_EXPECTED_VALUE(-1, -ClampedNumeric<Dst>(1));
- TEST_EXPECTED_VALUE(1, -ClampedNumeric<Dst>(-1));
- TEST_EXPECTED_VALUE(static_cast<Dst>(DstLimits::max() * -1),
- -ClampedNumeric<Dst>(DstLimits::max()));
-
- // The runtime paths for saturated negation differ significantly from what
- // gets evaluated at compile-time. Making this test volatile forces the
- // compiler to generate code rather than fold constant expressions.
- volatile Dst value = Dst(0);
- TEST_EXPECTED_VALUE(0, -MakeClampedNum(value));
- value = Dst(1);
- TEST_EXPECTED_VALUE(-1, -MakeClampedNum(value));
- value = Dst(2);
- TEST_EXPECTED_VALUE(-2, -MakeClampedNum(value));
- value = Dst(-1);
- TEST_EXPECTED_VALUE(1, -MakeClampedNum(value));
- value = Dst(-2);
- TEST_EXPECTED_VALUE(2, -MakeClampedNum(value));
- value = DstLimits::max();
- TEST_EXPECTED_VALUE(Dst(DstLimits::max() * -1), -MakeClampedNum(value));
- value = Dst(-1 * DstLimits::max());
- TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
- value = DstLimits::lowest();
- TEST_EXPECTED_VALUE(DstLimits::max(), -MakeClampedNum(value));
- }
-
- // Generic absolute value.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>().Abs());
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1).Abs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- CheckedNumeric<Dst>(DstLimits::max()).Abs());
-
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>().Abs());
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1).Abs());
- TEST_EXPECTED_VALUE(DstLimits::max(),
- ClampedNumeric<Dst>(DstLimits::max()).Abs());
-
- // Generic addition.
- TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>() + 1));
- TEST_EXPECTED_VALUE(2, (CheckedNumeric<Dst>(1) + 1));
- if (numeric_limits<Dst>::is_signed)
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) + 1));
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::lowest()) + 1);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) +
- DstLimits::max());
-
- TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>() + 1));
- TEST_EXPECTED_VALUE(2, (ClampedNumeric<Dst>(1) + 1));
- if (numeric_limits<Dst>::is_signed)
- TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) + 1));
- TEST_EXPECTED_VALUE(DstLimits::lowest() + 1,
- ClampedNumeric<Dst>(DstLimits::lowest()) + 1);
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::max()) + DstLimits::max());
-
- // Generic subtraction.
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(1) - 1));
- TEST_EXPECTED_SUCCESS(CheckedNumeric<Dst>(DstLimits::max()) - 1);
- if (numeric_limits<Dst>::is_signed) {
- TEST_EXPECTED_VALUE(-1, (CheckedNumeric<Dst>() - 1));
- TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) - 1));
- } else {
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) - -1);
- }
-
- TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(1) - 1));
- TEST_EXPECTED_VALUE(DstLimits::max() - 1,
- ClampedNumeric<Dst>(DstLimits::max()) - 1);
- if (numeric_limits<Dst>::is_signed) {
- TEST_EXPECTED_VALUE(-1, (ClampedNumeric<Dst>() - 1));
- TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) - 1));
- } else {
- TEST_EXPECTED_VALUE(DstLimits::max(),
- ClampedNumeric<Dst>(DstLimits::max()) - -1);
- }
-
- // Generic multiplication.
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>() * 1));
- TEST_EXPECTED_VALUE(1, (CheckedNumeric<Dst>(1) * 1));
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * 0));
- if (numeric_limits<Dst>::is_signed) {
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(-1) * 0));
- TEST_EXPECTED_VALUE(0, (CheckedNumeric<Dst>(0) * -1));
- TEST_EXPECTED_VALUE(-2, (CheckedNumeric<Dst>(-1) * 2));
- } else {
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) * -2);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
- CheckedNumeric<uintmax_t>(-2));
- }
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(DstLimits::max()) *
- DstLimits::max());
-
- TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>() * 1));
- TEST_EXPECTED_VALUE(1, (ClampedNumeric<Dst>(1) * 1));
- TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * 0));
- if (numeric_limits<Dst>::is_signed) {
- TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(-1) * 0));
- TEST_EXPECTED_VALUE(0, (ClampedNumeric<Dst>(0) * -1));
- TEST_EXPECTED_VALUE(-2, (ClampedNumeric<Dst>(-1) * 2));
- } else {
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- ClampedNumeric<Dst>(DstLimits::max()) * -2);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(DstLimits::max()) *
- ClampedNumeric<uintmax_t>(-2));
- }
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- ClampedNumeric<Dst>(DstLimits::max()) * DstLimits::max());
-
- // Generic division.
- TEST_EXPECTED_VALUE(0, CheckedNumeric<Dst>() / 1);
- TEST_EXPECTED_VALUE(1, CheckedNumeric<Dst>(1) / 1);
- TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
- CheckedNumeric<Dst>(DstLimits::lowest()) / 2);
- TEST_EXPECTED_VALUE(DstLimits::max() / 2,
- CheckedNumeric<Dst>(DstLimits::max()) / 2);
- TEST_EXPECTED_FAILURE(CheckedNumeric<Dst>(1) / 0);
-
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>() / 1);
- TEST_EXPECTED_VALUE(1, ClampedNumeric<Dst>(1) / 1);
- TEST_EXPECTED_VALUE(DstLimits::lowest() / 2,
- ClampedNumeric<Dst>(DstLimits::lowest()) / 2);
- TEST_EXPECTED_VALUE(DstLimits::max() / 2,
- ClampedNumeric<Dst>(DstLimits::max()) / 2);
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), ClampedNumeric<Dst>(1) / 0);
- TEST_EXPECTED_VALUE(DstLimits::Underflow(), ClampedNumeric<Dst>(-1) / 0);
- TEST_EXPECTED_VALUE(0, ClampedNumeric<Dst>(0) / 0);
-
- TestSpecializedArithmetic<Dst>(dst, line);
-}
-
-// Helper macro to wrap displaying the conversion types and line numbers.
-#define TEST_ARITHMETIC(Dst) TestArithmetic<Dst>(#Dst, __LINE__)
-
-TEST(SafeNumerics, SignedIntegerMath) {
- TEST_ARITHMETIC(int8_t);
- TEST_ARITHMETIC(int16_t);
- TEST_ARITHMETIC(int);
- TEST_ARITHMETIC(intptr_t);
- TEST_ARITHMETIC(intmax_t);
-}
-
-TEST(SafeNumerics, UnsignedIntegerMath) {
- TEST_ARITHMETIC(uint8_t);
- TEST_ARITHMETIC(uint16_t);
- TEST_ARITHMETIC(unsigned int);
- TEST_ARITHMETIC(uintptr_t);
- TEST_ARITHMETIC(uintmax_t);
-}
-
-TEST(SafeNumerics, FloatingPointMath) {
- TEST_ARITHMETIC(float);
- TEST_ARITHMETIC(double);
-}
-
-// Enumerates the five different conversions types we need to test.
-enum NumericConversionType {
- SIGN_PRESERVING_VALUE_PRESERVING,
- SIGN_PRESERVING_NARROW,
- SIGN_TO_UNSIGN_WIDEN_OR_EQUAL,
- SIGN_TO_UNSIGN_NARROW,
- UNSIGN_TO_SIGN_NARROW_OR_EQUAL,
-};
-
-// Template covering the different conversion tests.
-template <typename Dst, typename Src, NumericConversionType conversion>
-struct TestNumericConversion {};
-
-enum RangeConstraint {
- RANGE_VALID = 0x0, // Value can be represented by the destination type.
- RANGE_UNDERFLOW = 0x1, // Value would underflow.
- RANGE_OVERFLOW = 0x2, // Value would overflow.
- RANGE_INVALID = RANGE_UNDERFLOW | RANGE_OVERFLOW // Invalid (i.e. NaN).
-};
-
-// These are some wrappers to make the tests a bit cleaner.
-constexpr RangeConstraint RangeCheckToEnum(const RangeCheck constraint) {
- return static_cast<RangeConstraint>(
- static_cast<int>(constraint.IsOverflowFlagSet()) << 1 |
- static_cast<int>(constraint.IsUnderflowFlagSet()));
-}
-
-// EXPECT_EQ wrappers providing specific detail on test failures.
-#define TEST_EXPECTED_RANGE(expected, actual) \
- EXPECT_EQ(expected, \
- RangeCheckToEnum(DstRangeRelationToSrcRange<Dst>(actual))) \
- << "Conversion test: " << src << " value " << actual << " to " << dst \
- << " on line " << line
-
-template <typename Dst, typename Src>
-void TestStrictComparison(const char* dst, const char* src, int line) {
- using DstLimits = numeric_limits<Dst>;
- using SrcLimits = numeric_limits<Src>;
- static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < DstLimits::max(), "");
- static_assert(StrictNumeric<Src>(SrcLimits::lowest()) < SrcLimits::max(), "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= DstLimits::max()),
- "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) >= SrcLimits::max()),
- "");
- static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= DstLimits::max(),
- "");
- static_assert(StrictNumeric<Src>(SrcLimits::lowest()) <= SrcLimits::max(),
- "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > DstLimits::max()),
- "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::lowest()) > SrcLimits::max()),
- "");
- static_assert(StrictNumeric<Src>(SrcLimits::max()) > DstLimits::lowest(), "");
- static_assert(StrictNumeric<Src>(SrcLimits::max()) > SrcLimits::lowest(), "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= DstLimits::lowest()),
- "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::max()) <= SrcLimits::lowest()),
- "");
- static_assert(StrictNumeric<Src>(SrcLimits::max()) >= DstLimits::lowest(),
- "");
- static_assert(StrictNumeric<Src>(SrcLimits::max()) >= SrcLimits::lowest(),
- "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < DstLimits::lowest()),
- "");
- static_assert(!(StrictNumeric<Src>(SrcLimits::max()) < SrcLimits::lowest()),
- "");
- static_assert(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(1),
- "");
- static_assert(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(0),
- "");
- static_assert(StrictNumeric<Src>(SrcLimits::max()) != static_cast<Dst>(0),
- "");
- static_assert(StrictNumeric<Src>(SrcLimits::max()) != DstLimits::lowest(),
- "");
- static_assert(
- !(StrictNumeric<Src>(static_cast<Src>(1)) != static_cast<Dst>(1)), "");
- static_assert(
- !(StrictNumeric<Src>(static_cast<Src>(1)) == static_cast<Dst>(0)), "");
-
- // Due to differences in float handling between compilers, these aren't
- // compile-time constants everywhere. So, we use run-time tests.
- EXPECT_EQ(
- SrcLimits::max(),
- MakeCheckedNum(SrcLimits::max()).Max(DstLimits::lowest()).ValueOrDie());
- EXPECT_EQ(
- DstLimits::max(),
- MakeCheckedNum(SrcLimits::lowest()).Max(DstLimits::max()).ValueOrDie());
- EXPECT_EQ(
- DstLimits::lowest(),
- MakeCheckedNum(SrcLimits::max()).Min(DstLimits::lowest()).ValueOrDie());
- EXPECT_EQ(
- SrcLimits::lowest(),
- MakeCheckedNum(SrcLimits::lowest()).Min(DstLimits::max()).ValueOrDie());
- EXPECT_EQ(SrcLimits::lowest(), CheckMin(MakeStrictNum(1), MakeCheckedNum(0),
- DstLimits::max(), SrcLimits::lowest())
- .ValueOrDie());
- EXPECT_EQ(DstLimits::max(), CheckMax(MakeStrictNum(1), MakeCheckedNum(0),
- DstLimits::max(), SrcLimits::lowest())
- .ValueOrDie());
-
- EXPECT_EQ(SrcLimits::max(),
- MakeClampedNum(SrcLimits::max()).Max(DstLimits::lowest()));
- EXPECT_EQ(DstLimits::max(),
- MakeClampedNum(SrcLimits::lowest()).Max(DstLimits::max()));
- EXPECT_EQ(DstLimits::lowest(),
- MakeClampedNum(SrcLimits::max()).Min(DstLimits::lowest()));
- EXPECT_EQ(SrcLimits::lowest(),
- MakeClampedNum(SrcLimits::lowest()).Min(DstLimits::max()));
- EXPECT_EQ(SrcLimits::lowest(),
- ClampMin(MakeStrictNum(1), MakeClampedNum(0), DstLimits::max(),
- SrcLimits::lowest()));
- EXPECT_EQ(DstLimits::max(), ClampMax(MakeStrictNum(1), MakeClampedNum(0),
- DstLimits::max(), SrcLimits::lowest()));
-
- if (IsValueInRangeForNumericType<Dst>(SrcLimits::max())) {
- TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), (CommonMax<Dst, Src>()));
- TEST_EXPECTED_VALUE(Dst(SrcLimits::max()),
- (CommonMaxOrMin<Dst, Src>(false)));
- } else {
- TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMax<Dst, Src>()));
- TEST_EXPECTED_VALUE(DstLimits::max(), (CommonMaxOrMin<Dst, Src>(false)));
- }
-
- if (IsValueInRangeForNumericType<Dst>(SrcLimits::lowest())) {
- TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()), (CommonMin<Dst, Src>()));
- TEST_EXPECTED_VALUE(Dst(SrcLimits::lowest()),
- (CommonMaxOrMin<Dst, Src>(true)));
- } else {
- TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMin<Dst, Src>()));
- TEST_EXPECTED_VALUE(DstLimits::lowest(), (CommonMaxOrMin<Dst, Src>(true)));
- }
-}
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_VALUE_PRESERVING> {
- static void Test(const char* dst, const char* src, int line) {
- using SrcLimits = SaturationDefaultLimits<Src>;
- using DstLimits = SaturationDefaultLimits<Dst>;
- // Integral to floating.
- static_assert((DstLimits::is_iec559 && SrcLimits::is_integer) ||
- // Not floating to integral and...
- (!(DstLimits::is_integer && SrcLimits::is_iec559) &&
- // Same sign, same numeric, source is narrower or same.
- ((SrcLimits::is_signed == DstLimits::is_signed &&
- MaxExponent<Dst>::value >= MaxExponent<Src>::value) ||
- // Or signed destination and source is smaller
- (DstLimits::is_signed &&
- MaxExponent<Dst>::value >= MaxExponent<Src>::value))),
- "Comparison must be sign preserving and value preserving");
-
- TestStrictComparison<Dst, Src>(dst, src, line);
-
- const CheckedNumeric<Dst> checked_dst = SrcLimits::max();
- const ClampedNumeric<Dst> clamped_dst = SrcLimits::max();
- TEST_EXPECTED_SUCCESS(checked_dst);
- TEST_EXPECTED_VALUE(Dst(SrcLimits::max()), clamped_dst);
- if (MaxExponent<Dst>::value > MaxExponent<Src>::value) {
- if (MaxExponent<Dst>::value >= MaxExponent<Src>::value * 2 - 1) {
- // At least twice larger type.
- TEST_EXPECTED_SUCCESS(SrcLimits::max() * checked_dst);
- TEST_EXPECTED_VALUE(SrcLimits::max() * clamped_dst,
- Dst(SrcLimits::max()) * SrcLimits::max());
- } else { // Larger, but not at least twice as large.
- TEST_EXPECTED_FAILURE(SrcLimits::max() * checked_dst);
- TEST_EXPECTED_SUCCESS(checked_dst + 1);
- TEST_EXPECTED_VALUE(DstLimits::Overflow(),
- SrcLimits::max() * clamped_dst);
- TEST_EXPECTED_VALUE(Dst(SrcLimits::max()) + Dst(1),
- clamped_dst + Dst(1));
- }
- } else { // Same width type.
- TEST_EXPECTED_FAILURE(checked_dst + 1);
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + Dst(1));
- }
-
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- if (SrcLimits::is_iec559) {
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max() * static_cast<Src>(-1));
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
- TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
- } else if (numeric_limits<Src>::is_signed) {
- // This block reverses the Src to Dst relationship so we don't have to
- // complicate the test macros.
- if (!std::is_same<Src, Dst>::value) {
- TEST_EXPECTED_SUCCESS(CheckDiv(SrcLimits::lowest(), Dst(-1)));
- }
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
- }
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_PRESERVING_NARROW> {
- static void Test(const char* dst, const char* src, int line) {
- using SrcLimits = SaturationDefaultLimits<Src>;
- using DstLimits = SaturationDefaultLimits<Dst>;
- static_assert(SrcLimits::is_signed == DstLimits::is_signed,
- "Destination and source sign must be the same");
- static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
- "Destination must be narrower than source");
-
- TestStrictComparison<Dst, Src>(dst, src, line);
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(1, checked_dst + Src(1));
- TEST_EXPECTED_FAILURE(checked_dst - SrcLimits::max());
-
- ClampedNumeric<Dst> clamped_dst;
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(1, clamped_dst + Src(1));
- TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst - SrcLimits::max());
- clamped_dst += SrcLimits::max();
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
- clamped_dst = DstLimits::max();
- clamped_dst += SrcLimits::max();
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
- clamped_dst = DstLimits::max();
- clamped_dst -= SrcLimits::max();
- TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
- clamped_dst = 0;
-
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- if (SrcLimits::is_iec559) {
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
- TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
- if (DstLimits::is_integer) {
- if (SrcLimits::digits < DstLimits::digits) {
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
- static_cast<Src>(DstLimits::max()));
- } else {
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
- }
- TEST_EXPECTED_RANGE(
- RANGE_VALID,
- static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
- }
- } else if (SrcLimits::is_signed) {
- TEST_EXPECTED_VALUE(-1, checked_dst - static_cast<Src>(1));
- TEST_EXPECTED_VALUE(-1, clamped_dst - static_cast<Src>(1));
- TEST_EXPECTED_VALUE(Src(Src(0) - DstLimits::lowest()),
- ClampDiv(DstLimits::lowest(), Src(-1)));
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(-1));
- } else {
- TEST_EXPECTED_FAILURE(checked_dst - static_cast<Src>(1));
- TEST_EXPECTED_VALUE(Dst(0), clamped_dst - static_cast<Src>(1));
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
- }
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL> {
- static void Test(const char* dst, const char* src, int line) {
- using SrcLimits = SaturationDefaultLimits<Src>;
- using DstLimits = SaturationDefaultLimits<Dst>;
- static_assert(MaxExponent<Dst>::value >= MaxExponent<Src>::value,
- "Destination must be equal or wider than source.");
- static_assert(SrcLimits::is_signed, "Source must be signed");
- static_assert(!DstLimits::is_signed, "Destination must be unsigned");
-
- TestStrictComparison<Dst, Src>(dst, src, line);
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_VALUE(SrcLimits::max(), checked_dst + SrcLimits::max());
- TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
- TEST_EXPECTED_SUCCESS(checked_dst * static_cast<Src>(-1));
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
- TEST_EXPECTED_VALUE(Dst(0), CheckDiv(Dst(0), Src(-1)));
-
- const ClampedNumeric<Dst> clamped_dst;
- TEST_EXPECTED_VALUE(SrcLimits::max(), clamped_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- clamped_dst + static_cast<Src>(-1));
- TEST_EXPECTED_VALUE(0, clamped_dst * static_cast<Src>(-1));
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- clamped_dst + SrcLimits::lowest());
-
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, SIGN_TO_UNSIGN_NARROW> {
- static void Test(const char* dst, const char* src, int line) {
- using SrcLimits = SaturationDefaultLimits<Src>;
- using DstLimits = SaturationDefaultLimits<Dst>;
- static_assert(MaxExponent<Dst>::value < MaxExponent<Src>::value,
- "Destination must be narrower than source.");
- static_assert(SrcLimits::is_signed, "Source must be signed.");
- static_assert(!DstLimits::is_signed, "Destination must be unsigned.");
-
- TestStrictComparison<Dst, Src>(dst, src, line);
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
- TEST_EXPECTED_FAILURE(checked_dst + static_cast<Src>(-1));
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::lowest());
-
- ClampedNumeric<Dst> clamped_dst;
- TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- clamped_dst + static_cast<Src>(-1));
- TEST_EXPECTED_VALUE(DstLimits::Underflow(),
- clamped_dst + SrcLimits::lowest());
- clamped_dst += SrcLimits::max();
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
- clamped_dst = DstLimits::max();
- clamped_dst += SrcLimits::max();
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst);
- clamped_dst = DstLimits::max();
- clamped_dst -= SrcLimits::max();
- TEST_EXPECTED_VALUE(DstLimits::Underflow(), clamped_dst);
- clamped_dst = 0;
-
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, static_cast<Src>(-1));
-
- // Additional saturation tests.
- EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
- EXPECT_EQ(DstLimits::lowest(), saturated_cast<Dst>(SrcLimits::lowest()));
-
- if (SrcLimits::is_iec559) {
- EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::quiet_NaN()));
-
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::max() * -1);
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::infinity());
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::infinity() * -1);
- TEST_EXPECTED_RANGE(RANGE_INVALID, SrcLimits::quiet_NaN());
- if (DstLimits::is_integer) {
- if (SrcLimits::digits < DstLimits::digits) {
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW,
- static_cast<Src>(DstLimits::max()));
- } else {
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::max()));
- }
- TEST_EXPECTED_RANGE(
- RANGE_VALID,
- static_cast<Src>(GetMaxConvertibleToFloat<Src, Dst>()));
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(DstLimits::lowest()));
- }
- } else {
- TEST_EXPECTED_RANGE(RANGE_UNDERFLOW, SrcLimits::lowest());
- }
- }
-};
-
-template <typename Dst, typename Src>
-struct TestNumericConversion<Dst, Src, UNSIGN_TO_SIGN_NARROW_OR_EQUAL> {
- static void Test(const char* dst, const char* src, int line) {
- using SrcLimits = SaturationDefaultLimits<Src>;
- using DstLimits = SaturationDefaultLimits<Dst>;
- static_assert(MaxExponent<Dst>::value <= MaxExponent<Src>::value,
- "Destination must be narrower or equal to source.");
- static_assert(!SrcLimits::is_signed, "Source must be unsigned.");
- static_assert(DstLimits::is_signed, "Destination must be signed.");
-
- TestStrictComparison<Dst, Src>(dst, src, line);
-
- const CheckedNumeric<Dst> checked_dst;
- TEST_EXPECTED_VALUE(1, checked_dst + static_cast<Src>(1));
- TEST_EXPECTED_FAILURE(checked_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(SrcLimits::lowest(), checked_dst + SrcLimits::lowest());
-
- const ClampedNumeric<Dst> clamped_dst;
- TEST_EXPECTED_VALUE(1, clamped_dst + static_cast<Src>(1));
- TEST_EXPECTED_VALUE(DstLimits::Overflow(), clamped_dst + SrcLimits::max());
- TEST_EXPECTED_VALUE(SrcLimits::lowest(), clamped_dst + SrcLimits::lowest());
-
- TEST_EXPECTED_RANGE(RANGE_VALID, SrcLimits::lowest());
- TEST_EXPECTED_RANGE(RANGE_OVERFLOW, SrcLimits::max());
- TEST_EXPECTED_RANGE(RANGE_VALID, static_cast<Src>(1));
-
- // Additional saturation tests.
- EXPECT_EQ(DstLimits::max(), saturated_cast<Dst>(SrcLimits::max()));
- EXPECT_EQ(Dst(0), saturated_cast<Dst>(SrcLimits::lowest()));
- }
-};
-
-// Helper macro to wrap displaying the conversion types and line numbers
-#define TEST_NUMERIC_CONVERSION(d, s, t) \
- TestNumericConversion<d, s, t>::Test(#d, #s, __LINE__)
-
-TEST(SafeNumerics, IntMinOperations) {
- TEST_NUMERIC_CONVERSION(int8_t, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(uint8_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(int8_t, int16_t, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int8_t, int, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, uint16_t, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, unsigned int, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int8_t, float, SIGN_PRESERVING_NARROW);
-
- TEST_NUMERIC_CONVERSION(uint8_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
-
- TEST_NUMERIC_CONVERSION(uint8_t, int16_t, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, int, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uint8_t, float, SIGN_TO_UNSIGN_NARROW);
-
- TEST_NUMERIC_CONVERSION(int8_t, uint16_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int8_t, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int8_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, Int16Operations) {
- TEST_NUMERIC_CONVERSION(int16_t, int16_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(uint16_t, uint16_t, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(int16_t, int, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(uint16_t, unsigned int, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int16_t, float, SIGN_PRESERVING_NARROW);
-
- TEST_NUMERIC_CONVERSION(uint16_t, int16_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
-
- TEST_NUMERIC_CONVERSION(uint16_t, int, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uint16_t, intmax_t, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uint16_t, float, SIGN_TO_UNSIGN_NARROW);
-
- TEST_NUMERIC_CONVERSION(int16_t, unsigned int,
- UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int16_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, IntOperations) {
- TEST_NUMERIC_CONVERSION(int, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(unsigned int, unsigned int,
- SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(int, int8_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(unsigned int, uint8_t,
- SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(int, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(int, intmax_t, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(unsigned int, uintmax_t, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int, float, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(int, double, SIGN_PRESERVING_NARROW);
-
- TEST_NUMERIC_CONVERSION(unsigned int, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(unsigned int, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
-
- TEST_NUMERIC_CONVERSION(unsigned int, intmax_t, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(unsigned int, float, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(unsigned int, double, SIGN_TO_UNSIGN_NARROW);
-
- TEST_NUMERIC_CONVERSION(int, unsigned int, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, IntMaxOperations) {
- TEST_NUMERIC_CONVERSION(intmax_t, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(uintmax_t, uintmax_t,
- SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(intmax_t, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(uintmax_t, unsigned int,
- SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(intmax_t, unsigned int,
- SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(intmax_t, uint8_t, SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(intmax_t, float, SIGN_PRESERVING_NARROW);
- TEST_NUMERIC_CONVERSION(intmax_t, double, SIGN_PRESERVING_NARROW);
-
- TEST_NUMERIC_CONVERSION(uintmax_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(uintmax_t, int8_t, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
-
- TEST_NUMERIC_CONVERSION(uintmax_t, float, SIGN_TO_UNSIGN_NARROW);
- TEST_NUMERIC_CONVERSION(uintmax_t, double, SIGN_TO_UNSIGN_NARROW);
-
- TEST_NUMERIC_CONVERSION(intmax_t, uintmax_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-TEST(SafeNumerics, FloatOperations) {
- TEST_NUMERIC_CONVERSION(float, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(float, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(float, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(float, unsigned int,
- SIGN_PRESERVING_VALUE_PRESERVING);
-
- TEST_NUMERIC_CONVERSION(float, double, SIGN_PRESERVING_NARROW);
-}
-
-TEST(SafeNumerics, DoubleOperations) {
- TEST_NUMERIC_CONVERSION(double, intmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(double, uintmax_t, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(double, int, SIGN_PRESERVING_VALUE_PRESERVING);
- TEST_NUMERIC_CONVERSION(double, unsigned int,
- SIGN_PRESERVING_VALUE_PRESERVING);
-}
-
-TEST(SafeNumerics, SizeTOperations) {
- TEST_NUMERIC_CONVERSION(size_t, int, SIGN_TO_UNSIGN_WIDEN_OR_EQUAL);
- TEST_NUMERIC_CONVERSION(int, size_t, UNSIGN_TO_SIGN_NARROW_OR_EQUAL);
-}
-
-// A one-off test to ensure StrictNumeric won't resolve to an incorrect type.
-// If this fails we'll just get a compiler error on an ambiguous overload.
-int TestOverload(int) { // Overload fails.
- return 0;
-}
-uint8_t TestOverload(uint8_t) { // Overload fails.
- return 0;
-}
-size_t TestOverload(size_t) { // Overload succeeds.
- return 0;
-}
-
-static_assert(
- std::is_same<decltype(TestOverload(StrictNumeric<int>())), int>::value,
- "");
-static_assert(std::is_same<decltype(TestOverload(StrictNumeric<size_t>())),
- size_t>::value,
- "");
-
-template <typename T>
-struct CastTest1 {
- static constexpr T NaN() { return -1; }
- static constexpr T max() { return numeric_limits<T>::max() - 1; }
- static constexpr T Overflow() { return max(); }
- static constexpr T lowest() { return numeric_limits<T>::lowest() + 1; }
- static constexpr T Underflow() { return lowest(); }
-};
-
-template <typename T>
-struct CastTest2 {
- static constexpr T NaN() { return 11; }
- static constexpr T max() { return 10; }
- static constexpr T Overflow() { return max(); }
- static constexpr T lowest() { return 1; }
- static constexpr T Underflow() { return lowest(); }
-};
-
-TEST(SafeNumerics, CastTests) {
-// MSVC catches and warns that we're forcing saturation in these tests.
-// Since that's intentional, we need to shut this warning off.
-#if defined(COMPILER_MSVC)
-#pragma warning(disable : 4756)
-#endif
-
- int small_positive = 1;
- int small_negative = -1;
- double double_small = 1.0;
- double double_large = numeric_limits<double>::max();
- double double_infinity = numeric_limits<float>::infinity();
- double double_large_int = numeric_limits<int>::max();
- double double_small_int = numeric_limits<int>::lowest();
-
- // Just test that the casts compile, since the other tests cover logic.
- EXPECT_EQ(0, checked_cast<int>(static_cast<size_t>(0)));
- EXPECT_EQ(0, strict_cast<int>(static_cast<char>(0)));
- EXPECT_EQ(0, strict_cast<int>(static_cast<unsigned char>(0)));
- EXPECT_EQ(0U, strict_cast<unsigned>(static_cast<unsigned char>(0)));
- EXPECT_EQ(1ULL, static_cast<uint64_t>(StrictNumeric<size_t>(1U)));
- EXPECT_EQ(1ULL, static_cast<uint64_t>(SizeT(1U)));
- EXPECT_EQ(1U, static_cast<size_t>(StrictNumeric<unsigned>(1U)));
-
- EXPECT_TRUE(CheckedNumeric<uint64_t>(StrictNumeric<unsigned>(1U)).IsValid());
- EXPECT_TRUE(CheckedNumeric<int>(StrictNumeric<unsigned>(1U)).IsValid());
- EXPECT_FALSE(CheckedNumeric<unsigned>(StrictNumeric<int>(-1)).IsValid());
-
- EXPECT_TRUE(IsValueNegative(-1));
- EXPECT_TRUE(IsValueNegative(numeric_limits<int>::lowest()));
- EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::lowest()));
- EXPECT_TRUE(IsValueNegative(numeric_limits<double>::lowest()));
- EXPECT_FALSE(IsValueNegative(0));
- EXPECT_FALSE(IsValueNegative(1));
- EXPECT_FALSE(IsValueNegative(0u));
- EXPECT_FALSE(IsValueNegative(1u));
- EXPECT_FALSE(IsValueNegative(numeric_limits<int>::max()));
- EXPECT_FALSE(IsValueNegative(numeric_limits<unsigned>::max()));
- EXPECT_FALSE(IsValueNegative(numeric_limits<double>::max()));
-
- // These casts and coercions will fail to compile:
- // EXPECT_EQ(0, strict_cast<int>(static_cast<size_t>(0)));
- // EXPECT_EQ(0, strict_cast<size_t>(static_cast<int>(0)));
- // EXPECT_EQ(1ULL, StrictNumeric<size_t>(1));
- // EXPECT_EQ(1, StrictNumeric<size_t>(1U));
-
- // Test various saturation corner cases.
- EXPECT_EQ(saturated_cast<int>(small_negative),
- static_cast<int>(small_negative));
- EXPECT_EQ(saturated_cast<int>(small_positive),
- static_cast<int>(small_positive));
- EXPECT_EQ(saturated_cast<unsigned>(small_negative), static_cast<unsigned>(0));
- EXPECT_EQ(saturated_cast<int>(double_small), static_cast<int>(double_small));
- EXPECT_EQ(saturated_cast<int>(double_large), numeric_limits<int>::max());
- EXPECT_EQ(saturated_cast<float>(double_large), double_infinity);
- EXPECT_EQ(saturated_cast<float>(-double_large), -double_infinity);
- EXPECT_EQ(numeric_limits<int>::lowest(),
- saturated_cast<int>(double_small_int));
- EXPECT_EQ(numeric_limits<int>::max(), saturated_cast<int>(double_large_int));
-
- // Test the saturated cast overrides.
- using FloatLimits = numeric_limits<float>;
- using IntLimits = numeric_limits<int>;
- EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(FloatLimits::quiet_NaN())));
- EXPECT_EQ(CastTest1<int>::max(),
- (saturated_cast<int, CastTest1>(FloatLimits::infinity())));
- EXPECT_EQ(CastTest1<int>::max(),
- (saturated_cast<int, CastTest1>(FloatLimits::max())));
- EXPECT_EQ(CastTest1<int>::max(),
- (saturated_cast<int, CastTest1>(float(IntLimits::max()))));
- EXPECT_EQ(CastTest1<int>::lowest(),
- (saturated_cast<int, CastTest1>(-FloatLimits::infinity())));
- EXPECT_EQ(CastTest1<int>::lowest(),
- (saturated_cast<int, CastTest1>(FloatLimits::lowest())));
- EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0.0)));
- EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1.0)));
- EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1.0)));
- EXPECT_EQ(0, (saturated_cast<int, CastTest1>(0)));
- EXPECT_EQ(1, (saturated_cast<int, CastTest1>(1)));
- EXPECT_EQ(-1, (saturated_cast<int, CastTest1>(-1)));
- EXPECT_EQ(CastTest1<int>::lowest(),
- (saturated_cast<int, CastTest1>(float(IntLimits::lowest()))));
- EXPECT_EQ(11, (saturated_cast<int, CastTest2>(FloatLimits::quiet_NaN())));
- EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::infinity())));
- EXPECT_EQ(10, (saturated_cast<int, CastTest2>(FloatLimits::max())));
- EXPECT_EQ(1, (saturated_cast<int, CastTest2>(-FloatLimits::infinity())));
- EXPECT_EQ(1, (saturated_cast<int, CastTest2>(FloatLimits::lowest())));
- EXPECT_EQ(1, (saturated_cast<int, CastTest2>(0U)));
-
- float not_a_number = std::numeric_limits<float>::infinity() -
- std::numeric_limits<float>::infinity();
- EXPECT_TRUE(std::isnan(not_a_number));
- EXPECT_EQ(0, saturated_cast<int>(not_a_number));
-
- // Test the CheckedNumeric value extractions functions.
- auto int8_min = MakeCheckedNum(numeric_limits<int8_t>::lowest());
- auto int8_max = MakeCheckedNum(numeric_limits<int8_t>::max());
- auto double_max = MakeCheckedNum(numeric_limits<double>::max());
- static_assert(
- std::is_same<int16_t,
- decltype(int8_min.ValueOrDie<int16_t>())::type>::value,
- "ValueOrDie returning incorrect type.");
- static_assert(
- std::is_same<int16_t,
- decltype(int8_min.ValueOrDefault<int16_t>(0))::type>::value,
- "ValueOrDefault returning incorrect type.");
- EXPECT_FALSE(IsValidForType<uint8_t>(int8_min));
- EXPECT_TRUE(IsValidForType<uint8_t>(int8_max));
- EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::lowest()),
- ValueOrDieForType<int>(int8_min));
- EXPECT_TRUE(IsValidForType<uint32_t>(int8_max));
- EXPECT_EQ(static_cast<int>(numeric_limits<int8_t>::max()),
- ValueOrDieForType<int>(int8_max));
- EXPECT_EQ(0, ValueOrDefaultForType<int>(double_max, 0));
- uint8_t uint8_dest = 0;
- int16_t int16_dest = 0;
- double double_dest = 0;
- EXPECT_TRUE(int8_max.AssignIfValid(&uint8_dest));
- EXPECT_EQ(static_cast<uint8_t>(numeric_limits<int8_t>::max()), uint8_dest);
- EXPECT_FALSE(int8_min.AssignIfValid(&uint8_dest));
- EXPECT_TRUE(int8_max.AssignIfValid(&int16_dest));
- EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::max()), int16_dest);
- EXPECT_TRUE(int8_min.AssignIfValid(&int16_dest));
- EXPECT_EQ(static_cast<int16_t>(numeric_limits<int8_t>::lowest()), int16_dest);
- EXPECT_FALSE(double_max.AssignIfValid(&uint8_dest));
- EXPECT_FALSE(double_max.AssignIfValid(&int16_dest));
- EXPECT_TRUE(double_max.AssignIfValid(&double_dest));
- EXPECT_EQ(numeric_limits<double>::max(), double_dest);
- EXPECT_EQ(1, checked_cast<int>(StrictNumeric<int>(1)));
- EXPECT_EQ(1, saturated_cast<int>(StrictNumeric<int>(1)));
- EXPECT_EQ(1, strict_cast<int>(StrictNumeric<int>(1)));
-
- enum class EnumTest { kOne = 1 };
- EXPECT_EQ(1, checked_cast<int>(EnumTest::kOne));
- EXPECT_EQ(1, saturated_cast<int>(EnumTest::kOne));
- EXPECT_EQ(1, strict_cast<int>(EnumTest::kOne));
-}
-
-TEST(SafeNumerics, IsValueInRangeForNumericType) {
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(2));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(0xffffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0xffffffff)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000000)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(UINT64_C(0x100000001)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
- std::numeric_limits<int32_t>::lowest()));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint32_t>(
- std::numeric_limits<int64_t>::lowest()));
-
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(2));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffff));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(0x7fffffffu));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0x80000000u));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(0xffffffffu));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x80000000)));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0xffffffff)));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(INT64_C(0x100000000)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
- std::numeric_limits<int32_t>::lowest()));
- EXPECT_TRUE(IsValueInRangeForNumericType<int32_t>(
- static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
- static_cast<int64_t>(std::numeric_limits<int32_t>::lowest()) - 1));
- EXPECT_FALSE(IsValueInRangeForNumericType<int32_t>(
- std::numeric_limits<int64_t>::lowest()));
-
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(2));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(0xffffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0xffffffff)));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000000)));
- EXPECT_TRUE(IsValueInRangeForNumericType<uint64_t>(UINT64_C(0x100000001)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
- std::numeric_limits<int32_t>::lowest()));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(INT64_C(-1)));
- EXPECT_FALSE(IsValueInRangeForNumericType<uint64_t>(
- std::numeric_limits<int64_t>::lowest()));
-
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(2));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(-1));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffff));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x7fffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0x80000000u));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(0xffffffffu));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x80000000)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0xffffffff)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(INT64_C(0x100000000)));
- EXPECT_TRUE(
- IsValueInRangeForNumericType<int64_t>(INT64_C(0x7fffffffffffffff)));
- EXPECT_TRUE(
- IsValueInRangeForNumericType<int64_t>(UINT64_C(0x7fffffffffffffff)));
- EXPECT_FALSE(
- IsValueInRangeForNumericType<int64_t>(UINT64_C(0x8000000000000000)));
- EXPECT_FALSE(
- IsValueInRangeForNumericType<int64_t>(UINT64_C(0xffffffffffffffff)));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
- std::numeric_limits<int32_t>::lowest()));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
- static_cast<int64_t>(std::numeric_limits<int32_t>::lowest())));
- EXPECT_TRUE(IsValueInRangeForNumericType<int64_t>(
- std::numeric_limits<int64_t>::lowest()));
-}
-
-TEST(SafeNumerics, CompoundNumericOperations) {
- CheckedNumeric<int> a = 1;
- CheckedNumeric<int> b = 2;
- CheckedNumeric<int> c = 3;
- CheckedNumeric<int> d = 4;
- a += b;
- EXPECT_EQ(3, a.ValueOrDie());
- a -= c;
- EXPECT_EQ(0, a.ValueOrDie());
- d /= b;
- EXPECT_EQ(2, d.ValueOrDie());
- d *= d;
- EXPECT_EQ(4, d.ValueOrDie());
-
- CheckedNumeric<int> too_large = std::numeric_limits<int>::max();
- EXPECT_TRUE(too_large.IsValid());
- too_large += d;
- EXPECT_FALSE(too_large.IsValid());
- too_large -= d;
- EXPECT_FALSE(too_large.IsValid());
- too_large /= d;
- EXPECT_FALSE(too_large.IsValid());
-}
-
-TEST(SafeNumerics, VariadicNumericOperations) {
- { // Synthetic scope to avoid variable naming collisions.
- auto a = CheckAdd(1, 2UL, MakeCheckedNum(3LL), 4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
- auto b = CheckSub(MakeCheckedNum(20.0), 2UL, 4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
- auto c = CheckMul(20.0, MakeCheckedNum(1), 5, 3UL).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
- auto d = CheckDiv(20.0, 2.0, MakeCheckedNum(5LL), -4).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
- auto e = CheckMod(MakeCheckedNum(20), 3).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
- auto f = CheckLsh(1, MakeCheckedNum(2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
- auto g = CheckRsh(4, MakeCheckedNum(2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
- auto h = CheckRsh(CheckAdd(1, 1, 1, 1), CheckSub(4, 2)).ValueOrDie();
- EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
- }
-
- {
- auto a = ClampAdd(1, 2UL, MakeClampedNum(3LL), 4);
- EXPECT_EQ(static_cast<decltype(a)::type>(10), a);
- auto b = ClampSub(MakeClampedNum(20.0), 2UL, 4);
- EXPECT_EQ(static_cast<decltype(b)::type>(14.0), b);
- auto c = ClampMul(20.0, MakeClampedNum(1), 5, 3UL);
- EXPECT_EQ(static_cast<decltype(c)::type>(300.0), c);
- auto d = ClampDiv(20.0, 2.0, MakeClampedNum(5LL), -4);
- EXPECT_EQ(static_cast<decltype(d)::type>(-.5), d);
- auto e = ClampMod(MakeClampedNum(20), 3);
- EXPECT_EQ(static_cast<decltype(e)::type>(2), e);
- auto f = ClampLsh(1, MakeClampedNum(2U));
- EXPECT_EQ(static_cast<decltype(f)::type>(4), f);
- auto g = ClampRsh(4, MakeClampedNum(2U));
- EXPECT_EQ(static_cast<decltype(g)::type>(1), g);
- auto h = ClampRsh(ClampAdd(1, 1, 1, 1), ClampSub(4U, 2));
- EXPECT_EQ(static_cast<decltype(h)::type>(1), h);
- }
-}
-
-#if defined(__clang__)
-#pragma clang diagnostic pop // -Winteger-overflow
-#endif
-
-} // namespace internal
-} // namespace base
diff --git a/base/scoped_native_library_unittest.cc b/base/scoped_native_library_unittest.cc
deleted file mode 100644
index 763b45f6c3..0000000000
--- a/base/scoped_native_library_unittest.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2011 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/scoped_native_library.h"
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include "base/files/file_path.h"
-#include "base/strings/utf_string_conversions.h"
-#endif
-
-namespace base {
-
-// Tests whether or not a function pointer retrieved via ScopedNativeLibrary
-// is available only in a scope.
-TEST(ScopedNativeLibrary, Basic) {
-#if defined(OS_WIN)
- // Get the pointer to DirectDrawCreate() from "ddraw.dll" and verify it
- // is valid only in this scope.
- // FreeLibrary() doesn't actually unload a DLL until its reference count
- // becomes zero, i.e. function pointer is still valid if the DLL used
- // in this test is also used by another part of this executable.
- // So, this test uses "ddraw.dll", which is not used by Chrome at all but
- // installed on all versions of Windows.
- const char kFunctionName[] = "DirectDrawCreate";
- NativeLibrary native_library;
- {
- FilePath path(FilePath::FromUTF8Unsafe(GetNativeLibraryName("ddraw")));
- native_library = LoadNativeLibrary(path, nullptr);
- ScopedNativeLibrary library(native_library);
- EXPECT_TRUE(library.is_valid());
- EXPECT_EQ(native_library, library.get());
- FARPROC test_function =
- reinterpret_cast<FARPROC>(library.GetFunctionPointer(kFunctionName));
- EXPECT_EQ(0, IsBadCodePtr(test_function));
- EXPECT_EQ(
- GetFunctionPointerFromNativeLibrary(native_library, kFunctionName),
- test_function);
- }
- EXPECT_FALSE(
- GetFunctionPointerFromNativeLibrary(native_library, kFunctionName));
-#endif
-}
-
-} // namespace base
diff --git a/base/sequenced_task_runner_unittest.cc b/base/sequenced_task_runner_unittest.cc
deleted file mode 100644
index 4dcc7e5a30..0000000000
--- a/base/sequenced_task_runner_unittest.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2016 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/sequenced_task_runner.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/gtest_prod_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class FlagOnDelete {
- public:
- FlagOnDelete(bool* deleted,
- scoped_refptr<SequencedTaskRunner> expected_deletion_sequence)
- : deleted_(deleted),
- expected_deletion_sequence_(std::move(expected_deletion_sequence)) {}
-
- private:
- friend class DeleteHelper<FlagOnDelete>;
- FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerTest,
- OnTaskRunnerDeleterTargetStoppedEarly);
-
- ~FlagOnDelete() {
- EXPECT_FALSE(*deleted_);
- *deleted_ = true;
- if (expected_deletion_sequence_)
- EXPECT_TRUE(expected_deletion_sequence_->RunsTasksInCurrentSequence());
- }
-
- bool* deleted_;
- const scoped_refptr<SequencedTaskRunner> expected_deletion_sequence_;
-
- DISALLOW_COPY_AND_ASSIGN(FlagOnDelete);
-};
-
-class SequencedTaskRunnerTest : public testing::Test {
- protected:
- SequencedTaskRunnerTest() : foreign_thread_("foreign") {}
-
- void SetUp() override {
- main_runner_ = message_loop_.task_runner();
-
- foreign_thread_.Start();
- foreign_runner_ = foreign_thread_.task_runner();
- }
-
- scoped_refptr<SequencedTaskRunner> main_runner_;
- scoped_refptr<SequencedTaskRunner> foreign_runner_;
-
- Thread foreign_thread_;
-
- private:
- MessageLoop message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(SequencedTaskRunnerTest);
-};
-
-using SequenceBoundUniquePtr =
- std::unique_ptr<FlagOnDelete, OnTaskRunnerDeleter>;
-
-TEST_F(SequencedTaskRunnerTest, OnTaskRunnerDeleterOnMainThread) {
- bool deleted_on_main_thread = false;
- SequenceBoundUniquePtr ptr(
- new FlagOnDelete(&deleted_on_main_thread, main_runner_),
- OnTaskRunnerDeleter(main_runner_));
- EXPECT_FALSE(deleted_on_main_thread);
- foreign_runner_->PostTask(
- FROM_HERE, BindOnce([](SequenceBoundUniquePtr) {}, std::move(ptr)));
-
- {
- RunLoop run_loop;
- foreign_runner_->PostTaskAndReply(FROM_HERE, BindOnce([] {}),
- run_loop.QuitClosure());
- run_loop.Run();
- }
- EXPECT_TRUE(deleted_on_main_thread);
-}
-
-TEST_F(SequencedTaskRunnerTest, OnTaskRunnerDeleterTargetStoppedEarly) {
- bool deleted_on_main_thread = false;
- FlagOnDelete* raw = new FlagOnDelete(&deleted_on_main_thread, main_runner_);
- SequenceBoundUniquePtr ptr(raw, OnTaskRunnerDeleter(foreign_runner_));
- EXPECT_FALSE(deleted_on_main_thread);
-
- // Stopping the target ahead of deleting |ptr| should make its
- // OnTaskRunnerDeleter no-op.
- foreign_thread_.Stop();
- ptr = nullptr;
- EXPECT_FALSE(deleted_on_main_thread);
-
- delete raw;
- EXPECT_TRUE(deleted_on_main_thread);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/strings/latin1_string_conversions.cc b/base/strings/latin1_string_conversions.cc
deleted file mode 100644
index dca62ced53..0000000000
--- a/base/strings/latin1_string_conversions.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2013 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/strings/latin1_string_conversions.h"
-
-namespace base {
-
-string16 Latin1OrUTF16ToUTF16(size_t length,
- const Latin1Char* latin1,
- const char16* utf16) {
- if (!length)
- return string16();
- if (latin1)
- return string16(latin1, latin1 + length);
- return string16(utf16, utf16 + length);
-}
-
-} // namespace base
diff --git a/base/strings/latin1_string_conversions.h b/base/strings/latin1_string_conversions.h
deleted file mode 100644
index 42113ef612..0000000000
--- a/base/strings/latin1_string_conversions.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_STRINGS_LATIN1_STRING_CONVERSIONS_H_
-#define BASE_STRINGS_LATIN1_STRING_CONVERSIONS_H_
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/strings/string16.h"
-
-namespace base {
-
-// This definition of Latin1Char matches the definition of LChar in Blink. We
-// use unsigned char rather than char to make less tempting to mix and match
-// Latin-1 and UTF-8 characters..
-typedef unsigned char Latin1Char;
-
-// This somewhat odd function is designed to help us convert from Blink Strings
-// to string16. A Blink string is either backed by an array of Latin-1
-// characters or an array of UTF-16 characters. This function is called by
-// WebString::operator string16() to convert one or the other character array
-// to string16. This function is defined here rather than in WebString.h to
-// avoid binary bloat in all the callers of the conversion operator.
-BASE_EXPORT string16 Latin1OrUTF16ToUTF16(size_t length,
- const Latin1Char* latin1,
- const char16* utf16);
-
-} // namespace base
-
-#endif // BASE_STRINGS_LATIN1_STRING_CONVERSIONS_H_
diff --git a/base/strings/utf_offset_string_conversions.cc b/base/strings/utf_offset_string_conversions.cc
deleted file mode 100644
index b91ee03832..0000000000
--- a/base/strings/utf_offset_string_conversions.cc
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright (c) 2011 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/strings/utf_offset_string_conversions.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <memory>
-
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_string_conversion_utils.h"
-
-namespace base {
-
-OffsetAdjuster::Adjustment::Adjustment(size_t original_offset,
- size_t original_length,
- size_t output_length)
- : original_offset(original_offset),
- original_length(original_length),
- output_length(output_length) {
-}
-
-// static
-void OffsetAdjuster::AdjustOffsets(const Adjustments& adjustments,
- std::vector<size_t>* offsets_for_adjustment,
- size_t limit) {
- DCHECK(offsets_for_adjustment);
- for (std::vector<size_t>::iterator i(offsets_for_adjustment->begin());
- i != offsets_for_adjustment->end(); ++i)
- AdjustOffset(adjustments, &(*i), limit);
-}
-
-// static
-void OffsetAdjuster::AdjustOffset(const Adjustments& adjustments,
- size_t* offset,
- size_t limit) {
- DCHECK(offset);
- if (*offset == string16::npos)
- return;
- int adjustment = 0;
- for (Adjustments::const_iterator i = adjustments.begin();
- i != adjustments.end(); ++i) {
- if (*offset <= i->original_offset)
- break;
- if (*offset < (i->original_offset + i->original_length)) {
- *offset = string16::npos;
- return;
- }
- adjustment += static_cast<int>(i->original_length - i->output_length);
- }
- *offset -= adjustment;
-
- if (*offset > limit)
- *offset = string16::npos;
-}
-
-// static
-void OffsetAdjuster::UnadjustOffsets(
- const Adjustments& adjustments,
- std::vector<size_t>* offsets_for_unadjustment) {
- if (!offsets_for_unadjustment || adjustments.empty())
- return;
- for (std::vector<size_t>::iterator i(offsets_for_unadjustment->begin());
- i != offsets_for_unadjustment->end(); ++i)
- UnadjustOffset(adjustments, &(*i));
-}
-
-// static
-void OffsetAdjuster::UnadjustOffset(const Adjustments& adjustments,
- size_t* offset) {
- if (*offset == string16::npos)
- return;
- int adjustment = 0;
- for (Adjustments::const_iterator i = adjustments.begin();
- i != adjustments.end(); ++i) {
- if (*offset + adjustment <= i->original_offset)
- break;
- adjustment += static_cast<int>(i->original_length - i->output_length);
- if ((*offset + adjustment) <
- (i->original_offset + i->original_length)) {
- *offset = string16::npos;
- return;
- }
- }
- *offset += adjustment;
-}
-
-// static
-void OffsetAdjuster::MergeSequentialAdjustments(
- const Adjustments& first_adjustments,
- Adjustments* adjustments_on_adjusted_string) {
- Adjustments::iterator adjusted_iter = adjustments_on_adjusted_string->begin();
- Adjustments::const_iterator first_iter = first_adjustments.begin();
- // Simultaneously iterate over all |adjustments_on_adjusted_string| and
- // |first_adjustments|, adding adjustments to or correcting the adjustments
- // in |adjustments_on_adjusted_string| as we go. |shift| keeps track of the
- // current number of characters collapsed by |first_adjustments| up to this
- // point. |currently_collapsing| keeps track of the number of characters
- // collapsed by |first_adjustments| into the current |adjusted_iter|'s
- // length. These are characters that will change |shift| as soon as we're
- // done processing the current |adjusted_iter|; they are not yet reflected in
- // |shift|.
- size_t shift = 0;
- size_t currently_collapsing = 0;
- while (adjusted_iter != adjustments_on_adjusted_string->end()) {
- if ((first_iter == first_adjustments.end()) ||
- ((adjusted_iter->original_offset + shift +
- adjusted_iter->original_length) <= first_iter->original_offset)) {
- // Entire |adjusted_iter| (accounting for its shift and including its
- // whole original length) comes before |first_iter|.
- //
- // Correct the offset at |adjusted_iter| and move onto the next
- // adjustment that needs revising.
- adjusted_iter->original_offset += shift;
- shift += currently_collapsing;
- currently_collapsing = 0;
- ++adjusted_iter;
- } else if ((adjusted_iter->original_offset + shift) >
- first_iter->original_offset) {
- // |first_iter| comes before the |adjusted_iter| (as adjusted by |shift|).
-
- // It's not possible for the adjustments to overlap. (It shouldn't
- // be possible that we have an |adjusted_iter->original_offset| that,
- // when adjusted by the computed |shift|, is in the middle of
- // |first_iter|'s output's length. After all, that would mean the
- // current adjustment_on_adjusted_string somehow points to an offset
- // that was supposed to have been eliminated by the first set of
- // adjustments.)
- DCHECK_LE(first_iter->original_offset + first_iter->output_length,
- adjusted_iter->original_offset + shift);
-
- // Add the |first_adjustment_iter| to the full set of adjustments while
- // making sure |adjusted_iter| continues pointing to the same element.
- // We do this by inserting the |first_adjustment_iter| right before
- // |adjusted_iter|, then incrementing |adjusted_iter| so it points to
- // the following element.
- shift += first_iter->original_length - first_iter->output_length;
- adjusted_iter = adjustments_on_adjusted_string->insert(
- adjusted_iter, *first_iter);
- ++adjusted_iter;
- ++first_iter;
- } else {
- // The first adjustment adjusted something that then got further adjusted
- // by the second set of adjustments. In other words, |first_iter| points
- // to something in the range covered by |adjusted_iter|'s length (after
- // accounting for |shift|). Precisely,
- // adjusted_iter->original_offset + shift
- // <=
- // first_iter->original_offset
- // <=
- // adjusted_iter->original_offset + shift +
- // adjusted_iter->original_length
-
- // Modify the current |adjusted_iter| to include whatever collapsing
- // happened in |first_iter|, then advance to the next |first_adjustments|
- // because we dealt with the current one.
- const int collapse = static_cast<int>(first_iter->original_length) -
- static_cast<int>(first_iter->output_length);
- // This function does not know how to deal with a string that expands and
- // then gets modified, only strings that collapse and then get modified.
- DCHECK_GT(collapse, 0);
- adjusted_iter->original_length += collapse;
- currently_collapsing += collapse;
- ++first_iter;
- }
- }
- DCHECK_EQ(0u, currently_collapsing);
- if (first_iter != first_adjustments.end()) {
- // Only first adjustments are left. These do not need to be modified.
- // (Their offsets are already correct with respect to the original string.)
- // Append them all.
- DCHECK(adjusted_iter == adjustments_on_adjusted_string->end());
- adjustments_on_adjusted_string->insert(
- adjustments_on_adjusted_string->end(), first_iter,
- first_adjustments.end());
- }
-}
-
-// Converts the given source Unicode character type to the given destination
-// Unicode character type as a STL string. The given input buffer and size
-// determine the source, and the given output STL string will be replaced by
-// the result. If non-NULL, |adjustments| is set to reflect the all the
-// alterations to the string that are not one-character-to-one-character.
-// It will always be sorted by increasing offset.
-template<typename SrcChar, typename DestStdString>
-bool ConvertUnicode(const SrcChar* src,
- size_t src_len,
- DestStdString* output,
- OffsetAdjuster::Adjustments* adjustments) {
- if (adjustments)
- adjustments->clear();
- // ICU requires 32-bit numbers.
- bool success = true;
- int32_t src_len32 = static_cast<int32_t>(src_len);
- for (int32_t i = 0; i < src_len32; i++) {
- uint32_t code_point;
- size_t original_i = i;
- size_t chars_written = 0;
- if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) {
- chars_written = WriteUnicodeCharacter(code_point, output);
- } else {
- chars_written = WriteUnicodeCharacter(0xFFFD, output);
- success = false;
- }
-
- // Only bother writing an adjustment if this modification changed the
- // length of this character.
- // NOTE: ReadUnicodeCharacter() adjusts |i| to point _at_ the last
- // character read, not after it (so that incrementing it in the loop
- // increment will place it at the right location), so we need to account
- // for that in determining the amount that was read.
- if (adjustments && ((i - original_i + 1) != chars_written)) {
- adjustments->push_back(OffsetAdjuster::Adjustment(
- original_i, i - original_i + 1, chars_written));
- }
- }
- return success;
-}
-
-bool UTF8ToUTF16WithAdjustments(
- const char* src,
- size_t src_len,
- string16* output,
- base::OffsetAdjuster::Adjustments* adjustments) {
- PrepareForUTF16Or32Output(src, src_len, output);
- return ConvertUnicode(src, src_len, output, adjustments);
-}
-
-string16 UTF8ToUTF16WithAdjustments(
- const base::StringPiece& utf8,
- base::OffsetAdjuster::Adjustments* adjustments) {
- string16 result;
- UTF8ToUTF16WithAdjustments(utf8.data(), utf8.length(), &result, adjustments);
- return result;
-}
-
-string16 UTF8ToUTF16AndAdjustOffsets(
- const base::StringPiece& utf8,
- std::vector<size_t>* offsets_for_adjustment) {
- for (size_t& offset : *offsets_for_adjustment) {
- if (offset > utf8.length())
- offset = string16::npos;
- }
- OffsetAdjuster::Adjustments adjustments;
- string16 result = UTF8ToUTF16WithAdjustments(utf8, &adjustments);
- OffsetAdjuster::AdjustOffsets(adjustments, offsets_for_adjustment);
- return result;
-}
-
-std::string UTF16ToUTF8AndAdjustOffsets(
- const base::StringPiece16& utf16,
- std::vector<size_t>* offsets_for_adjustment) {
- for (size_t& offset : *offsets_for_adjustment) {
- if (offset > utf16.length())
- offset = string16::npos;
- }
- std::string result;
- PrepareForUTF8Output(utf16.data(), utf16.length(), &result);
- OffsetAdjuster::Adjustments adjustments;
- ConvertUnicode(utf16.data(), utf16.length(), &result, &adjustments);
- OffsetAdjuster::AdjustOffsets(adjustments, offsets_for_adjustment);
- return result;
-}
-
-} // namespace base
diff --git a/base/strings/utf_offset_string_conversions.h b/base/strings/utf_offset_string_conversions.h
deleted file mode 100644
index f7419551da..0000000000
--- a/base/strings/utf_offset_string_conversions.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_STRINGS_UTF_OFFSET_STRING_CONVERSIONS_H_
-#define BASE_STRINGS_UTF_OFFSET_STRING_CONVERSIONS_H_
-
-#include <stddef.h>
-
-#include <string>
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-
-namespace base {
-
-// A helper class and associated data structures to adjust offsets into a
-// string in response to various adjustments one might do to that string
-// (e.g., eliminating a range). For details on offsets, see the comments by
-// the AdjustOffsets() function below.
-class BASE_EXPORT OffsetAdjuster {
- public:
- struct BASE_EXPORT Adjustment {
- Adjustment(size_t original_offset,
- size_t original_length,
- size_t output_length);
-
- size_t original_offset;
- size_t original_length;
- size_t output_length;
- };
- typedef std::vector<Adjustment> Adjustments;
-
- // Adjusts all offsets in |offsets_for_adjustment| to reflect the adjustments
- // recorded in |adjustments|. Adjusted offsets greater than |limit| will be
- // set to string16::npos.
- //
- // Offsets represents insertion/selection points between characters: if |src|
- // is "abcd", then 0 is before 'a', 2 is between 'b' and 'c', and 4 is at the
- // end of the string. Valid input offsets range from 0 to |src_len|. On
- // exit, each offset will have been modified to point at the same logical
- // position in the output string. If an offset cannot be successfully
- // adjusted (e.g., because it points into the middle of a multibyte sequence),
- // it will be set to string16::npos.
- static void AdjustOffsets(const Adjustments& adjustments,
- std::vector<size_t>* offsets_for_adjustment,
- size_t limit = string16::npos);
-
- // Adjusts the single |offset| to reflect the adjustments recorded in
- // |adjustments|.
- static void AdjustOffset(const Adjustments& adjustments,
- size_t* offset,
- size_t limit = string16::npos);
-
- // Adjusts all offsets in |offsets_for_unadjustment| to reflect the reverse
- // of the adjustments recorded in |adjustments|. In other words, the offsets
- // provided represent offsets into an adjusted string and the caller wants
- // to know the offsets they correspond to in the original string. If an
- // offset cannot be successfully unadjusted (e.g., because it points into
- // the middle of a multibyte sequence), it will be set to string16::npos.
- static void UnadjustOffsets(const Adjustments& adjustments,
- std::vector<size_t>* offsets_for_unadjustment);
-
- // Adjusts the single |offset| to reflect the reverse of the adjustments
- // recorded in |adjustments|.
- static void UnadjustOffset(const Adjustments& adjustments,
- size_t* offset);
-
- // Combines two sequential sets of adjustments, storing the combined revised
- // adjustments in |adjustments_on_adjusted_string|. That is, suppose a
- // string was altered in some way, with the alterations recorded as
- // adjustments in |first_adjustments|. Then suppose the resulting string is
- // further altered, with the alterations recorded as adjustments scored in
- // |adjustments_on_adjusted_string|, with the offsets recorded in these
- // adjustments being with respect to the intermediate string. This function
- // combines the two sets of adjustments into one, storing the result in
- // |adjustments_on_adjusted_string|, whose offsets are correct with respect
- // to the original string.
- //
- // Assumes both parameters are sorted by increasing offset.
- //
- // WARNING: Only supports |first_adjustments| that involve collapsing ranges
- // of text, not expanding ranges.
- static void MergeSequentialAdjustments(
- const Adjustments& first_adjustments,
- Adjustments* adjustments_on_adjusted_string);
-};
-
-// Like the conversions in utf_string_conversions.h, but also fills in an
-// |adjustments| parameter that reflects the alterations done to the string.
-// It may be NULL.
-BASE_EXPORT bool UTF8ToUTF16WithAdjustments(
- const char* src,
- size_t src_len,
- string16* output,
- base::OffsetAdjuster::Adjustments* adjustments);
-BASE_EXPORT string16 UTF8ToUTF16WithAdjustments(
- const base::StringPiece& utf8,
- base::OffsetAdjuster::Adjustments* adjustments);
-// As above, but instead internally examines the adjustments and applies them
-// to |offsets_for_adjustment|. Input offsets greater than the length of the
-// input string will be set to string16::npos. See comments by AdjustOffsets().
-BASE_EXPORT string16 UTF8ToUTF16AndAdjustOffsets(
- const base::StringPiece& utf8,
- std::vector<size_t>* offsets_for_adjustment);
-BASE_EXPORT std::string UTF16ToUTF8AndAdjustOffsets(
- const base::StringPiece16& utf16,
- std::vector<size_t>* offsets_for_adjustment);
-
-} // namespace base
-
-#endif // BASE_STRINGS_UTF_OFFSET_STRING_CONVERSIONS_H_
diff --git a/base/strings/utf_offset_string_conversions_unittest.cc b/base/strings/utf_offset_string_conversions_unittest.cc
deleted file mode 100644
index c5ce647a99..0000000000
--- a/base/strings/utf_offset_string_conversions_unittest.cc
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright (c) 2011 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 <stddef.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_offset_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-static const size_t kNpos = string16::npos;
-
-} // namespace
-
-TEST(UTFOffsetStringConversionsTest, AdjustOffset) {
- struct UTF8ToUTF16Case {
- const char* utf8;
- size_t input_offset;
- size_t output_offset;
- } utf8_to_utf16_cases[] = {
- {"", 0, 0},
- {"", kNpos, kNpos},
- {"\xe4\xbd\xa0\xe5\xa5\xbd", 1, kNpos},
- {"\xe4\xbd\xa0\xe5\xa5\xbd", 3, 1},
- {"\xed\xb0\x80z", 3, 3},
- {"A\xF0\x90\x8C\x80z", 1, 1},
- {"A\xF0\x90\x8C\x80z", 2, kNpos},
- {"A\xF0\x90\x8C\x80z", 5, 3},
- {"A\xF0\x90\x8C\x80z", 6, 4},
- {"A\xF0\x90\x8C\x80z", kNpos, kNpos},
- };
- for (size_t i = 0; i < arraysize(utf8_to_utf16_cases); ++i) {
- const size_t offset = utf8_to_utf16_cases[i].input_offset;
- std::vector<size_t> offsets;
- offsets.push_back(offset);
- UTF8ToUTF16AndAdjustOffsets(utf8_to_utf16_cases[i].utf8, &offsets);
- EXPECT_EQ(utf8_to_utf16_cases[i].output_offset, offsets[0]);
- }
-
- struct UTF16ToUTF8Case {
- char16 utf16[10];
- size_t input_offset;
- size_t output_offset;
- } utf16_to_utf8_cases[] = {
- {{}, 0, 0},
- // Converted to 3-byte utf-8 sequences
- {{0x5909, 0x63DB}, 3, kNpos},
- {{0x5909, 0x63DB}, 2, 6},
- {{0x5909, 0x63DB}, 1, 3},
- {{0x5909, 0x63DB}, 0, 0},
- // Converted to 2-byte utf-8 sequences
- {{'A', 0x00bc, 0x00be, 'z'}, 1, 1},
- {{'A', 0x00bc, 0x00be, 'z'}, 2, 3},
- {{'A', 0x00bc, 0x00be, 'z'}, 3, 5},
- {{'A', 0x00bc, 0x00be, 'z'}, 4, 6},
- // Surrogate pair
- {{'A', 0xd800, 0xdf00, 'z'}, 1, 1},
- {{'A', 0xd800, 0xdf00, 'z'}, 2, kNpos},
- {{'A', 0xd800, 0xdf00, 'z'}, 3, 5},
- {{'A', 0xd800, 0xdf00, 'z'}, 4, 6},
- };
- for (size_t i = 0; i < arraysize(utf16_to_utf8_cases); ++i) {
- size_t offset = utf16_to_utf8_cases[i].input_offset;
- std::vector<size_t> offsets;
- offsets.push_back(offset);
- UTF16ToUTF8AndAdjustOffsets(utf16_to_utf8_cases[i].utf16, &offsets);
- EXPECT_EQ(utf16_to_utf8_cases[i].output_offset, offsets[0]) << i;
- }
-}
-
-TEST(UTFOffsetStringConversionsTest, LimitOffsets) {
- const OffsetAdjuster::Adjustments kNoAdjustments;
- const size_t kLimit = 10;
- const size_t kItems = 20;
- std::vector<size_t> size_ts;
- for (size_t t = 0; t < kItems; ++t) {
- size_ts.push_back(t);
- OffsetAdjuster::AdjustOffset(kNoAdjustments, &size_ts.back(), kLimit);
- }
- size_t unlimited_count = 0;
- for (std::vector<size_t>::iterator ti = size_ts.begin(); ti != size_ts.end();
- ++ti) {
- if (*ti != kNpos)
- ++unlimited_count;
- }
- EXPECT_EQ(11U, unlimited_count);
-
- // Reverse the values in the vector and try again.
- size_ts.clear();
- for (size_t t = kItems; t > 0; --t) {
- size_ts.push_back(t - 1);
- OffsetAdjuster::AdjustOffset(kNoAdjustments, &size_ts.back(), kLimit);
- }
- unlimited_count = 0;
- for (std::vector<size_t>::iterator ti = size_ts.begin(); ti != size_ts.end();
- ++ti) {
- if (*ti != kNpos)
- ++unlimited_count;
- }
- EXPECT_EQ(11U, unlimited_count);
-}
-
-TEST(UTFOffsetStringConversionsTest, AdjustOffsets) {
- // Imagine we have strings as shown in the following cases where the
- // X's represent encoded characters.
- // 1: abcXXXdef ==> abcXdef
- {
- std::vector<size_t> offsets;
- for (size_t t = 0; t <= 9; ++t)
- offsets.push_back(t);
- OffsetAdjuster::Adjustments adjustments;
- adjustments.push_back(OffsetAdjuster::Adjustment(3, 3, 1));
- OffsetAdjuster::AdjustOffsets(adjustments, &offsets);
- size_t expected_1[] = {0, 1, 2, 3, kNpos, kNpos, 4, 5, 6, 7};
- EXPECT_EQ(offsets.size(), arraysize(expected_1));
- for (size_t i = 0; i < arraysize(expected_1); ++i)
- EXPECT_EQ(expected_1[i], offsets[i]);
- }
-
- // 2: XXXaXXXXbcXXXXXXXdefXXX ==> XaXXbcXXXXdefX
- {
- std::vector<size_t> offsets;
- for (size_t t = 0; t <= 23; ++t)
- offsets.push_back(t);
- OffsetAdjuster::Adjustments adjustments;
- adjustments.push_back(OffsetAdjuster::Adjustment(0, 3, 1));
- adjustments.push_back(OffsetAdjuster::Adjustment(4, 4, 2));
- adjustments.push_back(OffsetAdjuster::Adjustment(10, 7, 4));
- adjustments.push_back(OffsetAdjuster::Adjustment(20, 3, 1));
- OffsetAdjuster::AdjustOffsets(adjustments, &offsets);
- size_t expected_2[] = {
- 0, kNpos, kNpos, 1, 2, kNpos, kNpos, kNpos, 4, 5, 6, kNpos, kNpos, kNpos,
- kNpos, kNpos, kNpos, 10, 11, 12, 13, kNpos, kNpos, 14
- };
- EXPECT_EQ(offsets.size(), arraysize(expected_2));
- for (size_t i = 0; i < arraysize(expected_2); ++i)
- EXPECT_EQ(expected_2[i], offsets[i]);
- }
-
- // 3: XXXaXXXXbcdXXXeXX ==> aXXXXbcdXXXe
- {
- std::vector<size_t> offsets;
- for (size_t t = 0; t <= 17; ++t)
- offsets.push_back(t);
- OffsetAdjuster::Adjustments adjustments;
- adjustments.push_back(OffsetAdjuster::Adjustment(0, 3, 0));
- adjustments.push_back(OffsetAdjuster::Adjustment(4, 4, 4));
- adjustments.push_back(OffsetAdjuster::Adjustment(11, 3, 3));
- adjustments.push_back(OffsetAdjuster::Adjustment(15, 2, 0));
- OffsetAdjuster::AdjustOffsets(adjustments, &offsets);
- size_t expected_3[] = {
- 0, kNpos, kNpos, 0, 1, kNpos, kNpos, kNpos, 5, 6, 7, 8, kNpos, kNpos, 11,
- 12, kNpos, 12
- };
- EXPECT_EQ(offsets.size(), arraysize(expected_3));
- for (size_t i = 0; i < arraysize(expected_3); ++i)
- EXPECT_EQ(expected_3[i], offsets[i]);
- }
-}
-
-TEST(UTFOffsetStringConversionsTest, UnadjustOffsets) {
- // Imagine we have strings as shown in the following cases where the
- // X's represent encoded characters.
- // 1: abcXXXdef ==> abcXdef
- {
- std::vector<size_t> offsets;
- for (size_t t = 0; t <= 7; ++t)
- offsets.push_back(t);
- OffsetAdjuster::Adjustments adjustments;
- adjustments.push_back(OffsetAdjuster::Adjustment(3, 3, 1));
- OffsetAdjuster::UnadjustOffsets(adjustments, &offsets);
- size_t expected_1[] = {0, 1, 2, 3, 6, 7, 8, 9};
- EXPECT_EQ(offsets.size(), arraysize(expected_1));
- for (size_t i = 0; i < arraysize(expected_1); ++i)
- EXPECT_EQ(expected_1[i], offsets[i]);
- }
-
- // 2: XXXaXXXXbcXXXXXXXdefXXX ==> XaXXbcXXXXdefX
- {
- std::vector<size_t> offsets;
- for (size_t t = 0; t <= 14; ++t)
- offsets.push_back(t);
- OffsetAdjuster::Adjustments adjustments;
- adjustments.push_back(OffsetAdjuster::Adjustment(0, 3, 1));
- adjustments.push_back(OffsetAdjuster::Adjustment(4, 4, 2));
- adjustments.push_back(OffsetAdjuster::Adjustment(10, 7, 4));
- adjustments.push_back(OffsetAdjuster::Adjustment(20, 3, 1));
- OffsetAdjuster::UnadjustOffsets(adjustments, &offsets);
- size_t expected_2[] = {
- 0, 3, 4, kNpos, 8, 9, 10, kNpos, kNpos, kNpos, 17, 18, 19, 20, 23
- };
- EXPECT_EQ(offsets.size(), arraysize(expected_2));
- for (size_t i = 0; i < arraysize(expected_2); ++i)
- EXPECT_EQ(expected_2[i], offsets[i]);
- }
-
- // 3: XXXaXXXXbcdXXXeXX ==> aXXXXbcdXXXe
- {
- std::vector<size_t> offsets;
- for (size_t t = 0; t <= 12; ++t)
- offsets.push_back(t);
- OffsetAdjuster::Adjustments adjustments;
- adjustments.push_back(OffsetAdjuster::Adjustment(0, 3, 0));
- adjustments.push_back(OffsetAdjuster::Adjustment(4, 4, 4));
- adjustments.push_back(OffsetAdjuster::Adjustment(11, 3, 3));
- adjustments.push_back(OffsetAdjuster::Adjustment(15, 2, 0));
- OffsetAdjuster::UnadjustOffsets(adjustments, &offsets);
- size_t expected_3[] = {
- 0, // this could just as easily be 3
- 4, kNpos, kNpos, kNpos, 8, 9, 10, 11, kNpos, kNpos, 14,
- 15 // this could just as easily be 17
- };
- EXPECT_EQ(offsets.size(), arraysize(expected_3));
- for (size_t i = 0; i < arraysize(expected_3); ++i)
- EXPECT_EQ(expected_3[i], offsets[i]);
- }
-}
-
-// MergeSequentialAdjustments is used by net/base/escape.{h,cc} and
-// net/base/net_util.{h,cc}. The two tests EscapeTest.AdjustOffset and
-// NetUtilTest.FormatUrlWithOffsets test its behavior extensively. This
-// is simply a short, additional test.
-TEST(UTFOffsetStringConversionsTest, MergeSequentialAdjustments) {
- // Pretend the input string is "abcdefghijklmnopqrstuvwxyz".
-
- // Set up |first_adjustments| to
- // - remove the leading "a"
- // - combine the "bc" into one character (call it ".")
- // - remove the "f"
- // - remove the "tuv"
- // The resulting string should be ".deghijklmnopqrswxyz".
- OffsetAdjuster::Adjustments first_adjustments;
- first_adjustments.push_back(OffsetAdjuster::Adjustment(0, 1, 0));
- first_adjustments.push_back(OffsetAdjuster::Adjustment(1, 2, 1));
- first_adjustments.push_back(OffsetAdjuster::Adjustment(5, 1, 0));
- first_adjustments.push_back(OffsetAdjuster::Adjustment(19, 3, 0));
-
- // Set up |adjustments_on_adjusted_string| to
- // - combine the "." character that replaced "bc" with "d" into one character
- // (call it "?")
- // - remove the "egh"
- // - expand the "i" into two characters (call them "12")
- // - combine the "jkl" into one character (call it "@")
- // - expand the "z" into two characters (call it "34")
- // The resulting string should be "?12@mnopqrswxy34".
- OffsetAdjuster::Adjustments adjustments_on_adjusted_string;
- adjustments_on_adjusted_string.push_back(OffsetAdjuster::Adjustment(
- 0, 2, 1));
- adjustments_on_adjusted_string.push_back(OffsetAdjuster::Adjustment(
- 2, 3, 0));
- adjustments_on_adjusted_string.push_back(OffsetAdjuster::Adjustment(
- 5, 1, 2));
- adjustments_on_adjusted_string.push_back(OffsetAdjuster::Adjustment(
- 6, 3, 1));
- adjustments_on_adjusted_string.push_back(OffsetAdjuster::Adjustment(
- 19, 1, 2));
-
- // Now merge the adjustments and check the results.
- OffsetAdjuster::MergeSequentialAdjustments(first_adjustments,
- &adjustments_on_adjusted_string);
- // The merged adjustments should look like
- // - combine abcd into "?"
- // - note: it's also reasonable for the Merge function to instead produce
- // two adjustments instead of this, one to remove a and another to
- // combine bcd into "?". This test verifies the current behavior.
- // - remove efgh
- // - expand i into "12"
- // - combine jkl into "@"
- // - remove tuv
- // - expand z into "34"
- ASSERT_EQ(6u, adjustments_on_adjusted_string.size());
- EXPECT_EQ(0u, adjustments_on_adjusted_string[0].original_offset);
- EXPECT_EQ(4u, adjustments_on_adjusted_string[0].original_length);
- EXPECT_EQ(1u, adjustments_on_adjusted_string[0].output_length);
- EXPECT_EQ(4u, adjustments_on_adjusted_string[1].original_offset);
- EXPECT_EQ(4u, adjustments_on_adjusted_string[1].original_length);
- EXPECT_EQ(0u, adjustments_on_adjusted_string[1].output_length);
- EXPECT_EQ(8u, adjustments_on_adjusted_string[2].original_offset);
- EXPECT_EQ(1u, adjustments_on_adjusted_string[2].original_length);
- EXPECT_EQ(2u, adjustments_on_adjusted_string[2].output_length);
- EXPECT_EQ(9u, adjustments_on_adjusted_string[3].original_offset);
- EXPECT_EQ(3u, adjustments_on_adjusted_string[3].original_length);
- EXPECT_EQ(1u, adjustments_on_adjusted_string[3].output_length);
- EXPECT_EQ(19u, adjustments_on_adjusted_string[4].original_offset);
- EXPECT_EQ(3u, adjustments_on_adjusted_string[4].original_length);
- EXPECT_EQ(0u, adjustments_on_adjusted_string[4].output_length);
- EXPECT_EQ(25u, adjustments_on_adjusted_string[5].original_offset);
- EXPECT_EQ(1u, adjustments_on_adjusted_string[5].original_length);
- EXPECT_EQ(2u, adjustments_on_adjusted_string[5].output_length);
-}
-
-} // namespace base
diff --git a/base/supports_user_data.cc b/base/supports_user_data.cc
deleted file mode 100644
index 43ab21a679..0000000000
--- a/base/supports_user_data.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/supports_user_data.h"
-
-namespace base {
-
-SupportsUserData::SupportsUserData() {
- // Harmless to construct on a different execution sequence to subsequent
- // usage.
- sequence_checker_.DetachFromSequence();
-}
-
-SupportsUserData::Data* SupportsUserData::GetUserData(const void* key) const {
- DCHECK(sequence_checker_.CalledOnValidSequence());
- // Avoid null keys; they are too vulnerable to collision.
- DCHECK(key);
- DataMap::const_iterator found = user_data_.find(key);
- if (found != user_data_.end())
- return found->second.get();
- return nullptr;
-}
-
-void SupportsUserData::SetUserData(const void* key,
- std::unique_ptr<Data> data) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
- // Avoid null keys; they are too vulnerable to collision.
- DCHECK(key);
- user_data_[key] = std::move(data);
-}
-
-void SupportsUserData::RemoveUserData(const void* key) {
- DCHECK(sequence_checker_.CalledOnValidSequence());
- user_data_.erase(key);
-}
-
-void SupportsUserData::DetachFromSequence() {
- sequence_checker_.DetachFromSequence();
-}
-
-SupportsUserData::~SupportsUserData() {
- DCHECK(sequence_checker_.CalledOnValidSequence() || user_data_.empty());
- DataMap local_user_data;
- user_data_.swap(local_user_data);
- // Now this->user_data_ is empty, and any destructors called transitively from
- // the destruction of |local_user_data| will see it that way instead of
- // examining a being-destroyed object.
-}
-
-} // namespace base
diff --git a/base/supports_user_data.h b/base/supports_user_data.h
deleted file mode 100644
index 356c97329b..0000000000
--- a/base/supports_user_data.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_SUPPORTS_USER_DATA_H_
-#define BASE_SUPPORTS_USER_DATA_H_
-
-#include <map>
-#include <memory>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequence_checker.h"
-
-// TODO(gab): Removing this include causes IWYU failures in other headers,
-// remove it in a follow- up CL.
-#include "base/threading/thread_checker.h"
-
-namespace base {
-
-// This is a helper for classes that want to allow users to stash random data by
-// key. At destruction all the objects will be destructed.
-class BASE_EXPORT SupportsUserData {
- public:
- SupportsUserData();
-
- // Derive from this class and add your own data members to associate extra
- // information with this object. Alternatively, add this as a public base
- // class to any class with a virtual destructor.
- class BASE_EXPORT Data {
- public:
- virtual ~Data() = default;
- };
-
- // The user data allows the clients to associate data with this object.
- // Multiple user data values can be stored under different keys.
- // This object will TAKE OWNERSHIP of the given data pointer, and will
- // delete the object if it is changed or the object is destroyed.
- // |key| must not be null--that value is too vulnerable for collision.
- Data* GetUserData(const void* key) const;
- void SetUserData(const void* key, std::unique_ptr<Data> data);
- void RemoveUserData(const void* key);
-
- // SupportsUserData is not thread-safe, and on debug build will assert it is
- // only used on one execution sequence. Calling this method allows the caller
- // to hand the SupportsUserData instance across execution sequences. Use only
- // if you are taking full control of the synchronization of that hand over.
- void DetachFromSequence();
-
- protected:
- virtual ~SupportsUserData();
-
- private:
- using DataMap = std::map<const void*, std::unique_ptr<Data>>;
-
- // Externally-defined data accessible by key.
- DataMap user_data_;
- // Guards usage of |user_data_|
- SequenceChecker sequence_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(SupportsUserData);
-};
-
-// Adapter class that releases a refcounted object when the
-// SupportsUserData::Data object is deleted.
-template <typename T>
-class UserDataAdapter : public base::SupportsUserData::Data {
- public:
- static T* Get(const SupportsUserData* supports_user_data, const void* key) {
- UserDataAdapter* data =
- static_cast<UserDataAdapter*>(supports_user_data->GetUserData(key));
- return data ? static_cast<T*>(data->object_.get()) : NULL;
- }
-
- UserDataAdapter(T* object) : object_(object) {}
- T* release() { return object_.release(); }
-
- private:
- scoped_refptr<T> object_;
-
- DISALLOW_COPY_AND_ASSIGN(UserDataAdapter);
-};
-
-} // namespace base
-
-#endif // BASE_SUPPORTS_USER_DATA_H_
diff --git a/base/supports_user_data_unittest.cc b/base/supports_user_data_unittest.cc
deleted file mode 100644
index 2e0a724bda..0000000000
--- a/base/supports_user_data_unittest.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// 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/supports_user_data.h"
-
-#include <vector>
-
-#include "base/memory/ptr_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-struct TestSupportsUserData : public SupportsUserData {};
-
-struct UsesItself : public SupportsUserData::Data {
- UsesItself(SupportsUserData* supports_user_data, const void* key)
- : supports_user_data_(supports_user_data),
- key_(key) {
- }
-
- ~UsesItself() override {
- EXPECT_EQ(nullptr, supports_user_data_->GetUserData(key_));
- }
-
- SupportsUserData* supports_user_data_;
- const void* key_;
-};
-
-TEST(SupportsUserDataTest, ClearWorksRecursively) {
- TestSupportsUserData supports_user_data;
- char key = 0;
- supports_user_data.SetUserData(
- &key, std::make_unique<UsesItself>(&supports_user_data, &key));
- // Destruction of supports_user_data runs the actual test.
-}
-
-} // namespace
-} // namespace base
diff --git a/base/synchronization/waitable_event_watcher_unittest.cc b/base/synchronization/waitable_event_watcher_unittest.cc
deleted file mode 100644
index ec056effe5..0000000000
--- a/base/synchronization/waitable_event_watcher_unittest.cc
+++ /dev/null
@@ -1,429 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/synchronization/waitable_event_watcher.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// The message loops on which each waitable event timer should be tested.
-const MessageLoop::Type testing_message_loops[] = {
- MessageLoop::TYPE_DEFAULT,
- MessageLoop::TYPE_IO,
-#if !defined(OS_IOS) // iOS does not allow direct running of the UI loop.
- MessageLoop::TYPE_UI,
-#endif
-};
-
-void QuitWhenSignaled(WaitableEvent* event) {
- RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-class DecrementCountContainer {
- public:
- explicit DecrementCountContainer(int* counter) : counter_(counter) {}
- void OnWaitableEventSignaled(WaitableEvent* object) {
- // NOTE: |object| may be already deleted.
- --(*counter_);
- }
-
- private:
- int* counter_;
-};
-
-} // namespace
-
-class WaitableEventWatcherTest
- : public testing::TestWithParam<MessageLoop::Type> {};
-
-TEST_P(WaitableEventWatcherTest, BasicSignalManual) {
- MessageLoop message_loop(GetParam());
-
- // A manual-reset event that is not yet signaled.
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitableEventWatcher watcher;
- watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
-
- event.Signal();
-
- RunLoop().Run();
-
- EXPECT_TRUE(event.IsSignaled());
-}
-
-TEST_P(WaitableEventWatcherTest, BasicSignalAutomatic) {
- MessageLoop message_loop(GetParam());
-
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitableEventWatcher watcher;
- watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
-
- event.Signal();
-
- RunLoop().Run();
-
- // The WaitableEventWatcher consumes the event signal.
- EXPECT_FALSE(event.IsSignaled());
-}
-
-TEST_P(WaitableEventWatcherTest, BasicCancel) {
- MessageLoop message_loop(GetParam());
-
- // A manual-reset event that is not yet signaled.
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitableEventWatcher watcher;
-
- watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
-
- watcher.StopWatching();
-}
-
-TEST_P(WaitableEventWatcherTest, CancelAfterSet) {
- MessageLoop message_loop(GetParam());
-
- // A manual-reset event that is not yet signaled.
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitableEventWatcher watcher;
-
- int counter = 1;
- DecrementCountContainer delegate(&counter);
- WaitableEventWatcher::EventCallback callback = BindOnce(
- &DecrementCountContainer::OnWaitableEventSignaled, Unretained(&delegate));
- watcher.StartWatching(&event, std::move(callback),
- SequencedTaskRunnerHandle::Get());
-
- event.Signal();
-
- // Let the background thread do its business
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
-
- watcher.StopWatching();
-
- RunLoop().RunUntilIdle();
-
- // Our delegate should not have fired.
- EXPECT_EQ(1, counter);
-}
-
-TEST_P(WaitableEventWatcherTest, OutlivesMessageLoop) {
- // Simulate a MessageLoop that dies before an WaitableEventWatcher. This
- // ordinarily doesn't happen when people use the Thread class, but it can
- // happen when people use the Singleton pattern or atexit.
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- {
- std::unique_ptr<WaitableEventWatcher> watcher;
- {
- MessageLoop message_loop(GetParam());
- watcher = std::make_unique<WaitableEventWatcher>();
-
- watcher->StartWatching(&event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
- }
- }
-}
-
-TEST_P(WaitableEventWatcherTest, SignaledAtStartManual) {
- MessageLoop message_loop(GetParam());
-
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::SIGNALED);
-
- WaitableEventWatcher watcher;
- watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
-
- RunLoop().Run();
-
- EXPECT_TRUE(event.IsSignaled());
-}
-
-TEST_P(WaitableEventWatcherTest, SignaledAtStartAutomatic) {
- MessageLoop message_loop(GetParam());
-
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::SIGNALED);
-
- WaitableEventWatcher watcher;
- watcher.StartWatching(&event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
-
- RunLoop().Run();
-
- // The watcher consumes the event signal.
- EXPECT_FALSE(event.IsSignaled());
-}
-
-TEST_P(WaitableEventWatcherTest, StartWatchingInCallback) {
- MessageLoop message_loop(GetParam());
-
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitableEventWatcher watcher;
- watcher.StartWatching(
- &event,
- BindOnce(
- [](WaitableEventWatcher* watcher, WaitableEvent* event) {
- // |event| is manual, so the second watcher will run
- // immediately.
- watcher->StartWatching(event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
- },
- &watcher),
- SequencedTaskRunnerHandle::Get());
-
- event.Signal();
-
- RunLoop().Run();
-}
-
-TEST_P(WaitableEventWatcherTest, MultipleWatchersManual) {
- MessageLoop message_loop(GetParam());
-
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- int counter1 = 0;
- int counter2 = 0;
-
- auto callback = [](RunLoop* run_loop, int* counter, WaitableEvent* event) {
- ++(*counter);
- run_loop->QuitWhenIdle();
- };
-
- RunLoop run_loop;
-
- WaitableEventWatcher watcher1;
- watcher1.StartWatching(
- &event, BindOnce(callback, Unretained(&run_loop), Unretained(&counter1)),
- SequencedTaskRunnerHandle::Get());
-
- WaitableEventWatcher watcher2;
- watcher2.StartWatching(
- &event, BindOnce(callback, Unretained(&run_loop), Unretained(&counter2)),
- SequencedTaskRunnerHandle::Get());
-
- event.Signal();
- run_loop.Run();
-
- EXPECT_EQ(1, counter1);
- EXPECT_EQ(1, counter2);
- EXPECT_TRUE(event.IsSignaled());
-}
-
-// Tests that only one async waiter gets called back for an auto-reset event.
-TEST_P(WaitableEventWatcherTest, MultipleWatchersAutomatic) {
- MessageLoop message_loop(GetParam());
-
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- int counter1 = 0;
- int counter2 = 0;
-
- auto callback = [](RunLoop** run_loop, int* counter, WaitableEvent* event) {
- ++(*counter);
- (*run_loop)->QuitWhenIdle();
- };
-
- // The same RunLoop instance cannot be Run more than once, and it is
- // undefined which watcher will get called back first. Have the callback
- // dereference this pointer to quit the loop, which will be updated on each
- // Run.
- RunLoop* current_run_loop;
-
- WaitableEventWatcher watcher1;
- watcher1.StartWatching(
- &event,
- BindOnce(callback, Unretained(&current_run_loop), Unretained(&counter1)),
- SequencedTaskRunnerHandle::Get());
-
- WaitableEventWatcher watcher2;
- watcher2.StartWatching(
- &event,
- BindOnce(callback, Unretained(&current_run_loop), Unretained(&counter2)),
- SequencedTaskRunnerHandle::Get());
-
- event.Signal();
- {
- RunLoop run_loop;
- current_run_loop = &run_loop;
- run_loop.Run();
- }
-
- // Only one of the waiters should have been signaled.
- EXPECT_TRUE((counter1 == 1) ^ (counter2 == 1));
-
- EXPECT_FALSE(event.IsSignaled());
-
- event.Signal();
- {
- RunLoop run_loop;
- current_run_loop = &run_loop;
- run_loop.Run();
- }
-
- EXPECT_FALSE(event.IsSignaled());
-
- // The other watcher should have been signaled.
- EXPECT_EQ(1, counter1);
- EXPECT_EQ(1, counter2);
-}
-
-// To help detect errors around deleting WaitableEventWatcher, an additional
-// bool parameter is used to test sleeping between watching and deletion.
-class WaitableEventWatcherDeletionTest
- : public testing::TestWithParam<std::tuple<MessageLoop::Type, bool>> {};
-
-TEST_P(WaitableEventWatcherDeletionTest, DeleteUnder) {
- MessageLoop::Type message_loop_type;
- bool delay_after_delete;
- std::tie(message_loop_type, delay_after_delete) = GetParam();
-
- // Delete the WaitableEvent out from under the Watcher. This is explictly
- // allowed by the interface.
-
- MessageLoop message_loop(message_loop_type);
-
- {
- WaitableEventWatcher watcher;
-
- auto* event = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- watcher.StartWatching(event, BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
-
- if (delay_after_delete) {
- // On Windows that sleep() improves the chance to catch some problems.
- // It postpones the dtor |watcher| (which immediately cancel the waiting)
- // and gives some time to run to a created background thread.
- // Unfortunately, that thread is under OS control and we can't
- // manipulate it directly.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
- }
-
- delete event;
- }
-}
-
-TEST_P(WaitableEventWatcherDeletionTest, SignalAndDelete) {
- MessageLoop::Type message_loop_type;
- bool delay_after_delete;
- std::tie(message_loop_type, delay_after_delete) = GetParam();
-
- // Signal and immediately delete the WaitableEvent out from under the Watcher.
-
- MessageLoop message_loop(message_loop_type);
-
- {
- WaitableEventWatcher watcher;
-
- auto event = std::make_unique<WaitableEvent>(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- watcher.StartWatching(event.get(), BindOnce(&QuitWhenSignaled),
- SequencedTaskRunnerHandle::Get());
- event->Signal();
- event.reset();
-
- if (delay_after_delete) {
- // On Windows that sleep() improves the chance to catch some problems.
- // It postpones the dtor |watcher| (which immediately cancel the waiting)
- // and gives some time to run to a created background thread.
- // Unfortunately, that thread is under OS control and we can't
- // manipulate it directly.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
- }
-
- // Wait for the watcher callback.
- RunLoop().Run();
- }
-}
-
-// Tests deleting the WaitableEventWatcher between signaling the event and
-// when the callback should be run.
-TEST_P(WaitableEventWatcherDeletionTest, DeleteWatcherBeforeCallback) {
- MessageLoop::Type message_loop_type;
- bool delay_after_delete;
- std::tie(message_loop_type, delay_after_delete) = GetParam();
-
- MessageLoop message_loop(message_loop_type);
- scoped_refptr<SingleThreadTaskRunner> task_runner =
- message_loop.task_runner();
-
- // Flag used to esnure that the |watcher_callback| never runs.
- bool did_callback = false;
-
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- auto watcher = std::make_unique<WaitableEventWatcher>();
-
- // Queue up a series of tasks:
- // 1. StartWatching the WaitableEvent
- // 2. Signal the event (which will result in another task getting posted to
- // the |task_runner|)
- // 3. Delete the WaitableEventWatcher
- // 4. WaitableEventWatcher callback should run (from #2)
-
- WaitableEventWatcher::EventCallback watcher_callback = BindOnce(
- [](bool* did_callback, WaitableEvent*) {
- *did_callback = true;
- },
- Unretained(&did_callback));
-
- task_runner->PostTask(
- FROM_HERE, BindOnce(IgnoreResult(&WaitableEventWatcher::StartWatching),
- Unretained(watcher.get()), Unretained(&event),
- std::move(watcher_callback), task_runner));
- task_runner->PostTask(FROM_HERE,
- BindOnce(&WaitableEvent::Signal, Unretained(&event)));
- task_runner->DeleteSoon(FROM_HERE, std::move(watcher));
- if (delay_after_delete) {
- task_runner->PostTask(FROM_HERE, BindOnce(&PlatformThread::Sleep,
- TimeDelta::FromMilliseconds(30)));
- }
-
- RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(did_callback);
-}
-
-INSTANTIATE_TEST_CASE_P(,
- WaitableEventWatcherTest,
- testing::ValuesIn(testing_message_loops));
-
-INSTANTIATE_TEST_CASE_P(
- ,
- WaitableEventWatcherDeletionTest,
- testing::Combine(testing::ValuesIn(testing_message_loops),
- testing::Bool()));
-
-} // namespace base
diff --git a/base/sys_byteorder_unittest.cc b/base/sys_byteorder_unittest.cc
deleted file mode 100644
index 8167be3b9a..0000000000
--- a/base/sys_byteorder_unittest.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2016 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/sys_byteorder.h"
-
-#include <stdint.h>
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-const uint16_t k16BitTestData = 0xaabb;
-const uint16_t k16BitSwappedTestData = 0xbbaa;
-const uint32_t k32BitTestData = 0xaabbccdd;
-const uint32_t k32BitSwappedTestData = 0xddccbbaa;
-const uint64_t k64BitTestData = 0xaabbccdd44332211;
-const uint64_t k64BitSwappedTestData = 0x11223344ddccbbaa;
-
-} // namespace
-
-TEST(ByteOrderTest, ByteSwap16) {
- uint16_t swapped = base::ByteSwap(k16BitTestData);
- EXPECT_EQ(k16BitSwappedTestData, swapped);
- uint16_t reswapped = base::ByteSwap(swapped);
- EXPECT_EQ(k16BitTestData, reswapped);
-}
-
-TEST(ByteOrderTest, ByteSwap32) {
- uint32_t swapped = base::ByteSwap(k32BitTestData);
- EXPECT_EQ(k32BitSwappedTestData, swapped);
- uint32_t reswapped = base::ByteSwap(swapped);
- EXPECT_EQ(k32BitTestData, reswapped);
-}
-
-TEST(ByteOrderTest, ByteSwap64) {
- uint64_t swapped = base::ByteSwap(k64BitTestData);
- EXPECT_EQ(k64BitSwappedTestData, swapped);
- uint64_t reswapped = base::ByteSwap(swapped);
- EXPECT_EQ(k64BitTestData, reswapped);
-}
-
-TEST(ByteOrderTest, ByteSwapUintPtrT) {
-#if defined(ARCH_CPU_64_BITS)
- const uintptr_t test_data = static_cast<uintptr_t>(k64BitTestData);
- const uintptr_t swapped_test_data =
- static_cast<uintptr_t>(k64BitSwappedTestData);
-#elif defined(ARCH_CPU_32_BITS)
- const uintptr_t test_data = static_cast<uintptr_t>(k32BitTestData);
- const uintptr_t swapped_test_data =
- static_cast<uintptr_t>(k32BitSwappedTestData);
-#else
-#error architecture not supported
-#endif
-
- uintptr_t swapped = base::ByteSwapUintPtrT(test_data);
- EXPECT_EQ(swapped_test_data, swapped);
- uintptr_t reswapped = base::ByteSwapUintPtrT(swapped);
- EXPECT_EQ(test_data, reswapped);
-}
-
-TEST(ByteOrderTest, ByteSwapToLE16) {
- uint16_t le = base::ByteSwapToLE16(k16BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k16BitTestData, le);
-#else
- EXPECT_EQ(k16BitSwappedTestData, le);
-#endif
-}
-
-TEST(ByteOrderTest, ByteSwapToLE32) {
- uint32_t le = base::ByteSwapToLE32(k32BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k32BitTestData, le);
-#else
- EXPECT_EQ(k32BitSwappedTestData, le);
-#endif
-}
-
-TEST(ByteOrderTest, ByteSwapToLE64) {
- uint64_t le = base::ByteSwapToLE64(k64BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k64BitTestData, le);
-#else
- EXPECT_EQ(k64BitSwappedTestData, le);
-#endif
-}
-
-TEST(ByteOrderTest, NetToHost16) {
- uint16_t h = base::NetToHost16(k16BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k16BitSwappedTestData, h);
-#else
- EXPECT_EQ(k16BitTestData, h);
-#endif
-}
-
-TEST(ByteOrderTest, NetToHost32) {
- uint32_t h = base::NetToHost32(k32BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k32BitSwappedTestData, h);
-#else
- EXPECT_EQ(k32BitTestData, h);
-#endif
-}
-
-TEST(ByteOrderTest, NetToHost64) {
- uint64_t h = base::NetToHost64(k64BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k64BitSwappedTestData, h);
-#else
- EXPECT_EQ(k64BitTestData, h);
-#endif
-}
-
-TEST(ByteOrderTest, HostToNet16) {
- uint16_t n = base::HostToNet16(k16BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k16BitSwappedTestData, n);
-#else
- EXPECT_EQ(k16BitTestData, n);
-#endif
-}
-
-TEST(ByteOrderTest, HostToNet32) {
- uint32_t n = base::HostToNet32(k32BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k32BitSwappedTestData, n);
-#else
- EXPECT_EQ(k32BitTestData, n);
-#endif
-}
-
-TEST(ByteOrderTest, HostToNet64) {
- uint64_t n = base::HostToNet64(k64BitTestData);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
- EXPECT_EQ(k64BitSwappedTestData, n);
-#else
- EXPECT_EQ(k64BitTestData, n);
-#endif
-}
diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc
deleted file mode 100644
index 77047962f1..0000000000
--- a/base/sys_info_android.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/sys_info.h"
-
-#include <dlfcn.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/system_properties.h>
-
-#include "base/android/jni_android.h"
-#include "base/android/sys_utils.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/sys_info_internal.h"
-
-#if (__ANDROID_API__ >= 21 /* 5.0 - Lollipop */)
-
-namespace {
-
-typedef int (SystemPropertyGetFunction)(const char*, char*);
-
-SystemPropertyGetFunction* DynamicallyLoadRealSystemPropertyGet() {
- // libc.so should already be open, get a handle to it.
- void* handle = dlopen("libc.so", RTLD_NOLOAD);
- if (!handle) {
- LOG(FATAL) << "Cannot dlopen libc.so: " << dlerror();
- }
- SystemPropertyGetFunction* real_system_property_get =
- reinterpret_cast<SystemPropertyGetFunction*>(
- dlsym(handle, "__system_property_get"));
- if (!real_system_property_get) {
- LOG(FATAL) << "Cannot resolve __system_property_get(): " << dlerror();
- }
- return real_system_property_get;
-}
-
-static base::LazyInstance<base::internal::LazySysInfoValue<
- SystemPropertyGetFunction*, DynamicallyLoadRealSystemPropertyGet> >::Leaky
- g_lazy_real_system_property_get = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-// Android 'L' removes __system_property_get from the NDK, however it is still
-// a hidden symbol in libc. Until we remove all calls of __system_property_get
-// from Chrome we work around this by defining a weak stub here, which uses
-// dlsym to but ensures that Chrome uses the real system
-// implementatation when loaded. http://crbug.com/392191.
-BASE_EXPORT int __system_property_get(const char* name, char* value) {
- return g_lazy_real_system_property_get.Get().value()(name, value);
-}
-
-#endif
-
-namespace {
-
-// Default version of Android to fall back to when actual version numbers
-// cannot be acquired. Use the latest Android release with a higher bug fix
-// version to avoid unnecessarily comparison errors with the latest release.
-// This should be manually kept up to date on each Android release.
-const int kDefaultAndroidMajorVersion = 8;
-const int kDefaultAndroidMinorVersion = 1;
-const int kDefaultAndroidBugfixVersion = 99;
-
-// Get and parse out the OS version numbers from the system properties.
-// Note if parse fails, the "default" version is returned as fallback.
-void GetOsVersionStringAndNumbers(std::string* version_string,
- int32_t* major_version,
- int32_t* minor_version,
- int32_t* bugfix_version) {
- // Read the version number string out from the properties.
- char os_version_str[PROP_VALUE_MAX];
- __system_property_get("ro.build.version.release", os_version_str);
-
- if (os_version_str[0]) {
- // Try to parse out the version numbers from the string.
- int num_read = sscanf(os_version_str, "%d.%d.%d", major_version,
- minor_version, bugfix_version);
-
- if (num_read > 0) {
- // If we don't have a full set of version numbers, make the extras 0.
- if (num_read < 2)
- *minor_version = 0;
- if (num_read < 3)
- *bugfix_version = 0;
- *version_string = std::string(os_version_str);
- return;
- }
- }
-
- // For some reason, we couldn't parse the version number string.
- *major_version = kDefaultAndroidMajorVersion;
- *minor_version = kDefaultAndroidMinorVersion;
- *bugfix_version = kDefaultAndroidBugfixVersion;
- *version_string = ::base::StringPrintf("%d.%d.%d", *major_version,
- *minor_version, *bugfix_version);
-}
-
-// Parses a system property (specified with unit 'k','m' or 'g').
-// Returns a value in bytes.
-// Returns -1 if the string could not be parsed.
-int64_t ParseSystemPropertyBytes(const base::StringPiece& str) {
- const int64_t KB = 1024;
- const int64_t MB = 1024 * KB;
- const int64_t GB = 1024 * MB;
- if (str.size() == 0u)
- return -1;
- int64_t unit_multiplier = 1;
- size_t length = str.size();
- if (str[length - 1] == 'k') {
- unit_multiplier = KB;
- length--;
- } else if (str[length - 1] == 'm') {
- unit_multiplier = MB;
- length--;
- } else if (str[length - 1] == 'g') {
- unit_multiplier = GB;
- length--;
- }
- int64_t result = 0;
- bool parsed = base::StringToInt64(str.substr(0, length), &result);
- bool negative = result <= 0;
- bool overflow =
- result >= std::numeric_limits<int64_t>::max() / unit_multiplier;
- if (!parsed || negative || overflow)
- return -1;
- return result * unit_multiplier;
-}
-
-int GetDalvikHeapSizeMB() {
- char heap_size_str[PROP_VALUE_MAX];
- __system_property_get("dalvik.vm.heapsize", heap_size_str);
- // dalvik.vm.heapsize property is writable by a root user.
- // Clamp it to reasonable range as a sanity check,
- // a typical android device will never have less than 48MB.
- const int64_t MB = 1024 * 1024;
- int64_t result = ParseSystemPropertyBytes(heap_size_str);
- if (result == -1) {
- // We should consider not exposing these values if they are not reliable.
- LOG(ERROR) << "Can't parse dalvik.vm.heapsize: " << heap_size_str;
- result = base::SysInfo::AmountOfPhysicalMemoryMB() / 3;
- }
- result =
- std::min<int64_t>(std::max<int64_t>(32 * MB, result), 1024 * MB) / MB;
- return static_cast<int>(result);
-}
-
-int GetDalvikHeapGrowthLimitMB() {
- char heap_size_str[PROP_VALUE_MAX];
- __system_property_get("dalvik.vm.heapgrowthlimit", heap_size_str);
- // dalvik.vm.heapgrowthlimit property is writable by a root user.
- // Clamp it to reasonable range as a sanity check,
- // a typical android device will never have less than 24MB.
- const int64_t MB = 1024 * 1024;
- int64_t result = ParseSystemPropertyBytes(heap_size_str);
- if (result == -1) {
- // We should consider not exposing these values if they are not reliable.
- LOG(ERROR) << "Can't parse dalvik.vm.heapgrowthlimit: " << heap_size_str;
- result = base::SysInfo::AmountOfPhysicalMemoryMB() / 6;
- }
- result = std::min<int64_t>(std::max<int64_t>(16 * MB, result), 512 * MB) / MB;
- return static_cast<int>(result);
-}
-
-} // anonymous namespace
-
-namespace base {
-
-std::string SysInfo::HardwareModelName() {
- char device_model_str[PROP_VALUE_MAX];
- __system_property_get("ro.product.model", device_model_str);
- return std::string(device_model_str);
-}
-
-std::string SysInfo::OperatingSystemName() {
- return "Android";
-}
-
-std::string SysInfo::OperatingSystemVersion() {
- std::string version_string;
- int32_t major, minor, bugfix;
- GetOsVersionStringAndNumbers(&version_string, &major, &minor, &bugfix);
- return version_string;
-}
-
-void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
- int32_t* minor_version,
- int32_t* bugfix_version) {
- std::string version_string;
- GetOsVersionStringAndNumbers(&version_string, major_version, minor_version,
- bugfix_version);
-}
-
-std::string SysInfo::GetAndroidBuildCodename() {
- char os_version_codename_str[PROP_VALUE_MAX];
- __system_property_get("ro.build.version.codename", os_version_codename_str);
- return std::string(os_version_codename_str);
-}
-
-std::string SysInfo::GetAndroidBuildID() {
- char os_build_id_str[PROP_VALUE_MAX];
- __system_property_get("ro.build.id", os_build_id_str);
- return std::string(os_build_id_str);
-}
-
-int SysInfo::DalvikHeapSizeMB() {
- static int heap_size = GetDalvikHeapSizeMB();
- return heap_size;
-}
-
-int SysInfo::DalvikHeapGrowthLimitMB() {
- static int heap_growth_limit = GetDalvikHeapGrowthLimitMB();
- return heap_growth_limit;
-}
-
-static base::LazyInstance<
- base::internal::LazySysInfoValue<bool,
- android::SysUtils::IsLowEndDeviceFromJni> >::Leaky
- g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER;
-
-bool SysInfo::IsLowEndDeviceImpl() {
- // This code might be used in some environments
- // which might not have a Java environment.
- // Note that we need to call the Java version here.
- // There exists a complete native implementation in
- // sys_info.cc but calling that here would mean that
- // the Java code and the native code would call different
- // implementations which could give different results.
- // Also the Java code cannot depend on the native code
- // since it might not be loaded yet.
- if (!base::android::IsVMInitialized())
- return false;
- return g_lazy_low_end_device.Get().value();
-}
-
-
-} // namespace base
diff --git a/base/syslog_logging.cc b/base/syslog_logging.cc
deleted file mode 100644
index 53bc1aaab6..0000000000
--- a/base/syslog_logging.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2016 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/syslog_logging.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/debug/stack_trace.h"
-#elif defined(OS_LINUX)
-// <syslog.h> defines LOG_INFO, LOG_WARNING macros that could conflict with
-// base::LOG_INFO, base::LOG_WARNING.
-#include <syslog.h>
-#undef LOG_INFO
-#undef LOG_WARNING
-#endif
-
-#include <ostream>
-#include <string>
-
-namespace logging {
-
-#if defined(OS_WIN)
-
-namespace {
-
-std::string* g_event_source_name = nullptr;
-uint16_t g_category = 0;
-uint32_t g_event_id = 0;
-
-} // namespace
-
-void SetEventSource(const std::string& name,
- uint16_t category,
- uint32_t event_id) {
- DCHECK_EQ(nullptr, g_event_source_name);
- g_event_source_name = new std::string(name);
- g_category = category;
- g_event_id = event_id;
-}
-
-#endif // defined(OS_WIN)
-
-EventLogMessage::EventLogMessage(const char* file,
- int line,
- LogSeverity severity)
- : log_message_(file, line, severity) {
-}
-
-EventLogMessage::~EventLogMessage() {
-#if defined(OS_WIN)
- // If g_event_source_name is nullptr (which it is per default) SYSLOG will
- // degrade gracefully to regular LOG. If you see this happening most probably
- // you are using SYSLOG before you called SetEventSourceName.
- if (g_event_source_name == nullptr)
- return;
-
- HANDLE event_log_handle =
- RegisterEventSourceA(nullptr, g_event_source_name->c_str());
- if (event_log_handle == nullptr) {
- stream() << " !!NOT ADDED TO EVENTLOG!!";
- return;
- }
-
- base::ScopedClosureRunner auto_deregister(
- base::Bind(base::IgnoreResult(&DeregisterEventSource), event_log_handle));
- std::string message(log_message_.str());
- WORD log_type = EVENTLOG_ERROR_TYPE;
- switch (log_message_.severity()) {
- case LOG_INFO:
- log_type = EVENTLOG_INFORMATION_TYPE;
- break;
- case LOG_WARNING:
- log_type = EVENTLOG_WARNING_TYPE;
- break;
- case LOG_ERROR:
- case LOG_FATAL:
- // The price of getting the stack trace is not worth the hassle for
- // non-error conditions.
- base::debug::StackTrace trace;
- message.append(trace.ToString());
- log_type = EVENTLOG_ERROR_TYPE;
- break;
- }
- LPCSTR strings[1] = {message.data()};
- if (!ReportEventA(event_log_handle, log_type, g_category, g_event_id, nullptr,
- 1, 0, strings, nullptr)) {
- stream() << " !!NOT ADDED TO EVENTLOG!!";
- }
-#elif defined(OS_LINUX)
- const char kEventSource[] = "chrome";
- openlog(kEventSource, LOG_NOWAIT | LOG_PID, LOG_USER);
- // We can't use the defined names for the logging severity from syslog.h
- // because they collide with the names of our own severity levels. Therefore
- // we use the actual values which of course do not match ours.
- // See sys/syslog.h for reference.
- int priority = 3;
- switch (log_message_.severity()) {
- case LOG_INFO:
- priority = 6;
- break;
- case LOG_WARNING:
- priority = 4;
- break;
- case LOG_ERROR:
- priority = 3;
- break;
- case LOG_FATAL:
- priority = 2;
- break;
- }
- syslog(priority, "%s", log_message_.str().c_str());
- closelog();
-#endif // defined(OS_WIN)
-}
-
-} // namespace logging
diff --git a/base/syslog_logging.h b/base/syslog_logging.h
deleted file mode 100644
index 736a5b2efe..0000000000
--- a/base/syslog_logging.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_SYSLOG_LOGGING_H_
-#define BASE_SYSLOG_LOGGING_H_
-
-#include <iosfwd>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-namespace logging {
-
-// Keep in mind that the syslog is always active regardless of the logging level
-// and applied flags. Use only for important information that a system
-// administrator might need to maintain the browser installation.
-#define SYSLOG_STREAM(severity) \
- COMPACT_GOOGLE_LOG_EX_ ## severity(EventLogMessage).stream()
-#define SYSLOG(severity) \
- SYSLOG_STREAM(severity)
-
-#if defined(OS_WIN)
-// Sets the name, category and event id of the event source for logging to the
-// Windows Event Log. Call this function once before using the SYSLOG macro or
-// otherwise it will behave as a regular LOG macro.
-void BASE_EXPORT SetEventSource(const std::string& name,
- uint16_t category,
- uint32_t event_id);
-#endif // defined(OS_WIN)
-
-// Creates a formatted message on the system event log. That would be the
-// Application Event log on Windows and the messages log file on POSIX systems.
-class BASE_EXPORT EventLogMessage {
- public:
- EventLogMessage(const char* file, int line, LogSeverity severity);
-
- ~EventLogMessage();
-
- std::ostream& stream() { return log_message_.stream(); }
-
- private:
- LogMessage log_message_;
-
- DISALLOW_COPY_AND_ASSIGN(EventLogMessage);
-};
-
-} // namespace logging
-
-#endif // BASE_SYSLOG_LOGGING_H_
diff --git a/base/system_monitor/system_monitor.cc b/base/system_monitor/system_monitor.cc
deleted file mode 100644
index 71e4f07847..0000000000
--- a/base/system_monitor/system_monitor.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/system_monitor/system_monitor.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "base/time/time.h"
-
-namespace base {
-
-static SystemMonitor* g_system_monitor = nullptr;
-
-SystemMonitor::SystemMonitor()
- : devices_changed_observer_list_(
- new ObserverListThreadSafe<DevicesChangedObserver>()) {
- DCHECK(!g_system_monitor);
- g_system_monitor = this;
-}
-
-SystemMonitor::~SystemMonitor() {
- DCHECK_EQ(this, g_system_monitor);
- g_system_monitor = nullptr;
-}
-
-// static
-SystemMonitor* SystemMonitor::Get() {
- return g_system_monitor;
-}
-
-void SystemMonitor::ProcessDevicesChanged(DeviceType device_type) {
- NotifyDevicesChanged(device_type);
-}
-
-void SystemMonitor::AddDevicesChangedObserver(DevicesChangedObserver* obs) {
- devices_changed_observer_list_->AddObserver(obs);
-}
-
-void SystemMonitor::RemoveDevicesChangedObserver(DevicesChangedObserver* obs) {
- devices_changed_observer_list_->RemoveObserver(obs);
-}
-
-void SystemMonitor::NotifyDevicesChanged(DeviceType device_type) {
- DVLOG(1) << "DevicesChanged with device type " << device_type;
- devices_changed_observer_list_->Notify(
- FROM_HERE, &DevicesChangedObserver::OnDevicesChanged, device_type);
-}
-
-} // namespace base
diff --git a/base/system_monitor/system_monitor.h b/base/system_monitor/system_monitor.h
deleted file mode 100644
index 7f21e47bad..0000000000
--- a/base/system_monitor/system_monitor.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_SYSTEM_MONITOR_SYSTEM_MONITOR_H_
-#define BASE_SYSTEM_MONITOR_SYSTEM_MONITOR_H_
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/observer_list_threadsafe.h"
-#include "build/build_config.h"
-
-namespace base {
-
-// Class for monitoring various system-related subsystems
-// such as power management, network status, etc.
-// TODO(mbelshe): Add support beyond just power management.
-class BASE_EXPORT SystemMonitor {
- public:
- // Type of devices whose change need to be monitored, such as add/remove.
- enum DeviceType {
- DEVTYPE_AUDIO, // Audio device, e.g., microphone.
- DEVTYPE_VIDEO_CAPTURE, // Video capture device, e.g., webcam.
- DEVTYPE_UNKNOWN, // Other devices.
- };
-
- // Create SystemMonitor. Only one SystemMonitor instance per application
- // is allowed.
- SystemMonitor();
- ~SystemMonitor();
-
- // Get the application-wide SystemMonitor (if not present, returns NULL).
- static SystemMonitor* Get();
-
- class BASE_EXPORT DevicesChangedObserver {
- public:
- // Notification that the devices connected to the system have changed.
- // This is only implemented on Windows currently.
- virtual void OnDevicesChanged(DeviceType device_type) {}
-
- protected:
- virtual ~DevicesChangedObserver() = default;
- };
-
- // Add a new observer.
- // Can be called from any thread.
- // Must not be called from within a notification callback.
- void AddDevicesChangedObserver(DevicesChangedObserver* obs);
-
- // Remove an existing observer.
- // Can be called from any thread.
- // Must not be called from within a notification callback.
- void RemoveDevicesChangedObserver(DevicesChangedObserver* obs);
-
- // The ProcessFoo() style methods are a broken pattern and should not
- // be copied. Any significant addition to this class is blocked on
- // refactoring to improve the state of affairs. See http://crbug.com/149059
-
- // Cross-platform handling of a device change event.
- void ProcessDevicesChanged(DeviceType device_type);
-
- private:
- // Functions to trigger notifications.
- void NotifyDevicesChanged(DeviceType device_type);
-
- scoped_refptr<ObserverListThreadSafe<DevicesChangedObserver> >
- devices_changed_observer_list_;
-
- DISALLOW_COPY_AND_ASSIGN(SystemMonitor);
-};
-
-} // namespace base
-
-#endif // BASE_SYSTEM_MONITOR_SYSTEM_MONITOR_H_
diff --git a/base/system_monitor/system_monitor_unittest.cc b/base/system_monitor/system_monitor_unittest.cc
deleted file mode 100644
index 8963f7b072..0000000000
--- a/base/system_monitor/system_monitor_unittest.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/system_monitor/system_monitor.h"
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/test/mock_devices_changed_observer.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class SystemMonitorTest : public testing::Test {
- protected:
- SystemMonitorTest() {
- system_monitor_.reset(new SystemMonitor);
- }
-
- MessageLoop message_loop_;
- std::unique_ptr<SystemMonitor> system_monitor_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SystemMonitorTest);
-};
-
-TEST_F(SystemMonitorTest, DeviceChangeNotifications) {
- const int kObservers = 5;
-
- testing::Sequence mock_sequencer[kObservers];
- MockDevicesChangedObserver observers[kObservers];
- for (int index = 0; index < kObservers; ++index) {
- system_monitor_->AddDevicesChangedObserver(&observers[index]);
-
- EXPECT_CALL(observers[index],
- OnDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN))
- .Times(3)
- .InSequence(mock_sequencer[index]);
- }
-
- system_monitor_->ProcessDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN);
- RunLoop().RunUntilIdle();
-
- system_monitor_->ProcessDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN);
- system_monitor_->ProcessDevicesChanged(SystemMonitor::DEVTYPE_UNKNOWN);
- RunLoop().RunUntilIdle();
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/task_scheduler/delayed_task_manager_unittest.cc b/base/task_scheduler/delayed_task_manager_unittest.cc
deleted file mode 100644
index 67c797acde..0000000000
--- a/base/task_scheduler/delayed_task_manager_unittest.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2016 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/task_scheduler/delayed_task_manager.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/task.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/threading/thread.h"
-#include "base/time/time.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-namespace {
-
-constexpr TimeDelta kLongDelay = TimeDelta::FromHours(1);
-
-class MockTask {
- public:
- MOCK_METHOD0(Run, void());
-};
-
-void RunTask(Task task) {
- std::move(task.task).Run();
-}
-
-class TaskSchedulerDelayedTaskManagerTest : public testing::Test {
- protected:
- TaskSchedulerDelayedTaskManagerTest()
- : delayed_task_manager_(
- service_thread_task_runner_->DeprecatedGetMockTickClock()),
- task_(FROM_HERE,
- BindOnce(&MockTask::Run, Unretained(&mock_task_)),
- TaskTraits(),
- kLongDelay) {
- // The constructor of Task computes |delayed_run_time| by adding |delay| to
- // the real time. Recompute it by adding |delay| to the mock time.
- task_.delayed_run_time =
- service_thread_task_runner_->GetMockTickClock()->NowTicks() +
- kLongDelay;
- }
- ~TaskSchedulerDelayedTaskManagerTest() override = default;
-
- const scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner_ =
- MakeRefCounted<TestMockTimeTaskRunner>();
- DelayedTaskManager delayed_task_manager_;
- testing::StrictMock<MockTask> mock_task_;
- Task task_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerDelayedTaskManagerTest);
-};
-
-} // namespace
-
-// Verify that a delayed task isn't forwarded before Start().
-TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunBeforeStart) {
- // Send |task| to the DelayedTaskManager.
- delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
-
- // Fast-forward time until the task is ripe for execution. Since Start() has
- // not been called, the task should not be forwarded to RunTask() (MockTask is
- // a StrictMock without expectations so test will fail if RunTask() runs it).
- service_thread_task_runner_->FastForwardBy(kLongDelay);
-}
-
-// Verify that a delayed task added before Start() and whose delay expires after
-// Start() is forwarded when its delay expires.
-TEST_F(TaskSchedulerDelayedTaskManagerTest,
- DelayedTaskPostedBeforeStartExpiresAfterStartRunsOnExpire) {
- // Send |task| to the DelayedTaskManager.
- delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
-
- delayed_task_manager_.Start(service_thread_task_runner_);
-
- // Run tasks on the service thread. Don't expect any forwarding to
- // |task_target_| since the task isn't ripe for execution.
- service_thread_task_runner_->RunUntilIdle();
-
- // Fast-forward time until the task is ripe for execution. Expect the task to
- // be forwarded to RunTask().
- EXPECT_CALL(mock_task_, Run());
- service_thread_task_runner_->FastForwardBy(kLongDelay);
-}
-
-// Verify that a delayed task added before Start() and whose delay expires
-// before Start() is forwarded when Start() is called.
-TEST_F(TaskSchedulerDelayedTaskManagerTest,
- DelayedTaskPostedBeforeStartExpiresBeforeStartRunsOnStart) {
- // Send |task| to the DelayedTaskManager.
- delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
-
- // Run tasks on the service thread. Don't expect any forwarding to
- // |task_target_| since the task isn't ripe for execution.
- service_thread_task_runner_->RunUntilIdle();
-
- // Fast-forward time until the task is ripe for execution. Don't expect the
- // task to be forwarded since Start() hasn't been called yet.
- service_thread_task_runner_->FastForwardBy(kLongDelay);
-
- // Start the DelayedTaskManager. Expect the task to be forwarded to RunTask().
- EXPECT_CALL(mock_task_, Run());
- delayed_task_manager_.Start(service_thread_task_runner_);
- service_thread_task_runner_->RunUntilIdle();
-}
-
-// Verify that a delayed task added after Start() isn't forwarded before it is
-// ripe for execution.
-TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunTooEarly) {
- delayed_task_manager_.Start(service_thread_task_runner_);
-
- // Send |task| to the DelayedTaskManager.
- delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
-
- // Run tasks that are ripe for execution. Don't expect any forwarding to
- // RunTask().
- service_thread_task_runner_->RunUntilIdle();
-}
-
-// Verify that a delayed task added after Start() is forwarded when it is ripe
-// for execution.
-TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskRunsAfterDelay) {
- delayed_task_manager_.Start(service_thread_task_runner_);
-
- // Send |task| to the DelayedTaskManager.
- delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
-
- // Fast-forward time. Expect the task to be forwarded to RunTask().
- EXPECT_CALL(mock_task_, Run());
- service_thread_task_runner_->FastForwardBy(kLongDelay);
-}
-
-// Verify that multiple delayed tasks added after Start() are forwarded when
-// they are ripe for execution.
-TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTasksRunAfterDelay) {
- delayed_task_manager_.Start(service_thread_task_runner_);
-
- testing::StrictMock<MockTask> mock_task_a;
- Task task_a(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_a)),
- TaskTraits(), TimeDelta::FromHours(1));
-
- testing::StrictMock<MockTask> mock_task_b;
- Task task_b(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_b)),
- TaskTraits(), TimeDelta::FromHours(2));
-
- testing::StrictMock<MockTask> mock_task_c;
- Task task_c(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_c)),
- TaskTraits(), TimeDelta::FromHours(1));
-
- // Send tasks to the DelayedTaskManager.
- delayed_task_manager_.AddDelayedTask(std::move(task_a), BindOnce(&RunTask));
- delayed_task_manager_.AddDelayedTask(std::move(task_b), BindOnce(&RunTask));
- delayed_task_manager_.AddDelayedTask(std::move(task_c), BindOnce(&RunTask));
-
- // Run tasks that are ripe for execution on the service thread. Don't expect
- // any call to RunTask().
- service_thread_task_runner_->RunUntilIdle();
-
- // Fast-forward time. Expect |task_a| and |task_c| to be forwarded to
- // |task_target_|.
- EXPECT_CALL(mock_task_a, Run());
- EXPECT_CALL(mock_task_c, Run());
- service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1));
- testing::Mock::VerifyAndClear(&mock_task_a);
- testing::Mock::VerifyAndClear(&mock_task_c);
-
- // Fast-forward time. Expect |task_b| to be forwarded to RunTask().
- EXPECT_CALL(mock_task_b, Run());
- service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1));
- testing::Mock::VerifyAndClear(&mock_task_b);
-}
-
-TEST_F(TaskSchedulerDelayedTaskManagerTest, PostTaskDuringStart) {
- Thread other_thread("Test");
- other_thread.StartAndWaitForTesting();
-
- WaitableEvent task_posted;
-
- other_thread.task_runner()->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
- delayed_task_manager_.AddDelayedTask(
- std::move(task_),
- BindOnce(&RunTask));
- task_posted.Signal();
- }));
-
- delayed_task_manager_.Start(service_thread_task_runner_);
-
- // The test is testing a race between AddDelayedTask/Start but it still needs
- // synchronization to ensure we don't do the final verification before the
- // task itself is posted.
- task_posted.Wait();
-
- // Fast-forward time. Expect the task to be forwarded to RunTask().
- EXPECT_CALL(mock_task_, Run());
- service_thread_task_runner_->FastForwardBy(kLongDelay);
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/initialization_util.cc b/base/task_scheduler/initialization_util.cc
deleted file mode 100644
index 7accd19c6f..0000000000
--- a/base/task_scheduler/initialization_util.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 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/task_scheduler/initialization_util.h"
-
-#include <algorithm>
-
-#include "base/sys_info.h"
-
-namespace base {
-
-int RecommendedMaxNumberOfThreadsInPool(int min,
- int max,
- double cores_multiplier,
- int offset) {
- const int num_of_cores = SysInfo::NumberOfProcessors();
- const int threads = std::ceil<int>(num_of_cores * cores_multiplier) + offset;
- return std::min(max, std::max(min, threads));
-}
-
-} // namespace base
diff --git a/base/task_scheduler/initialization_util.h b/base/task_scheduler/initialization_util.h
deleted file mode 100644
index c3bd9e7c4a..0000000000
--- a/base/task_scheduler/initialization_util.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TASK_SCHEDULER_INITIALIZATION_UTIL_H_
-#define BASE_TASK_SCHEDULER_INITIALIZATION_UTIL_H_
-
-#include "base/base_export.h"
-
-namespace base {
-
-// Computes a value that may be used as the maximum number of threads in a
-// TaskScheduler pool. Developers may use other methods to choose this maximum.
-BASE_EXPORT int RecommendedMaxNumberOfThreadsInPool(int min,
- int max,
- double cores_multiplier,
- int offset);
-
-} // namespace base
-
-#endif // BASE_TASK_SCHEDULER_INITIALIZATION_UTIL_H_
diff --git a/base/task_scheduler/priority_queue_unittest.cc b/base/task_scheduler/priority_queue_unittest.cc
deleted file mode 100644
index f131c55fe7..0000000000
--- a/base/task_scheduler/priority_queue_unittest.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2016 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/task_scheduler/priority_queue.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/sequence.h"
-#include "base/task_scheduler/task.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-class ThreadBeginningTransaction : public SimpleThread {
- public:
- explicit ThreadBeginningTransaction(PriorityQueue* priority_queue)
- : SimpleThread("ThreadBeginningTransaction"),
- priority_queue_(priority_queue) {}
-
- // SimpleThread:
- void Run() override {
- std::unique_ptr<PriorityQueue::Transaction> transaction =
- priority_queue_->BeginTransaction();
- transaction_began_.Signal();
- }
-
- void ExpectTransactionDoesNotBegin() {
- // After a few milliseconds, the call to BeginTransaction() should not have
- // returned.
- EXPECT_FALSE(
- transaction_began_.TimedWait(TimeDelta::FromMilliseconds(250)));
- }
-
- private:
- PriorityQueue* const priority_queue_;
- WaitableEvent transaction_began_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadBeginningTransaction);
-};
-
-} // namespace
-
-TEST(TaskSchedulerPriorityQueueTest, PushPopPeek) {
- // Create test sequences.
- scoped_refptr<Sequence> sequence_a(new Sequence);
- sequence_a->PushTask(Task(FROM_HERE, DoNothing(),
- TaskTraits(TaskPriority::USER_VISIBLE),
- TimeDelta()));
- SequenceSortKey sort_key_a = sequence_a->GetSortKey();
-
- scoped_refptr<Sequence> sequence_b(new Sequence);
- sequence_b->PushTask(Task(FROM_HERE, DoNothing(),
- TaskTraits(TaskPriority::USER_BLOCKING),
- TimeDelta()));
- SequenceSortKey sort_key_b = sequence_b->GetSortKey();
-
- scoped_refptr<Sequence> sequence_c(new Sequence);
- sequence_c->PushTask(Task(FROM_HERE, DoNothing(),
- TaskTraits(TaskPriority::USER_BLOCKING),
- TimeDelta()));
- SequenceSortKey sort_key_c = sequence_c->GetSortKey();
-
- scoped_refptr<Sequence> sequence_d(new Sequence);
- sequence_d->PushTask(Task(FROM_HERE, DoNothing(),
- TaskTraits(TaskPriority::BACKGROUND), TimeDelta()));
- SequenceSortKey sort_key_d = sequence_d->GetSortKey();
-
- // Create a PriorityQueue and a Transaction.
- PriorityQueue pq;
- auto transaction(pq.BeginTransaction());
- EXPECT_TRUE(transaction->IsEmpty());
-
- // Push |sequence_a| in the PriorityQueue. It becomes the sequence with the
- // highest priority.
- transaction->Push(sequence_a, sort_key_a);
- EXPECT_EQ(sort_key_a, transaction->PeekSortKey());
-
- // Push |sequence_b| in the PriorityQueue. It becomes the sequence with the
- // highest priority.
- transaction->Push(sequence_b, sort_key_b);
- EXPECT_EQ(sort_key_b, transaction->PeekSortKey());
-
- // Push |sequence_c| in the PriorityQueue. |sequence_b| is still the sequence
- // with the highest priority.
- transaction->Push(sequence_c, sort_key_c);
- EXPECT_EQ(sort_key_b, transaction->PeekSortKey());
-
- // Push |sequence_d| in the PriorityQueue. |sequence_b| is still the sequence
- // with the highest priority.
- transaction->Push(sequence_d, sort_key_d);
- EXPECT_EQ(sort_key_b, transaction->PeekSortKey());
-
- // Pop |sequence_b| from the PriorityQueue. |sequence_c| becomes the sequence
- // with the highest priority.
- EXPECT_EQ(sequence_b, transaction->PopSequence());
- EXPECT_EQ(sort_key_c, transaction->PeekSortKey());
-
- // Pop |sequence_c| from the PriorityQueue. |sequence_a| becomes the sequence
- // with the highest priority.
- EXPECT_EQ(sequence_c, transaction->PopSequence());
- EXPECT_EQ(sort_key_a, transaction->PeekSortKey());
-
- // Pop |sequence_a| from the PriorityQueue. |sequence_d| becomes the sequence
- // with the highest priority.
- EXPECT_EQ(sequence_a, transaction->PopSequence());
- EXPECT_EQ(sort_key_d, transaction->PeekSortKey());
-
- // Pop |sequence_d| from the PriorityQueue. It is now empty.
- EXPECT_EQ(sequence_d, transaction->PopSequence());
- EXPECT_TRUE(transaction->IsEmpty());
-}
-
-// Check that creating Transactions on the same thread for 2 unrelated
-// PriorityQueues causes a crash.
-TEST(TaskSchedulerPriorityQueueTest, IllegalTwoTransactionsSameThread) {
- PriorityQueue pq_a;
- PriorityQueue pq_b;
-
- EXPECT_DCHECK_DEATH(
- {
- std::unique_ptr<PriorityQueue::Transaction> transaction_a =
- pq_a.BeginTransaction();
- std::unique_ptr<PriorityQueue::Transaction> transaction_b =
- pq_b.BeginTransaction();
- });
-}
-
-// Check that it is possible to begin multiple Transactions for the same
-// PriorityQueue on different threads. The call to BeginTransaction() on the
-// second thread should block until the Transaction has ended on the first
-// thread.
-TEST(TaskSchedulerPriorityQueueTest, TwoTransactionsTwoThreads) {
- PriorityQueue pq;
-
- // Call BeginTransaction() on this thread and keep the Transaction alive.
- std::unique_ptr<PriorityQueue::Transaction> transaction =
- pq.BeginTransaction();
-
- // Call BeginTransaction() on another thread.
- ThreadBeginningTransaction thread_beginning_transaction(&pq);
- thread_beginning_transaction.Start();
-
- // After a few milliseconds, the call to BeginTransaction() on the other
- // thread should not have returned.
- thread_beginning_transaction.ExpectTransactionDoesNotBegin();
-
- // End the Transaction on the current thread.
- transaction.reset();
-
- // The other thread should exit after its call to BeginTransaction() returns.
- thread_beginning_transaction.Join();
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
deleted file mode 100644
index 8eb02f3a9d..0000000000
--- a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
+++ /dev/null
@@ -1,662 +0,0 @@
-// Copyright 2017 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/task_scheduler/scheduler_single_thread_task_runner_manager.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/memory/ptr_util.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/delayed_task_manager.h"
-#include "base/task_scheduler/environment_config.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/scheduler_worker_pool_params.h"
-#include "base/task_scheduler/task_tracker.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-
-#include "base/win/com_init_util.h"
-#include "base/win/current_module.h"
-#endif // defined(OS_WIN)
-
-namespace base {
-namespace internal {
-
-namespace {
-
-class TaskSchedulerSingleThreadTaskRunnerManagerTest : public testing::Test {
- public:
- TaskSchedulerSingleThreadTaskRunnerManagerTest()
- : service_thread_("TaskSchedulerServiceThread") {}
-
- void SetUp() override {
- service_thread_.Start();
- delayed_task_manager_.Start(service_thread_.task_runner());
- single_thread_task_runner_manager_ =
- std::make_unique<SchedulerSingleThreadTaskRunnerManager>(
- task_tracker_.GetTrackedRef(), &delayed_task_manager_);
- StartSingleThreadTaskRunnerManagerFromSetUp();
- }
-
- void TearDown() override {
- if (single_thread_task_runner_manager_)
- TearDownSingleThreadTaskRunnerManager();
- service_thread_.Stop();
- }
-
- protected:
- virtual void StartSingleThreadTaskRunnerManagerFromSetUp() {
- single_thread_task_runner_manager_->Start();
- }
-
- virtual void TearDownSingleThreadTaskRunnerManager() {
- single_thread_task_runner_manager_->JoinForTesting();
- single_thread_task_runner_manager_.reset();
- }
-
- Thread service_thread_;
- TaskTracker task_tracker_ = {"Test"};
- DelayedTaskManager delayed_task_manager_;
- std::unique_ptr<SchedulerSingleThreadTaskRunnerManager>
- single_thread_task_runner_manager_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTest);
-};
-
-void CaptureThreadRef(PlatformThreadRef* thread_ref) {
- ASSERT_TRUE(thread_ref);
- *thread_ref = PlatformThread::CurrentRef();
-}
-
-void CaptureThreadPriority(ThreadPriority* thread_priority) {
- ASSERT_TRUE(thread_priority);
- *thread_priority = PlatformThread::GetCurrentThreadPriority();
-}
-
-void CaptureThreadName(std::string* thread_name) {
- *thread_name = PlatformThread::GetName();
-}
-
-void ShouldNotRun() {
- ADD_FAILURE() << "Ran a task that shouldn't run.";
-}
-
-} // namespace
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) {
- scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::DEDICATED);
- scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::DEDICATED);
-
- PlatformThreadRef thread_ref_1;
- task_runner_1->PostTask(FROM_HERE,
- BindOnce(&CaptureThreadRef, &thread_ref_1));
- PlatformThreadRef thread_ref_2;
- task_runner_2->PostTask(FROM_HERE,
- BindOnce(&CaptureThreadRef, &thread_ref_2));
-
- task_tracker_.Shutdown();
-
- ASSERT_FALSE(thread_ref_1.is_null());
- ASSERT_FALSE(thread_ref_2.is_null());
- EXPECT_NE(thread_ref_1, thread_ref_2);
-}
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, SameThreadUsed) {
- scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::SHARED);
- scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::SHARED);
-
- PlatformThreadRef thread_ref_1;
- task_runner_1->PostTask(FROM_HERE,
- BindOnce(&CaptureThreadRef, &thread_ref_1));
- PlatformThreadRef thread_ref_2;
- task_runner_2->PostTask(FROM_HERE,
- BindOnce(&CaptureThreadRef, &thread_ref_2));
-
- task_tracker_.Shutdown();
-
- ASSERT_FALSE(thread_ref_1.is_null());
- ASSERT_FALSE(thread_ref_2.is_null());
- EXPECT_EQ(thread_ref_1, thread_ref_2);
-}
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest,
- RunsTasksInCurrentSequence) {
- scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::DEDICATED);
- scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::DEDICATED);
-
- EXPECT_FALSE(task_runner_1->RunsTasksInCurrentSequence());
- EXPECT_FALSE(task_runner_2->RunsTasksInCurrentSequence());
-
- task_runner_1->PostTask(
- FROM_HERE,
- BindOnce(
- [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
- scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
- EXPECT_TRUE(task_runner_1->RunsTasksInCurrentSequence());
- EXPECT_FALSE(task_runner_2->RunsTasksInCurrentSequence());
- },
- task_runner_1, task_runner_2));
-
- task_runner_2->PostTask(
- FROM_HERE,
- BindOnce(
- [](scoped_refptr<SingleThreadTaskRunner> task_runner_1,
- scoped_refptr<SingleThreadTaskRunner> task_runner_2) {
- EXPECT_FALSE(task_runner_1->RunsTasksInCurrentSequence());
- EXPECT_TRUE(task_runner_2->RunsTasksInCurrentSequence());
- },
- task_runner_1, task_runner_2));
-
- task_tracker_.Shutdown();
-}
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest,
- SharedWithBaseSyncPrimitivesDCHECKs) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- EXPECT_DCHECK_DEATH({
- single_thread_task_runner_manager_->CreateSingleThreadTaskRunnerWithTraits(
- {WithBaseSyncPrimitives()}, SingleThreadTaskRunnerThreadMode::SHARED);
- });
-}
-
-// Regression test for https://crbug.com/829786
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest,
- ContinueOnShutdownDoesNotBlockBlockShutdown) {
- WaitableEvent task_has_started;
- WaitableEvent task_can_continue;
-
- // Post a CONTINUE_ON_SHUTDOWN task that waits on
- // |task_can_continue| to a shared SingleThreadTaskRunner.
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::SHARED)
- ->PostTask(FROM_HERE, base::BindOnce(
- [](WaitableEvent* task_has_started,
- WaitableEvent* task_can_continue) {
- task_has_started->Signal();
- ScopedAllowBaseSyncPrimitivesForTesting
- allow_base_sync_primitives;
- task_can_continue->Wait();
- },
- Unretained(&task_has_started),
- Unretained(&task_can_continue)));
-
- task_has_started.Wait();
-
- // Post a BLOCK_SHUTDOWN task to a shared SingleThreadTaskRunner.
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::SHARED)
- ->PostTask(FROM_HERE, DoNothing());
-
- // Shutdown should not hang even though the first task hasn't finished.
- task_tracker_.Shutdown();
-
- // Let the first task finish.
- task_can_continue.Signal();
-
- // Tear down from the test body to prevent accesses to |task_can_continue|
- // after it goes out of scope.
- TearDownSingleThreadTaskRunnerManager();
-}
-
-namespace {
-
-class TaskSchedulerSingleThreadTaskRunnerManagerCommonTest
- : public TaskSchedulerSingleThreadTaskRunnerManagerTest,
- public ::testing::WithParamInterface<SingleThreadTaskRunnerThreadMode> {
- public:
- TaskSchedulerSingleThreadTaskRunnerManagerCommonTest() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- TaskSchedulerSingleThreadTaskRunnerManagerCommonTest);
-};
-
-} // namespace
-
-TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest,
- PrioritySetCorrectly) {
- // Why are events used here instead of the task tracker?
- // Shutting down can cause priorities to get raised. This means we have to use
- // events to determine when a task is run.
- scoped_refptr<SingleThreadTaskRunner> task_runner_background =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits({TaskPriority::BACKGROUND},
- GetParam());
- scoped_refptr<SingleThreadTaskRunner> task_runner_normal =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits({TaskPriority::USER_VISIBLE},
- GetParam());
-
- ThreadPriority thread_priority_background;
- task_runner_background->PostTask(
- FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_background));
- WaitableEvent waitable_event_background;
- task_runner_background->PostTask(
- FROM_HERE,
- BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_background)));
-
- ThreadPriority thread_priority_normal;
- task_runner_normal->PostTask(
- FROM_HERE, BindOnce(&CaptureThreadPriority, &thread_priority_normal));
- WaitableEvent waitable_event_normal;
- task_runner_normal->PostTask(
- FROM_HERE,
- BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_normal)));
-
- waitable_event_background.Wait();
- waitable_event_normal.Wait();
-
- if (CanUseBackgroundPriorityForSchedulerWorker())
- EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background);
- else
- EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background);
- EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_normal);
-}
-
-TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, ThreadNamesSet) {
- constexpr TaskTraits foo_traits = {TaskPriority::BACKGROUND,
- TaskShutdownBehavior::BLOCK_SHUTDOWN};
- scoped_refptr<SingleThreadTaskRunner> foo_task_runner =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(foo_traits, GetParam());
- std::string foo_captured_name;
- foo_task_runner->PostTask(FROM_HERE,
- BindOnce(&CaptureThreadName, &foo_captured_name));
-
- constexpr TaskTraits user_blocking_traits = {
- TaskPriority::USER_BLOCKING, MayBlock(),
- TaskShutdownBehavior::BLOCK_SHUTDOWN};
- scoped_refptr<SingleThreadTaskRunner> user_blocking_task_runner =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(user_blocking_traits,
- GetParam());
-
- std::string user_blocking_captured_name;
- user_blocking_task_runner->PostTask(
- FROM_HERE, BindOnce(&CaptureThreadName, &user_blocking_captured_name));
-
- task_tracker_.Shutdown();
-
- EXPECT_NE(std::string::npos,
- foo_captured_name.find(
- kEnvironmentParams[GetEnvironmentIndexForTraits(foo_traits)]
- .name_suffix));
- EXPECT_NE(
- std::string::npos,
- user_blocking_captured_name.find(
- kEnvironmentParams[GetEnvironmentIndexForTraits(user_blocking_traits)]
- .name_suffix));
-
- if (GetParam() == SingleThreadTaskRunnerThreadMode::DEDICATED) {
- EXPECT_EQ(std::string::npos, foo_captured_name.find("Shared"));
- EXPECT_EQ(std::string::npos, user_blocking_captured_name.find("Shared"));
- } else {
- EXPECT_NE(std::string::npos, foo_captured_name.find("Shared"));
- EXPECT_NE(std::string::npos, user_blocking_captured_name.find("Shared"));
- }
-}
-
-TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest,
- PostTaskAfterShutdown) {
- auto task_runner =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits(), GetParam());
- task_tracker_.Shutdown();
- EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
-}
-
-// Verify that a Task runs shortly after its delay expires.
-TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest, PostDelayedTask) {
- TimeTicks start_time = TimeTicks::Now();
-
- WaitableEvent task_ran(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- auto task_runner =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits(), GetParam());
-
- // Wait until the task runner is up and running to make sure the test below is
- // solely timing the delayed task, not bringing up a physical thread.
- task_runner->PostTask(
- FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)));
- task_ran.Wait();
- ASSERT_TRUE(!task_ran.IsSignaled());
-
- // Post a task with a short delay.
- EXPECT_TRUE(task_runner->PostDelayedTask(
- FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_ran)),
- TestTimeouts::tiny_timeout()));
-
- // Wait until the task runs.
- task_ran.Wait();
-
- // Expect the task to run after its delay expires, but no more than 250 ms
- // after that.
- const TimeDelta actual_delay = TimeTicks::Now() - start_time;
- EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout());
- EXPECT_LT(actual_delay,
- TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout());
-}
-
-// Verify that posting tasks after the single-thread manager is destroyed fails
-// but doesn't crash.
-TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest,
- PostTaskAfterDestroy) {
- auto task_runner =
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits(), GetParam());
- EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
- task_tracker_.Shutdown();
- TearDownSingleThreadTaskRunnerManager();
- EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
-}
-
-INSTANTIATE_TEST_CASE_P(
- AllModes,
- TaskSchedulerSingleThreadTaskRunnerManagerCommonTest,
- ::testing::Values(SingleThreadTaskRunnerThreadMode::SHARED,
- SingleThreadTaskRunnerThreadMode::DEDICATED));
-
-namespace {
-
-class CallJoinFromDifferentThread : public SimpleThread {
- public:
- CallJoinFromDifferentThread(
- SchedulerSingleThreadTaskRunnerManager* manager_to_join)
- : SimpleThread("SchedulerSingleThreadTaskRunnerManagerJoinThread"),
- manager_to_join_(manager_to_join) {}
-
- ~CallJoinFromDifferentThread() override = default;
-
- void Run() override {
- run_started_event_.Signal();
- manager_to_join_->JoinForTesting();
- }
-
- void WaitForRunToStart() { run_started_event_.Wait(); }
-
- private:
- SchedulerSingleThreadTaskRunnerManager* const manager_to_join_;
- WaitableEvent run_started_event_;
-
- DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
-};
-
-class TaskSchedulerSingleThreadTaskRunnerManagerJoinTest
- : public TaskSchedulerSingleThreadTaskRunnerManagerTest {
- public:
- TaskSchedulerSingleThreadTaskRunnerManagerJoinTest() = default;
- ~TaskSchedulerSingleThreadTaskRunnerManagerJoinTest() override = default;
-
- protected:
- void TearDownSingleThreadTaskRunnerManager() override {
- // The tests themselves are responsible for calling JoinForTesting().
- single_thread_task_runner_manager_.reset();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest);
-};
-
-} // namespace
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) {
- // Exercises the codepath where the workers are unavailable for unregistration
- // because of a Join call.
- WaitableEvent task_running;
- WaitableEvent task_blocking;
-
- {
- auto task_runner = single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {WithBaseSyncPrimitives()},
- SingleThreadTaskRunnerThreadMode::DEDICATED);
- EXPECT_TRUE(task_runner->PostTask(
- FROM_HERE,
- BindOnce(&WaitableEvent::Signal, Unretained(&task_running))));
- EXPECT_TRUE(task_runner->PostTask(
- FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking))));
- }
-
- task_running.Wait();
- CallJoinFromDifferentThread join_from_different_thread(
- single_thread_task_runner_manager_.get());
- join_from_different_thread.Start();
- join_from_different_thread.WaitForRunToStart();
- task_blocking.Signal();
- join_from_different_thread.Join();
-}
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest,
- ConcurrentJoinExtraSkippedTask) {
- // Tests to make sure that tasks are properly cleaned up at Join, allowing
- // SingleThreadTaskRunners to unregister themselves.
- WaitableEvent task_running;
- WaitableEvent task_blocking;
-
- {
- auto task_runner = single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- {WithBaseSyncPrimitives()},
- SingleThreadTaskRunnerThreadMode::DEDICATED);
- EXPECT_TRUE(task_runner->PostTask(
- FROM_HERE,
- BindOnce(&WaitableEvent::Signal, Unretained(&task_running))));
- EXPECT_TRUE(task_runner->PostTask(
- FROM_HERE, BindOnce(&WaitableEvent::Wait, Unretained(&task_blocking))));
- EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
- }
-
- task_running.Wait();
- CallJoinFromDifferentThread join_from_different_thread(
- single_thread_task_runner_manager_.get());
- join_from_different_thread.Start();
- join_from_different_thread.WaitForRunToStart();
- task_blocking.Signal();
- join_from_different_thread.Join();
-}
-
-#if defined(OS_WIN)
-
-TEST_P(TaskSchedulerSingleThreadTaskRunnerManagerCommonTest,
- COMSTAInitialized) {
- scoped_refptr<SingleThreadTaskRunner> com_task_runner =
- single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN}, GetParam());
-
- com_task_runner->PostTask(FROM_HERE, BindOnce(&win::AssertComApartmentType,
- win::ComApartmentType::STA));
-
- task_tracker_.Shutdown();
-}
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTASameThreadUsed) {
- scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
- single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::SHARED);
- scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
- single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::SHARED);
-
- PlatformThreadRef thread_ref_1;
- task_runner_1->PostTask(FROM_HERE,
- BindOnce(&CaptureThreadRef, &thread_ref_1));
- PlatformThreadRef thread_ref_2;
- task_runner_2->PostTask(FROM_HERE,
- BindOnce(&CaptureThreadRef, &thread_ref_2));
-
- task_tracker_.Shutdown();
-
- ASSERT_FALSE(thread_ref_1.is_null());
- ASSERT_FALSE(thread_ref_2.is_null());
- EXPECT_EQ(thread_ref_1, thread_ref_2);
-}
-
-namespace {
-
-const wchar_t* const kTestWindowClassName =
- L"TaskSchedulerSingleThreadTaskRunnerManagerTestWinMessageWindow";
-
-class TaskSchedulerSingleThreadTaskRunnerManagerTestWin
- : public TaskSchedulerSingleThreadTaskRunnerManagerTest {
- public:
- TaskSchedulerSingleThreadTaskRunnerManagerTestWin() = default;
-
- void SetUp() override {
- TaskSchedulerSingleThreadTaskRunnerManagerTest::SetUp();
- register_class_succeeded_ = RegisterTestWindowClass();
- ASSERT_TRUE(register_class_succeeded_);
- }
-
- void TearDown() override {
- if (register_class_succeeded_)
- ::UnregisterClass(kTestWindowClassName, CURRENT_MODULE());
-
- TaskSchedulerSingleThreadTaskRunnerManagerTest::TearDown();
- }
-
- HWND CreateTestWindow() {
- return CreateWindow(kTestWindowClassName, kTestWindowClassName, 0, 0, 0, 0,
- 0, HWND_MESSAGE, nullptr, CURRENT_MODULE(), nullptr);
- }
-
- private:
- bool RegisterTestWindowClass() {
- WNDCLASSEX window_class = {};
- window_class.cbSize = sizeof(window_class);
- window_class.lpfnWndProc = &::DefWindowProc;
- window_class.hInstance = CURRENT_MODULE();
- window_class.lpszClassName = kTestWindowClassName;
- return !!::RegisterClassEx(&window_class);
- }
-
- bool register_class_succeeded_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin);
-};
-
-} // namespace
-
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) {
- scoped_refptr<SingleThreadTaskRunner> com_task_runner =
- single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- SingleThreadTaskRunnerThreadMode::DEDICATED);
- HWND hwnd = nullptr;
- // HWNDs process messages on the thread that created them, so we have to
- // create them within the context of the task runner to properly simulate a
- // COM callback.
- com_task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](TaskSchedulerSingleThreadTaskRunnerManagerTestWin* test_harness,
- HWND* hwnd) { *hwnd = test_harness->CreateTestWindow(); },
- Unretained(this), &hwnd));
-
- task_tracker_.FlushForTesting();
-
- ASSERT_NE(hwnd, nullptr);
- // If the message pump isn't running, we will hang here. This simulates how
- // COM would receive a callback with its own message HWND.
- SendMessage(hwnd, WM_USER, 0, 0);
-
- com_task_runner->PostTask(
- FROM_HERE, BindOnce([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd));
-
- task_tracker_.Shutdown();
-}
-
-#endif // defined(OS_WIN)
-
-namespace {
-
-class TaskSchedulerSingleThreadTaskRunnerManagerStartTest
- : public TaskSchedulerSingleThreadTaskRunnerManagerTest {
- public:
- TaskSchedulerSingleThreadTaskRunnerManagerStartTest() = default;
-
- private:
- void StartSingleThreadTaskRunnerManagerFromSetUp() override {
- // Start() is called in the test body rather than in SetUp().
- }
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerStartTest);
-};
-
-} // namespace
-
-// Verify that a task posted before Start() doesn't run until Start() is called.
-TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerStartTest,
- PostTaskBeforeStart) {
- AtomicFlag manager_started;
- WaitableEvent task_finished;
- single_thread_task_runner_manager_
- ->CreateSingleThreadTaskRunnerWithTraits(
- TaskTraits(), SingleThreadTaskRunnerThreadMode::DEDICATED)
- ->PostTask(
- FROM_HERE,
- BindOnce(
- [](WaitableEvent* task_finished, AtomicFlag* manager_started) {
- // The task should not run before Start().
- EXPECT_TRUE(manager_started->IsSet());
- task_finished->Signal();
- },
- Unretained(&task_finished), Unretained(&manager_started)));
-
- // Wait a little bit to make sure that the task doesn't run before start.
- // Note: This test won't catch a case where the task runs between setting
- // |manager_started| and calling Start(). However, we expect the test to be
- // flaky if the tested code allows that to happen.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- manager_started.Set();
- single_thread_task_runner_manager_->Start();
-
- // Wait for the task to complete to keep |manager_started| alive.
- task_finished.Wait();
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
deleted file mode 100644
index f510194770..0000000000
--- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
+++ /dev/null
@@ -1,1707 +0,0 @@
-// Copyright 2016 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/task_scheduler/scheduler_worker_pool_impl.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <unordered_set>
-#include <vector>
-
-#include "base/atomicops.h"
-#include "base/barrier_closure.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_runner.h"
-#include "base/task_scheduler/delayed_task_manager.h"
-#include "base/task_scheduler/scheduler_worker_pool_params.h"
-#include "base/task_scheduler/sequence.h"
-#include "base/task_scheduler/sequence_sort_key.h"
-#include "base/task_scheduler/task_tracker.h"
-#include "base/task_scheduler/test_task_factory.h"
-#include "base/task_scheduler/test_utils.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/scoped_blocking_call.h"
-#include "base/threading/simple_thread.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker_impl.h"
-#include "base/threading/thread_local_storage.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include "base/win/com_init_util.h"
-#endif // defined(OS_WIN)
-
-namespace base {
-namespace internal {
-namespace {
-
-constexpr size_t kMaxTasks = 4;
-constexpr size_t kNumThreadsPostingTasks = 4;
-constexpr size_t kNumTasksPostedPerThread = 150;
-// This can't be lower because Windows' WaitableEvent wakes up too early when a
-// small timeout is used. This results in many spurious wake ups before a worker
-// is allowed to cleanup.
-constexpr TimeDelta kReclaimTimeForCleanupTests =
- TimeDelta::FromMilliseconds(500);
-
-// Waits on |event| in a scope where the blocking observer is null, to avoid
-// affecting the max tasks.
-void WaitWithoutBlockingObserver(WaitableEvent* event) {
- internal::ScopedClearBlockingObserverForTesting clear_blocking_observer;
- ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
- event->Wait();
-}
-
-class TaskSchedulerWorkerPoolImplTestBase {
- protected:
- TaskSchedulerWorkerPoolImplTestBase()
- : service_thread_("TaskSchedulerServiceThread"){};
-
- void CommonSetUp(TimeDelta suggested_reclaim_time = TimeDelta::Max()) {
- CreateAndStartWorkerPool(suggested_reclaim_time, kMaxTasks);
- }
-
- void CommonTearDown() {
- service_thread_.Stop();
- task_tracker_.FlushForTesting();
- if (worker_pool_)
- worker_pool_->JoinForTesting();
- }
-
- void CreateWorkerPool() {
- ASSERT_FALSE(worker_pool_);
- service_thread_.Start();
- delayed_task_manager_.Start(service_thread_.task_runner());
- worker_pool_ = std::make_unique<SchedulerWorkerPoolImpl>(
- "TestWorkerPool", "A", ThreadPriority::NORMAL,
- task_tracker_.GetTrackedRef(), &delayed_task_manager_);
- ASSERT_TRUE(worker_pool_);
- }
-
- virtual void StartWorkerPool(TimeDelta suggested_reclaim_time,
- size_t max_tasks) {
- ASSERT_TRUE(worker_pool_);
- worker_pool_->Start(
- SchedulerWorkerPoolParams(max_tasks, suggested_reclaim_time), max_tasks,
- service_thread_.task_runner(), nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
- }
-
- void CreateAndStartWorkerPool(TimeDelta suggested_reclaim_time,
- size_t max_tasks) {
- CreateWorkerPool();
- StartWorkerPool(suggested_reclaim_time, max_tasks);
- }
-
- Thread service_thread_;
- TaskTracker task_tracker_ = {"Test"};
-
- std::unique_ptr<SchedulerWorkerPoolImpl> worker_pool_;
-
- private:
- DelayedTaskManager delayed_task_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTestBase);
-};
-
-class TaskSchedulerWorkerPoolImplTest
- : public TaskSchedulerWorkerPoolImplTestBase,
- public testing::Test {
- protected:
- TaskSchedulerWorkerPoolImplTest() = default;
-
- void SetUp() override { TaskSchedulerWorkerPoolImplTestBase::CommonSetUp(); }
-
- void TearDown() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonTearDown();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTest);
-};
-
-class TaskSchedulerWorkerPoolImplTestParam
- : public TaskSchedulerWorkerPoolImplTestBase,
- public testing::TestWithParam<test::ExecutionMode> {
- protected:
- TaskSchedulerWorkerPoolImplTestParam() = default;
-
- void SetUp() override { TaskSchedulerWorkerPoolImplTestBase::CommonSetUp(); }
-
- void TearDown() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonTearDown();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTestParam);
-};
-
-using PostNestedTask = test::TestTaskFactory::PostNestedTask;
-
-class ThreadPostingTasksWaitIdle : public SimpleThread {
- public:
- // Constructs a thread that posts tasks to |worker_pool| through an
- // |execution_mode| task runner. The thread waits until all workers in
- // |worker_pool| are idle before posting a new task.
- ThreadPostingTasksWaitIdle(SchedulerWorkerPoolImpl* worker_pool,
- test::ExecutionMode execution_mode)
- : SimpleThread("ThreadPostingTasksWaitIdle"),
- worker_pool_(worker_pool),
- factory_(CreateTaskRunnerWithExecutionMode(worker_pool, execution_mode),
- execution_mode) {
- DCHECK(worker_pool_);
- }
-
- const test::TestTaskFactory* factory() const { return &factory_; }
-
- private:
- void Run() override {
- EXPECT_FALSE(factory_.task_runner()->RunsTasksInCurrentSequence());
-
- for (size_t i = 0; i < kNumTasksPostedPerThread; ++i) {
- worker_pool_->WaitForAllWorkersIdleForTesting();
- EXPECT_TRUE(factory_.PostTask(PostNestedTask::NO, Closure()));
- }
- }
-
- SchedulerWorkerPoolImpl* const worker_pool_;
- const scoped_refptr<TaskRunner> task_runner_;
- test::TestTaskFactory factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasksWaitIdle);
-};
-
-} // namespace
-
-TEST_P(TaskSchedulerWorkerPoolImplTestParam, PostTasksWaitAllWorkersIdle) {
- // Create threads to post tasks. To verify that workers can sleep and be woken
- // up when new tasks are posted, wait for all workers to become idle before
- // posting a new task.
- std::vector<std::unique_ptr<ThreadPostingTasksWaitIdle>>
- threads_posting_tasks;
- for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) {
- threads_posting_tasks.push_back(
- std::make_unique<ThreadPostingTasksWaitIdle>(worker_pool_.get(),
- GetParam()));
- threads_posting_tasks.back()->Start();
- }
-
- // Wait for all tasks to run.
- for (const auto& thread_posting_tasks : threads_posting_tasks) {
- thread_posting_tasks->Join();
- thread_posting_tasks->factory()->WaitForAllTasksToRun();
- }
-
- // Wait until all workers are idle to be sure that no task accesses its
- // TestTaskFactory after |thread_posting_tasks| is destroyed.
- worker_pool_->WaitForAllWorkersIdleForTesting();
-}
-
-TEST_P(TaskSchedulerWorkerPoolImplTestParam, PostTasksWithOneAvailableWorker) {
- // Post blocking tasks to keep all workers busy except one until |event| is
- // signaled. Use different factories so that tasks are added to different
- // sequences and can run simultaneously when the execution mode is SEQUENCED.
- WaitableEvent event;
- std::vector<std::unique_ptr<test::TestTaskFactory>> blocked_task_factories;
- for (size_t i = 0; i < (kMaxTasks - 1); ++i) {
- blocked_task_factories.push_back(std::make_unique<test::TestTaskFactory>(
- CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()),
- GetParam()));
- EXPECT_TRUE(blocked_task_factories.back()->PostTask(
- PostNestedTask::NO,
- BindOnce(&WaitWithoutBlockingObserver, Unretained(&event))));
- blocked_task_factories.back()->WaitForAllTasksToRun();
- }
-
- // Post |kNumTasksPostedPerThread| tasks that should all run despite the fact
- // that only one worker in |worker_pool_| isn't busy.
- test::TestTaskFactory short_task_factory(
- CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()),
- GetParam());
- for (size_t i = 0; i < kNumTasksPostedPerThread; ++i)
- EXPECT_TRUE(short_task_factory.PostTask(PostNestedTask::NO, Closure()));
- short_task_factory.WaitForAllTasksToRun();
-
- // Release tasks waiting on |event|.
- event.Signal();
-
- // Wait until all workers are idle to be sure that no task accesses
- // its TestTaskFactory after it is destroyed.
- worker_pool_->WaitForAllWorkersIdleForTesting();
-}
-
-TEST_P(TaskSchedulerWorkerPoolImplTestParam, Saturate) {
- // Verify that it is possible to have |kMaxTasks| tasks/sequences running
- // simultaneously. Use different factories so that the blocking tasks are
- // added to different sequences and can run simultaneously when the execution
- // mode is SEQUENCED.
- WaitableEvent event;
- std::vector<std::unique_ptr<test::TestTaskFactory>> factories;
- for (size_t i = 0; i < kMaxTasks; ++i) {
- factories.push_back(std::make_unique<test::TestTaskFactory>(
- CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam()),
- GetParam()));
- EXPECT_TRUE(factories.back()->PostTask(
- PostNestedTask::NO,
- BindOnce(&WaitWithoutBlockingObserver, Unretained(&event))));
- factories.back()->WaitForAllTasksToRun();
- }
-
- // Release tasks waiting on |event|.
- event.Signal();
-
- // Wait until all workers are idle to be sure that no task accesses
- // its TestTaskFactory after it is destroyed.
- worker_pool_->WaitForAllWorkersIdleForTesting();
-}
-
-#if defined(OS_WIN)
-TEST_P(TaskSchedulerWorkerPoolImplTestParam, NoEnvironment) {
- // Verify that COM is not initialized in a SchedulerWorkerPoolImpl initialized
- // with SchedulerWorkerPoolImpl::WorkerEnvironment::NONE.
- scoped_refptr<TaskRunner> task_runner =
- CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam());
-
- WaitableEvent task_running;
- task_runner->PostTask(
- FROM_HERE, BindOnce(
- [](WaitableEvent* task_running) {
- win::AssertComApartmentType(win::ComApartmentType::NONE);
- task_running->Signal();
- },
- &task_running));
-
- task_running.Wait();
-
- worker_pool_->WaitForAllWorkersIdleForTesting();
-}
-#endif // defined(OS_WIN)
-
-INSTANTIATE_TEST_CASE_P(Parallel,
- TaskSchedulerWorkerPoolImplTestParam,
- ::testing::Values(test::ExecutionMode::PARALLEL));
-INSTANTIATE_TEST_CASE_P(Sequenced,
- TaskSchedulerWorkerPoolImplTestParam,
- ::testing::Values(test::ExecutionMode::SEQUENCED));
-
-#if defined(OS_WIN)
-
-namespace {
-
-class TaskSchedulerWorkerPoolImplTestCOMMTAParam
- : public TaskSchedulerWorkerPoolImplTestBase,
- public testing::TestWithParam<test::ExecutionMode> {
- protected:
- TaskSchedulerWorkerPoolImplTestCOMMTAParam() = default;
-
- void SetUp() override { TaskSchedulerWorkerPoolImplTestBase::CommonSetUp(); }
-
- void TearDown() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonTearDown();
- }
-
- private:
- void StartWorkerPool(TimeDelta suggested_reclaim_time,
- size_t max_tasks) override {
- ASSERT_TRUE(worker_pool_);
- worker_pool_->Start(
- SchedulerWorkerPoolParams(max_tasks, suggested_reclaim_time), max_tasks,
- service_thread_.task_runner(), nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::COM_MTA);
- }
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTestCOMMTAParam);
-};
-
-} // namespace
-
-TEST_P(TaskSchedulerWorkerPoolImplTestCOMMTAParam, COMMTAInitialized) {
- // Verify that SchedulerWorkerPoolImpl workers have a COM MTA available.
- scoped_refptr<TaskRunner> task_runner =
- CreateTaskRunnerWithExecutionMode(worker_pool_.get(), GetParam());
-
- WaitableEvent task_running;
- task_runner->PostTask(
- FROM_HERE, BindOnce(
- [](WaitableEvent* task_running) {
- win::AssertComApartmentType(win::ComApartmentType::MTA);
- task_running->Signal();
- },
- &task_running));
-
- task_running.Wait();
-
- worker_pool_->WaitForAllWorkersIdleForTesting();
-}
-
-INSTANTIATE_TEST_CASE_P(Parallel,
- TaskSchedulerWorkerPoolImplTestCOMMTAParam,
- ::testing::Values(test::ExecutionMode::PARALLEL));
-INSTANTIATE_TEST_CASE_P(Sequenced,
- TaskSchedulerWorkerPoolImplTestCOMMTAParam,
- ::testing::Values(test::ExecutionMode::SEQUENCED));
-
-#endif // defined(OS_WIN)
-
-namespace {
-
-class TaskSchedulerWorkerPoolImplStartInBodyTest
- : public TaskSchedulerWorkerPoolImplTest {
- public:
- void SetUp() override {
- CreateWorkerPool();
- // Let the test start the worker pool.
- }
-};
-
-void TaskPostedBeforeStart(PlatformThreadRef* platform_thread_ref,
- WaitableEvent* task_running,
- WaitableEvent* barrier) {
- *platform_thread_ref = PlatformThread::CurrentRef();
- task_running->Signal();
- WaitWithoutBlockingObserver(barrier);
-}
-
-} // namespace
-
-// Verify that 2 tasks posted before Start() to a SchedulerWorkerPoolImpl with
-// more than 2 workers run on different workers when Start() is called.
-TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, PostTasksBeforeStart) {
- PlatformThreadRef task_1_thread_ref;
- PlatformThreadRef task_2_thread_ref;
- WaitableEvent task_1_running;
- WaitableEvent task_2_running;
-
- // This event is used to prevent a task from completing before the other task
- // starts running. If that happened, both tasks could run on the same worker
- // and this test couldn't verify that the correct number of workers were woken
- // up.
- WaitableEvent barrier;
-
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()})
- ->PostTask(
- FROM_HERE,
- BindOnce(&TaskPostedBeforeStart, Unretained(&task_1_thread_ref),
- Unretained(&task_1_running), Unretained(&barrier)));
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()})
- ->PostTask(
- FROM_HERE,
- BindOnce(&TaskPostedBeforeStart, Unretained(&task_2_thread_ref),
- Unretained(&task_2_running), Unretained(&barrier)));
-
- // Workers should not be created and tasks should not run before the pool is
- // started.
- EXPECT_EQ(0U, worker_pool_->NumberOfWorkersForTesting());
- EXPECT_FALSE(task_1_running.IsSignaled());
- EXPECT_FALSE(task_2_running.IsSignaled());
-
- StartWorkerPool(TimeDelta::Max(), kMaxTasks);
-
- // Tasks should run shortly after the pool is started.
- task_1_running.Wait();
- task_2_running.Wait();
-
- // Tasks should run on different threads.
- EXPECT_NE(task_1_thread_ref, task_2_thread_ref);
-
- barrier.Signal();
- task_tracker_.FlushForTesting();
-}
-
-// Verify that posting many tasks before Start will cause the number of workers
-// to grow to |max_tasks_| during Start.
-TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, PostManyTasks) {
- scoped_refptr<TaskRunner> task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
- constexpr size_t kNumTasksPosted = 2 * kMaxTasks;
- for (size_t i = 0; i < kNumTasksPosted; ++i)
- task_runner->PostTask(FROM_HERE, DoNothing());
-
- EXPECT_EQ(0U, worker_pool_->NumberOfWorkersForTesting());
-
- StartWorkerPool(TimeDelta::Max(), kMaxTasks);
- ASSERT_GT(kNumTasksPosted, worker_pool_->GetMaxTasksForTesting());
- EXPECT_EQ(kMaxTasks, worker_pool_->GetMaxTasksForTesting());
-
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(),
- worker_pool_->GetMaxTasksForTesting());
-}
-
-namespace {
-
-constexpr size_t kMagicTlsValue = 42;
-
-class TaskSchedulerWorkerPoolCheckTlsReuse
- : public TaskSchedulerWorkerPoolImplTest {
- public:
- void SetTlsValueAndWait() {
- slot_.Set(reinterpret_cast<void*>(kMagicTlsValue));
- WaitWithoutBlockingObserver(&waiter_);
- }
-
- void CountZeroTlsValuesAndWait(WaitableEvent* count_waiter) {
- if (!slot_.Get())
- subtle::NoBarrier_AtomicIncrement(&zero_tls_values_, 1);
-
- count_waiter->Signal();
- WaitWithoutBlockingObserver(&waiter_);
- }
-
- protected:
- TaskSchedulerWorkerPoolCheckTlsReuse() = default;
-
- void SetUp() override {
- CreateAndStartWorkerPool(kReclaimTimeForCleanupTests, kMaxTasks);
- }
-
- subtle::Atomic32 zero_tls_values_ = 0;
-
- WaitableEvent waiter_;
-
- private:
- ThreadLocalStorage::Slot slot_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolCheckTlsReuse);
-};
-
-} // namespace
-
-// Checks that at least one worker has been cleaned up by checking the TLS.
-TEST_F(TaskSchedulerWorkerPoolCheckTlsReuse, CheckCleanupWorkers) {
- // Saturate the workers and mark each worker's thread with a magic TLS value.
- std::vector<std::unique_ptr<test::TestTaskFactory>> factories;
- for (size_t i = 0; i < kMaxTasks; ++i) {
- factories.push_back(std::make_unique<test::TestTaskFactory>(
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()}),
- test::ExecutionMode::PARALLEL));
- ASSERT_TRUE(factories.back()->PostTask(
- PostNestedTask::NO,
- Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::SetTlsValueAndWait,
- Unretained(this))));
- factories.back()->WaitForAllTasksToRun();
- }
-
- // Release tasks waiting on |waiter_|.
- waiter_.Signal();
- worker_pool_->WaitForAllWorkersIdleForTesting();
-
- // All workers should be done running by now, so reset for the next phase.
- waiter_.Reset();
-
- // Wait for the worker pool to clean up at least one worker.
- worker_pool_->WaitForWorkersCleanedUpForTesting(1U);
-
- // Saturate and count the worker threads that do not have the magic TLS value.
- // If the value is not there, that means we're at a new worker.
- std::vector<std::unique_ptr<WaitableEvent>> count_waiters;
- for (auto& factory : factories) {
- count_waiters.push_back(std::make_unique<WaitableEvent>());
- ASSERT_TRUE(factory->PostTask(
- PostNestedTask::NO,
- Bind(&TaskSchedulerWorkerPoolCheckTlsReuse::CountZeroTlsValuesAndWait,
- Unretained(this),
- count_waiters.back().get())));
- factory->WaitForAllTasksToRun();
- }
-
- // Wait for all counters to complete.
- for (auto& count_waiter : count_waiters)
- count_waiter->Wait();
-
- EXPECT_GT(subtle::NoBarrier_Load(&zero_tls_values_), 0);
-
- // Release tasks waiting on |waiter_|.
- waiter_.Signal();
-}
-
-namespace {
-
-class TaskSchedulerWorkerPoolHistogramTest
- : public TaskSchedulerWorkerPoolImplTest {
- public:
- TaskSchedulerWorkerPoolHistogramTest() = default;
-
- protected:
- // Override SetUp() to allow every test case to initialize a worker pool with
- // its own arguments.
- void SetUp() override {}
-
- // Floods |worker_pool_| with a single task each that blocks until
- // |continue_event| is signaled. Every worker in the pool is blocked on
- // |continue_event| when this method returns. Note: this helper can easily be
- // generalized to be useful in other tests, but it's here for now because it's
- // only used in a TaskSchedulerWorkerPoolHistogramTest at the moment.
- void FloodPool(WaitableEvent* continue_event) {
- ASSERT_FALSE(continue_event->IsSignaled());
-
- auto task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- const auto max_tasks = worker_pool_->GetMaxTasksForTesting();
-
- WaitableEvent workers_flooded;
- RepeatingClosure all_workers_running_barrier = BarrierClosure(
- max_tasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&workers_flooded)));
- for (size_t i = 0; i < max_tasks; ++i) {
- task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](OnceClosure on_running, WaitableEvent* continue_event) {
- std::move(on_running).Run();
- WaitWithoutBlockingObserver(continue_event);
- },
- all_workers_running_barrier, continue_event));
- }
- workers_flooded.Wait();
- }
-
- private:
- std::unique_ptr<StatisticsRecorder> statistics_recorder_ =
- StatisticsRecorder::CreateTemporaryForTesting();
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolHistogramTest);
-};
-
-} // namespace
-
-TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) {
- WaitableEvent event;
- CreateAndStartWorkerPool(TimeDelta::Max(), kMaxTasks);
- auto task_runner = worker_pool_->CreateSequencedTaskRunnerWithTraits(
- {WithBaseSyncPrimitives()});
-
- // Post a task.
- task_runner->PostTask(
- FROM_HERE, BindOnce(&WaitWithoutBlockingObserver, Unretained(&event)));
-
- // Post 2 more tasks while the first task hasn't completed its execution. It
- // is guaranteed that these tasks will run immediately after the first task,
- // without allowing the worker to sleep.
- task_runner->PostTask(FROM_HERE, DoNothing());
- task_runner->PostTask(FROM_HERE, DoNothing());
-
- // Allow tasks to run and wait until the SchedulerWorker is idle.
- event.Signal();
- worker_pool_->WaitForAllWorkersIdleForTesting();
-
- // Wake up the SchedulerWorker that just became idle by posting a task and
- // wait until it becomes idle again. The SchedulerWorker should record the
- // TaskScheduler.NumTasksBetweenWaits.* histogram on wake up.
- task_runner->PostTask(FROM_HERE, DoNothing());
- worker_pool_->WaitForAllWorkersIdleForTesting();
-
- // Verify that counts were recorded to the histogram as expected.
- const auto* histogram = worker_pool_->num_tasks_between_waits_histogram();
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
- EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
-}
-
-// Verifies that NumTasksBetweenWaits histogram is logged as expected across
-// idle and cleanup periods.
-TEST_F(TaskSchedulerWorkerPoolHistogramTest,
- NumTasksBetweenWaitsWithIdlePeriodAndCleanup) {
- WaitableEvent tasks_can_exit_event;
- CreateAndStartWorkerPool(kReclaimTimeForCleanupTests, kMaxTasks);
-
- WaitableEvent workers_continue;
-
- FloodPool(&workers_continue);
-
- const auto* histogram = worker_pool_->num_tasks_between_waits_histogram();
-
- // NumTasksBetweenWaits shouldn't be logged until idle.
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(1));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
-
- // Make all workers go idle.
- workers_continue.Signal();
- worker_pool_->WaitForAllWorkersIdleForTesting();
-
- // All workers should have reported a single hit in the "1" bucket per the the
- // histogram being reported when going idle and each worker having processed
- // precisely 1 task per the controlled flooding logic above.
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
- EXPECT_EQ(static_cast<int>(kMaxTasks),
- histogram->SnapshotSamples()->GetCount(1));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
-
- worker_pool_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 1);
-
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
- EXPECT_EQ(static_cast<int>(kMaxTasks),
- histogram->SnapshotSamples()->GetCount(1));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
-
- // Flooding the pool once again (without letting any workers go idle)
- // shouldn't affect the counts either.
-
- workers_continue.Reset();
- FloodPool(&workers_continue);
-
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
- EXPECT_EQ(static_cast<int>(kMaxTasks),
- histogram->SnapshotSamples()->GetCount(1));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
-
- workers_continue.Signal();
- worker_pool_->WaitForAllWorkersIdleForTesting();
-}
-
-TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeCleanup) {
- CreateWorkerPool();
- auto histogrammed_thread_task_runner =
- worker_pool_->CreateSequencedTaskRunnerWithTraits(
- {WithBaseSyncPrimitives()});
-
- // Post 3 tasks and hold the thread for idle thread stack ordering.
- // This test assumes |histogrammed_thread_task_runner| gets assigned the same
- // thread for each of its tasks.
- PlatformThreadRef thread_ref;
- histogrammed_thread_task_runner->PostTask(
- FROM_HERE, BindOnce(
- [](PlatformThreadRef* thread_ref) {
- ASSERT_TRUE(thread_ref);
- *thread_ref = PlatformThread::CurrentRef();
- },
- Unretained(&thread_ref)));
- histogrammed_thread_task_runner->PostTask(
- FROM_HERE, BindOnce(
- [](PlatformThreadRef* thread_ref) {
- ASSERT_FALSE(thread_ref->is_null());
- EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef());
- },
- Unretained(&thread_ref)));
-
- WaitableEvent cleanup_thread_running;
- WaitableEvent cleanup_thread_continue;
- histogrammed_thread_task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](PlatformThreadRef* thread_ref,
- WaitableEvent* cleanup_thread_running,
- WaitableEvent* cleanup_thread_continue) {
- ASSERT_FALSE(thread_ref->is_null());
- EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef());
- cleanup_thread_running->Signal();
- WaitWithoutBlockingObserver(cleanup_thread_continue);
- },
- Unretained(&thread_ref), Unretained(&cleanup_thread_running),
- Unretained(&cleanup_thread_continue)));
-
- // Start the worker pool with 2 workers, to avoid depending on the scheduler's
- // logic to always keep one extra idle worker.
- //
- // The pool is started after the 3 initial tasks have been posted to ensure
- // that they are scheduled on the same worker. If the tasks could run as they
- // are posted, there would be a chance that:
- // 1. Worker #1: Runs a tasks and empties the sequence, without adding
- // itself to the idle stack yet.
- // 2. Posting thread: Posts another task to the now empty sequence. Wakes
- // up a new worker, since worker #1 isn't on the idle
- // stack yet.
- // 3: Worker #2: Runs the tasks, violating the expectation that the 3
- // initial tasks run on the same worker.
- constexpr size_t kTwoWorkers = 2;
- StartWorkerPool(kReclaimTimeForCleanupTests, kTwoWorkers);
-
- // Wait until the 3rd task is scheduled.
- cleanup_thread_running.Wait();
-
- // To allow the SchedulerWorker associated with
- // |histogrammed_thread_task_runner| to cleanup, make sure it isn't on top of
- // the idle stack by waking up another SchedulerWorker via
- // |task_runner_for_top_idle|. |histogrammed_thread_task_runner| should
- // release and go idle first and then |task_runner_for_top_idle| should
- // release and go idle. This allows the SchedulerWorker associated with
- // |histogrammed_thread_task_runner| to cleanup.
- WaitableEvent top_idle_thread_running;
- WaitableEvent top_idle_thread_continue;
- auto task_runner_for_top_idle =
- worker_pool_->CreateSequencedTaskRunnerWithTraits(
- {WithBaseSyncPrimitives()});
- task_runner_for_top_idle->PostTask(
- FROM_HERE, BindOnce(
- [](PlatformThreadRef thread_ref,
- WaitableEvent* top_idle_thread_running,
- WaitableEvent* top_idle_thread_continue) {
- ASSERT_FALSE(thread_ref.is_null());
- EXPECT_NE(thread_ref, PlatformThread::CurrentRef())
- << "Worker reused. Worker will not cleanup and the "
- "histogram value will be wrong.";
- top_idle_thread_running->Signal();
- WaitWithoutBlockingObserver(top_idle_thread_continue);
- },
- thread_ref, Unretained(&top_idle_thread_running),
- Unretained(&top_idle_thread_continue)));
- top_idle_thread_running.Wait();
- EXPECT_EQ(0U, worker_pool_->NumberOfIdleWorkersForTesting());
- cleanup_thread_continue.Signal();
- // Wait for the cleanup thread to also become idle.
- worker_pool_->WaitForWorkersIdleForTesting(1U);
- top_idle_thread_continue.Signal();
- // Allow the thread processing the |histogrammed_thread_task_runner| work to
- // cleanup.
- worker_pool_->WaitForWorkersCleanedUpForTesting(1U);
-
- // Verify that counts were recorded to the histogram as expected.
- const auto* histogram = worker_pool_->num_tasks_before_detach_histogram();
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(1));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(2));
- EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(4));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(5));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(6));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
-}
-
-namespace {
-
-class TaskSchedulerWorkerPoolStandbyPolicyTest
- : public TaskSchedulerWorkerPoolImplTestBase,
- public testing::Test {
- public:
- TaskSchedulerWorkerPoolStandbyPolicyTest() = default;
-
- void SetUp() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonSetUp(
- kReclaimTimeForCleanupTests);
- }
-
- void TearDown() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonTearDown();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolStandbyPolicyTest);
-};
-
-} // namespace
-
-TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, InitOne) {
- EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
-}
-
-// Verify that the SchedulerWorkerPoolImpl keeps at least one idle standby
-// thread, capacity permitting.
-TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, VerifyStandbyThread) {
- auto task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC);
- WaitableEvent threads_continue;
-
- RepeatingClosure thread_blocker = BindLambdaForTesting([&]() {
- thread_running.Signal();
- WaitWithoutBlockingObserver(&threads_continue);
- });
-
- // There should be one idle thread until we reach capacity
- for (size_t i = 0; i < kMaxTasks; ++i) {
- EXPECT_EQ(i + 1, worker_pool_->NumberOfWorkersForTesting());
- task_runner->PostTask(FROM_HERE, thread_blocker);
- thread_running.Wait();
- }
-
- // There should not be an extra idle thread if it means going above capacity
- EXPECT_EQ(kMaxTasks, worker_pool_->NumberOfWorkersForTesting());
-
- threads_continue.Signal();
- // Wait long enough for all but one worker to clean up.
- worker_pool_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 1);
- EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
- // Give extra time for a worker to cleanup : none should as the pool is
- // expected to keep a worker ready regardless of how long it was idle for.
- PlatformThread::Sleep(kReclaimTimeForCleanupTests);
- EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
-}
-
-// Verify that being "the" idle thread counts as being active (i.e. won't be
-// reclaimed even if not on top of the idle stack when reclaim timeout expires).
-// Regression test for https://crbug.com/847501.
-TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest,
- InAndOutStandbyThreadIsActive) {
- auto sequenced_task_runner =
- worker_pool_->CreateSequencedTaskRunnerWithTraits({});
-
- WaitableEvent timer_started;
-
- RepeatingTimer recurring_task;
- sequenced_task_runner->PostTask(
- FROM_HERE, BindLambdaForTesting([&]() {
- recurring_task.Start(FROM_HERE, kReclaimTimeForCleanupTests / 2,
- DoNothing());
- timer_started.Signal();
- }));
-
- timer_started.Wait();
-
- // Running a task should have brought up a new standby thread.
- EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
-
- // Give extra time for a worker to cleanup : none should as the two workers
- // are both considered "active" per the timer ticking faster than the reclaim
- // timeout.
- PlatformThread::Sleep(kReclaimTimeForCleanupTests * 2);
- EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
-
- sequenced_task_runner->PostTask(
- FROM_HERE, BindLambdaForTesting([&]() { recurring_task.Stop(); }));
-
- // Stopping the recurring task should let the second worker be reclaimed per
- // not being "the" standby thread for a full reclaim timeout.
- worker_pool_->WaitForWorkersCleanedUpForTesting(1);
- EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
-}
-
-// Verify that being "the" idle thread counts as being active but isn't sticky.
-// Regression test for https://crbug.com/847501.
-TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, OnlyKeepActiveStandbyThreads) {
- auto sequenced_task_runner =
- worker_pool_->CreateSequencedTaskRunnerWithTraits({});
-
- // Start this test like
- // TaskSchedulerWorkerPoolStandbyPolicyTest.InAndOutStandbyThreadIsActive and
- // give it some time to stabilize.
- RepeatingTimer recurring_task;
- sequenced_task_runner->PostTask(
- FROM_HERE, BindLambdaForTesting([&]() {
- recurring_task.Start(FROM_HERE, kReclaimTimeForCleanupTests / 2,
- DoNothing());
- }));
-
- PlatformThread::Sleep(kReclaimTimeForCleanupTests * 2);
- EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
-
- // Then also flood the pool (cycling the top of the idle stack).
- {
- auto task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC);
- WaitableEvent threads_continue;
-
- RepeatingClosure thread_blocker = BindLambdaForTesting([&]() {
- thread_running.Signal();
- WaitWithoutBlockingObserver(&threads_continue);
- });
-
- for (size_t i = 0; i < kMaxTasks; ++i) {
- task_runner->PostTask(FROM_HERE, thread_blocker);
- thread_running.Wait();
- }
-
- EXPECT_EQ(kMaxTasks, worker_pool_->NumberOfWorkersForTesting());
- threads_continue.Signal();
-
- // Flush to ensure all references to |threads_continue| are gone before it
- // goes out of scope.
- task_tracker_.FlushForTesting();
- }
-
- // All workers should clean up but two (since the timer is still running).
- worker_pool_->WaitForWorkersCleanedUpForTesting(kMaxTasks - 2);
- EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
-
- // Extra time shouldn't change this.
- PlatformThread::Sleep(kReclaimTimeForCleanupTests * 2);
- EXPECT_EQ(2U, worker_pool_->NumberOfWorkersForTesting());
-
- // Stopping the timer should let the number of active threads go down to one.
- sequenced_task_runner->PostTask(
- FROM_HERE, BindLambdaForTesting([&]() { recurring_task.Stop(); }));
- worker_pool_->WaitForWorkersCleanedUpForTesting(1);
- EXPECT_EQ(1U, worker_pool_->NumberOfWorkersForTesting());
-}
-
-namespace {
-
-enum class OptionalBlockingType {
- NO_BLOCK,
- MAY_BLOCK,
- WILL_BLOCK,
-};
-
-struct NestedBlockingType {
- NestedBlockingType(BlockingType first_in,
- OptionalBlockingType second_in,
- BlockingType behaves_as_in)
- : first(first_in), second(second_in), behaves_as(behaves_as_in) {}
-
- BlockingType first;
- OptionalBlockingType second;
- BlockingType behaves_as;
-};
-
-class NestedScopedBlockingCall {
- public:
- NestedScopedBlockingCall(const NestedBlockingType& nested_blocking_type)
- : first_scoped_blocking_call_(nested_blocking_type.first),
- second_scoped_blocking_call_(
- nested_blocking_type.second == OptionalBlockingType::WILL_BLOCK
- ? std::make_unique<ScopedBlockingCall>(BlockingType::WILL_BLOCK)
- : (nested_blocking_type.second ==
- OptionalBlockingType::MAY_BLOCK
- ? std::make_unique<ScopedBlockingCall>(
- BlockingType::MAY_BLOCK)
- : nullptr)) {}
-
- private:
- ScopedBlockingCall first_scoped_blocking_call_;
- std::unique_ptr<ScopedBlockingCall> second_scoped_blocking_call_;
-
- DISALLOW_COPY_AND_ASSIGN(NestedScopedBlockingCall);
-};
-
-} // namespace
-
-class TaskSchedulerWorkerPoolBlockingTest
- : public TaskSchedulerWorkerPoolImplTestBase,
- public testing::TestWithParam<NestedBlockingType> {
- public:
- TaskSchedulerWorkerPoolBlockingTest() = default;
-
- static std::string ParamInfoToString(
- ::testing::TestParamInfo<NestedBlockingType> param_info) {
- std::string str = param_info.param.first == BlockingType::MAY_BLOCK
- ? "MAY_BLOCK"
- : "WILL_BLOCK";
- if (param_info.param.second == OptionalBlockingType::MAY_BLOCK)
- str += "_MAY_BLOCK";
- else if (param_info.param.second == OptionalBlockingType::WILL_BLOCK)
- str += "_WILL_BLOCK";
- return str;
- }
-
- void SetUp() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonSetUp();
- task_runner_ =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
- }
-
- void TearDown() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonTearDown();
- }
-
- protected:
- // Saturates the worker pool with a task that first blocks, waits to be
- // unblocked, then exits.
- void SaturateWithBlockingTasks(
- const NestedBlockingType& nested_blocking_type) {
- ASSERT_FALSE(blocking_threads_running_.IsSignaled());
-
- RepeatingClosure blocking_threads_running_closure = BarrierClosure(
- kMaxTasks, BindOnce(&WaitableEvent::Signal,
- Unretained(&blocking_threads_running_)));
-
- for (size_t i = 0; i < kMaxTasks; ++i) {
- task_runner_->PostTask(
- FROM_HERE,
- BindOnce(
- [](Closure* blocking_threads_running_closure,
- WaitableEvent* blocking_threads_continue_,
- const NestedBlockingType& nested_blocking_type) {
- NestedScopedBlockingCall nested_scoped_blocking_call(
- nested_blocking_type);
- blocking_threads_running_closure->Run();
- WaitWithoutBlockingObserver(blocking_threads_continue_);
- },
- Unretained(&blocking_threads_running_closure),
- Unretained(&blocking_threads_continue_), nested_blocking_type));
- }
- blocking_threads_running_.Wait();
- }
-
- // Returns how long we can expect a change to |max_tasks_| to occur
- // after a task has become blocked.
- TimeDelta GetMaxTasksChangeSleepTime() {
- return std::max(SchedulerWorkerPoolImpl::kBlockedWorkersPollPeriod,
- worker_pool_->MayBlockThreshold()) +
- TestTimeouts::tiny_timeout();
- }
-
- // Waits indefinitely, until |worker_pool_|'s max tasks increases to
- // |expected_max_tasks|.
- void ExpectMaxTasksIncreasesTo(size_t expected_max_tasks) {
- size_t max_tasks = worker_pool_->GetMaxTasksForTesting();
- while (max_tasks != expected_max_tasks) {
- PlatformThread::Sleep(GetMaxTasksChangeSleepTime());
- size_t new_max_tasks = worker_pool_->GetMaxTasksForTesting();
- ASSERT_GE(new_max_tasks, max_tasks);
- max_tasks = new_max_tasks;
- }
- }
-
- // Unblocks tasks posted by SaturateWithBlockingTasks().
- void UnblockTasks() { blocking_threads_continue_.Signal(); }
-
- scoped_refptr<TaskRunner> task_runner_;
-
- private:
- WaitableEvent blocking_threads_running_;
- WaitableEvent blocking_threads_continue_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolBlockingTest);
-};
-
-// Verify that BlockingScopeEntered() causes max tasks to increase and creates a
-// worker if needed. Also verify that BlockingScopeExited() decreases max tasks
-// after an increase.
-TEST_P(TaskSchedulerWorkerPoolBlockingTest, ThreadBlockedUnblocked) {
- ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-
- SaturateWithBlockingTasks(GetParam());
- if (GetParam().behaves_as == BlockingType::MAY_BLOCK)
- ExpectMaxTasksIncreasesTo(2 * kMaxTasks);
- // A range of possible number of workers is accepted because of
- // crbug.com/757897.
- EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(), kMaxTasks + 1);
- EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), 2 * kMaxTasks);
-
- UnblockTasks();
- task_tracker_.FlushForTesting();
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-}
-
-// Verify that tasks posted in a saturated pool before a ScopedBlockingCall will
-// execute after ScopedBlockingCall is instantiated.
-TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) {
- WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC);
- WaitableEvent thread_can_block;
- WaitableEvent threads_continue;
-
- for (size_t i = 0; i < kMaxTasks; ++i) {
- task_runner_->PostTask(
- FROM_HERE,
- BindOnce(
- [](const NestedBlockingType& nested_blocking_type,
- WaitableEvent* thread_running, WaitableEvent* thread_can_block,
- WaitableEvent* threads_continue) {
- thread_running->Signal();
- WaitWithoutBlockingObserver(thread_can_block);
-
- NestedScopedBlockingCall nested_scoped_blocking_call(
- nested_blocking_type);
- WaitWithoutBlockingObserver(threads_continue);
- },
- GetParam(), Unretained(&thread_running),
- Unretained(&thread_can_block), Unretained(&threads_continue)));
- thread_running.Wait();
- }
-
- // All workers should be occupied and the pool should be saturated. Workers
- // have not entered ScopedBlockingCall yet.
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), kMaxTasks);
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-
- WaitableEvent extra_threads_running;
- WaitableEvent extra_threads_continue;
- RepeatingClosure extra_threads_running_barrier = BarrierClosure(
- kMaxTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&extra_threads_running)));
- for (size_t i = 0; i < kMaxTasks; ++i) {
- task_runner_->PostTask(FROM_HERE,
- BindOnce(
- [](Closure* extra_threads_running_barrier,
- WaitableEvent* extra_threads_continue) {
- extra_threads_running_barrier->Run();
- WaitWithoutBlockingObserver(
- extra_threads_continue);
- },
- Unretained(&extra_threads_running_barrier),
- Unretained(&extra_threads_continue)));
- }
-
- // Allow tasks to enter ScopedBlockingCall. Workers should be created for the
- // tasks we just posted.
- thread_can_block.Signal();
- if (GetParam().behaves_as == BlockingType::MAY_BLOCK)
- ExpectMaxTasksIncreasesTo(2 * kMaxTasks);
-
- // Should not block forever.
- extra_threads_running.Wait();
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
- extra_threads_continue.Signal();
-
- threads_continue.Signal();
- task_tracker_.FlushForTesting();
-}
-// Verify that workers become idle when the pool is over-capacity and that
-// those workers do no work.
-TEST_P(TaskSchedulerWorkerPoolBlockingTest, WorkersIdleWhenOverCapacity) {
- ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-
- SaturateWithBlockingTasks(GetParam());
- if (GetParam().behaves_as == BlockingType::MAY_BLOCK)
- ExpectMaxTasksIncreasesTo(2 * kMaxTasks);
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), 2 * kMaxTasks);
- // A range of possible number of workers is accepted because of
- // crbug.com/757897.
- EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(), kMaxTasks + 1);
- EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
-
- WaitableEvent threads_running;
- WaitableEvent threads_continue;
-
- RepeatingClosure threads_running_barrier = BarrierClosure(
- kMaxTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&threads_running)));
- // Posting these tasks should cause new workers to be created.
- for (size_t i = 0; i < kMaxTasks; ++i) {
- auto callback = BindOnce(
- [](Closure* threads_running_barrier, WaitableEvent* threads_continue) {
- threads_running_barrier->Run();
- WaitWithoutBlockingObserver(threads_continue);
- },
- Unretained(&threads_running_barrier), Unretained(&threads_continue));
- task_runner_->PostTask(FROM_HERE, std::move(callback));
- }
- threads_running.Wait();
-
- ASSERT_EQ(worker_pool_->NumberOfIdleWorkersForTesting(), 0U);
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), 2 * kMaxTasks);
-
- AtomicFlag is_exiting;
- // These tasks should not get executed until after other tasks become
- // unblocked.
- for (size_t i = 0; i < kMaxTasks; ++i) {
- task_runner_->PostTask(FROM_HERE, BindOnce(
- [](AtomicFlag* is_exiting) {
- EXPECT_TRUE(is_exiting->IsSet());
- },
- Unretained(&is_exiting)));
- }
-
- // The original |kMaxTasks| will finish their tasks after being
- // unblocked. There will be work in the work queue, but the pool should now
- // be over-capacity and workers will become idle.
- UnblockTasks();
- worker_pool_->WaitForWorkersIdleForTesting(kMaxTasks);
- EXPECT_EQ(worker_pool_->NumberOfIdleWorkersForTesting(), kMaxTasks);
-
- // Posting more tasks should not cause workers idle from the pool being over
- // capacity to begin doing work.
- for (size_t i = 0; i < kMaxTasks; ++i) {
- task_runner_->PostTask(FROM_HERE, BindOnce(
- [](AtomicFlag* is_exiting) {
- EXPECT_TRUE(is_exiting->IsSet());
- },
- Unretained(&is_exiting)));
- }
-
- // Give time for those idle workers to possibly do work (which should not
- // happen).
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- is_exiting.Set();
- // Unblocks the new workers.
- threads_continue.Signal();
- task_tracker_.FlushForTesting();
-}
-
-INSTANTIATE_TEST_CASE_P(
- ,
- TaskSchedulerWorkerPoolBlockingTest,
- ::testing::Values(NestedBlockingType(BlockingType::MAY_BLOCK,
- OptionalBlockingType::NO_BLOCK,
- BlockingType::MAY_BLOCK),
- NestedBlockingType(BlockingType::WILL_BLOCK,
- OptionalBlockingType::NO_BLOCK,
- BlockingType::WILL_BLOCK),
- NestedBlockingType(BlockingType::MAY_BLOCK,
- OptionalBlockingType::WILL_BLOCK,
- BlockingType::WILL_BLOCK),
- NestedBlockingType(BlockingType::WILL_BLOCK,
- OptionalBlockingType::MAY_BLOCK,
- BlockingType::WILL_BLOCK)),
- TaskSchedulerWorkerPoolBlockingTest::ParamInfoToString);
-
-// Verify that if a thread enters the scope of a MAY_BLOCK ScopedBlockingCall,
-// but exits the scope before the MayBlockThreshold() is reached, that the max
-// tasks does not increase.
-TEST_F(TaskSchedulerWorkerPoolBlockingTest, ThreadBlockUnblockPremature) {
- ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-
- TimeDelta max_tasks_change_sleep = GetMaxTasksChangeSleepTime();
- worker_pool_->MaximizeMayBlockThresholdForTesting();
-
- SaturateWithBlockingTasks(NestedBlockingType(BlockingType::MAY_BLOCK,
- OptionalBlockingType::NO_BLOCK,
- BlockingType::MAY_BLOCK));
- PlatformThread::Sleep(max_tasks_change_sleep);
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), kMaxTasks);
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-
- UnblockTasks();
- task_tracker_.FlushForTesting();
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-}
-
-// Verify that if max tasks is incremented because of a MAY_BLOCK
-// ScopedBlockingCall, it isn't incremented again when there is a nested
-// WILL_BLOCK ScopedBlockingCall.
-TEST_F(TaskSchedulerWorkerPoolBlockingTest,
- MayBlockIncreaseCapacityNestedWillBlock) {
- ASSERT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
- auto task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
- WaitableEvent can_return;
-
- // Saturate the pool so that a MAY_BLOCK ScopedBlockingCall would increment
- // the max tasks.
- for (size_t i = 0; i < kMaxTasks - 1; ++i) {
- task_runner->PostTask(FROM_HERE, BindOnce(&WaitWithoutBlockingObserver,
- Unretained(&can_return)));
- }
-
- WaitableEvent can_instantiate_will_block;
- WaitableEvent did_instantiate_will_block;
-
- // Post a task that instantiates a MAY_BLOCK ScopedBlockingCall.
- task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](WaitableEvent* can_instantiate_will_block,
- WaitableEvent* did_instantiate_will_block,
- WaitableEvent* can_return) {
- ScopedBlockingCall may_block(BlockingType::MAY_BLOCK);
- WaitWithoutBlockingObserver(can_instantiate_will_block);
- ScopedBlockingCall will_block(BlockingType::WILL_BLOCK);
- did_instantiate_will_block->Signal();
- WaitWithoutBlockingObserver(can_return);
- },
- Unretained(&can_instantiate_will_block),
- Unretained(&did_instantiate_will_block), Unretained(&can_return)));
-
- // After a short delay, max tasks should be incremented.
- ExpectMaxTasksIncreasesTo(kMaxTasks + 1);
-
- // Wait until the task instantiates a WILL_BLOCK ScopedBlockingCall.
- can_instantiate_will_block.Signal();
- did_instantiate_will_block.Wait();
-
- // Max tasks shouldn't be incremented again.
- EXPECT_EQ(kMaxTasks + 1, worker_pool_->GetMaxTasksForTesting());
-
- // Tear down.
- can_return.Signal();
- task_tracker_.FlushForTesting();
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks);
-}
-
-// Verify that workers that become idle due to the pool being over capacity will
-// eventually cleanup.
-TEST(TaskSchedulerWorkerPoolOverCapacityTest, VerifyCleanup) {
- constexpr size_t kLocalMaxTasks = 3;
-
- TaskTracker task_tracker("Test");
- DelayedTaskManager delayed_task_manager;
- scoped_refptr<TaskRunner> service_thread_task_runner =
- MakeRefCounted<TestSimpleTaskRunner>();
- delayed_task_manager.Start(service_thread_task_runner);
- SchedulerWorkerPoolImpl worker_pool(
- "OverCapacityTestWorkerPool", "A", ThreadPriority::NORMAL,
- task_tracker.GetTrackedRef(), &delayed_task_manager);
- worker_pool.Start(
- SchedulerWorkerPoolParams(kLocalMaxTasks, kReclaimTimeForCleanupTests),
- kLocalMaxTasks, service_thread_task_runner, nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
-
- scoped_refptr<TaskRunner> task_runner =
- worker_pool.CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- WaitableEvent threads_running;
- WaitableEvent threads_continue;
- RepeatingClosure threads_running_barrier = BarrierClosure(
- kLocalMaxTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&threads_running)));
-
- WaitableEvent blocked_call_continue;
- RepeatingClosure closure = BindRepeating(
- [](Closure* threads_running_barrier, WaitableEvent* threads_continue,
- WaitableEvent* blocked_call_continue) {
- threads_running_barrier->Run();
- {
- ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
- WaitWithoutBlockingObserver(blocked_call_continue);
- }
- WaitWithoutBlockingObserver(threads_continue);
- },
- Unretained(&threads_running_barrier), Unretained(&threads_continue),
- Unretained(&blocked_call_continue));
-
- for (size_t i = 0; i < kLocalMaxTasks; ++i)
- task_runner->PostTask(FROM_HERE, closure);
-
- threads_running.Wait();
-
- WaitableEvent extra_threads_running;
- WaitableEvent extra_threads_continue;
-
- RepeatingClosure extra_threads_running_barrier = BarrierClosure(
- kLocalMaxTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&extra_threads_running)));
- // These tasks should run on the new threads from increasing max tasks.
- for (size_t i = 0; i < kLocalMaxTasks; ++i) {
- task_runner->PostTask(FROM_HERE,
- BindOnce(
- [](Closure* extra_threads_running_barrier,
- WaitableEvent* extra_threads_continue) {
- extra_threads_running_barrier->Run();
- WaitWithoutBlockingObserver(
- extra_threads_continue);
- },
- Unretained(&extra_threads_running_barrier),
- Unretained(&extra_threads_continue)));
- }
- extra_threads_running.Wait();
-
- ASSERT_EQ(kLocalMaxTasks * 2, worker_pool.NumberOfWorkersForTesting());
- EXPECT_EQ(kLocalMaxTasks * 2, worker_pool.GetMaxTasksForTesting());
- blocked_call_continue.Signal();
- extra_threads_continue.Signal();
-
- // Periodically post tasks to ensure that posting tasks does not prevent
- // workers that are idle due to the pool being over capacity from cleaning up.
- for (int i = 0; i < 16; ++i) {
- task_runner->PostDelayedTask(FROM_HERE, DoNothing(),
- kReclaimTimeForCleanupTests * i * 0.5);
- }
-
- // Note: one worker above capacity will not get cleaned up since it's on the
- // top of the idle stack.
- worker_pool.WaitForWorkersCleanedUpForTesting(kLocalMaxTasks - 1);
- EXPECT_EQ(kLocalMaxTasks + 1, worker_pool.NumberOfWorkersForTesting());
-
- threads_continue.Signal();
-
- worker_pool.JoinForTesting();
-}
-
-// Verify that the maximum number of workers is 256 and that hitting the max
-// leaves the pool in a valid state with regards to max tasks.
-TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
- constexpr size_t kMaxNumberOfWorkers = 256;
- constexpr size_t kNumExtraTasks = 10;
-
- WaitableEvent early_blocking_threads_running;
- RepeatingClosure early_threads_barrier_closure =
- BarrierClosure(kMaxNumberOfWorkers,
- BindOnce(&WaitableEvent::Signal,
- Unretained(&early_blocking_threads_running)));
-
- WaitableEvent early_threads_finished;
- RepeatingClosure early_threads_finished_barrier = BarrierClosure(
- kMaxNumberOfWorkers,
- BindOnce(&WaitableEvent::Signal, Unretained(&early_threads_finished)));
-
- WaitableEvent early_release_threads_continue;
-
- // Post ScopedBlockingCall tasks to hit the worker cap.
- for (size_t i = 0; i < kMaxNumberOfWorkers; ++i) {
- task_runner_->PostTask(FROM_HERE,
- BindOnce(
- [](Closure* early_threads_barrier_closure,
- WaitableEvent* early_release_threads_continue,
- Closure* early_threads_finished) {
- {
- ScopedBlockingCall scoped_blocking_call(
- BlockingType::WILL_BLOCK);
- early_threads_barrier_closure->Run();
- WaitWithoutBlockingObserver(
- early_release_threads_continue);
- }
- early_threads_finished->Run();
- },
- Unretained(&early_threads_barrier_closure),
- Unretained(&early_release_threads_continue),
- Unretained(&early_threads_finished_barrier)));
- }
-
- early_blocking_threads_running.Wait();
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(),
- kMaxTasks + kMaxNumberOfWorkers);
-
- WaitableEvent late_release_thread_contine;
- WaitableEvent late_blocking_threads_running;
-
- RepeatingClosure late_threads_barrier_closure = BarrierClosure(
- kNumExtraTasks, BindOnce(&WaitableEvent::Signal,
- Unretained(&late_blocking_threads_running)));
-
- // Posts additional tasks. Note: we should already have |kMaxNumberOfWorkers|
- // tasks running. These tasks should not be able to get executed yet as
- // the pool is already at its max worker cap.
- for (size_t i = 0; i < kNumExtraTasks; ++i) {
- task_runner_->PostTask(
- FROM_HERE,
- BindOnce(
- [](Closure* late_threads_barrier_closure,
- WaitableEvent* late_release_thread_contine) {
- ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
- late_threads_barrier_closure->Run();
- WaitWithoutBlockingObserver(late_release_thread_contine);
- },
- Unretained(&late_threads_barrier_closure),
- Unretained(&late_release_thread_contine)));
- }
-
- // Give time to see if we exceed the max number of workers.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(), kMaxNumberOfWorkers);
-
- early_release_threads_continue.Signal();
- early_threads_finished.Wait();
- late_blocking_threads_running.Wait();
-
- WaitableEvent final_tasks_running;
- WaitableEvent final_tasks_continue;
- RepeatingClosure final_tasks_running_barrier = BarrierClosure(
- kMaxTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&final_tasks_running)));
-
- // Verify that we are still able to saturate the pool.
- for (size_t i = 0; i < kMaxTasks; ++i) {
- task_runner_->PostTask(
- FROM_HERE,
- BindOnce(
- [](Closure* closure, WaitableEvent* final_tasks_continue) {
- closure->Run();
- WaitWithoutBlockingObserver(final_tasks_continue);
- },
- Unretained(&final_tasks_running_barrier),
- Unretained(&final_tasks_continue)));
- }
- final_tasks_running.Wait();
- EXPECT_EQ(worker_pool_->GetMaxTasksForTesting(), kMaxTasks + kNumExtraTasks);
- late_release_thread_contine.Signal();
- final_tasks_continue.Signal();
- task_tracker_.FlushForTesting();
-}
-
-// Verify that the maximum number of background tasks that can run concurrently
-// is honored.
-TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, MaxBackgroundTasks) {
- constexpr int kMaxBackgroundTasks = kMaxTasks / 2;
- worker_pool_->Start(
- SchedulerWorkerPoolParams(kMaxTasks, base::TimeDelta::Max()),
- kMaxBackgroundTasks, service_thread_.task_runner(), nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
- const scoped_refptr<TaskRunner> foreground_runner =
- worker_pool_->CreateTaskRunnerWithTraits({MayBlock()});
- const scoped_refptr<TaskRunner> background_runner =
- worker_pool_->CreateTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND, MayBlock()});
-
- // It should be possible to have |kMaxBackgroundTasks|
- // TaskPriority::BACKGROUND tasks running concurrently.
- WaitableEvent background_tasks_running;
- WaitableEvent unblock_background_tasks;
- RepeatingClosure background_tasks_running_barrier = BarrierClosure(
- kMaxBackgroundTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&background_tasks_running)));
-
- for (int i = 0; i < kMaxBackgroundTasks; ++i) {
- background_runner->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- background_tasks_running_barrier.Run();
- WaitWithoutBlockingObserver(&unblock_background_tasks);
- }));
- }
- background_tasks_running.Wait();
-
- // No more TaskPriority::BACKGROUND task should run.
- AtomicFlag extra_background_task_can_run;
- WaitableEvent extra_background_task_running;
- background_runner->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- EXPECT_TRUE(extra_background_task_can_run.IsSet());
- extra_background_task_running.Signal();
- }));
-
- // An extra foreground task should be able to run.
- WaitableEvent foreground_task_running;
- foreground_runner->PostTask(
- FROM_HERE, base::BindOnce(&WaitableEvent::Signal,
- Unretained(&foreground_task_running)));
- foreground_task_running.Wait();
-
- // Completion of the TaskPriority::BACKGROUND tasks should allow the extra
- // TaskPriority::BACKGROUND task to run.
- extra_background_task_can_run.Set();
- unblock_background_tasks.Signal();
- extra_background_task_running.Wait();
-
- // Tear down.
- task_tracker_.FlushForTesting();
-}
-
-namespace {
-
-class TaskSchedulerWorkerPoolBlockingCallAndMaxBackgroundTasksTest
- : public TaskSchedulerWorkerPoolImplTestBase,
- public testing::TestWithParam<BlockingType> {
- public:
- static constexpr int kMaxBackgroundTasks = kMaxTasks / 2;
-
- TaskSchedulerWorkerPoolBlockingCallAndMaxBackgroundTasksTest() = default;
-
- void SetUp() override {
- CreateWorkerPool();
- worker_pool_->Start(
- SchedulerWorkerPoolParams(kMaxTasks, base::TimeDelta::Max()),
- kMaxBackgroundTasks, service_thread_.task_runner(), nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
- }
-
- void TearDown() override {
- TaskSchedulerWorkerPoolImplTestBase::CommonTearDown();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- TaskSchedulerWorkerPoolBlockingCallAndMaxBackgroundTasksTest);
-};
-
-} // namespace
-
-TEST_P(TaskSchedulerWorkerPoolBlockingCallAndMaxBackgroundTasksTest,
- BlockingCallAndMaxBackgroundTasksTest) {
- const scoped_refptr<TaskRunner> background_runner =
- worker_pool_->CreateTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND, MayBlock()});
-
- // Post |kMaxBackgroundTasks| TaskPriority::BACKGROUND tasks that block in a
- // ScopedBlockingCall.
- WaitableEvent blocking_background_tasks_running;
- WaitableEvent unblock_blocking_background_tasks;
- RepeatingClosure blocking_background_tasks_running_barrier =
- BarrierClosure(kMaxBackgroundTasks,
- BindOnce(&WaitableEvent::Signal,
- Unretained(&blocking_background_tasks_running)));
- for (int i = 0; i < kMaxBackgroundTasks; ++i) {
- background_runner->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- blocking_background_tasks_running_barrier.Run();
- ScopedBlockingCall scoped_blocking_call(GetParam());
- WaitWithoutBlockingObserver(&unblock_blocking_background_tasks);
- }));
- }
- blocking_background_tasks_running.Wait();
-
- // Post an extra |kMaxBackgroundTasks| TaskPriority::BACKGROUND tasks. They
- // should be able to run, because the existing TaskPriority::BACKGROUND tasks
- // are blocked within a ScopedBlockingCall.
- //
- // Note: We block the tasks until they have all started running to make sure
- // that it is possible to run an extra |kMaxBackgroundTasks| concurrently.
- WaitableEvent background_tasks_running;
- WaitableEvent unblock_background_tasks;
- RepeatingClosure background_tasks_running_barrier = BarrierClosure(
- kMaxBackgroundTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&background_tasks_running)));
- for (int i = 0; i < kMaxBackgroundTasks; ++i) {
- background_runner->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- background_tasks_running_barrier.Run();
- WaitWithoutBlockingObserver(&unblock_background_tasks);
- }));
- }
- background_tasks_running.Wait();
-
- // Unblock all tasks and tear down.
- unblock_blocking_background_tasks.Signal();
- unblock_background_tasks.Signal();
- task_tracker_.FlushForTesting();
-}
-
-INSTANTIATE_TEST_CASE_P(
- MayBlock,
- TaskSchedulerWorkerPoolBlockingCallAndMaxBackgroundTasksTest,
- ::testing::Values(BlockingType::MAY_BLOCK));
-INSTANTIATE_TEST_CASE_P(
- WillBlock,
- TaskSchedulerWorkerPoolBlockingCallAndMaxBackgroundTasksTest,
- ::testing::Values(BlockingType::WILL_BLOCK));
-
-// Verify that worker detachement doesn't race with worker cleanup, regression
-// test for https://crbug.com/810464.
-TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, RacyCleanup) {
-#if defined(OS_FUCHSIA)
- // Fuchsia + QEMU doesn't deal well with *many* threads being
- // created/destroyed at once: https://crbug.com/816575.
- constexpr size_t kLocalMaxTasks = 16;
-#else // defined(OS_FUCHSIA)
- constexpr size_t kLocalMaxTasks = 256;
-#endif // defined(OS_FUCHSIA)
- constexpr TimeDelta kReclaimTimeForRacyCleanupTest =
- TimeDelta::FromMilliseconds(10);
-
- worker_pool_->Start(
- SchedulerWorkerPoolParams(kLocalMaxTasks, kReclaimTimeForRacyCleanupTest),
- kLocalMaxTasks, service_thread_.task_runner(), nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
-
- scoped_refptr<TaskRunner> task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- WaitableEvent threads_running;
- WaitableEvent unblock_threads;
- RepeatingClosure threads_running_barrier = BarrierClosure(
- kLocalMaxTasks,
- BindOnce(&WaitableEvent::Signal, Unretained(&threads_running)));
-
- for (size_t i = 0; i < kLocalMaxTasks; ++i) {
- task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](OnceClosure on_running, WaitableEvent* unblock_threads) {
- std::move(on_running).Run();
- WaitWithoutBlockingObserver(unblock_threads);
- },
- threads_running_barrier, Unretained(&unblock_threads)));
- }
-
- // Wait for all workers to be ready and release them all at once.
- threads_running.Wait();
- unblock_threads.Signal();
-
- // Sleep to wakeup precisely when all workers are going to try to cleanup per
- // being idle.
- PlatformThread::Sleep(kReclaimTimeForRacyCleanupTest);
-
- worker_pool_->JoinForTesting();
-
- // Unwinding this test will be racy if worker cleanup can race with
- // SchedulerWorkerPoolImpl destruction : https://crbug.com/810464.
- worker_pool_.reset();
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/scheduler_worker_stack_unittest.cc b/base/task_scheduler/scheduler_worker_stack_unittest.cc
deleted file mode 100644
index 83d693a912..0000000000
--- a/base/task_scheduler/scheduler_worker_stack_unittest.cc
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2016 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/task_scheduler/scheduler_worker_stack.h"
-
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/task_scheduler/scheduler_worker.h"
-#include "base/task_scheduler/sequence.h"
-#include "base/task_scheduler/task_tracker.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-class MockSchedulerWorkerDelegate : public SchedulerWorker::Delegate {
- public:
- void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override {
- ADD_FAILURE() << "Unexpected call to OnCanScheduleSequence().";
- }
- SchedulerWorker::ThreadLabel GetThreadLabel() const override {
- return SchedulerWorker::ThreadLabel::DEDICATED;
- }
- void OnMainEntry(const SchedulerWorker* worker) override {}
- scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
- return nullptr;
- }
- void DidRunTask() override {
- ADD_FAILURE() << "Unexpected call to DidRunTask()";
- }
- void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override {
- ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()";
- }
- TimeDelta GetSleepTimeout() override {
- return TimeDelta::Max();
- }
-};
-
-class TaskSchedulerWorkerStackTest : public testing::Test {
- protected:
- void SetUp() override {
- worker_a_ = MakeRefCounted<SchedulerWorker>(
- ThreadPriority::NORMAL, WrapUnique(new MockSchedulerWorkerDelegate),
- task_tracker_.GetTrackedRef());
- ASSERT_TRUE(worker_a_);
- worker_b_ = MakeRefCounted<SchedulerWorker>(
- ThreadPriority::NORMAL, WrapUnique(new MockSchedulerWorkerDelegate),
- task_tracker_.GetTrackedRef());
- ASSERT_TRUE(worker_b_);
- worker_c_ = MakeRefCounted<SchedulerWorker>(
- ThreadPriority::NORMAL, WrapUnique(new MockSchedulerWorkerDelegate),
- task_tracker_.GetTrackedRef());
- ASSERT_TRUE(worker_c_);
- }
-
- private:
- TaskTracker task_tracker_ = {"Test"};
-
- protected:
- scoped_refptr<SchedulerWorker> worker_a_;
- scoped_refptr<SchedulerWorker> worker_b_;
- scoped_refptr<SchedulerWorker> worker_c_;
-};
-
-} // namespace
-
-// Verify that Push() and Pop() add/remove values in FIFO order.
-TEST_F(TaskSchedulerWorkerStackTest, PushPop) {
- SchedulerWorkerStack stack;
- EXPECT_EQ(nullptr, stack.Pop());
-
- EXPECT_TRUE(stack.IsEmpty());
- EXPECT_EQ(0U, stack.Size());
-
- stack.Push(worker_a_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(1U, stack.Size());
-
- stack.Push(worker_b_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(2U, stack.Size());
-
- stack.Push(worker_c_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(3U, stack.Size());
-
- EXPECT_EQ(worker_c_.get(), stack.Pop());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(2U, stack.Size());
-
- stack.Push(worker_c_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(3U, stack.Size());
-
- EXPECT_EQ(worker_c_.get(), stack.Pop());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(2U, stack.Size());
-
- EXPECT_EQ(worker_b_.get(), stack.Pop());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(1U, stack.Size());
-
- EXPECT_EQ(worker_a_.get(), stack.Pop());
- EXPECT_TRUE(stack.IsEmpty());
- EXPECT_EQ(0U, stack.Size());
-
- EXPECT_EQ(nullptr, stack.Pop());
-}
-
-// Verify that Peek() returns the correct values in FIFO order.
-TEST_F(TaskSchedulerWorkerStackTest, PeekPop) {
- SchedulerWorkerStack stack;
- EXPECT_EQ(nullptr, stack.Peek());
-
- EXPECT_TRUE(stack.IsEmpty());
- EXPECT_EQ(0U, stack.Size());
-
- stack.Push(worker_a_.get());
- EXPECT_EQ(worker_a_.get(), stack.Peek());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(1U, stack.Size());
-
- stack.Push(worker_b_.get());
- EXPECT_EQ(worker_b_.get(), stack.Peek());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(2U, stack.Size());
-
- stack.Push(worker_c_.get());
- EXPECT_EQ(worker_c_.get(), stack.Peek());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(3U, stack.Size());
-
- EXPECT_EQ(worker_c_.get(), stack.Pop());
- EXPECT_EQ(worker_b_.get(), stack.Peek());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(2U, stack.Size());
-
- EXPECT_EQ(worker_b_.get(), stack.Pop());
- EXPECT_EQ(worker_a_.get(), stack.Peek());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(1U, stack.Size());
-
- EXPECT_EQ(worker_a_.get(), stack.Pop());
- EXPECT_TRUE(stack.IsEmpty());
- EXPECT_EQ(0U, stack.Size());
-
- EXPECT_EQ(nullptr, stack.Peek());
-}
-
-// Verify that Contains() returns true for workers on the stack.
-TEST_F(TaskSchedulerWorkerStackTest, Contains) {
- SchedulerWorkerStack stack;
- EXPECT_FALSE(stack.Contains(worker_a_.get()));
- EXPECT_FALSE(stack.Contains(worker_b_.get()));
- EXPECT_FALSE(stack.Contains(worker_c_.get()));
-
- stack.Push(worker_a_.get());
- EXPECT_TRUE(stack.Contains(worker_a_.get()));
- EXPECT_FALSE(stack.Contains(worker_b_.get()));
- EXPECT_FALSE(stack.Contains(worker_c_.get()));
-
- stack.Push(worker_b_.get());
- EXPECT_TRUE(stack.Contains(worker_a_.get()));
- EXPECT_TRUE(stack.Contains(worker_b_.get()));
- EXPECT_FALSE(stack.Contains(worker_c_.get()));
-
- stack.Push(worker_c_.get());
- EXPECT_TRUE(stack.Contains(worker_a_.get()));
- EXPECT_TRUE(stack.Contains(worker_b_.get()));
- EXPECT_TRUE(stack.Contains(worker_c_.get()));
-
- stack.Pop();
- EXPECT_TRUE(stack.Contains(worker_a_.get()));
- EXPECT_TRUE(stack.Contains(worker_b_.get()));
- EXPECT_FALSE(stack.Contains(worker_c_.get()));
-
- stack.Pop();
- EXPECT_TRUE(stack.Contains(worker_a_.get()));
- EXPECT_FALSE(stack.Contains(worker_b_.get()));
- EXPECT_FALSE(stack.Contains(worker_c_.get()));
-
- stack.Pop();
- EXPECT_FALSE(stack.Contains(worker_a_.get()));
- EXPECT_FALSE(stack.Contains(worker_b_.get()));
- EXPECT_FALSE(stack.Contains(worker_c_.get()));
-}
-
-// Verify that a value can be removed by Remove().
-TEST_F(TaskSchedulerWorkerStackTest, Remove) {
- SchedulerWorkerStack stack;
- EXPECT_TRUE(stack.IsEmpty());
- EXPECT_EQ(0U, stack.Size());
-
- stack.Push(worker_a_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(1U, stack.Size());
-
- stack.Push(worker_b_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(2U, stack.Size());
-
- stack.Push(worker_c_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(3U, stack.Size());
-
- stack.Remove(worker_b_.get());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(2U, stack.Size());
-
- EXPECT_EQ(worker_c_.get(), stack.Pop());
- EXPECT_FALSE(stack.IsEmpty());
- EXPECT_EQ(1U, stack.Size());
-
- EXPECT_EQ(worker_a_.get(), stack.Pop());
- EXPECT_TRUE(stack.IsEmpty());
- EXPECT_EQ(0U, stack.Size());
-}
-
-// Verify that a value can be pushed again after it has been removed.
-TEST_F(TaskSchedulerWorkerStackTest, PushAfterRemove) {
- SchedulerWorkerStack stack;
- EXPECT_EQ(0U, stack.Size());
-
- stack.Push(worker_a_.get());
- EXPECT_EQ(1U, stack.Size());
-
- // Need to also push worker B for this test as it's illegal to Remove() the
- // top of the stack.
- stack.Push(worker_b_.get());
- EXPECT_EQ(2U, stack.Size());
-
- stack.Remove(worker_a_.get());
- EXPECT_EQ(1U, stack.Size());
-
- stack.Push(worker_a_.get());
- EXPECT_EQ(2U, stack.Size());
-}
-
-// Verify that Push() DCHECKs when a value is inserted twice.
-TEST_F(TaskSchedulerWorkerStackTest, PushTwice) {
- SchedulerWorkerStack stack;
- stack.Push(worker_a_.get());
- EXPECT_DCHECK_DEATH({ stack.Push(worker_a_.get()); });
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc
deleted file mode 100644
index 1112f55e6c..0000000000
--- a/base/task_scheduler/scheduler_worker_unittest.cc
+++ /dev/null
@@ -1,897 +0,0 @@
-// Copyright 2016 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/task_scheduler/scheduler_worker.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/environment_config.h"
-#include "base/task_scheduler/scheduler_lock.h"
-#include "base/task_scheduler/scheduler_worker_observer.h"
-#include "base/task_scheduler/sequence.h"
-#include "base/task_scheduler/task.h"
-#include "base/task_scheduler/task_tracker.h"
-#include "base/task_scheduler/test_utils.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include <objbase.h>
-
-#include "base/win/com_init_check_hook.h"
-#endif
-
-using testing::_;
-using testing::Mock;
-using testing::Ne;
-using testing::StrictMock;
-
-namespace base {
-namespace internal {
-namespace {
-
-const size_t kNumSequencesPerTest = 150;
-
-class SchedulerWorkerDefaultDelegate : public SchedulerWorker::Delegate {
- public:
- SchedulerWorkerDefaultDelegate() = default;
-
- // SchedulerWorker::Delegate:
- void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override {
- ADD_FAILURE() << "Unexpected call to OnCanScheduleSequence().";
- }
- SchedulerWorker::ThreadLabel GetThreadLabel() const override {
- return SchedulerWorker::ThreadLabel::DEDICATED;
- }
- void OnMainEntry(const SchedulerWorker* worker) override {}
- scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
- return nullptr;
- }
- void DidRunTask() override {
- ADD_FAILURE() << "Unexpected call to DidRunTask()";
- }
- void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override {
- ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()";
- }
- TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate);
-};
-
-// The test parameter is the number of Tasks per Sequence returned by GetWork().
-class TaskSchedulerWorkerTest : public testing::TestWithParam<size_t> {
- protected:
- TaskSchedulerWorkerTest()
- : num_get_work_cv_(lock_.CreateConditionVariable()) {}
-
- void SetUp() override {
- worker_ = MakeRefCounted<SchedulerWorker>(
- ThreadPriority::NORMAL,
- std::make_unique<TestSchedulerWorkerDelegate>(this),
- task_tracker_.GetTrackedRef());
- ASSERT_TRUE(worker_);
- worker_->Start();
- worker_set_.Signal();
- main_entry_called_.Wait();
- }
-
- void TearDown() override {
- // |worker_| needs to be released before ~TaskTracker() as it holds a
- // TrackedRef to it.
- worker_->JoinForTesting();
- worker_ = nullptr;
- }
-
- size_t TasksPerSequence() const { return GetParam(); }
-
- // Wait until GetWork() has been called |num_get_work| times.
- void WaitForNumGetWork(size_t num_get_work) {
- AutoSchedulerLock auto_lock(lock_);
- while (num_get_work_ < num_get_work)
- num_get_work_cv_->Wait();
- }
-
- void SetMaxGetWork(size_t max_get_work) {
- AutoSchedulerLock auto_lock(lock_);
- max_get_work_ = max_get_work;
- }
-
- void SetNumSequencesToCreate(size_t num_sequences_to_create) {
- AutoSchedulerLock auto_lock(lock_);
- EXPECT_EQ(0U, num_sequences_to_create_);
- num_sequences_to_create_ = num_sequences_to_create;
- }
-
- size_t NumRunTasks() {
- AutoSchedulerLock auto_lock(lock_);
- return num_run_tasks_;
- }
-
- std::vector<scoped_refptr<Sequence>> CreatedSequences() {
- AutoSchedulerLock auto_lock(lock_);
- return created_sequences_;
- }
-
- std::vector<scoped_refptr<Sequence>> EnqueuedSequences() {
- AutoSchedulerLock auto_lock(lock_);
- return re_enqueued_sequences_;
- }
-
- scoped_refptr<SchedulerWorker> worker_;
-
- private:
- class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate {
- public:
- TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer)
- : outer_(outer) {}
-
- ~TestSchedulerWorkerDelegate() override {
- EXPECT_FALSE(IsCallToDidRunTaskExpected());
- }
-
- // SchedulerWorker::Delegate:
- void OnMainEntry(const SchedulerWorker* worker) override {
- outer_->worker_set_.Wait();
- EXPECT_EQ(outer_->worker_.get(), worker);
- EXPECT_FALSE(IsCallToDidRunTaskExpected());
-
- // Without synchronization, OnMainEntry() could be called twice without
- // generating an error.
- AutoSchedulerLock auto_lock(outer_->lock_);
- EXPECT_FALSE(outer_->main_entry_called_.IsSignaled());
- outer_->main_entry_called_.Signal();
- }
-
- scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
- EXPECT_FALSE(IsCallToDidRunTaskExpected());
- EXPECT_EQ(outer_->worker_.get(), worker);
-
- {
- AutoSchedulerLock auto_lock(outer_->lock_);
-
- // Increment the number of times that this method has been called.
- ++outer_->num_get_work_;
- outer_->num_get_work_cv_->Signal();
-
- // Verify that this method isn't called more times than expected.
- EXPECT_LE(outer_->num_get_work_, outer_->max_get_work_);
-
- // Check if a Sequence should be returned.
- if (outer_->num_sequences_to_create_ == 0)
- return nullptr;
- --outer_->num_sequences_to_create_;
- }
-
- // Create a Sequence with TasksPerSequence() Tasks.
- scoped_refptr<Sequence> sequence(new Sequence);
- for (size_t i = 0; i < outer_->TasksPerSequence(); ++i) {
- Task task(FROM_HERE,
- BindOnce(&TaskSchedulerWorkerTest::RunTaskCallback,
- Unretained(outer_)),
- TaskTraits(), TimeDelta());
- EXPECT_TRUE(outer_->task_tracker_.WillPostTask(&task));
- sequence->PushTask(std::move(task));
- }
-
- ExpectCallToDidRunTask();
-
- {
- // Add the Sequence to the vector of created Sequences.
- AutoSchedulerLock auto_lock(outer_->lock_);
- outer_->created_sequences_.push_back(sequence);
- }
-
- sequence = outer_->task_tracker_.WillScheduleSequence(std::move(sequence),
- nullptr);
- EXPECT_TRUE(sequence);
- return sequence;
- }
-
- void DidRunTask() override {
- AutoSchedulerLock auto_lock(expect_did_run_task_lock_);
- EXPECT_TRUE(expect_did_run_task_);
- expect_did_run_task_ = false;
- }
-
- // This override verifies that |sequence| contains the expected number of
- // Tasks and adds it to |enqueued_sequences_|. Unlike a normal
- // EnqueueSequence implementation, it doesn't reinsert |sequence| into a
- // queue for further execution.
- void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override {
- EXPECT_FALSE(IsCallToDidRunTaskExpected());
- EXPECT_GT(outer_->TasksPerSequence(), 1U);
-
- // Verify that |sequence| contains TasksPerSequence() - 1 Tasks.
- for (size_t i = 0; i < outer_->TasksPerSequence() - 1; ++i) {
- EXPECT_TRUE(sequence->TakeTask());
- EXPECT_EQ(i == outer_->TasksPerSequence() - 2, sequence->Pop());
- }
-
- // Add |sequence| to |re_enqueued_sequences_|.
- AutoSchedulerLock auto_lock(outer_->lock_);
- outer_->re_enqueued_sequences_.push_back(std::move(sequence));
- EXPECT_LE(outer_->re_enqueued_sequences_.size(),
- outer_->created_sequences_.size());
- }
-
- private:
- // Expect a call to DidRunTask() before the next call to any other method of
- // this delegate.
- void ExpectCallToDidRunTask() {
- AutoSchedulerLock auto_lock(expect_did_run_task_lock_);
- expect_did_run_task_ = true;
- }
-
- bool IsCallToDidRunTaskExpected() const {
- AutoSchedulerLock auto_lock(expect_did_run_task_lock_);
- return expect_did_run_task_;
- }
-
- TaskSchedulerWorkerTest* outer_;
-
- // Synchronizes access to |expect_did_run_task_|.
- mutable SchedulerLock expect_did_run_task_lock_;
-
- // Whether the next method called on this delegate should be DidRunTask().
- bool expect_did_run_task_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(TestSchedulerWorkerDelegate);
- };
-
- void RunTaskCallback() {
- AutoSchedulerLock auto_lock(lock_);
- ++num_run_tasks_;
- EXPECT_LE(num_run_tasks_, created_sequences_.size());
- }
-
- TaskTracker task_tracker_ = {"Test"};
-
- // Synchronizes access to all members below.
- mutable SchedulerLock lock_;
-
- // Signaled once OnMainEntry() has been called.
- WaitableEvent main_entry_called_;
-
- // Number of Sequences that should be created by GetWork(). When this
- // is 0, GetWork() returns nullptr.
- size_t num_sequences_to_create_ = 0;
-
- // Number of times that GetWork() has been called.
- size_t num_get_work_ = 0;
-
- // Maximum number of times that GetWork() can be called.
- size_t max_get_work_ = 0;
-
- // Condition variable signaled when |num_get_work_| is incremented.
- std::unique_ptr<ConditionVariable> num_get_work_cv_;
-
- // Sequences created by GetWork().
- std::vector<scoped_refptr<Sequence>> created_sequences_;
-
- // Sequences passed to EnqueueSequence().
- std::vector<scoped_refptr<Sequence>> re_enqueued_sequences_;
-
- // Number of times that RunTaskCallback() has been called.
- size_t num_run_tasks_ = 0;
-
- // Signaled after |worker_| is set.
- WaitableEvent worker_set_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerTest);
-};
-
-} // namespace
-
-// Verify that when GetWork() continuously returns Sequences, all Tasks in these
-// Sequences run successfully. The test wakes up the SchedulerWorker once.
-TEST_P(TaskSchedulerWorkerTest, ContinuousWork) {
- // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to
- // return nullptr.
- SetNumSequencesToCreate(kNumSequencesPerTest);
-
- // Expect |kNumSequencesPerTest| calls to GetWork() in which it returns a
- // Sequence and one call in which its returns nullptr.
- const size_t kExpectedNumGetWork = kNumSequencesPerTest + 1;
- SetMaxGetWork(kExpectedNumGetWork);
-
- // Wake up |worker_| and wait until GetWork() has been invoked the
- // expected amount of times.
- worker_->WakeUp();
- WaitForNumGetWork(kExpectedNumGetWork);
-
- // All tasks should have run.
- EXPECT_EQ(kNumSequencesPerTest, NumRunTasks());
-
- // If Sequences returned by GetWork() contain more than one Task, they aren't
- // empty after the worker pops Tasks from them and thus should be returned to
- // EnqueueSequence().
- if (TasksPerSequence() > 1)
- EXPECT_EQ(CreatedSequences(), EnqueuedSequences());
- else
- EXPECT_TRUE(EnqueuedSequences().empty());
-}
-
-// Verify that when GetWork() alternates between returning a Sequence and
-// returning nullptr, all Tasks in the returned Sequences run successfully. The
-// test wakes up the SchedulerWorker once for each Sequence.
-TEST_P(TaskSchedulerWorkerTest, IntermittentWork) {
- for (size_t i = 0; i < kNumSequencesPerTest; ++i) {
- // Set GetWork() to return 1 Sequence before starting to return
- // nullptr.
- SetNumSequencesToCreate(1);
-
- // Expect |i + 1| calls to GetWork() in which it returns a Sequence and
- // |i + 1| calls in which it returns nullptr.
- const size_t expected_num_get_work = 2 * (i + 1);
- SetMaxGetWork(expected_num_get_work);
-
- // Wake up |worker_| and wait until GetWork() has been invoked
- // the expected amount of times.
- worker_->WakeUp();
- WaitForNumGetWork(expected_num_get_work);
-
- // The Task should have run
- EXPECT_EQ(i + 1, NumRunTasks());
-
- // If Sequences returned by GetWork() contain more than one Task, they
- // aren't empty after the worker pops Tasks from them and thus should be
- // returned to EnqueueSequence().
- if (TasksPerSequence() > 1)
- EXPECT_EQ(CreatedSequences(), EnqueuedSequences());
- else
- EXPECT_TRUE(EnqueuedSequences().empty());
- }
-}
-
-INSTANTIATE_TEST_CASE_P(OneTaskPerSequence,
- TaskSchedulerWorkerTest,
- ::testing::Values(1));
-INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence,
- TaskSchedulerWorkerTest,
- ::testing::Values(2));
-
-namespace {
-
-class ControllableCleanupDelegate : public SchedulerWorkerDefaultDelegate {
- public:
- class Controls : public RefCountedThreadSafe<Controls> {
- public:
- Controls() = default;
-
- void HaveWorkBlock() { work_running_.Reset(); }
-
- void UnblockWork() { work_running_.Signal(); }
-
- void WaitForWorkToRun() { work_processed_.Wait(); }
-
- void WaitForCleanupRequest() { cleanup_requested_.Wait(); }
-
- void WaitForDelegateDestroy() { destroyed_.Wait(); }
-
- void WaitForMainExit() { exited_.Wait(); }
-
- void set_expect_get_work(bool expect_get_work) {
- expect_get_work_ = expect_get_work;
- }
-
- void ResetState() {
- work_running_.Signal();
- work_processed_.Reset();
- cleanup_requested_.Reset();
- exited_.Reset();
- work_requested_ = false;
- }
-
- void set_can_cleanup(bool can_cleanup) { can_cleanup_ = can_cleanup; }
-
- private:
- friend class ControllableCleanupDelegate;
- friend class RefCountedThreadSafe<Controls>;
- ~Controls() = default;
-
- WaitableEvent work_running_{WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::SIGNALED};
- WaitableEvent work_processed_;
- WaitableEvent cleanup_requested_;
- WaitableEvent destroyed_;
- WaitableEvent exited_;
-
- bool expect_get_work_ = true;
- bool can_cleanup_ = false;
- bool work_requested_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(Controls);
- };
-
- ControllableCleanupDelegate(TaskTracker* task_tracker)
- : task_tracker_(task_tracker), controls_(new Controls()) {}
-
- ~ControllableCleanupDelegate() override { controls_->destroyed_.Signal(); }
-
- scoped_refptr<Sequence> GetWork(SchedulerWorker* worker)
- override {
- EXPECT_TRUE(controls_->expect_get_work_);
-
- // Sends one item of work to signal |work_processed_|. On subsequent calls,
- // sends nullptr to indicate there's no more work to be done.
- if (controls_->work_requested_) {
- if (CanCleanup(worker)) {
- OnCleanup();
- worker->Cleanup();
- controls_->set_expect_get_work(false);
- }
- return nullptr;
- }
-
- controls_->work_requested_ = true;
- scoped_refptr<Sequence> sequence(new Sequence);
- Task task(
- FROM_HERE,
- BindOnce(
- [](WaitableEvent* work_processed, WaitableEvent* work_running) {
- work_processed->Signal();
- work_running->Wait();
- },
- Unretained(&controls_->work_processed_),
- Unretained(&controls_->work_running_)),
- {WithBaseSyncPrimitives(), TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- TimeDelta());
- EXPECT_TRUE(task_tracker_->WillPostTask(&task));
- sequence->PushTask(std::move(task));
- sequence =
- task_tracker_->WillScheduleSequence(std::move(sequence), nullptr);
- EXPECT_TRUE(sequence);
- return sequence;
- }
-
- void DidRunTask() override {}
-
- void OnMainExit(SchedulerWorker* worker) override {
- controls_->exited_.Signal();
- }
-
- bool CanCleanup(SchedulerWorker* worker) {
- // Saving |can_cleanup_| now so that callers waiting on |cleanup_requested_|
- // have the thread go to sleep and then allow timing out.
- bool can_cleanup = controls_->can_cleanup_;
- controls_->cleanup_requested_.Signal();
- return can_cleanup;
- }
-
- void OnCleanup() {
- EXPECT_TRUE(controls_->can_cleanup_);
- EXPECT_TRUE(controls_->cleanup_requested_.IsSignaled());
- }
-
- // ControllableCleanupDelegate:
- scoped_refptr<Controls> controls() { return controls_; }
-
- private:
- scoped_refptr<Sequence> work_sequence_;
- TaskTracker* const task_tracker_;
- scoped_refptr<Controls> controls_;
-
- DISALLOW_COPY_AND_ASSIGN(ControllableCleanupDelegate);
-};
-
-class MockedControllableCleanupDelegate : public ControllableCleanupDelegate {
- public:
- MockedControllableCleanupDelegate(TaskTracker* task_tracker)
- : ControllableCleanupDelegate(task_tracker){};
- ~MockedControllableCleanupDelegate() override = default;
-
- // SchedulerWorker::Delegate:
- MOCK_METHOD1(OnMainEntry, void(const SchedulerWorker* worker));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockedControllableCleanupDelegate);
-};
-
-} // namespace
-
-// Verify that calling SchedulerWorker::Cleanup() from GetWork() causes
-// the SchedulerWorker's thread to exit.
-TEST(TaskSchedulerWorkerTest, WorkerCleanupFromGetWork) {
- TaskTracker task_tracker("Test");
- // Will be owned by SchedulerWorker.
- MockedControllableCleanupDelegate* delegate =
- new StrictMock<MockedControllableCleanupDelegate>(&task_tracker);
- scoped_refptr<ControllableCleanupDelegate::Controls> controls =
- delegate->controls();
- controls->set_can_cleanup(true);
- EXPECT_CALL(*delegate, OnMainEntry(_));
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
- WrapUnique(delegate),
- task_tracker.GetTrackedRef());
- worker->Start();
- worker->WakeUp();
- controls->WaitForWorkToRun();
- Mock::VerifyAndClear(delegate);
- controls->WaitForMainExit();
-}
-
-TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringWork) {
- TaskTracker task_tracker("Test");
- // Will be owned by SchedulerWorker.
- // No mock here as that's reasonably covered by other tests and the delegate
- // may destroy on a different thread. Mocks aren't designed with that in mind.
- std::unique_ptr<ControllableCleanupDelegate> delegate =
- std::make_unique<ControllableCleanupDelegate>(&task_tracker);
- scoped_refptr<ControllableCleanupDelegate::Controls> controls =
- delegate->controls();
-
- controls->HaveWorkBlock();
-
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
- std::move(delegate),
- task_tracker.GetTrackedRef());
- worker->Start();
- worker->WakeUp();
-
- controls->WaitForWorkToRun();
- worker->Cleanup();
- worker = nullptr;
- controls->UnblockWork();
- controls->WaitForDelegateDestroy();
-}
-
-TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringWait) {
- TaskTracker task_tracker("Test");
- // Will be owned by SchedulerWorker.
- // No mock here as that's reasonably covered by other tests and the delegate
- // may destroy on a different thread. Mocks aren't designed with that in mind.
- std::unique_ptr<ControllableCleanupDelegate> delegate =
- std::make_unique<ControllableCleanupDelegate>(&task_tracker);
- scoped_refptr<ControllableCleanupDelegate::Controls> controls =
- delegate->controls();
-
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
- std::move(delegate),
- task_tracker.GetTrackedRef());
- worker->Start();
- worker->WakeUp();
-
- controls->WaitForCleanupRequest();
- worker->Cleanup();
- worker = nullptr;
- controls->WaitForDelegateDestroy();
-}
-
-TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringShutdown) {
- TaskTracker task_tracker("Test");
- // Will be owned by SchedulerWorker.
- // No mock here as that's reasonably covered by other tests and the delegate
- // may destroy on a different thread. Mocks aren't designed with that in mind.
- std::unique_ptr<ControllableCleanupDelegate> delegate =
- std::make_unique<ControllableCleanupDelegate>(&task_tracker);
- scoped_refptr<ControllableCleanupDelegate::Controls> controls =
- delegate->controls();
-
- controls->HaveWorkBlock();
-
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
- std::move(delegate),
- task_tracker.GetTrackedRef());
- worker->Start();
- worker->WakeUp();
-
- controls->WaitForWorkToRun();
- task_tracker.Shutdown();
- worker->Cleanup();
- worker = nullptr;
- controls->UnblockWork();
- controls->WaitForDelegateDestroy();
-}
-
-// Verify that Start() is a no-op after Cleanup().
-TEST(TaskSchedulerWorkerTest, CleanupBeforeStart) {
- TaskTracker task_tracker("Test");
- // Will be owned by SchedulerWorker.
- // No mock here as that's reasonably covered by other tests and the delegate
- // may destroy on a different thread. Mocks aren't designed with that in mind.
- std::unique_ptr<ControllableCleanupDelegate> delegate =
- std::make_unique<ControllableCleanupDelegate>(&task_tracker);
- scoped_refptr<ControllableCleanupDelegate::Controls> controls =
- delegate->controls();
- controls->set_expect_get_work(false);
-
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
- std::move(delegate),
- task_tracker.GetTrackedRef());
-
- worker->Cleanup();
- worker->Start();
-
- EXPECT_FALSE(worker->ThreadAliveForTesting());
-}
-
-namespace {
-
-class CallJoinFromDifferentThread : public SimpleThread {
- public:
- CallJoinFromDifferentThread(SchedulerWorker* worker_to_join)
- : SimpleThread("SchedulerWorkerJoinThread"),
- worker_to_join_(worker_to_join) {}
-
- ~CallJoinFromDifferentThread() override = default;
-
- void Run() override {
- run_started_event_.Signal();
- worker_to_join_->JoinForTesting();
- }
-
- void WaitForRunToStart() { run_started_event_.Wait(); }
-
- private:
- SchedulerWorker* const worker_to_join_;
- WaitableEvent run_started_event_;
- DISALLOW_COPY_AND_ASSIGN(CallJoinFromDifferentThread);
-};
-
-} // namespace
-
-TEST(TaskSchedulerWorkerTest, WorkerCleanupDuringJoin) {
- TaskTracker task_tracker("Test");
- // Will be owned by SchedulerWorker.
- // No mock here as that's reasonably covered by other tests and the
- // delegate may destroy on a different thread. Mocks aren't designed with that
- // in mind.
- std::unique_ptr<ControllableCleanupDelegate> delegate =
- std::make_unique<ControllableCleanupDelegate>(&task_tracker);
- scoped_refptr<ControllableCleanupDelegate::Controls> controls =
- delegate->controls();
-
- controls->HaveWorkBlock();
-
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
- std::move(delegate),
- task_tracker.GetTrackedRef());
- worker->Start();
- worker->WakeUp();
-
- controls->WaitForWorkToRun();
- CallJoinFromDifferentThread join_from_different_thread(worker.get());
- join_from_different_thread.Start();
- join_from_different_thread.WaitForRunToStart();
- // Sleep here to give the other thread a chance to call JoinForTesting().
- // Receiving a signal that Run() was called doesn't mean JoinForTesting() was
- // necessarily called, and we can't signal after JoinForTesting() as
- // JoinForTesting() blocks until we call UnblockWork().
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- worker->Cleanup();
- worker = nullptr;
- controls->UnblockWork();
- controls->WaitForDelegateDestroy();
- join_from_different_thread.Join();
-}
-
-namespace {
-
-class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate {
- public:
- ExpectThreadPriorityDelegate()
- : priority_verified_in_get_work_event_(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED),
- expected_thread_priority_(ThreadPriority::BACKGROUND) {}
-
- void SetExpectedThreadPriority(ThreadPriority expected_thread_priority) {
- expected_thread_priority_ = expected_thread_priority;
- }
-
- void WaitForPriorityVerifiedInGetWork() {
- priority_verified_in_get_work_event_.Wait();
- }
-
- // SchedulerWorker::Delegate:
- void OnMainEntry(const SchedulerWorker* worker) override {
- VerifyThreadPriority();
- }
- scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
- VerifyThreadPriority();
- priority_verified_in_get_work_event_.Signal();
- return nullptr;
- }
-
- private:
- void VerifyThreadPriority() {
- AutoSchedulerLock auto_lock(expected_thread_priority_lock_);
- EXPECT_EQ(expected_thread_priority_,
- PlatformThread::GetCurrentThreadPriority());
- }
-
- // Signaled after GetWork() has verified the priority of the worker thread.
- WaitableEvent priority_verified_in_get_work_event_;
-
- // Synchronizes access to |expected_thread_priority_|.
- SchedulerLock expected_thread_priority_lock_;
-
- // Expected thread priority for the next call to OnMainEntry() or GetWork().
- ThreadPriority expected_thread_priority_;
-
- DISALLOW_COPY_AND_ASSIGN(ExpectThreadPriorityDelegate);
-};
-
-} // namespace
-
-TEST(TaskSchedulerWorkerTest, BumpPriorityOfAliveThreadDuringShutdown) {
- if (!CanUseBackgroundPriorityForSchedulerWorker())
- return;
-
- TaskTracker task_tracker("Test");
-
- std::unique_ptr<ExpectThreadPriorityDelegate> delegate(
- new ExpectThreadPriorityDelegate);
- ExpectThreadPriorityDelegate* delegate_raw = delegate.get();
- delegate_raw->SetExpectedThreadPriority(ThreadPriority::BACKGROUND);
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::BACKGROUND,
- std::move(delegate),
- task_tracker.GetTrackedRef());
- worker->Start();
-
- // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread
- // priority can't be increased).
- worker->WakeUp();
- delegate_raw->WaitForPriorityVerifiedInGetWork();
-
- // Verify that the thread priority is bumped to NORMAL during shutdown.
- delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL);
- task_tracker.SetHasShutdownStartedForTesting();
- worker->WakeUp();
- delegate_raw->WaitForPriorityVerifiedInGetWork();
-
- worker->JoinForTesting();
-}
-
-namespace {
-
-class VerifyCallsToObserverDelegate : public SchedulerWorkerDefaultDelegate {
- public:
- VerifyCallsToObserverDelegate(test::MockSchedulerWorkerObserver* observer)
- : observer_(observer) {}
-
- // SchedulerWorker::Delegate:
- void OnMainEntry(const SchedulerWorker* worker) override {
- Mock::VerifyAndClear(observer_);
- }
-
- void OnMainExit(SchedulerWorker* worker) override {
- EXPECT_CALL(*observer_, OnSchedulerWorkerMainExit());
- }
-
- private:
- test::MockSchedulerWorkerObserver* const observer_;
-
- DISALLOW_COPY_AND_ASSIGN(VerifyCallsToObserverDelegate);
-};
-
-} // namespace
-
-// Flaky: crbug.com/846121
-#if defined(OS_LINUX) && defined(ADDRESS_SANITIZER)
-#define MAYBE_SchedulerWorkerObserver DISABLED_SchedulerWorkerObserver
-#else
-#define MAYBE_SchedulerWorkerObserver SchedulerWorkerObserver
-#endif
-
-// Verify that the SchedulerWorkerObserver is notified when the worker enters
-// and exits its main function.
-TEST(TaskSchedulerWorkerTest, MAYBE_SchedulerWorkerObserver) {
- StrictMock<test::MockSchedulerWorkerObserver> observer;
- {
- TaskTracker task_tracker("Test");
- auto delegate = std::make_unique<VerifyCallsToObserverDelegate>(&observer);
- auto worker = MakeRefCounted<SchedulerWorker>(ThreadPriority::NORMAL,
- std::move(delegate),
- task_tracker.GetTrackedRef());
-
- EXPECT_CALL(observer, OnSchedulerWorkerMainEntry());
- worker->Start(&observer);
- worker->Cleanup();
- worker = nullptr;
- }
- Mock::VerifyAndClear(&observer);
-}
-
-#if defined(OS_WIN)
-
-namespace {
-
-class CoInitializeDelegate : public SchedulerWorkerDefaultDelegate {
- public:
- CoInitializeDelegate() = default;
-
- scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
- EXPECT_FALSE(get_work_returned_.IsSignaled());
- EXPECT_EQ(E_UNEXPECTED, coinitialize_hresult_);
-
- coinitialize_hresult_ = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
- if (SUCCEEDED(coinitialize_hresult_))
- CoUninitialize();
-
- get_work_returned_.Signal();
- return nullptr;
- }
-
- void WaitUntilGetWorkReturned() { get_work_returned_.Wait(); }
-
- HRESULT coinitialize_hresult() const { return coinitialize_hresult_; }
-
- private:
- WaitableEvent get_work_returned_;
- HRESULT coinitialize_hresult_ = E_UNEXPECTED;
-
- DISALLOW_COPY_AND_ASSIGN(CoInitializeDelegate);
-};
-
-} // namespace
-
-TEST(TaskSchedulerWorkerTest, BackwardCompatibilityEnabled) {
- TaskTracker task_tracker("Test");
- auto delegate = std::make_unique<CoInitializeDelegate>();
- CoInitializeDelegate* const delegate_raw = delegate.get();
-
- // Create a worker with backward compatibility ENABLED. Wake it up and wait
- // until GetWork() returns.
- auto worker = MakeRefCounted<SchedulerWorker>(
- ThreadPriority::NORMAL, std::move(delegate), task_tracker.GetTrackedRef(),
- nullptr, SchedulerBackwardCompatibility::INIT_COM_STA);
- worker->Start();
- worker->WakeUp();
- delegate_raw->WaitUntilGetWorkReturned();
-
- // The call to CoInitializeEx() should have returned S_FALSE to indicate that
- // the COM library was already initialized on the thread.
- // See SchedulerWorker::Thread::ThreadMain for why we expect two different
- // results here.
-#if defined(COM_INIT_CHECK_HOOK_ENABLED)
- EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult());
-#else
- EXPECT_EQ(S_FALSE, delegate_raw->coinitialize_hresult());
-#endif
-
- worker->JoinForTesting();
-}
-
-TEST(TaskSchedulerWorkerTest, BackwardCompatibilityDisabled) {
- TaskTracker task_tracker("Test");
- auto delegate = std::make_unique<CoInitializeDelegate>();
- CoInitializeDelegate* const delegate_raw = delegate.get();
-
- // Create a worker with backward compatibility DISABLED. Wake it up and wait
- // until GetWork() returns.
- auto worker = MakeRefCounted<SchedulerWorker>(
- ThreadPriority::NORMAL, std::move(delegate), task_tracker.GetTrackedRef(),
- nullptr, SchedulerBackwardCompatibility::DISABLED);
- worker->Start();
- worker->WakeUp();
- delegate_raw->WaitUntilGetWorkReturned();
-
- // The call to CoInitializeEx() should have returned S_OK to indicate that the
- // COM library wasn't already initialized on the thread.
- EXPECT_EQ(S_OK, delegate_raw->coinitialize_hresult());
-
- worker->JoinForTesting();
-}
-
-#endif // defined(OS_WIN)
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/task_scheduler_impl_unittest.cc b/base/task_scheduler/task_scheduler_impl_unittest.cc
deleted file mode 100644
index 94c5293903..0000000000
--- a/base/task_scheduler/task_scheduler_impl_unittest.cc
+++ /dev/null
@@ -1,841 +0,0 @@
-// Copyright 2016 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/task_scheduler/task_scheduler_impl.h"
-
-#include <stddef.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/cfi_buildflags.h"
-#include "base/debug/stack_trace.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/environment_config.h"
-#include "base/task_scheduler/scheduler_worker_observer.h"
-#include "base/task_scheduler/scheduler_worker_pool_params.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/task_scheduler/test_task_factory.h"
-#include "base/task_scheduler/test_utils.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequence_local_storage_slot.h"
-#include "base/threading/simple_thread.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include <unistd.h>
-
-#include "base/debug/leak_annotations.h"
-#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/files/file_util.h"
-#include "base/posix/eintr_wrapper.h"
-#endif // defined(OS_POSIX)
-
-#if defined(OS_WIN)
-#include "base/win/com_init_util.h"
-#endif // defined(OS_WIN)
-
-namespace base {
-namespace internal {
-
-namespace {
-
-struct TraitsExecutionModePair {
- TraitsExecutionModePair(const TaskTraits& traits,
- test::ExecutionMode execution_mode)
- : traits(traits), execution_mode(execution_mode) {}
-
- TaskTraits traits;
- test::ExecutionMode execution_mode;
-};
-
-#if DCHECK_IS_ON()
-// Returns whether I/O calls are allowed on the current thread.
-bool GetIOAllowed() {
- const bool previous_value = ThreadRestrictions::SetIOAllowed(true);
- ThreadRestrictions::SetIOAllowed(previous_value);
- return previous_value;
-}
-#endif
-
-// Verify that the current thread priority and I/O restrictions are appropriate
-// to run a Task with |traits|.
-// Note: ExecutionMode is verified inside TestTaskFactory.
-void VerifyTaskEnvironment(const TaskTraits& traits) {
- EXPECT_EQ(CanUseBackgroundPriorityForSchedulerWorker() &&
- traits.priority() == TaskPriority::BACKGROUND
- ? ThreadPriority::BACKGROUND
- : ThreadPriority::NORMAL,
- PlatformThread::GetCurrentThreadPriority());
-
-#if DCHECK_IS_ON()
- // The #if above is required because GetIOAllowed() always returns true when
- // !DCHECK_IS_ON(), even when |traits| don't allow file I/O.
- EXPECT_EQ(traits.may_block(), GetIOAllowed());
-#endif
-
- // Verify that the thread the task is running on is named as expected.
- const std::string current_thread_name(PlatformThread::GetName());
- EXPECT_NE(std::string::npos, current_thread_name.find("TaskScheduler"));
-
- if (current_thread_name.find("SingleThread") != std::string::npos) {
- // For now, single-threaded background tasks run on their own threads.
- // TODO(fdoray): Run single-threaded background tasks on foreground workers
- // on platforms that don't support background thread priority.
- EXPECT_NE(
- std::string::npos,
- current_thread_name.find(traits.priority() == TaskPriority::BACKGROUND
- ? "Background"
- : "Foreground"));
- } else {
- EXPECT_NE(std::string::npos,
- current_thread_name.find(
- CanUseBackgroundPriorityForSchedulerWorker() &&
- traits.priority() == TaskPriority::BACKGROUND
- ? "Background"
- : "Foreground"));
- }
- EXPECT_EQ(traits.may_block(),
- current_thread_name.find("Blocking") != std::string::npos);
-}
-
-void VerifyTaskEnvironmentAndSignalEvent(const TaskTraits& traits,
- WaitableEvent* event) {
- DCHECK(event);
- VerifyTaskEnvironment(traits);
- event->Signal();
-}
-
-void VerifyTimeAndTaskEnvironmentAndSignalEvent(const TaskTraits& traits,
- TimeTicks expected_time,
- WaitableEvent* event) {
- DCHECK(event);
- EXPECT_LE(expected_time, TimeTicks::Now());
- VerifyTaskEnvironment(traits);
- event->Signal();
-}
-
-scoped_refptr<TaskRunner> CreateTaskRunnerWithTraitsAndExecutionMode(
- TaskScheduler* scheduler,
- const TaskTraits& traits,
- test::ExecutionMode execution_mode,
- SingleThreadTaskRunnerThreadMode default_single_thread_task_runner_mode =
- SingleThreadTaskRunnerThreadMode::SHARED) {
- switch (execution_mode) {
- case test::ExecutionMode::PARALLEL:
- return scheduler->CreateTaskRunnerWithTraits(traits);
- case test::ExecutionMode::SEQUENCED:
- return scheduler->CreateSequencedTaskRunnerWithTraits(traits);
- case test::ExecutionMode::SINGLE_THREADED: {
- return scheduler->CreateSingleThreadTaskRunnerWithTraits(
- traits, default_single_thread_task_runner_mode);
- }
- }
- ADD_FAILURE() << "Unknown ExecutionMode";
- return nullptr;
-}
-
-class ThreadPostingTasks : public SimpleThread {
- public:
- // Creates a thread that posts Tasks to |scheduler| with |traits| and
- // |execution_mode|.
- ThreadPostingTasks(TaskSchedulerImpl* scheduler,
- const TaskTraits& traits,
- test::ExecutionMode execution_mode)
- : SimpleThread("ThreadPostingTasks"),
- traits_(traits),
- factory_(CreateTaskRunnerWithTraitsAndExecutionMode(scheduler,
- traits,
- execution_mode),
- execution_mode) {}
-
- void WaitForAllTasksToRun() { factory_.WaitForAllTasksToRun(); }
-
- private:
- void Run() override {
- EXPECT_FALSE(factory_.task_runner()->RunsTasksInCurrentSequence());
-
- const size_t kNumTasksPerThread = 150;
- for (size_t i = 0; i < kNumTasksPerThread; ++i) {
- factory_.PostTask(test::TestTaskFactory::PostNestedTask::NO,
- Bind(&VerifyTaskEnvironment, traits_));
- }
- }
-
- const TaskTraits traits_;
- test::TestTaskFactory factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks);
-};
-
-// Returns a vector with a TraitsExecutionModePair for each valid
-// combination of {ExecutionMode, TaskPriority, MayBlock()}.
-std::vector<TraitsExecutionModePair> GetTraitsExecutionModePairs() {
- std::vector<TraitsExecutionModePair> params;
-
- const test::ExecutionMode execution_modes[] = {
- test::ExecutionMode::PARALLEL, test::ExecutionMode::SEQUENCED,
- test::ExecutionMode::SINGLE_THREADED};
-
- for (test::ExecutionMode execution_mode : execution_modes) {
- for (size_t priority_index = static_cast<size_t>(TaskPriority::LOWEST);
- priority_index <= static_cast<size_t>(TaskPriority::HIGHEST);
- ++priority_index) {
- const TaskPriority priority = static_cast<TaskPriority>(priority_index);
- params.push_back(TraitsExecutionModePair({priority}, execution_mode));
- params.push_back(TraitsExecutionModePair({MayBlock()}, execution_mode));
- }
- }
-
- return params;
-}
-
-class TaskSchedulerImplTest
- : public testing::TestWithParam<TraitsExecutionModePair> {
- protected:
- TaskSchedulerImplTest() : scheduler_("Test"), field_trial_list_(nullptr) {}
-
- void EnableAllTasksUserBlocking() {
- constexpr char kFieldTrialName[] = "BrowserScheduler";
- constexpr char kFieldTrialTestGroup[] = "DummyGroup";
- std::map<std::string, std::string> variation_params;
- variation_params["AllTasksUserBlocking"] = "true";
- base::AssociateFieldTrialParams(kFieldTrialName, kFieldTrialTestGroup,
- variation_params);
- base::FieldTrialList::CreateFieldTrial(kFieldTrialName,
- kFieldTrialTestGroup);
- }
-
- void set_scheduler_worker_observer(
- SchedulerWorkerObserver* scheduler_worker_observer) {
- scheduler_worker_observer_ = scheduler_worker_observer;
- }
-
- void StartTaskScheduler() {
- constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30);
- constexpr int kMaxNumBackgroundThreads = 1;
- constexpr int kMaxNumBackgroundBlockingThreads = 3;
- constexpr int kMaxNumForegroundThreads = 4;
- constexpr int kMaxNumForegroundBlockingThreads = 12;
-
- scheduler_.Start(
- {{kMaxNumBackgroundThreads, kSuggestedReclaimTime},
- {kMaxNumBackgroundBlockingThreads, kSuggestedReclaimTime},
- {kMaxNumForegroundThreads, kSuggestedReclaimTime},
- {kMaxNumForegroundBlockingThreads, kSuggestedReclaimTime}},
- scheduler_worker_observer_);
- }
-
- void TearDown() override {
- if (did_tear_down_)
- return;
-
- scheduler_.FlushForTesting();
- scheduler_.JoinForTesting();
- did_tear_down_ = true;
- }
-
- TaskSchedulerImpl scheduler_;
-
- private:
- base::FieldTrialList field_trial_list_;
- SchedulerWorkerObserver* scheduler_worker_observer_ = nullptr;
- bool did_tear_down_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerImplTest);
-};
-
-} // namespace
-
-// Verifies that a Task posted via PostDelayedTaskWithTraits with parameterized
-// TaskTraits and no delay runs on a thread with the expected priority and I/O
-// restrictions. The ExecutionMode parameter is ignored by this test.
-TEST_P(TaskSchedulerImplTest, PostDelayedTaskWithTraitsNoDelay) {
- StartTaskScheduler();
- WaitableEvent task_ran;
- scheduler_.PostDelayedTaskWithTraits(
- FROM_HERE, GetParam().traits,
- BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetParam().traits,
- Unretained(&task_ran)),
- TimeDelta());
- task_ran.Wait();
-}
-
-// Verifies that a Task posted via PostDelayedTaskWithTraits with parameterized
-// TaskTraits and a non-zero delay runs on a thread with the expected priority
-// and I/O restrictions after the delay expires. The ExecutionMode parameter is
-// ignored by this test.
-TEST_P(TaskSchedulerImplTest, PostDelayedTaskWithTraitsWithDelay) {
- StartTaskScheduler();
- WaitableEvent task_ran;
- scheduler_.PostDelayedTaskWithTraits(
- FROM_HERE, GetParam().traits,
- BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetParam().traits,
- TimeTicks::Now() + TestTimeouts::tiny_timeout(),
- Unretained(&task_ran)),
- TestTimeouts::tiny_timeout());
- task_ran.Wait();
-}
-
-// Verifies that Tasks posted via a TaskRunner with parameterized TaskTraits and
-// ExecutionMode run on a thread with the expected priority and I/O restrictions
-// and respect the characteristics of their ExecutionMode.
-TEST_P(TaskSchedulerImplTest, PostTasksViaTaskRunner) {
- StartTaskScheduler();
- test::TestTaskFactory factory(
- CreateTaskRunnerWithTraitsAndExecutionMode(&scheduler_, GetParam().traits,
- GetParam().execution_mode),
- GetParam().execution_mode);
- EXPECT_FALSE(factory.task_runner()->RunsTasksInCurrentSequence());
-
- const size_t kNumTasksPerTest = 150;
- for (size_t i = 0; i < kNumTasksPerTest; ++i) {
- factory.PostTask(test::TestTaskFactory::PostNestedTask::NO,
- Bind(&VerifyTaskEnvironment, GetParam().traits));
- }
-
- factory.WaitForAllTasksToRun();
-}
-
-// Verifies that a task posted via PostDelayedTaskWithTraits without a delay
-// doesn't run before Start() is called.
-TEST_P(TaskSchedulerImplTest, PostDelayedTaskWithTraitsNoDelayBeforeStart) {
- WaitableEvent task_running;
- scheduler_.PostDelayedTaskWithTraits(
- FROM_HERE, GetParam().traits,
- BindOnce(&VerifyTaskEnvironmentAndSignalEvent, GetParam().traits,
- Unretained(&task_running)),
- TimeDelta());
-
- // Wait a little bit to make sure that the task doesn't run before Start().
- // Note: This test won't catch a case where the task runs just after the check
- // and before Start(). However, we expect the test to be flaky if the tested
- // code allows that to happen.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(task_running.IsSignaled());
-
- StartTaskScheduler();
- task_running.Wait();
-}
-
-// Verifies that a task posted via PostDelayedTaskWithTraits with a delay
-// doesn't run before Start() is called.
-TEST_P(TaskSchedulerImplTest, PostDelayedTaskWithTraitsWithDelayBeforeStart) {
- WaitableEvent task_running;
- scheduler_.PostDelayedTaskWithTraits(
- FROM_HERE, GetParam().traits,
- BindOnce(&VerifyTimeAndTaskEnvironmentAndSignalEvent, GetParam().traits,
- TimeTicks::Now() + TestTimeouts::tiny_timeout(),
- Unretained(&task_running)),
- TestTimeouts::tiny_timeout());
-
- // Wait a little bit to make sure that the task doesn't run before Start().
- // Note: This test won't catch a case where the task runs just after the check
- // and before Start(). However, we expect the test to be flaky if the tested
- // code allows that to happen.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(task_running.IsSignaled());
-
- StartTaskScheduler();
- task_running.Wait();
-}
-
-// Verifies that a task posted via a TaskRunner doesn't run before Start() is
-// called.
-TEST_P(TaskSchedulerImplTest, PostTaskViaTaskRunnerBeforeStart) {
- WaitableEvent task_running;
- CreateTaskRunnerWithTraitsAndExecutionMode(&scheduler_, GetParam().traits,
- GetParam().execution_mode)
- ->PostTask(FROM_HERE,
- BindOnce(&VerifyTaskEnvironmentAndSignalEvent,
- GetParam().traits, Unretained(&task_running)));
-
- // Wait a little bit to make sure that the task doesn't run before Start().
- // Note: This test won't catch a case where the task runs just after the check
- // and before Start(). However, we expect the test to be flaky if the tested
- // code allows that to happen.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(task_running.IsSignaled());
-
- StartTaskScheduler();
-
- // This should not hang if the task runs after Start().
- task_running.Wait();
-}
-
-// Verify that all tasks posted to a TaskRunner after Start() run in a
-// USER_BLOCKING environment when the AllTasksUserBlocking variation param of
-// the BrowserScheduler experiment is true.
-TEST_P(TaskSchedulerImplTest, AllTasksAreUserBlockingTaskRunner) {
- EnableAllTasksUserBlocking();
- StartTaskScheduler();
-
- WaitableEvent task_running;
- CreateTaskRunnerWithTraitsAndExecutionMode(&scheduler_, GetParam().traits,
- GetParam().execution_mode)
- ->PostTask(FROM_HERE,
- BindOnce(&VerifyTaskEnvironmentAndSignalEvent,
- TaskTraits::Override(GetParam().traits,
- {TaskPriority::USER_BLOCKING}),
- Unretained(&task_running)));
- task_running.Wait();
-}
-
-// Verify that all tasks posted via PostDelayedTaskWithTraits() after Start()
-// run in a USER_BLOCKING environment when the AllTasksUserBlocking variation
-// param of the BrowserScheduler experiment is true.
-TEST_P(TaskSchedulerImplTest, AllTasksAreUserBlocking) {
- EnableAllTasksUserBlocking();
- StartTaskScheduler();
-
- WaitableEvent task_running;
- // Ignore |params.execution_mode| in this test.
- scheduler_.PostDelayedTaskWithTraits(
- FROM_HERE, GetParam().traits,
- BindOnce(&VerifyTaskEnvironmentAndSignalEvent,
- TaskTraits::Override(GetParam().traits,
- {TaskPriority::USER_BLOCKING}),
- Unretained(&task_running)),
- TimeDelta());
- task_running.Wait();
-}
-
-// Verifies that FlushAsyncForTesting() calls back correctly for all trait and
-// execution mode pairs.
-TEST_P(TaskSchedulerImplTest, FlushAsyncForTestingSimple) {
- StartTaskScheduler();
-
- WaitableEvent unblock_task;
- CreateTaskRunnerWithTraitsAndExecutionMode(
- &scheduler_,
- TaskTraits::Override(GetParam().traits, {WithBaseSyncPrimitives()}),
- GetParam().execution_mode, SingleThreadTaskRunnerThreadMode::DEDICATED)
- ->PostTask(FROM_HERE,
- BindOnce(&WaitableEvent::Wait, Unretained(&unblock_task)));
-
- WaitableEvent flush_event;
- scheduler_.FlushAsyncForTesting(
- BindOnce(&WaitableEvent::Signal, Unretained(&flush_event)));
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(flush_event.IsSignaled());
-
- unblock_task.Signal();
-
- flush_event.Wait();
-}
-
-INSTANTIATE_TEST_CASE_P(OneTraitsExecutionModePair,
- TaskSchedulerImplTest,
- ::testing::ValuesIn(GetTraitsExecutionModePairs()));
-
-// Spawns threads that simultaneously post Tasks to TaskRunners with various
-// TaskTraits and ExecutionModes. Verifies that each Task runs on a thread with
-// the expected priority and I/O restrictions and respects the characteristics
-// of its ExecutionMode.
-TEST_F(TaskSchedulerImplTest, MultipleTraitsExecutionModePairs) {
- StartTaskScheduler();
- std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
- for (const auto& traits_execution_mode_pair : GetTraitsExecutionModePairs()) {
- threads_posting_tasks.push_back(WrapUnique(
- new ThreadPostingTasks(&scheduler_, traits_execution_mode_pair.traits,
- traits_execution_mode_pair.execution_mode)));
- threads_posting_tasks.back()->Start();
- }
-
- for (const auto& thread : threads_posting_tasks) {
- thread->WaitForAllTasksToRun();
- thread->Join();
- }
-}
-
-TEST_F(TaskSchedulerImplTest,
- GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated) {
- StartTaskScheduler();
-
- // GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated() does not support
- // TaskPriority::BACKGROUND.
- EXPECT_DCHECK_DEATH({
- scheduler_.GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
- {TaskPriority::BACKGROUND});
- });
- EXPECT_DCHECK_DEATH({
- scheduler_.GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
- {MayBlock(), TaskPriority::BACKGROUND});
- });
-
- EXPECT_EQ(4, scheduler_.GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
- {TaskPriority::USER_VISIBLE}));
- EXPECT_EQ(12, scheduler_.GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
- {MayBlock(), TaskPriority::USER_VISIBLE}));
- EXPECT_EQ(4, scheduler_.GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
- {TaskPriority::USER_BLOCKING}));
- EXPECT_EQ(12, scheduler_.GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
- {MayBlock(), TaskPriority::USER_BLOCKING}));
-}
-
-// Verify that the RunsTasksInCurrentSequence() method of a SequencedTaskRunner
-// returns false when called from a task that isn't part of the sequence.
-TEST_F(TaskSchedulerImplTest, SequencedRunsTasksInCurrentSequence) {
- StartTaskScheduler();
- auto single_thread_task_runner =
- scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- TaskTraits(), SingleThreadTaskRunnerThreadMode::SHARED);
- auto sequenced_task_runner =
- scheduler_.CreateSequencedTaskRunnerWithTraits(TaskTraits());
-
- WaitableEvent task_ran;
- single_thread_task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](scoped_refptr<TaskRunner> sequenced_task_runner,
- WaitableEvent* task_ran) {
- EXPECT_FALSE(sequenced_task_runner->RunsTasksInCurrentSequence());
- task_ran->Signal();
- },
- sequenced_task_runner, Unretained(&task_ran)));
- task_ran.Wait();
-}
-
-// Verify that the RunsTasksInCurrentSequence() method of a
-// SingleThreadTaskRunner returns false when called from a task that isn't part
-// of the sequence.
-TEST_F(TaskSchedulerImplTest, SingleThreadRunsTasksInCurrentSequence) {
- StartTaskScheduler();
- auto sequenced_task_runner =
- scheduler_.CreateSequencedTaskRunnerWithTraits(TaskTraits());
- auto single_thread_task_runner =
- scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- TaskTraits(), SingleThreadTaskRunnerThreadMode::SHARED);
-
- WaitableEvent task_ran;
- sequenced_task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](scoped_refptr<TaskRunner> single_thread_task_runner,
- WaitableEvent* task_ran) {
- EXPECT_FALSE(
- single_thread_task_runner->RunsTasksInCurrentSequence());
- task_ran->Signal();
- },
- single_thread_task_runner, Unretained(&task_ran)));
- task_ran.Wait();
-}
-
-#if defined(OS_WIN)
-TEST_F(TaskSchedulerImplTest, COMSTATaskRunnersRunWithCOMSTA) {
- StartTaskScheduler();
- auto com_sta_task_runner = scheduler_.CreateCOMSTATaskRunnerWithTraits(
- TaskTraits(), SingleThreadTaskRunnerThreadMode::SHARED);
-
- WaitableEvent task_ran;
- com_sta_task_runner->PostTask(
- FROM_HERE, Bind(
- [](WaitableEvent* task_ran) {
- win::AssertComApartmentType(win::ComApartmentType::STA);
- task_ran->Signal();
- },
- Unretained(&task_ran)));
- task_ran.Wait();
-}
-#endif // defined(OS_WIN)
-
-TEST_F(TaskSchedulerImplTest, DelayedTasksNotRunAfterShutdown) {
- StartTaskScheduler();
- // As with delayed tasks in general, this is racy. If the task does happen to
- // run after Shutdown within the timeout, it will fail this test.
- //
- // The timeout should be set sufficiently long enough to ensure that the
- // delayed task did not run. 2x is generally good enough.
- //
- // A non-racy way to do this would be to post two sequenced tasks:
- // 1) Regular Post Task: A WaitableEvent.Wait
- // 2) Delayed Task: ADD_FAILURE()
- // and signalling the WaitableEvent after Shutdown() on a different thread
- // since Shutdown() will block. However, the cost of managing this extra
- // thread was deemed to be too great for the unlikely race.
- scheduler_.PostDelayedTaskWithTraits(FROM_HERE, TaskTraits(),
- BindOnce([]() { ADD_FAILURE(); }),
- TestTimeouts::tiny_timeout());
- scheduler_.Shutdown();
- PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 2);
-}
-
-#if defined(OS_POSIX)
-
-TEST_F(TaskSchedulerImplTest, FileDescriptorWatcherNoOpsAfterShutdown) {
- StartTaskScheduler();
-
- int pipes[2];
- ASSERT_EQ(0, pipe(pipes));
-
- scoped_refptr<TaskRunner> blocking_task_runner =
- scheduler_.CreateSequencedTaskRunnerWithTraits(
- {TaskShutdownBehavior::BLOCK_SHUTDOWN});
- blocking_task_runner->PostTask(
- FROM_HERE,
- BindOnce(
- [](int read_fd) {
- std::unique_ptr<FileDescriptorWatcher::Controller> controller =
- FileDescriptorWatcher::WatchReadable(
- read_fd, BindRepeating([]() { NOTREACHED(); }));
-
- // This test is for components that intentionally leak their
- // watchers at shutdown. We can't clean |controller| up because its
- // destructor will assert that it's being called from the correct
- // sequence. After the task scheduler is shutdown, it is not
- // possible to run tasks on this sequence.
- //
- // Note: Do not inline the controller.release() call into the
- // ANNOTATE_LEAKING_OBJECT_PTR as the annotation is removed
- // by the preprocessor in non-LEAK_SANITIZER builds,
- // effectively breaking this test.
- ANNOTATE_LEAKING_OBJECT_PTR(controller.get());
- controller.release();
- },
- pipes[0]));
-
- scheduler_.Shutdown();
-
- constexpr char kByte = '!';
- ASSERT_TRUE(WriteFileDescriptor(pipes[1], &kByte, sizeof(kByte)));
-
- // Give a chance for the file watcher to fire before closing the handles.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- EXPECT_EQ(0, IGNORE_EINTR(close(pipes[0])));
- EXPECT_EQ(0, IGNORE_EINTR(close(pipes[1])));
-}
-#endif // defined(OS_POSIX)
-
-// Verify that tasks posted on the same sequence access the same values on
-// SequenceLocalStorage, and tasks on different sequences see different values.
-TEST_F(TaskSchedulerImplTest, SequenceLocalStorage) {
- StartTaskScheduler();
-
- SequenceLocalStorageSlot<int> slot;
- auto sequenced_task_runner1 =
- scheduler_.CreateSequencedTaskRunnerWithTraits(TaskTraits());
- auto sequenced_task_runner2 =
- scheduler_.CreateSequencedTaskRunnerWithTraits(TaskTraits());
-
- sequenced_task_runner1->PostTask(
- FROM_HERE,
- BindOnce([](SequenceLocalStorageSlot<int>* slot) { slot->Set(11); },
- &slot));
-
- sequenced_task_runner1->PostTask(FROM_HERE,
- BindOnce(
- [](SequenceLocalStorageSlot<int>* slot) {
- EXPECT_EQ(slot->Get(), 11);
- },
- &slot));
-
- sequenced_task_runner2->PostTask(FROM_HERE,
- BindOnce(
- [](SequenceLocalStorageSlot<int>* slot) {
- EXPECT_NE(slot->Get(), 11);
- },
- &slot));
-
- scheduler_.FlushForTesting();
-}
-
-TEST_F(TaskSchedulerImplTest, FlushAsyncNoTasks) {
- StartTaskScheduler();
- bool called_back = false;
- scheduler_.FlushAsyncForTesting(
- BindOnce([](bool* called_back) { *called_back = true; },
- Unretained(&called_back)));
- EXPECT_TRUE(called_back);
-}
-
-namespace {
-
-// Verifies that |query| is found on the current stack. Ignores failures if this
-// configuration doesn't have symbols.
-void VerifyHasStringOnStack(const std::string& query) {
- const std::string stack = debug::StackTrace().ToString();
- SCOPED_TRACE(stack);
- const bool found_on_stack = stack.find(query) != std::string::npos;
- const bool stack_has_symbols =
- stack.find("SchedulerWorker") != std::string::npos;
- EXPECT_TRUE(found_on_stack || !stack_has_symbols) << query;
-}
-
-} // namespace
-
-#if defined(OS_POSIX)
-// Many POSIX bots flakily crash on |debug::StackTrace().ToString()|,
-// https://crbug.com/840429.
-#define MAYBE_IdentifiableStacks DISABLED_IdentifiableStacks
-#elif defined(OS_WIN) && \
- (defined(ADDRESS_SANITIZER) || BUILDFLAG(CFI_CAST_CHECK))
-// Hangs on WinASan and WinCFI (grabbing StackTrace() too slow?),
-// https://crbug.com/845010#c7.
-#define MAYBE_IdentifiableStacks DISABLED_IdentifiableStacks
-#else
-#define MAYBE_IdentifiableStacks IdentifiableStacks
-#endif
-
-// Integration test that verifies that workers have a frame on their stacks
-// which easily identifies the type of worker (useful to diagnose issues from
-// logs without memory dumps).
-TEST_F(TaskSchedulerImplTest, MAYBE_IdentifiableStacks) {
- StartTaskScheduler();
-
- scheduler_.CreateSequencedTaskRunnerWithTraits({})->PostTask(
- FROM_HERE, BindOnce(&VerifyHasStringOnStack, "RunPooledWorker"));
- scheduler_.CreateSequencedTaskRunnerWithTraits({TaskPriority::BACKGROUND})
- ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack,
- "RunBackgroundPooledWorker"));
-
- scheduler_
- .CreateSingleThreadTaskRunnerWithTraits(
- {}, SingleThreadTaskRunnerThreadMode::SHARED)
- ->PostTask(FROM_HERE,
- BindOnce(&VerifyHasStringOnStack, "RunSharedWorker"));
- scheduler_
- .CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::SHARED)
- ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack,
- "RunBackgroundSharedWorker"));
-
- scheduler_
- .CreateSingleThreadTaskRunnerWithTraits(
- {}, SingleThreadTaskRunnerThreadMode::DEDICATED)
- ->PostTask(FROM_HERE,
- BindOnce(&VerifyHasStringOnStack, "RunDedicatedWorker"));
- scheduler_
- .CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND},
- SingleThreadTaskRunnerThreadMode::DEDICATED)
- ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack,
- "RunBackgroundDedicatedWorker"));
-
-#if defined(OS_WIN)
- scheduler_
- .CreateCOMSTATaskRunnerWithTraits(
- {}, SingleThreadTaskRunnerThreadMode::SHARED)
- ->PostTask(FROM_HERE,
- BindOnce(&VerifyHasStringOnStack, "RunSharedCOMWorker"));
- scheduler_
- .CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::SHARED)
- ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack,
- "RunBackgroundSharedCOMWorker"));
-
- scheduler_
- .CreateCOMSTATaskRunnerWithTraits(
- {}, SingleThreadTaskRunnerThreadMode::DEDICATED)
- ->PostTask(FROM_HERE,
- BindOnce(&VerifyHasStringOnStack, "RunDedicatedCOMWorker"));
- scheduler_
- .CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::BACKGROUND},
- SingleThreadTaskRunnerThreadMode::DEDICATED)
- ->PostTask(FROM_HERE, BindOnce(&VerifyHasStringOnStack,
- "RunBackgroundDedicatedCOMWorker"));
-#endif // defined(OS_WIN)
-
- scheduler_.FlushForTesting();
-}
-
-TEST_F(TaskSchedulerImplTest, SchedulerWorkerObserver) {
- testing::StrictMock<test::MockSchedulerWorkerObserver> observer;
- set_scheduler_worker_observer(&observer);
-
- // A worker should be created for each pool. After that, 8 threads should be
- // created for single-threaded work (16 on Windows).
- const int kExpectedNumPoolWorkers =
- CanUseBackgroundPriorityForSchedulerWorker() ? 4 : 2;
-#if defined(OS_WIN)
- const int kExpectedNumSingleThreadedWorkers = 16;
-#else
- const int kExpectedNumSingleThreadedWorkers = 8;
-#endif
- const int kExpectedNumWorkers =
- kExpectedNumPoolWorkers + kExpectedNumSingleThreadedWorkers;
-
- EXPECT_CALL(observer, OnSchedulerWorkerMainEntry())
- .Times(kExpectedNumWorkers);
-
- StartTaskScheduler();
-
- std::vector<scoped_refptr<SingleThreadTaskRunner>> task_runners;
-
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::SHARED));
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND, MayBlock()},
- SingleThreadTaskRunnerThreadMode::SHARED));
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING}, SingleThreadTaskRunnerThreadMode::SHARED));
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING, MayBlock()},
- SingleThreadTaskRunnerThreadMode::SHARED));
-
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::DEDICATED));
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::BACKGROUND, MayBlock()},
- SingleThreadTaskRunnerThreadMode::DEDICATED));
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING},
- SingleThreadTaskRunnerThreadMode::DEDICATED));
- task_runners.push_back(scheduler_.CreateSingleThreadTaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING, MayBlock()},
- SingleThreadTaskRunnerThreadMode::DEDICATED));
-
-#if defined(OS_WIN)
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::SHARED));
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::BACKGROUND, MayBlock()},
- SingleThreadTaskRunnerThreadMode::SHARED));
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING}, SingleThreadTaskRunnerThreadMode::SHARED));
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING, MayBlock()},
- SingleThreadTaskRunnerThreadMode::SHARED));
-
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::BACKGROUND}, SingleThreadTaskRunnerThreadMode::DEDICATED));
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::BACKGROUND, MayBlock()},
- SingleThreadTaskRunnerThreadMode::DEDICATED));
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING},
- SingleThreadTaskRunnerThreadMode::DEDICATED));
- task_runners.push_back(scheduler_.CreateCOMSTATaskRunnerWithTraits(
- {TaskPriority::USER_BLOCKING, MayBlock()},
- SingleThreadTaskRunnerThreadMode::DEDICATED));
-#endif
-
- for (auto& task_runner : task_runners)
- task_runner->PostTask(FROM_HERE, DoNothing());
-
- EXPECT_CALL(observer, OnSchedulerWorkerMainExit()).Times(kExpectedNumWorkers);
-
- // Allow single-threaded workers to be released.
- task_runners.clear();
-
- TearDown();
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/task_tracker_posix_unittest.cc b/base/task_scheduler/task_tracker_posix_unittest.cc
deleted file mode 100644
index 3ca753386b..0000000000
--- a/base/task_scheduler/task_tracker_posix_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2016 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/task_scheduler/task_tracker_posix.h"
-
-#include <unistd.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/run_loop.h"
-#include "base/sequence_token.h"
-#include "base/task_scheduler/task.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/task_scheduler/test_utils.h"
-#include "base/test/null_task_runner.h"
-#include "base/threading/thread.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-class TaskSchedulerTaskTrackerPosixTest : public testing::Test {
- public:
- TaskSchedulerTaskTrackerPosixTest() : service_thread_("ServiceThread") {
- Thread::Options service_thread_options;
- service_thread_options.message_loop_type = MessageLoop::TYPE_IO;
- service_thread_.StartWithOptions(service_thread_options);
- tracker_.set_watch_file_descriptor_message_loop(
- static_cast<MessageLoopForIO*>(service_thread_.message_loop()));
- }
-
- protected:
- Thread service_thread_;
- TaskTrackerPosix tracker_ = {"Test"};
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerPosixTest);
-};
-
-} // namespace
-
-// Verify that TaskTrackerPosix runs a Task it receives.
-TEST_F(TaskSchedulerTaskTrackerPosixTest, RunTask) {
- bool did_run = false;
- Task task(FROM_HERE,
- Bind([](bool* did_run) { *did_run = true; }, Unretained(&did_run)),
- TaskTraits(), TimeDelta());
-
- EXPECT_TRUE(tracker_.WillPostTask(&task));
-
- auto sequence = test::CreateSequenceWithTask(std::move(task));
- EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
- // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after
- // popping a task from it.
- EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence, nullptr));
-
- EXPECT_TRUE(did_run);
-}
-
-// Verify that FileDescriptorWatcher::WatchReadable() can be called from a task
-// running in TaskTrackerPosix without a crash.
-TEST_F(TaskSchedulerTaskTrackerPosixTest, FileDescriptorWatcher) {
- int fds[2];
- ASSERT_EQ(0, pipe(fds));
- Task task(FROM_HERE,
- Bind(IgnoreResult(&FileDescriptorWatcher::WatchReadable), fds[0],
- DoNothing()),
- TaskTraits(), TimeDelta());
- // FileDescriptorWatcher::WatchReadable needs a SequencedTaskRunnerHandle.
- task.sequenced_task_runner_ref = MakeRefCounted<NullTaskRunner>();
-
- EXPECT_TRUE(tracker_.WillPostTask(&task));
-
- auto sequence = test::CreateSequenceWithTask(std::move(task));
- EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
- // Expect RunAndPopNextTask to return nullptr since |sequence| is empty after
- // popping a task from it.
- EXPECT_FALSE(tracker_.RunAndPopNextTask(sequence, nullptr));
-
- // Join the service thread to make sure that the read watch is registered and
- // unregistered before file descriptors are closed.
- service_thread_.Stop();
-
- EXPECT_EQ(0, IGNORE_EINTR(close(fds[0])));
- EXPECT_EQ(0, IGNORE_EINTR(close(fds[1])));
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/task_tracker_unittest.cc b/base/task_scheduler/task_tracker_unittest.cc
deleted file mode 100644
index 159c9a9674..0000000000
--- a/base/task_scheduler/task_tracker_unittest.cc
+++ /dev/null
@@ -1,1364 +0,0 @@
-// Copyright 2016 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/task_scheduler/task_tracker.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/sequence_token.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/scheduler_lock.h"
-#include "base/task_scheduler/task.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/task_scheduler/test_utils.h"
-#include "base/test/gtest_util.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/simple_thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-constexpr size_t kLoadTestNumIterations = 75;
-
-class MockCanScheduleSequenceObserver : public CanScheduleSequenceObserver {
- public:
- void OnCanScheduleSequence(scoped_refptr<Sequence> sequence) override {
- MockOnCanScheduleSequence(sequence.get());
- }
-
- MOCK_METHOD1(MockOnCanScheduleSequence, void(Sequence*));
-};
-
-// Invokes a closure asynchronously.
-class CallbackThread : public SimpleThread {
- public:
- explicit CallbackThread(const Closure& closure)
- : SimpleThread("CallbackThread"), closure_(closure) {}
-
- // Returns true once the callback returns.
- bool has_returned() { return has_returned_.IsSet(); }
-
- private:
- void Run() override {
- closure_.Run();
- has_returned_.Set();
- }
-
- const Closure closure_;
- AtomicFlag has_returned_;
-
- DISALLOW_COPY_AND_ASSIGN(CallbackThread);
-};
-
-class ThreadPostingAndRunningTask : public SimpleThread {
- public:
- enum class Action {
- WILL_POST,
- RUN,
- WILL_POST_AND_RUN,
- };
-
- ThreadPostingAndRunningTask(TaskTracker* tracker,
- Task* task,
- Action action,
- bool expect_post_succeeds)
- : SimpleThread("ThreadPostingAndRunningTask"),
- tracker_(tracker),
- owned_task_(FROM_HERE, OnceClosure(), TaskTraits(), TimeDelta()),
- task_(task),
- action_(action),
- expect_post_succeeds_(expect_post_succeeds) {
- EXPECT_TRUE(task_);
-
- // Ownership of the Task is required to run it.
- EXPECT_NE(Action::RUN, action_);
- EXPECT_NE(Action::WILL_POST_AND_RUN, action_);
- }
-
- ThreadPostingAndRunningTask(TaskTracker* tracker,
- Task task,
- Action action,
- bool expect_post_succeeds)
- : SimpleThread("ThreadPostingAndRunningTask"),
- tracker_(tracker),
- owned_task_(std::move(task)),
- task_(&owned_task_),
- action_(action),
- expect_post_succeeds_(expect_post_succeeds) {
- EXPECT_TRUE(owned_task_.task);
- }
-
- private:
- void Run() override {
- bool post_succeeded = true;
- if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) {
- post_succeeded = tracker_->WillPostTask(task_);
- EXPECT_EQ(expect_post_succeeds_, post_succeeded);
- }
- if (post_succeeded &&
- (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) {
- EXPECT_TRUE(owned_task_.task);
-
- testing::StrictMock<MockCanScheduleSequenceObserver>
- never_notified_observer;
- auto sequence = tracker_->WillScheduleSequence(
- test::CreateSequenceWithTask(std::move(owned_task_)),
- &never_notified_observer);
- ASSERT_TRUE(sequence);
- // Expect RunAndPopNextTask to return nullptr since |sequence| is empty
- // after popping a task from it.
- EXPECT_FALSE(tracker_->RunAndPopNextTask(std::move(sequence),
- &never_notified_observer));
- }
- }
-
- TaskTracker* const tracker_;
- Task owned_task_;
- Task* task_;
- const Action action_;
- const bool expect_post_succeeds_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask);
-};
-
-class ScopedSetSingletonAllowed {
- public:
- ScopedSetSingletonAllowed(bool singleton_allowed)
- : previous_value_(
- ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {}
- ~ScopedSetSingletonAllowed() {
- ThreadRestrictions::SetSingletonAllowed(previous_value_);
- }
-
- private:
- const bool previous_value_;
-};
-
-class TaskSchedulerTaskTrackerTest
- : public testing::TestWithParam<TaskShutdownBehavior> {
- protected:
- TaskSchedulerTaskTrackerTest() = default;
-
- // Creates a task with |shutdown_behavior|.
- Task CreateTask(TaskShutdownBehavior shutdown_behavior) {
- return Task(
- FROM_HERE,
- Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)),
- TaskTraits(shutdown_behavior), TimeDelta());
- }
-
- void DispatchAndRunTaskWithTracker(Task task) {
- auto sequence = tracker_.WillScheduleSequence(
- test::CreateSequenceWithTask(std::move(task)),
- &never_notified_observer_);
- ASSERT_TRUE(sequence);
- tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_);
- }
-
- // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown()
- // method has been entered on the new thread, but it hasn't necessarily
- // returned.
- void CallShutdownAsync() {
- ASSERT_FALSE(thread_calling_shutdown_);
- thread_calling_shutdown_.reset(new CallbackThread(
- Bind(&TaskTracker::Shutdown, Unretained(&tracker_))));
- thread_calling_shutdown_->Start();
- while (!tracker_.HasShutdownStarted())
- PlatformThread::YieldCurrentThread();
- }
-
- void WaitForAsyncIsShutdownComplete() {
- ASSERT_TRUE(thread_calling_shutdown_);
- thread_calling_shutdown_->Join();
- EXPECT_TRUE(thread_calling_shutdown_->has_returned());
- EXPECT_TRUE(tracker_.IsShutdownComplete());
- }
-
- void VerifyAsyncShutdownInProgress() {
- ASSERT_TRUE(thread_calling_shutdown_);
- EXPECT_FALSE(thread_calling_shutdown_->has_returned());
- EXPECT_TRUE(tracker_.HasShutdownStarted());
- EXPECT_FALSE(tracker_.IsShutdownComplete());
- }
-
- // Calls tracker_->FlushForTesting() on a new thread.
- void CallFlushFromAnotherThread() {
- ASSERT_FALSE(thread_calling_flush_);
- thread_calling_flush_.reset(new CallbackThread(
- Bind(&TaskTracker::FlushForTesting, Unretained(&tracker_))));
- thread_calling_flush_->Start();
- }
-
- void WaitForAsyncFlushReturned() {
- ASSERT_TRUE(thread_calling_flush_);
- thread_calling_flush_->Join();
- EXPECT_TRUE(thread_calling_flush_->has_returned());
- }
-
- void VerifyAsyncFlushInProgress() {
- ASSERT_TRUE(thread_calling_flush_);
- EXPECT_FALSE(thread_calling_flush_->has_returned());
- }
-
- size_t NumTasksExecuted() {
- AutoSchedulerLock auto_lock(lock_);
- return num_tasks_executed_;
- }
-
- TaskTracker tracker_ = {"Test"};
- testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer_;
-
- private:
- void RunTaskCallback() {
- AutoSchedulerLock auto_lock(lock_);
- ++num_tasks_executed_;
- }
-
- std::unique_ptr<CallbackThread> thread_calling_shutdown_;
- std::unique_ptr<CallbackThread> thread_calling_flush_;
-
- // Synchronizes accesses to |num_tasks_executed_|.
- SchedulerLock lock_;
-
- size_t num_tasks_executed_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest);
-};
-
-#define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \
- do { \
- SCOPED_TRACE(""); \
- WaitForAsyncIsShutdownComplete(); \
- } while (false)
-
-#define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \
- do { \
- SCOPED_TRACE(""); \
- VerifyAsyncShutdownInProgress(); \
- } while (false)
-
-#define WAIT_FOR_ASYNC_FLUSH_RETURNED() \
- do { \
- SCOPED_TRACE(""); \
- WaitForAsyncFlushReturned(); \
- } while (false)
-
-#define VERIFY_ASYNC_FLUSH_IN_PROGRESS() \
- do { \
- SCOPED_TRACE(""); \
- VerifyAsyncFlushInProgress(); \
- } while (false)
-
-} // namespace
-
-TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) {
- Task task(CreateTask(GetParam()));
-
- // Inform |task_tracker_| that |task| will be posted.
- EXPECT_TRUE(tracker_.WillPostTask(&task));
-
- // Run the task.
- EXPECT_EQ(0U, NumTasksExecuted());
-
- DispatchAndRunTaskWithTracker(std::move(task));
- EXPECT_EQ(1U, NumTasksExecuted());
-
- // Shutdown() shouldn't block.
- tracker_.Shutdown();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) {
- // Create a task that signals |task_running| and blocks until |task_barrier|
- // is signaled.
- WaitableEvent task_running(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_barrier(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- Task blocked_task(
- FROM_HERE,
- Bind(
- [](WaitableEvent* task_running, WaitableEvent* task_barrier) {
- task_running->Signal();
- task_barrier->Wait();
- },
- Unretained(&task_running), Unretained(&task_barrier)),
- TaskTraits(WithBaseSyncPrimitives(), GetParam()), TimeDelta());
-
- // Inform |task_tracker_| that |blocked_task| will be posted.
- EXPECT_TRUE(tracker_.WillPostTask(&blocked_task));
-
- // Create a thread to run the task. Wait until the task starts running.
- ThreadPostingAndRunningTask thread_running_task(
- &tracker_, std::move(blocked_task),
- ThreadPostingAndRunningTask::Action::RUN, false);
- thread_running_task.Start();
- task_running.Wait();
-
- // Initiate shutdown after the task has started to run.
- CallShutdownAsync();
-
- if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) {
- // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress.
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
- } else {
- // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress.
- VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
- }
-
- // Unblock the task.
- task_barrier.Signal();
- thread_running_task.Join();
-
- // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task.
- if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) {
- // Inform |task_tracker_| that a task will be posted.
- Task task(CreateTask(GetParam()));
- EXPECT_TRUE(tracker_.WillPostTask(&task));
-
- // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
- // block shutdown.
- Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
- EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task));
-
- // Call Shutdown() asynchronously.
- CallShutdownAsync();
- VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
-
- // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it
- // should be discarded.
- EXPECT_EQ(0U, NumTasksExecuted());
- const bool should_run = GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN;
-
- DispatchAndRunTaskWithTracker(std::move(task));
- EXPECT_EQ(should_run ? 1U : 0U, NumTasksExecuted());
- VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
-
- // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task.
- DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
- EXPECT_EQ(should_run ? 2U : 1U, NumTasksExecuted());
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) {
- // Inform |task_tracker_| that a task will be posted.
- Task task(CreateTask(GetParam()));
- EXPECT_TRUE(tracker_.WillPostTask(&task));
-
- // Call Shutdown() asynchronously.
- CallShutdownAsync();
- EXPECT_EQ(0U, NumTasksExecuted());
-
- if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
- VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
-
- // Run the task to unblock shutdown.
- DispatchAndRunTaskWithTracker(std::move(task));
- EXPECT_EQ(1U, NumTasksExecuted());
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
-
- // It is not possible to test running a BLOCK_SHUTDOWN task posted before
- // shutdown after shutdown because Shutdown() won't return if there are
- // pending BLOCK_SHUTDOWN tasks.
- } else {
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
-
- // The task shouldn't be allowed to run after shutdown.
- DispatchAndRunTaskWithTracker(std::move(task));
- EXPECT_EQ(0U, NumTasksExecuted());
- }
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) {
- // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
- // block shutdown.
- Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
- EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task));
-
- // Call Shutdown() asynchronously.
- CallShutdownAsync();
- VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
-
- if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
- // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted.
- Task task(CreateTask(GetParam()));
- EXPECT_TRUE(tracker_.WillPostTask(&task));
-
- // Run the BLOCK_SHUTDOWN task.
- EXPECT_EQ(0U, NumTasksExecuted());
- DispatchAndRunTaskWithTracker(std::move(task));
- EXPECT_EQ(1U, NumTasksExecuted());
- } else {
- // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task.
- Task task(CreateTask(GetParam()));
- EXPECT_FALSE(tracker_.WillPostTask(&task));
-
- // Don't try to run the task, because it wasn't allowed to be posted.
- }
-
- // Unblock shutdown by running |block_shutdown_task|.
- VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
- DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
- EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U,
- NumTasksExecuted());
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) {
- tracker_.Shutdown();
-
- Task task(CreateTask(GetParam()));
-
- // |task_tracker_| shouldn't allow a task to be posted after shutdown.
- EXPECT_FALSE(tracker_.WillPostTask(&task));
-}
-
-// Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can
-// AssertSingletonAllowed() but CONTINUE_ON_SHUTDOWN tasks can't.
-TEST_P(TaskSchedulerTaskTrackerTest, SingletonAllowed) {
- const bool can_use_singletons =
- (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN);
-
- Task task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed),
- TaskTraits(GetParam()), TimeDelta());
- EXPECT_TRUE(tracker_.WillPostTask(&task));
-
- // Set the singleton allowed bit to the opposite of what it is expected to be
- // when |tracker| runs |task| to verify that |tracker| actually sets the
- // correct value.
- ScopedSetSingletonAllowed scoped_singleton_allowed(!can_use_singletons);
-
- // Running the task should fail iff the task isn't allowed to use singletons.
- if (can_use_singletons) {
- DispatchAndRunTaskWithTracker(std::move(task));
- } else {
- EXPECT_DCHECK_DEATH({ DispatchAndRunTaskWithTracker(std::move(task)); });
- }
-}
-
-// Verify that AssertIOAllowed() succeeds only for a MayBlock() task.
-TEST_P(TaskSchedulerTaskTrackerTest, IOAllowed) {
- // Unset the IO allowed bit. Expect TaskTracker to set it before running a
- // task with the MayBlock() trait.
- ThreadRestrictions::SetIOAllowed(false);
- Task task_with_may_block(FROM_HERE, Bind([]() {
- // Shouldn't fail.
- AssertBlockingAllowed();
- }),
- TaskTraits(MayBlock(), GetParam()), TimeDelta());
- EXPECT_TRUE(tracker_.WillPostTask(&task_with_may_block));
- DispatchAndRunTaskWithTracker(std::move(task_with_may_block));
-
- // Set the IO allowed bit. Expect TaskTracker to unset it before running a
- // task without the MayBlock() trait.
- ThreadRestrictions::SetIOAllowed(true);
- Task task_without_may_block(
- FROM_HERE,
- Bind([]() { EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); }); }),
- TaskTraits(GetParam()), TimeDelta());
- EXPECT_TRUE(tracker_.WillPostTask(&task_without_may_block));
- DispatchAndRunTaskWithTracker(std::move(task_without_may_block));
-}
-
-static void RunTaskRunnerHandleVerificationTask(TaskTracker* tracker,
- Task verify_task) {
- // Pretend |verify_task| is posted to respect TaskTracker's contract.
- EXPECT_TRUE(tracker->WillPostTask(&verify_task));
-
- // Confirm that the test conditions are right (no TaskRunnerHandles set
- // already).
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
-
- testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
- auto sequence = tracker->WillScheduleSequence(
- test::CreateSequenceWithTask(std::move(verify_task)),
- &never_notified_observer);
- ASSERT_TRUE(sequence);
- tracker->RunAndPopNextTask(std::move(sequence), &never_notified_observer);
-
- // TaskRunnerHandle state is reset outside of task's scope.
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
-}
-
-static void VerifyNoTaskRunnerHandle() {
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) {
- // Create a task that will verify that TaskRunnerHandles are not set in its
- // scope per no TaskRunner ref being set to it.
- Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle),
- TaskTraits(GetParam()), TimeDelta());
-
- RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
-}
-
-static void VerifySequencedTaskRunnerHandle(
- const SequencedTaskRunner* expected_task_runner) {
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_EQ(expected_task_runner, SequencedTaskRunnerHandle::Get());
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest,
- SequencedTaskRunnerHandleIsSetOnSequenced) {
- scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner);
-
- // Create a task that will verify that SequencedTaskRunnerHandle is properly
- // set to |test_task_runner| in its scope per |sequenced_task_runner_ref|
- // being set to it.
- Task verify_task(FROM_HERE,
- BindOnce(&VerifySequencedTaskRunnerHandle,
- Unretained(test_task_runner.get())),
- TaskTraits(GetParam()), TimeDelta());
- verify_task.sequenced_task_runner_ref = test_task_runner;
-
- RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
-}
-
-static void VerifyThreadTaskRunnerHandle(
- const SingleThreadTaskRunner* expected_task_runner) {
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- // SequencedTaskRunnerHandle inherits ThreadTaskRunnerHandle for thread.
- EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_EQ(expected_task_runner, ThreadTaskRunnerHandle::Get());
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest,
- ThreadTaskRunnerHandleIsSetOnSingleThreaded) {
- scoped_refptr<SingleThreadTaskRunner> test_task_runner(
- new TestSimpleTaskRunner);
-
- // Create a task that will verify that ThreadTaskRunnerHandle is properly set
- // to |test_task_runner| in its scope per |single_thread_task_runner_ref|
- // being set on it.
- Task verify_task(FROM_HERE,
- BindOnce(&VerifyThreadTaskRunnerHandle,
- Unretained(test_task_runner.get())),
- TaskTraits(GetParam()), TimeDelta());
- verify_task.single_thread_task_runner_ref = test_task_runner;
-
- RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task));
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingDelayedTask) {
- Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta::FromDays(1));
- tracker_.WillPostTask(&delayed_task);
- // FlushForTesting() should return even if the delayed task didn't run.
- tracker_.FlushForTesting();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) {
- Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta::FromDays(1));
- tracker_.WillPostTask(&delayed_task);
- // FlushAsyncForTesting() should callback even if the delayed task didn't run.
- bool called_back = false;
- tracker_.FlushAsyncForTesting(
- BindOnce([](bool* called_back) { *called_back = true; },
- Unretained(&called_back)));
- EXPECT_TRUE(called_back);
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingUndelayedTask) {
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushForTesting() shouldn't return before the undelayed task runs.
- CallFlushFromAnotherThread();
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- VERIFY_ASYNC_FLUSH_IN_PROGRESS();
-
- // FlushForTesting() should return after the undelayed task runs.
- DispatchAndRunTaskWithTracker(std::move(undelayed_task));
- WAIT_FOR_ASYNC_FLUSH_RETURNED();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) {
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
- WaitableEvent event;
- tracker_.FlushAsyncForTesting(
- BindOnce(&WaitableEvent::Signal, Unretained(&event)));
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(event.IsSignaled());
-
- // FlushAsyncForTesting() should callback after the undelayed task runs.
- DispatchAndRunTaskWithTracker(std::move(undelayed_task));
- event.Wait();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlush) {
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushForTesting() shouldn't return before the undelayed task runs.
- CallFlushFromAnotherThread();
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- VERIFY_ASYNC_FLUSH_IN_PROGRESS();
-
- // Simulate posting another undelayed task.
- Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&other_undelayed_task);
-
- // Run the first undelayed task.
- DispatchAndRunTaskWithTracker(std::move(undelayed_task));
-
- // FlushForTesting() shouldn't return before the second undelayed task runs.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- VERIFY_ASYNC_FLUSH_IN_PROGRESS();
-
- // FlushForTesting() should return after the second undelayed task runs.
- DispatchAndRunTaskWithTracker(std::move(other_undelayed_task));
- WAIT_FOR_ASYNC_FLUSH_RETURNED();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) {
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
- WaitableEvent event;
- tracker_.FlushAsyncForTesting(
- BindOnce(&WaitableEvent::Signal, Unretained(&event)));
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(event.IsSignaled());
-
- // Simulate posting another undelayed task.
- Task other_undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&other_undelayed_task);
-
- // Run the first undelayed task.
- DispatchAndRunTaskWithTracker(std::move(undelayed_task));
-
- // FlushAsyncForTesting() shouldn't callback before the second undelayed task
- // runs.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(event.IsSignaled());
-
- // FlushAsyncForTesting() should callback after the second undelayed task
- // runs.
- DispatchAndRunTaskWithTracker(std::move(other_undelayed_task));
- event.Wait();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlush) {
- // Simulate posting a delayed and an undelayed task.
- Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta::FromDays(1));
- tracker_.WillPostTask(&delayed_task);
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushForTesting() shouldn't return before the undelayed task runs.
- CallFlushFromAnotherThread();
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- VERIFY_ASYNC_FLUSH_IN_PROGRESS();
-
- // Run the delayed task.
- DispatchAndRunTaskWithTracker(std::move(delayed_task));
-
- // FlushForTesting() shouldn't return since there is still a pending undelayed
- // task.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- VERIFY_ASYNC_FLUSH_IN_PROGRESS();
-
- // Run the undelayed task.
- DispatchAndRunTaskWithTracker(std::move(undelayed_task));
-
- // FlushForTesting() should now return.
- WAIT_FOR_ASYNC_FLUSH_RETURNED();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) {
- // Simulate posting a delayed and an undelayed task.
- Task delayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta::FromDays(1));
- tracker_.WillPostTask(&delayed_task);
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
- WaitableEvent event;
- tracker_.FlushAsyncForTesting(
- BindOnce(&WaitableEvent::Signal, Unretained(&event)));
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(event.IsSignaled());
-
- // Run the delayed task.
- DispatchAndRunTaskWithTracker(std::move(delayed_task));
-
- // FlushAsyncForTesting() shouldn't callback since there is still a pending
- // undelayed task.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(event.IsSignaled());
-
- // Run the undelayed task.
- DispatchAndRunTaskWithTracker(std::move(undelayed_task));
-
- // FlushAsyncForTesting() should now callback.
- event.Wait();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdown) {
- if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
- return;
-
- // Simulate posting a task.
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // Shutdown() should return immediately since there are no pending
- // BLOCK_SHUTDOWN tasks.
- tracker_.Shutdown();
-
- // FlushForTesting() should return immediately after shutdown, even if an
- // undelayed task hasn't run.
- tracker_.FlushForTesting();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, FlushAfterShutdownAsync) {
- if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
- return;
-
- // Simulate posting a task.
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // Shutdown() should return immediately since there are no pending
- // BLOCK_SHUTDOWN tasks.
- tracker_.Shutdown();
-
- // FlushForTesting() should callback immediately after shutdown, even if an
- // undelayed task hasn't run.
- bool called_back = false;
- tracker_.FlushAsyncForTesting(
- BindOnce([](bool* called_back) { *called_back = true; },
- Unretained(&called_back)));
- EXPECT_TRUE(called_back);
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlush) {
- if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
- return;
-
- // Simulate posting a task.
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushForTesting() shouldn't return before the undelayed task runs or
- // shutdown completes.
- CallFlushFromAnotherThread();
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- VERIFY_ASYNC_FLUSH_IN_PROGRESS();
-
- // Shutdown() should return immediately since there are no pending
- // BLOCK_SHUTDOWN tasks.
- tracker_.Shutdown();
-
- // FlushForTesting() should now return, even if an undelayed task hasn't run.
- WAIT_FOR_ASYNC_FLUSH_RETURNED();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) {
- if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN)
- return;
-
- // Simulate posting a task.
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushAsyncForTesting() shouldn't callback before the undelayed task runs or
- // shutdown completes.
- WaitableEvent event;
- tracker_.FlushAsyncForTesting(
- BindOnce(&WaitableEvent::Signal, Unretained(&event)));
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(event.IsSignaled());
-
- // Shutdown() should return immediately since there are no pending
- // BLOCK_SHUTDOWN tasks.
- tracker_.Shutdown();
-
- // FlushAsyncForTesting() should now callback, even if an undelayed task
- // hasn't run.
- event.Wait();
-}
-
-TEST_P(TaskSchedulerTaskTrackerTest, DoublePendingFlushAsyncForTestingFails) {
- Task undelayed_task(FROM_HERE, DoNothing(), TaskTraits(GetParam()),
- TimeDelta());
- tracker_.WillPostTask(&undelayed_task);
-
- // FlushAsyncForTesting() shouldn't callback before the undelayed task runs.
- bool called_back = false;
- tracker_.FlushAsyncForTesting(
- BindOnce([](bool* called_back) { *called_back = true; },
- Unretained(&called_back)));
- EXPECT_FALSE(called_back);
- EXPECT_DCHECK_DEATH({ tracker_.FlushAsyncForTesting(BindOnce([]() {})); });
-}
-
-INSTANTIATE_TEST_CASE_P(
- ContinueOnShutdown,
- TaskSchedulerTaskTrackerTest,
- ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
-INSTANTIATE_TEST_CASE_P(
- SkipOnShutdown,
- TaskSchedulerTaskTrackerTest,
- ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
-INSTANTIATE_TEST_CASE_P(
- BlockShutdown,
- TaskSchedulerTaskTrackerTest,
- ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN));
-
-namespace {
-
-void ExpectSequenceToken(SequenceToken sequence_token) {
- EXPECT_EQ(sequence_token, SequenceToken::GetForCurrentThread());
-}
-
-} // namespace
-
-// Verify that SequenceToken::GetForCurrentThread() returns the Sequence's token
-// when a Task runs.
-TEST_F(TaskSchedulerTaskTrackerTest, CurrentSequenceToken) {
- scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
-
- const SequenceToken sequence_token = sequence->token();
- Task task(FROM_HERE, Bind(&ExpectSequenceToken, sequence_token), TaskTraits(),
- TimeDelta());
- tracker_.WillPostTask(&task);
-
- sequence->PushTask(std::move(task));
-
- EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
- sequence = tracker_.WillScheduleSequence(std::move(sequence),
- &never_notified_observer_);
- ASSERT_TRUE(sequence);
- tracker_.RunAndPopNextTask(std::move(sequence), &never_notified_observer_);
- EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
-}
-
-TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) {
- // Post and run tasks asynchronously.
- std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
-
- for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
- threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
- ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
- threads.back()->Start();
-
- threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
- ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
- threads.back()->Start();
-
- threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN),
- ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
- threads.back()->Start();
- }
-
- for (const auto& thread : threads)
- thread->Join();
-
- // Expect all tasks to be executed.
- EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted());
-
- // Should return immediately because no tasks are blocking shutdown.
- tracker_.Shutdown();
-}
-
-TEST_F(TaskSchedulerTaskTrackerTest,
- LoadWillPostBeforeShutdownAndRunDuringShutdown) {
- // Post tasks asynchronously.
- std::vector<Task> tasks_continue_on_shutdown;
- std::vector<Task> tasks_skip_on_shutdown;
- std::vector<Task> tasks_block_shutdown;
- for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
- tasks_continue_on_shutdown.push_back(
- CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
- tasks_skip_on_shutdown.push_back(
- CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN));
- tasks_block_shutdown.push_back(
- CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
- }
-
- std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads;
- for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
- post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, &tasks_continue_on_shutdown[i],
- ThreadPostingAndRunningTask::Action::WILL_POST, true));
- post_threads.back()->Start();
-
- post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, &tasks_skip_on_shutdown[i],
- ThreadPostingAndRunningTask::Action::WILL_POST, true));
- post_threads.back()->Start();
-
- post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, &tasks_block_shutdown[i],
- ThreadPostingAndRunningTask::Action::WILL_POST, true));
- post_threads.back()->Start();
- }
-
- for (const auto& thread : post_threads)
- thread->Join();
-
- // Call Shutdown() asynchronously.
- CallShutdownAsync();
-
- // Run tasks asynchronously.
- std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads;
- for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
- run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, std::move(tasks_continue_on_shutdown[i]),
- ThreadPostingAndRunningTask::Action::RUN, false));
- run_threads.back()->Start();
-
- run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, std::move(tasks_skip_on_shutdown[i]),
- ThreadPostingAndRunningTask::Action::RUN, false));
- run_threads.back()->Start();
-
- run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, std::move(tasks_block_shutdown[i]),
- ThreadPostingAndRunningTask::Action::RUN, false));
- run_threads.back()->Start();
- }
-
- for (const auto& thread : run_threads)
- thread->Join();
-
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
-
- // Expect BLOCK_SHUTDOWN tasks to have been executed.
- EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
-}
-
-TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) {
- // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to
- // block shutdown.
- Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN));
- EXPECT_TRUE(tracker_.WillPostTask(&block_shutdown_task));
-
- // Call Shutdown() asynchronously.
- CallShutdownAsync();
-
- // Post and run tasks asynchronously.
- std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads;
-
- for (size_t i = 0; i < kLoadTestNumIterations; ++i) {
- threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
- ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false));
- threads.back()->Start();
-
- threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN),
- ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, false));
- threads.back()->Start();
-
- threads.push_back(std::make_unique<ThreadPostingAndRunningTask>(
- &tracker_, CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN),
- ThreadPostingAndRunningTask::Action::WILL_POST_AND_RUN, true));
- threads.back()->Start();
- }
-
- for (const auto& thread : threads)
- thread->Join();
-
- // Expect BLOCK_SHUTDOWN tasks to have been executed.
- EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted());
-
- // Shutdown() shouldn't return before |block_shutdown_task| is executed.
- VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS();
-
- // Unblock shutdown by running |block_shutdown_task|.
- DispatchAndRunTaskWithTracker(std::move(block_shutdown_task));
- EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted());
- WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED();
-}
-
-// Verify that RunAndPopNextTask() returns the sequence from which it ran a task
-// when it can be rescheduled.
-TEST_F(TaskSchedulerTaskTrackerTest,
- RunAndPopNextTaskReturnsSequenceToReschedule) {
- Task task_1(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta());
- EXPECT_TRUE(tracker_.WillPostTask(&task_1));
- Task task_2(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta());
- EXPECT_TRUE(tracker_.WillPostTask(&task_2));
-
- scoped_refptr<Sequence> sequence =
- test::CreateSequenceWithTask(std::move(task_1));
- sequence->PushTask(std::move(task_2));
- EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
-
- EXPECT_EQ(sequence, tracker_.RunAndPopNextTask(sequence, nullptr));
-}
-
-// Verify that WillScheduleSequence() returns nullptr when it receives a
-// background sequence and the maximum number of background sequences that can
-// be scheduled concurrently is reached. Verify that an observer is notified
-// when a background sequence can be scheduled (i.e. when one of the previously
-// scheduled background sequences has run).
-TEST_F(TaskSchedulerTaskTrackerTest,
- WillScheduleBackgroundSequenceWithMaxBackgroundSequences) {
- constexpr int kMaxNumScheduledBackgroundSequences = 2;
- TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
-
- // Simulate posting |kMaxNumScheduledBackgroundSequences| background tasks
- // and scheduling the associated sequences. This should succeed.
- std::vector<scoped_refptr<Sequence>> scheduled_sequences;
- testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
- for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
- Task task(FROM_HERE, DoNothing(), TaskTraits(TaskPriority::BACKGROUND),
- TimeDelta());
- EXPECT_TRUE(tracker.WillPostTask(&task));
- scoped_refptr<Sequence> sequence =
- test::CreateSequenceWithTask(std::move(task));
- EXPECT_EQ(sequence,
- tracker.WillScheduleSequence(sequence, &never_notified_observer));
- scheduled_sequences.push_back(std::move(sequence));
- }
-
- // Simulate posting extra background tasks and scheduling the associated
- // sequences. This should fail because the maximum number of background
- // sequences that can be scheduled concurrently is already reached.
- std::vector<std::unique_ptr<bool>> extra_tasks_did_run;
- std::vector<
- std::unique_ptr<testing::StrictMock<MockCanScheduleSequenceObserver>>>
- extra_observers;
- std::vector<scoped_refptr<Sequence>> extra_sequences;
- for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
- extra_tasks_did_run.push_back(std::make_unique<bool>());
- Task extra_task(
- FROM_HERE,
- BindOnce([](bool* extra_task_did_run) { *extra_task_did_run = true; },
- Unretained(extra_tasks_did_run.back().get())),
- TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
- EXPECT_TRUE(tracker.WillPostTask(&extra_task));
- extra_sequences.push_back(
- test::CreateSequenceWithTask(std::move(extra_task)));
- extra_observers.push_back(
- std::make_unique<
- testing::StrictMock<MockCanScheduleSequenceObserver>>());
- EXPECT_EQ(nullptr,
- tracker.WillScheduleSequence(extra_sequences.back(),
- extra_observers.back().get()));
- }
-
- // Run the sequences scheduled at the beginning of the test. Expect an
- // observer from |extra_observer| to be notified every time a task finishes to
- // run.
- for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
- EXPECT_CALL(*extra_observers[i].get(),
- MockOnCanScheduleSequence(extra_sequences[i].get()));
- EXPECT_FALSE(tracker.RunAndPopNextTask(scheduled_sequences[i],
- &never_notified_observer));
- testing::Mock::VerifyAndClear(extra_observers[i].get());
- }
-
- // Run the extra sequences.
- for (int i = 0; i < kMaxNumScheduledBackgroundSequences; ++i) {
- EXPECT_FALSE(*extra_tasks_did_run[i]);
- EXPECT_FALSE(tracker.RunAndPopNextTask(extra_sequences[i],
- &never_notified_observer));
- EXPECT_TRUE(*extra_tasks_did_run[i]);
- }
-}
-
-namespace {
-
-void SetBool(bool* arg) {
- ASSERT_TRUE(arg);
- EXPECT_FALSE(*arg);
- *arg = true;
-}
-
-} // namespace
-
-// Verify that RunAndPopNextTask() doesn't reschedule the background sequence it
-// was assigned if there is a preempted background sequence with an earlier
-// sequence time (compared to the next task in the sequence assigned to
-// RunAndPopNextTask()).
-TEST_F(TaskSchedulerTaskTrackerTest,
- RunNextBackgroundTaskWithEarlierPendingBackgroundTask) {
- constexpr int kMaxNumScheduledBackgroundSequences = 1;
- TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
- testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
-
- // Simulate posting a background task and scheduling the associated sequence.
- // This should succeed.
- bool task_a_1_did_run = false;
- Task task_a_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_1_did_run)),
- TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
- EXPECT_TRUE(tracker.WillPostTask(&task_a_1));
- scoped_refptr<Sequence> sequence_a =
- test::CreateSequenceWithTask(std::move(task_a_1));
- EXPECT_EQ(sequence_a,
- tracker.WillScheduleSequence(sequence_a, &never_notified_observer));
-
- // Simulate posting an extra background task and scheduling the associated
- // sequence. This should fail because the maximum number of background
- // sequences that can be scheduled concurrently is already reached.
- bool task_b_1_did_run = false;
- Task task_b_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)),
- TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
- EXPECT_TRUE(tracker.WillPostTask(&task_b_1));
- scoped_refptr<Sequence> sequence_b =
- test::CreateSequenceWithTask(std::move(task_b_1));
- testing::StrictMock<MockCanScheduleSequenceObserver> task_b_1_observer;
- EXPECT_FALSE(tracker.WillScheduleSequence(sequence_b, &task_b_1_observer));
-
- // Wait to be sure that the sequence time of |task_a_2| is after the sequenced
- // time of |task_b_1|.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- // Post an extra background task in |sequence_a|.
- bool task_a_2_did_run = false;
- Task task_a_2(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_2_did_run)),
- TaskTraits(TaskPriority::BACKGROUND), TimeDelta());
- EXPECT_TRUE(tracker.WillPostTask(&task_a_2));
- sequence_a->PushTask(std::move(task_a_2));
-
- // Run the first task in |sequence_a|. RunAndPopNextTask() should return
- // nullptr since |sequence_a| can't be rescheduled immediately.
- // |task_b_1_observer| should be notified that |sequence_b| can be scheduled.
- testing::StrictMock<MockCanScheduleSequenceObserver> task_a_2_observer;
- EXPECT_CALL(task_b_1_observer, MockOnCanScheduleSequence(sequence_b.get()));
- EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &task_a_2_observer));
- testing::Mock::VerifyAndClear(&task_b_1_observer);
- EXPECT_TRUE(task_a_1_did_run);
-
- // Run the first task in |sequence_b|. RunAndPopNextTask() should return
- // nullptr since |sequence_b| is empty after popping a task from it.
- // |task_a_2_observer| should be notified that |sequence_a| can be
- // scheduled.
- EXPECT_CALL(task_a_2_observer, MockOnCanScheduleSequence(sequence_a.get()));
- EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_b, &never_notified_observer));
- testing::Mock::VerifyAndClear(&task_a_2_observer);
- EXPECT_TRUE(task_b_1_did_run);
-
- // Run the first task in |sequence_a|. RunAndPopNextTask() should return
- // nullptr since |sequence_b| is empty after popping a task from it. No
- // observer should be notified.
- EXPECT_FALSE(tracker.RunAndPopNextTask(sequence_a, &never_notified_observer));
- EXPECT_TRUE(task_a_2_did_run);
-}
-
-// Verify that preempted background sequences are scheduled when shutdown
-// starts.
-TEST_F(TaskSchedulerTaskTrackerTest,
- SchedulePreemptedBackgroundSequencesOnShutdown) {
- constexpr int kMaxNumScheduledBackgroundSequences = 0;
- TaskTracker tracker("Test", kMaxNumScheduledBackgroundSequences);
- testing::StrictMock<MockCanScheduleSequenceObserver> observer;
-
- // Simulate scheduling sequences. TaskTracker should prevent this.
- std::vector<scoped_refptr<Sequence>> preempted_sequences;
- for (int i = 0; i < 3; ++i) {
- Task task(FROM_HERE, DoNothing(),
- TaskTraits(TaskPriority::BACKGROUND,
- TaskShutdownBehavior::BLOCK_SHUTDOWN),
- TimeDelta());
- EXPECT_TRUE(tracker.WillPostTask(&task));
- scoped_refptr<Sequence> sequence =
- test::CreateSequenceWithTask(std::move(task));
- EXPECT_FALSE(tracker.WillScheduleSequence(sequence, &observer));
- preempted_sequences.push_back(std::move(sequence));
-
- // Wait to be sure that tasks have different |sequenced_time|.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- }
-
- // Perform shutdown. Expect |preempted_sequences| to be scheduled in posting
- // order.
- {
- testing::InSequence in_sequence;
- for (auto& preempted_sequence : preempted_sequences) {
- EXPECT_CALL(observer, MockOnCanScheduleSequence(preempted_sequence.get()))
- .WillOnce(testing::Invoke([&tracker](Sequence* sequence) {
- // Run the task to unblock shutdown.
- tracker.RunAndPopNextTask(sequence, nullptr);
- }));
- }
- tracker.Shutdown();
- }
-}
-
-namespace {
-
-class WaitAllowedTestThread : public SimpleThread {
- public:
- WaitAllowedTestThread() : SimpleThread("WaitAllowedTestThread") {}
-
- private:
- void Run() override {
- auto task_tracker = std::make_unique<TaskTracker>("Test");
-
- // Waiting is allowed by default. Expect TaskTracker to disallow it before
- // running a task without the WithBaseSyncPrimitives() trait.
- internal::AssertBaseSyncPrimitivesAllowed();
- Task task_without_sync_primitives(
- FROM_HERE, Bind([]() {
- EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
- }),
- TaskTraits(), TimeDelta());
- EXPECT_TRUE(task_tracker->WillPostTask(&task_without_sync_primitives));
- testing::StrictMock<MockCanScheduleSequenceObserver>
- never_notified_observer;
- auto sequence_without_sync_primitives = task_tracker->WillScheduleSequence(
- test::CreateSequenceWithTask(std::move(task_without_sync_primitives)),
- &never_notified_observer);
- ASSERT_TRUE(sequence_without_sync_primitives);
- task_tracker->RunAndPopNextTask(std::move(sequence_without_sync_primitives),
- &never_notified_observer);
-
- // Disallow waiting. Expect TaskTracker to allow it before running a task
- // with the WithBaseSyncPrimitives() trait.
- ThreadRestrictions::DisallowWaiting();
- Task task_with_sync_primitives(
- FROM_HERE, Bind([]() {
- // Shouldn't fail.
- internal::AssertBaseSyncPrimitivesAllowed();
- }),
- TaskTraits(WithBaseSyncPrimitives()), TimeDelta());
- EXPECT_TRUE(task_tracker->WillPostTask(&task_with_sync_primitives));
- auto sequence_with_sync_primitives = task_tracker->WillScheduleSequence(
- test::CreateSequenceWithTask(std::move(task_with_sync_primitives)),
- &never_notified_observer);
- ASSERT_TRUE(sequence_with_sync_primitives);
- task_tracker->RunAndPopNextTask(std::move(sequence_with_sync_primitives),
- &never_notified_observer);
-
- ScopedAllowBaseSyncPrimitivesForTesting
- allow_wait_in_task_tracker_destructor;
- task_tracker.reset();
- }
-
- DISALLOW_COPY_AND_ASSIGN(WaitAllowedTestThread);
-};
-
-} // namespace
-
-// Verify that AssertIOAllowed() succeeds only for a WithBaseSyncPrimitives()
-// task.
-TEST(TaskSchedulerTaskTrackerWaitAllowedTest, WaitAllowed) {
- // Run the test on the separate thread since it is not possible to reset the
- // "wait allowed" bit of a thread without being a friend of
- // ThreadRestrictions.
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- WaitAllowedTestThread wait_allowed_test_thread;
- wait_allowed_test_thread.Start();
- wait_allowed_test_thread.Join();
-}
-
-// Verify that TaskScheduler.TaskLatency.* histograms are correctly recorded
-// when a task runs.
-TEST(TaskSchedulerTaskTrackerHistogramTest, TaskLatency) {
- auto statistics_recorder = StatisticsRecorder::CreateTemporaryForTesting();
-
- TaskTracker tracker("Test");
- testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer;
-
- struct {
- const TaskTraits traits;
- const char* const expected_histogram;
- } static constexpr kTests[] = {
- {{TaskPriority::BACKGROUND},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "BackgroundTaskPriority"},
- {{MayBlock(), TaskPriority::BACKGROUND},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "BackgroundTaskPriority_MayBlock"},
- {{WithBaseSyncPrimitives(), TaskPriority::BACKGROUND},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "BackgroundTaskPriority_MayBlock"},
- {{TaskPriority::USER_VISIBLE},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "UserVisibleTaskPriority"},
- {{MayBlock(), TaskPriority::USER_VISIBLE},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "UserVisibleTaskPriority_MayBlock"},
- {{WithBaseSyncPrimitives(), TaskPriority::USER_VISIBLE},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "UserVisibleTaskPriority_MayBlock"},
- {{TaskPriority::USER_BLOCKING},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "UserBlockingTaskPriority"},
- {{MayBlock(), TaskPriority::USER_BLOCKING},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "UserBlockingTaskPriority_MayBlock"},
- {{WithBaseSyncPrimitives(), TaskPriority::USER_BLOCKING},
- "TaskScheduler.TaskLatencyMicroseconds.Test."
- "UserBlockingTaskPriority_MayBlock"}};
-
- for (const auto& test : kTests) {
- Task task(FROM_HERE, DoNothing(), test.traits, TimeDelta());
- ASSERT_TRUE(tracker.WillPostTask(&task));
-
- HistogramTester tester;
-
- auto sequence = tracker.WillScheduleSequence(
- test::CreateSequenceWithTask(std::move(task)),
- &never_notified_observer);
- ASSERT_TRUE(sequence);
- tracker.RunAndPopNextTask(std::move(sequence), &never_notified_observer);
- tester.ExpectTotalCount(test.expected_histogram, 1);
- }
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/task_unittest.cc b/base/task_scheduler/task_unittest.cc
deleted file mode 100644
index 31a59ded9f..0000000000
--- a/base/task_scheduler/task_unittest.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2016 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/task_scheduler/task.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-// Verify that the shutdown behavior of a BLOCK_SHUTDOWN delayed task is
-// adjusted to SKIP_ON_SHUTDOWN. The shutown behavior of other delayed tasks
-// should not change.
-TEST(TaskSchedulerTaskTest, ShutdownBehaviorChangeWithDelay) {
- Task continue_on_shutdown(FROM_HERE, DoNothing(),
- {TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- TimeDelta::FromSeconds(1));
- EXPECT_EQ(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN,
- continue_on_shutdown.traits.shutdown_behavior());
-
- Task skip_on_shutdown(FROM_HERE, DoNothing(),
- {TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
- TimeDelta::FromSeconds(1));
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- skip_on_shutdown.traits.shutdown_behavior());
-
- Task block_shutdown(FROM_HERE, DoNothing(),
- {TaskShutdownBehavior::BLOCK_SHUTDOWN},
- TimeDelta::FromSeconds(1));
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- block_shutdown.traits.shutdown_behavior());
-}
-
-// Verify that the shutdown behavior of undelayed tasks is not adjusted.
-TEST(TaskSchedulerTaskTest, NoShutdownBehaviorChangeNoDelay) {
- Task continue_on_shutdown(FROM_HERE, DoNothing(),
- {TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- TimeDelta());
- EXPECT_EQ(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN,
- continue_on_shutdown.traits.shutdown_behavior());
-
- Task skip_on_shutdown(FROM_HERE, DoNothing(),
- {TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, TimeDelta());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- skip_on_shutdown.traits.shutdown_behavior());
-
- Task block_shutdown(FROM_HERE, DoNothing(),
- {TaskShutdownBehavior::BLOCK_SHUTDOWN}, TimeDelta());
- EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN,
- block_shutdown.traits.shutdown_behavior());
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/test_task_factory.cc b/base/task_scheduler/test_task_factory.cc
deleted file mode 100644
index 08675470a5..0000000000
--- a/base/task_scheduler/test_task_factory.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2016 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/task_scheduler/test_task_factory.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-namespace test {
-
-TestTaskFactory::TestTaskFactory(scoped_refptr<TaskRunner> task_runner,
- ExecutionMode execution_mode)
- : cv_(&lock_),
- task_runner_(std::move(task_runner)),
- execution_mode_(execution_mode) {
- // Detach |thread_checker_| from the current thread. It will be attached to
- // the first thread that calls ThreadCheckerImpl::CalledOnValidThread().
- thread_checker_.DetachFromThread();
-}
-
-TestTaskFactory::~TestTaskFactory() {
- WaitForAllTasksToRun();
-}
-
-bool TestTaskFactory::PostTask(PostNestedTask post_nested_task,
- OnceClosure after_task_closure) {
- AutoLock auto_lock(lock_);
- return task_runner_->PostTask(
- FROM_HERE, BindOnce(&TestTaskFactory::RunTaskCallback, Unretained(this),
- num_posted_tasks_++, post_nested_task,
- std::move(after_task_closure)));
-}
-
-void TestTaskFactory::WaitForAllTasksToRun() const {
- AutoLock auto_lock(lock_);
- while (ran_tasks_.size() < num_posted_tasks_)
- cv_.Wait();
-}
-
-void TestTaskFactory::RunTaskCallback(size_t task_index,
- PostNestedTask post_nested_task,
- OnceClosure after_task_closure) {
- if (post_nested_task == PostNestedTask::YES)
- PostTask(PostNestedTask::NO, Closure());
-
- EXPECT_TRUE(task_runner_->RunsTasksInCurrentSequence());
-
- // Verify TaskRunnerHandles are set as expected in the task's scope.
- switch (execution_mode_) {
- case ExecutionMode::PARALLEL:
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
- break;
- case ExecutionMode::SEQUENCED:
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_, SequencedTaskRunnerHandle::Get());
- break;
- case ExecutionMode::SINGLE_THREADED:
- // SequencedTaskRunnerHandle inherits from ThreadTaskRunnerHandle so
- // both are expected to be "set" in the SINGLE_THREADED case.
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_, ThreadTaskRunnerHandle::Get());
- EXPECT_EQ(task_runner_, SequencedTaskRunnerHandle::Get());
- break;
- }
-
- {
- AutoLock auto_lock(lock_);
-
- DCHECK_LE(task_index, num_posted_tasks_);
-
- if ((execution_mode_ == ExecutionMode::SINGLE_THREADED ||
- execution_mode_ == ExecutionMode::SEQUENCED) &&
- task_index != ran_tasks_.size()) {
- ADD_FAILURE() << "A task didn't run in the expected order.";
- }
-
- if (execution_mode_ == ExecutionMode::SINGLE_THREADED)
- EXPECT_TRUE(thread_checker_.CalledOnValidThread());
-
- if (ran_tasks_.find(task_index) != ran_tasks_.end())
- ADD_FAILURE() << "A task ran more than once.";
- ran_tasks_.insert(task_index);
-
- cv_.Signal();
- }
-
- if (!after_task_closure.is_null())
- std::move(after_task_closure).Run();
-}
-
-} // namespace test
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/test_task_factory.h b/base/task_scheduler/test_task_factory.h
deleted file mode 100644
index 300b7bfbc5..0000000000
--- a/base/task_scheduler/test_task_factory.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TASK_SCHEDULER_TEST_TASK_FACTORY_H_
-#define BASE_TASK_SCHEDULER_TEST_TASK_FACTORY_H_
-
-#include <stddef.h>
-
-#include <unordered_set>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/task_runner.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/task_scheduler/test_utils.h"
-#include "base/threading/thread_checker_impl.h"
-
-namespace base {
-namespace internal {
-namespace test {
-
-// A TestTaskFactory posts tasks to a TaskRunner and verifies that they run as
-// expected. Generates a test failure when:
-// - The RunsTasksInCurrentSequence() method of the TaskRunner returns false on
-// a thread on which a Task is run.
-// - The TaskRunnerHandles set in the context of the task don't match what's
-// expected for the tested ExecutionMode.
-// - The ExecutionMode of the TaskRunner is SEQUENCED or SINGLE_THREADED and
-// Tasks don't run in posting order.
-// - The ExecutionMode of the TaskRunner is SINGLE_THREADED and Tasks don't run
-// on the same thread.
-// - A Task runs more than once.
-class TestTaskFactory {
- public:
- enum class PostNestedTask {
- YES,
- NO,
- };
-
- // Constructs a TestTaskFactory that posts tasks to |task_runner|.
- // |execution_mode| is the ExecutionMode of |task_runner|.
- TestTaskFactory(scoped_refptr<TaskRunner> task_runner,
- ExecutionMode execution_mode);
-
- ~TestTaskFactory();
-
- // Posts a task. The posted task will:
- // - Post a new task if |post_nested_task| is YES. The nested task won't run
- // |after_task_closure|.
- // - Verify conditions in which the task runs (see potential failures above).
- // - Run |after_task_closure| if it is not null.
- bool PostTask(PostNestedTask post_nested_task,
- OnceClosure after_task_closure);
-
- // Waits for all tasks posted by PostTask() to start running. It is not
- // guaranteed that the tasks have completed their execution when this returns.
- void WaitForAllTasksToRun() const;
-
- const TaskRunner* task_runner() const { return task_runner_.get(); }
-
- private:
- void RunTaskCallback(size_t task_index,
- PostNestedTask post_nested_task,
- OnceClosure after_task_closure);
-
- // Synchronizes access to all members.
- mutable Lock lock_;
-
- // Condition variable signaled when a task runs.
- mutable ConditionVariable cv_;
-
- // Task runner through which this factory posts tasks.
- const scoped_refptr<TaskRunner> task_runner_;
-
- // Execution mode of |task_runner_|.
- const ExecutionMode execution_mode_;
-
- // Number of tasks posted by PostTask().
- size_t num_posted_tasks_ = 0;
-
- // Indexes of tasks that ran.
- std::unordered_set<size_t> ran_tasks_;
-
- // Used to verify that all tasks run on the same thread when |execution_mode_|
- // is SINGLE_THREADED.
- ThreadCheckerImpl thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(TestTaskFactory);
-};
-
-} // namespace test
-} // namespace internal
-} // namespace base
-
-#endif // BASE_TASK_SCHEDULER_TEST_TASK_FACTORY_H_
diff --git a/base/test/android/java/src/org/chromium/base/ContentUriTestUtils.java b/base/test/android/java/src/org/chromium/base/ContentUriTestUtils.java
deleted file mode 100644
index fe9d5403de..0000000000
--- a/base/test/android/java/src/org/chromium/base/ContentUriTestUtils.java
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 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;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.MediaStore;
-
-import org.chromium.base.annotations.CalledByNative;
-
-/**
- * Utilities for testing operations on content URI.
- */
-public class ContentUriTestUtils {
- /**
- * Insert an image into the MediaStore, and return the content URI. If the
- * image already exists in the MediaStore, just retrieve the URI.
- *
- * @param path Path to the image file.
- * @return Content URI of the image.
- */
- @CalledByNative
- private static String insertImageIntoMediaStore(String path) {
- // Check whether the content URI exists.
- Cursor c = ContextUtils.getApplicationContext().getContentResolver().query(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
- new String[] {MediaStore.Video.VideoColumns._ID},
- MediaStore.Images.Media.DATA + " LIKE ?", new String[] {path}, null);
- if (c != null && c.getCount() > 0) {
- c.moveToFirst();
- int id = c.getInt(0);
- return Uri.withAppendedPath(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id).toString();
- }
-
- // Insert the content URI into MediaStore.
- ContentValues values = new ContentValues();
- values.put(MediaStore.MediaColumns.DATA, path);
- Uri uri = ContextUtils.getApplicationContext().getContentResolver().insert(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
- return uri.toString();
- }
-}
diff --git a/base/test/android/java/src/org/chromium/base/ITestCallback.aidl b/base/test/android/java/src/org/chromium/base/ITestCallback.aidl
deleted file mode 100644
index dd208d55da..0000000000
--- a/base/test/android/java/src/org/chromium/base/ITestCallback.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 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;
-
-import org.chromium.base.ITestController;
-import org.chromium.base.process_launcher.FileDescriptorInfo;
-
-/**
- * This interface is called by the child process to pass its controller to its parent.
- */
-interface ITestCallback {
- oneway void childConnected(ITestController controller);
-
- /**
- * Invoked by the service to notify that the main method returned.
- * IMPORTANT! Should not be marked oneway as the caller will terminate the running process after
- * this call. Marking it oneway would make the call asynchronous and the process could terminate
- * before the call was actually sent.
- */
- void mainReturned(int returnCode);
-}
diff --git a/base/test/android/java/src/org/chromium/base/ITestController.aidl b/base/test/android/java/src/org/chromium/base/ITestController.aidl
deleted file mode 100644
index d927ee5c87..0000000000
--- a/base/test/android/java/src/org/chromium/base/ITestController.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 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;
-
-import org.chromium.base.process_launcher.FileDescriptorInfo;
-
-/**
- * This interface is used to control child processes.
- */
-interface ITestController {
- /**
- * Forces the service process to terminate and block until the process stops.
- * @param exitCode the exit code the process should terminate with.
- * @return always true, a return value is only returned to force the call to be synchronous.
- */
- boolean forceStopSynchronous(int exitCode);
-
- /**
- * Forces the service process to terminate.
- * @param exitCode the exit code the process should terminate with.
- */
- oneway void forceStop(int exitCode);
-}
diff --git a/base/test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java b/base/test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java
deleted file mode 100644
index 3985e6a893..0000000000
--- a/base/test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2017 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;
-
-import android.os.Handler;
-import android.os.Process;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.CalledByNativeUnchecked;
-import org.chromium.base.annotations.JNINamespace;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-@JNINamespace("base::android")
-class JavaHandlerThreadHelpers {
- private static class TestException extends Exception {}
-
- // This is executed as part of base_unittests. This tests that JavaHandlerThread can be used
- // by itself without attaching to its native peer.
- @CalledByNative
- private static JavaHandlerThread testAndGetJavaHandlerThread() {
- final AtomicBoolean taskExecuted = new AtomicBoolean();
- final Object lock = new Object();
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- synchronized (lock) {
- taskExecuted.set(true);
- lock.notifyAll();
- }
- }
- };
-
- JavaHandlerThread thread =
- new JavaHandlerThread("base_unittests_java", Process.THREAD_PRIORITY_DEFAULT);
- thread.maybeStart();
-
- Handler handler = new Handler(thread.getLooper());
- handler.post(runnable);
- synchronized (lock) {
- while (!taskExecuted.get()) {
- try {
- lock.wait();
- } catch (InterruptedException e) {
- // ignore interrupts
- }
- }
- }
-
- return thread;
- }
-
- @CalledByNativeUnchecked
- private static void throwException() throws TestException {
- throw new TestException();
- }
-
- @CalledByNative
- private static boolean isExceptionTestException(Throwable exception) {
- if (exception == null) return false;
- return exception instanceof TestException;
- }
-}
diff --git a/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java b/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java
deleted file mode 100644
index 9756c97602..0000000000
--- a/base/test/android/java/src/org/chromium/base/MainReturnCodeResult.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 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;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-
-/**
- * Contains the result of a native main method that ran in a child process.
- */
-@JNINamespace("base::android")
-public final class MainReturnCodeResult {
- private final int mMainReturnCode;
- private final boolean mTimedOut;
-
- public static MainReturnCodeResult createMainResult(int returnCode) {
- return new MainReturnCodeResult(returnCode, false /* timedOut */);
- }
-
- public static MainReturnCodeResult createTimeoutMainResult() {
- return new MainReturnCodeResult(0, true /* timedOut */);
- }
-
- private MainReturnCodeResult(int mainReturnCode, boolean timedOut) {
- mMainReturnCode = mainReturnCode;
- mTimedOut = timedOut;
- }
-
- @CalledByNative
- public int getReturnCode() {
- return mMainReturnCode;
- }
-
- @CalledByNative
- public boolean hasTimedOut() {
- return mTimedOut;
- }
-}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java
deleted file mode 100644
index d0b1850bfc..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java
+++ /dev/null
@@ -1,383 +0,0 @@
-// Copyright 2016 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;
-
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.SparseArray;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.JNINamespace;
-import org.chromium.base.process_launcher.ChildConnectionAllocator;
-import org.chromium.base.process_launcher.ChildProcessConnection;
-import org.chromium.base.process_launcher.ChildProcessLauncher;
-import org.chromium.base.process_launcher.FileDescriptorInfo;
-import org.chromium.base.process_launcher.IChildProcessService;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.annotation.concurrent.GuardedBy;
-
-/**
- * Helper class for launching test client processes for multiprocess unit tests.
- */
-@JNINamespace("base::android")
-public final class MultiprocessTestClientLauncher {
- private static final String TAG = "cr_MProcTCLauncher";
-
- private static final int CONNECTION_TIMEOUT_MS = 10 * 1000;
-
- private static final SparseArray<MultiprocessTestClientLauncher> sPidToLauncher =
- new SparseArray<>();
-
- private static final SparseArray<Integer> sPidToMainResult = new SparseArray<>();
-
- private static final Object sLauncherHandlerInitLock = new Object();
- private static Handler sLauncherHandler;
-
- private static ChildConnectionAllocator sConnectionAllocator;
-
- private final ITestCallback.Stub mCallback = new ITestCallback.Stub() {
- @Override
- public void childConnected(ITestController controller) {
- mTestController = controller;
- // This method can be called before onServiceConnected below has set the PID.
- // Wait for mPid to be set before notifying.
- try {
- mPidReceived.await();
- } catch (InterruptedException ie) {
- Log.e(TAG, "Interrupted while waiting for connection PID.");
- return;
- }
- // Now we are fully initialized, notify clients.
- mConnectedLock.lock();
- try {
- mConnected = true;
- mConnectedCondition.signal();
- } finally {
- mConnectedLock.unlock();
- }
- }
-
- @Override
- public void mainReturned(int returnCode) {
- mMainReturnCodeLock.lock();
- try {
- mMainReturnCode = returnCode;
- mMainReturnCodeCondition.signal();
- } finally {
- mMainReturnCodeLock.unlock();
- }
-
- // Also store the return code in a map as the connection might get disconnected
- // before waitForMainToReturn is called and then we would not have a way to retrieve
- // the connection.
- sPidToMainResult.put(mPid, returnCode);
- }
- };
-
- private final ChildProcessLauncher.Delegate mLauncherDelegate =
- new ChildProcessLauncher.Delegate() {
- @Override
- public void onConnectionEstablished(ChildProcessConnection connection) {
- assert isRunningOnLauncherThread();
- int pid = connection.getPid();
- sPidToLauncher.put(pid, MultiprocessTestClientLauncher.this);
- mPid = pid;
- mPidReceived.countDown();
- }
-
- @Override
- public void onConnectionLost(ChildProcessConnection connection) {
- assert isRunningOnLauncherThread();
- assert sPidToLauncher.get(connection.getPid())
- == MultiprocessTestClientLauncher.this;
- sPidToLauncher.remove(connection.getPid());
- }
- };
-
- private final CountDownLatch mPidReceived = new CountDownLatch(1);
-
- private final ChildProcessLauncher mLauncher;
-
- private final ReentrantLock mConnectedLock = new ReentrantLock();
- private final Condition mConnectedCondition = mConnectedLock.newCondition();
- @GuardedBy("mConnectedLock")
- private boolean mConnected;
-
- private IChildProcessService mService = null;
- private int mPid;
- private ITestController mTestController;
-
- private final ReentrantLock mMainReturnCodeLock = new ReentrantLock();
- private final Condition mMainReturnCodeCondition = mMainReturnCodeLock.newCondition();
- // The return code returned by the service's main method.
- // null if the service has not sent it yet.
- @GuardedBy("mMainReturnCodeLock")
- private Integer mMainReturnCode;
-
- private MultiprocessTestClientLauncher(String[] commandLine, FileDescriptorInfo[] filesToMap) {
- assert isRunningOnLauncherThread();
-
- if (sConnectionAllocator == null) {
- sConnectionAllocator = ChildConnectionAllocator.create(
- ContextUtils.getApplicationContext(), sLauncherHandler, null,
- "org.chromium.native_test", "org.chromium.base.MultiprocessTestClientService",
- "org.chromium.native_test.NUM_TEST_CLIENT_SERVICES", false /* bindToCaller */,
- false /* bindAsExternalService */, false /* useStrongBinding */);
- }
- mLauncher = new ChildProcessLauncher(sLauncherHandler, mLauncherDelegate, commandLine,
- filesToMap, sConnectionAllocator, Arrays.asList(mCallback));
- }
-
- private boolean waitForConnection(long timeoutMs) {
- assert !isRunningOnLauncherThread();
-
- long timeoutNs = TimeUnit.MILLISECONDS.toNanos(timeoutMs);
- mConnectedLock.lock();
- try {
- while (!mConnected) {
- if (timeoutNs <= 0L) {
- return false;
- }
- try {
- mConnectedCondition.awaitNanos(timeoutNs);
- } catch (InterruptedException ie) {
- Log.e(TAG, "Interrupted while waiting for connection.");
- }
- }
- } finally {
- mConnectedLock.unlock();
- }
- return true;
- }
-
- private Integer getMainReturnCode(long timeoutMs) {
- assert isRunningOnLauncherThread();
-
- long timeoutNs = TimeUnit.MILLISECONDS.toNanos(timeoutMs);
- mMainReturnCodeLock.lock();
- try {
- while (mMainReturnCode == null) {
- if (timeoutNs <= 0L) {
- return null;
- }
- try {
- timeoutNs = mMainReturnCodeCondition.awaitNanos(timeoutNs);
- } catch (InterruptedException ie) {
- Log.e(TAG, "Interrupted while waiting for main return code.");
- }
- }
- return mMainReturnCode;
- } finally {
- mMainReturnCodeLock.unlock();
- }
- }
-
- /**
- * Spawns and connects to a child process.
- * May not be called from the main thread.
- *
- * @param commandLine the child process command line argv.
- * @return the PID of the started process or 0 if the process could not be started.
- */
- @CalledByNative
- private static int launchClient(
- final String[] commandLine, final FileDescriptorInfo[] filesToMap) {
- initLauncherThread();
-
- final MultiprocessTestClientLauncher launcher =
- runOnLauncherAndGetResult(new Callable<MultiprocessTestClientLauncher>() {
- @Override
- public MultiprocessTestClientLauncher call() {
- return createAndStartLauncherOnLauncherThread(commandLine, filesToMap);
- }
- });
- if (launcher == null) {
- return 0;
- }
-
- if (!launcher.waitForConnection(CONNECTION_TIMEOUT_MS)) {
- return 0; // Timed-out.
- }
-
- return runOnLauncherAndGetResult(new Callable<Integer>() {
- @Override
- public Integer call() {
- int pid = launcher.mLauncher.getPid();
- assert pid > 0;
- sPidToLauncher.put(pid, launcher);
- return pid;
- }
- });
- }
-
- private static MultiprocessTestClientLauncher createAndStartLauncherOnLauncherThread(
- String[] commandLine, FileDescriptorInfo[] filesToMap) {
- assert isRunningOnLauncherThread();
-
- MultiprocessTestClientLauncher launcher =
- new MultiprocessTestClientLauncher(commandLine, filesToMap);
- if (!launcher.mLauncher.start(
- true /* setupConnection */, true /* queueIfNoFreeConnection */)) {
- return null;
- }
-
- return launcher;
- }
-
- /**
- * Blocks until the main method invoked by a previous call to launchClient terminates or until
- * the specified time-out expires.
- * Returns immediately if main has already returned.
- * @param pid the process ID that was returned by the call to launchClient
- * @param timeoutMs the timeout in milliseconds after which the method returns even if main has
- * not returned.
- * @return the return code returned by the main method or whether it timed-out.
- */
- @CalledByNative
- private static MainReturnCodeResult waitForMainToReturn(final int pid, final int timeoutMs) {
- return runOnLauncherAndGetResult(new Callable<MainReturnCodeResult>() {
- @Override
- public MainReturnCodeResult call() {
- return waitForMainToReturnOnLauncherThread(pid, timeoutMs);
- }
- });
- }
-
- private static MainReturnCodeResult waitForMainToReturnOnLauncherThread(
- int pid, int timeoutMs) {
- assert isRunningOnLauncherThread();
-
- MultiprocessTestClientLauncher launcher = sPidToLauncher.get(pid);
- // The launcher can be null if it got cleaned-up (because the connection was lost) before
- // this gets called.
- if (launcher != null) {
- Integer mainResult = launcher.getMainReturnCode(timeoutMs);
- return mainResult == null ? MainReturnCodeResult.createTimeoutMainResult()
- : MainReturnCodeResult.createMainResult(mainResult);
- }
-
- Integer mainResult = sPidToMainResult.get(pid);
- if (mainResult == null) {
- Log.e(TAG, "waitForMainToReturn called on unknown connection for pid " + pid);
- return null;
- }
- sPidToMainResult.remove(pid);
- return MainReturnCodeResult.createMainResult(mainResult);
- }
-
- @CalledByNative
- private static boolean terminate(final int pid, final int exitCode, final boolean wait) {
- return runOnLauncherAndGetResult(new Callable<Boolean>() {
- @Override
- public Boolean call() {
- return terminateOnLauncherThread(pid, exitCode, wait);
- }
- });
- }
-
- private static boolean terminateOnLauncherThread(int pid, int exitCode, boolean wait) {
- assert isRunningOnLauncherThread();
-
- MultiprocessTestClientLauncher launcher = sPidToLauncher.get(pid);
- if (launcher == null) {
- Log.e(TAG, "terminate called on unknown launcher for pid " + pid);
- return false;
- }
- try {
- if (wait) {
- launcher.mTestController.forceStopSynchronous(exitCode);
- } else {
- launcher.mTestController.forceStop(exitCode);
- }
- } catch (RemoteException e) {
- // We expect this failure, since the forceStop's service implementation calls
- // System.exit().
- }
- return true;
- }
-
- private static void initLauncherThread() {
- synchronized (sLauncherHandlerInitLock) {
- if (sLauncherHandler != null) return;
-
- HandlerThread launcherThread = new HandlerThread("LauncherThread");
- launcherThread.start();
- sLauncherHandler = new Handler(launcherThread.getLooper());
- }
- }
-
- /** Does not take ownership of of fds. */
- @CalledByNative
- private static FileDescriptorInfo[] makeFdInfoArray(int[] keys, int[] fds) {
- FileDescriptorInfo[] fdInfos = new FileDescriptorInfo[keys.length];
- for (int i = 0; i < keys.length; i++) {
- FileDescriptorInfo fdInfo = makeFdInfo(keys[i], fds[i]);
- if (fdInfo == null) {
- Log.e(TAG, "Failed to make file descriptor (" + keys[i] + ", " + fds[i] + ").");
- return null;
- }
- fdInfos[i] = fdInfo;
- }
- return fdInfos;
- }
-
- private static FileDescriptorInfo makeFdInfo(int id, int fd) {
- ParcelFileDescriptor parcelableFd = null;
- try {
- parcelableFd = ParcelFileDescriptor.fromFd(fd);
- } catch (IOException e) {
- Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e);
- return null;
- }
- return new FileDescriptorInfo(id, parcelableFd, 0 /* offset */, 0 /* size */);
- }
-
- private static boolean isRunningOnLauncherThread() {
- return sLauncherHandler.getLooper() == Looper.myLooper();
- }
-
- private static void runOnLauncherThreadBlocking(final Runnable runnable) {
- assert !isRunningOnLauncherThread();
- final Semaphore done = new Semaphore(0);
- sLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- runnable.run();
- done.release();
- }
- });
- done.acquireUninterruptibly();
- }
-
- private static <R> R runOnLauncherAndGetResult(Callable<R> callable) {
- if (isRunningOnLauncherThread()) {
- try {
- return callable.call();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- try {
- FutureTask<R> task = new FutureTask<R>(callable);
- sLauncherHandler.post(task);
- return task.get();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService.java
deleted file mode 100644
index 9b500018bd..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 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;
-
-import org.chromium.base.process_launcher.ChildProcessService;
-
-/** The service implementation used to host all multiprocess test client code. */
-public class MultiprocessTestClientService extends ChildProcessService {
- public MultiprocessTestClientService() {
- super(new MultiprocessTestClientServiceDelegate());
- }
-}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService0.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService0.java
deleted file mode 100644
index 6bdd867e12..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService0.java
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2016 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;
-
-/**
- * A subclass used only to differentiate different test client service process instances.
- */
-public class MultiprocessTestClientService0 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService1.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService1.java
deleted file mode 100644
index 69827f0e8b..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService1.java
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2016 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;
-
-/**
- * A subclass used only to differentiate different test client service process instances.
- */
-public class MultiprocessTestClientService1 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService2.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService2.java
deleted file mode 100644
index aad11f1c23..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService2.java
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2016 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;
-
-/**
- * A subclass used only to differentiate different test client service process instances.
- */
-public class MultiprocessTestClientService2 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService3.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService3.java
deleted file mode 100644
index 20d2561b93..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService3.java
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2016 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;
-
-/**
- * A subclass used only to differentiate different test client service process instances.
- */
-public class MultiprocessTestClientService3 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService4.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService4.java
deleted file mode 100644
index 4b14551dc8..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientService4.java
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2016 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;
-
-/**
- * A subclass used only to differentiate different test client service process instances.
- */
-public class MultiprocessTestClientService4 extends MultiprocessTestClientService {}
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java
deleted file mode 100644
index 8a63fe8acb..0000000000
--- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2017 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;
-
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.SparseArray;
-
-import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.base.library_loader.ProcessInitException;
-import org.chromium.base.process_launcher.ChildProcessServiceDelegate;
-import org.chromium.native_test.MainRunner;
-
-import java.util.List;
-
-/** Implementation of the ChildProcessServiceDelegate used for the Multiprocess tests. */
-public class MultiprocessTestClientServiceDelegate implements ChildProcessServiceDelegate {
- private static final String TAG = "MPTestCSDelegate";
-
- private ITestCallback mTestCallback;
-
- private final ITestController.Stub mTestController = new ITestController.Stub() {
- @Override
- public boolean forceStopSynchronous(int exitCode) {
- System.exit(exitCode);
- return true;
- }
-
- @Override
- public void forceStop(int exitCode) {
- System.exit(exitCode);
- }
- };
-
- @Override
- public void onServiceCreated() {
- PathUtils.setPrivateDataDirectorySuffix("chrome_multiprocess_test_client_service");
- }
-
- @Override
- public void onServiceBound(Intent intent) {}
-
- @Override
- public void onConnectionSetup(Bundle connectionBundle, List<IBinder> callbacks) {
- mTestCallback = ITestCallback.Stub.asInterface(callbacks.get(0));
- }
-
- @Override
- public void onDestroy() {}
-
- @Override
- public void preloadNativeLibrary(Context hostContext) {
- LibraryLoader.getInstance().preloadNow();
- }
-
- @Override
- public boolean loadNativeLibrary(Context hostContext) {
- try {
- LibraryLoader.getInstance().loadNow();
- return true;
- } catch (ProcessInitException pie) {
- Log.e(TAG, "Unable to load native libraries.", pie);
- return false;
- }
- }
-
- @Override
- public SparseArray<String> getFileDescriptorsIdsToKeys() {
- return null;
- }
-
- @Override
- public void onBeforeMain() {
- try {
- mTestCallback.childConnected(mTestController);
- } catch (RemoteException re) {
- Log.e(TAG, "Failed to notify parent process of connection.");
- }
- }
-
- @Override
- public void runMain() {
- int result = MainRunner.runMain(CommandLine.getJavaSwitchesOrNull());
- try {
- mTestCallback.mainReturned(result);
- } catch (RemoteException re) {
- Log.e(TAG, "Failed to notify parent process of main returning.");
- }
- }
-}
diff --git a/base/test/android/java/src/org/chromium/base/TestUiThread.java b/base/test/android/java/src/org/chromium/base/TestUiThread.java
deleted file mode 100644
index 237c0ec64b..0000000000
--- a/base/test/android/java/src/org/chromium/base/TestUiThread.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 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;
-
-import android.os.Looper;
-
-import org.chromium.base.annotations.CalledByNative;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.annotation.concurrent.ThreadSafe;
-
-/**
- * Set up a thread as the Chromium UI Thread, and run its looper. This is is intended for C++ unit
- * tests (e.g. the net unit tests) that don't run with the UI thread as their main looper, but test
- * code that, on Android, uses UI thread events, so need a running UI thread.
- */
-@ThreadSafe
-public class TestUiThread {
- private static final AtomicBoolean sStarted = new AtomicBoolean(false);
- private static final String TAG = "cr.TestUiThread";
-
- @CalledByNative
- private static void loop() {
- // @{link ThreadUtils#setUiThread(Looper)} can only be called once in a test run, so do this
- // once, and leave it running.
- if (sStarted.getAndSet(true)) return;
-
- final CountDownLatch startLatch = new CountDownLatch(1);
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- Looper.prepare();
- ThreadUtils.setUiThread(Looper.myLooper());
- startLatch.countDown();
- Looper.loop();
- }
-
- }).start();
-
- try {
- startLatch.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "Failed to set UI Thread");
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
deleted file mode 100644
index 1476e9ef4a..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2017 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;
-
-import android.app.Activity;
-import android.app.Application;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.internal.runner.RunnerArgs;
-import android.support.test.internal.runner.TestExecutor;
-import android.support.test.internal.runner.TestLoader;
-import android.support.test.internal.runner.TestRequest;
-import android.support.test.internal.runner.TestRequestBuilder;
-import android.support.test.runner.AndroidJUnitRunner;
-
-import dalvik.system.DexFile;
-
-import org.chromium.base.BuildConfig;
-import org.chromium.base.Log;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.multidex.ChromiumMultiDexInstaller;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.List;
-
-/**
- * A custom AndroidJUnitRunner that supports multidex installer and list out test information.
- *
- * This class is the equivalent of BaseChromiumInstrumentationTestRunner in JUnit3. Please
- * beware that is this not a class runner. It is declared in test apk AndroidManifest.xml
- * <instrumentation>
- *
- * TODO(yolandyan): remove this class after all tests are converted to JUnit4. Use class runner
- * for test listing.
- */
-@MainDex
-public class BaseChromiumAndroidJUnitRunner extends AndroidJUnitRunner {
- private static final String LIST_ALL_TESTS_FLAG =
- "org.chromium.base.test.BaseChromiumAndroidJUnitRunner.TestList";
- private static final String LIST_TESTS_PACKAGE_FLAG =
- "org.chromium.base.test.BaseChromiumAndroidJUnitRunner.TestListPackage";
- /**
- * This flag is supported by AndroidJUnitRunner.
- *
- * See the following page for detail
- * https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html
- */
- private static final String ARGUMENT_TEST_PACKAGE = "package";
-
- /**
- * The following arguments are corresponding to AndroidJUnitRunner command line arguments.
- * `annotation`: run with only the argument annotation
- * `notAnnotation`: run all tests except the ones with argument annotation
- * `log`: run in log only mode, do not execute tests
- *
- * For more detail, please check
- * https://developer.android.com/reference/android/support/test/runner/AndroidJUnitRunner.html
- */
- private static final String ARGUMENT_ANNOTATION = "annotation";
- private static final String ARGUMENT_NOT_ANNOTATION = "notAnnotation";
- private static final String ARGUMENT_LOG_ONLY = "log";
-
- private static final String TAG = "BaseJUnitRunner";
-
- @Override
- public Application newApplication(ClassLoader cl, String className, Context context)
- throws ClassNotFoundException, IllegalAccessException, InstantiationException {
- // The multidex support library doesn't currently support having the test apk be multidex
- // as well as the under-test apk being multidex. If MultiDex.install() is called for both,
- // then re-extraction is triggered every time due to the support library caching only a
- // single timestamp & crc.
- //
- // Attempt to install test apk multidex only if the apk-under-test is not multidex.
- // It will likely continue to be true that the two are mutually exclusive because:
- // * ProGuard enabled =>
- // Under-test apk is single dex.
- // Test apk duplicates under-test classes, so may need multidex.
- // * ProGuard disabled =>
- // Under-test apk might be multidex
- // Test apk does not duplicate classes, so does not need multidex.
- // https://crbug.com/824523
- if (!BuildConfig.IS_MULTIDEX_ENABLED) {
- ChromiumMultiDexInstaller.install(new BaseChromiumRunnerCommon.MultiDexContextWrapper(
- getContext(), getTargetContext()));
- BaseChromiumRunnerCommon.reorderDexPathElements(cl, getContext(), getTargetContext());
- }
- return super.newApplication(cl, className, context);
- }
-
- /**
- * Add TestListInstrumentationRunListener when argument ask the runner to list tests info.
- *
- * The running mechanism when argument has "listAllTests" is equivalent to that of
- * {@link android.support.test.runner.AndroidJUnitRunner#onStart()} except it adds
- * only TestListInstrumentationRunListener to monitor the tests.
- */
- @Override
- public void onStart() {
- Bundle arguments = InstrumentationRegistry.getArguments();
- if (arguments != null && arguments.getString(LIST_ALL_TESTS_FLAG) != null) {
- Log.w(TAG,
- String.format("Runner will list out tests info in JSON without running tests. "
- + "Arguments: %s",
- arguments.toString()));
- listTests(); // Intentionally not calling super.onStart() to avoid additional work.
- } else {
- if (arguments != null && arguments.getString(ARGUMENT_LOG_ONLY) != null) {
- Log.e(TAG,
- String.format("Runner will log the tests without running tests."
- + " If this cause a test run to fail, please report to"
- + " crbug.com/754015. Arguments: %s",
- arguments.toString()));
- }
- super.onStart();
- }
- }
-
- // TODO(yolandyan): Move this to test harness side once this class gets removed
- private void addTestListPackage(Bundle bundle) {
- PackageManager pm = getContext().getPackageManager();
- InstrumentationInfo info;
- try {
- info = pm.getInstrumentationInfo(getComponentName(), PackageManager.GET_META_DATA);
- } catch (NameNotFoundException e) {
- Log.e(TAG, String.format("Could not find component %s", getComponentName()));
- throw new RuntimeException(e);
- }
- Bundle metaDataBundle = info.metaData;
- if (metaDataBundle != null && metaDataBundle.getString(LIST_TESTS_PACKAGE_FLAG) != null) {
- bundle.putString(
- ARGUMENT_TEST_PACKAGE, metaDataBundle.getString(LIST_TESTS_PACKAGE_FLAG));
- }
- }
-
- private void listTests() {
- Bundle results = new Bundle();
- TestListInstrumentationRunListener listener = new TestListInstrumentationRunListener();
- try {
- TestExecutor.Builder executorBuilder = new TestExecutor.Builder(this);
- executorBuilder.addRunListener(listener);
- Bundle junit3Arguments = new Bundle(InstrumentationRegistry.getArguments());
- junit3Arguments.putString(ARGUMENT_NOT_ANNOTATION, "org.junit.runner.RunWith");
- addTestListPackage(junit3Arguments);
- TestRequest listJUnit3TestRequest = createListTestRequest(junit3Arguments);
- results = executorBuilder.build().execute(listJUnit3TestRequest);
-
- Bundle junit4Arguments = new Bundle(InstrumentationRegistry.getArguments());
- junit4Arguments.putString(ARGUMENT_ANNOTATION, "org.junit.runner.RunWith");
- addTestListPackage(junit4Arguments);
-
- // Do not use Log runner from android test support.
- //
- // Test logging and execution skipping is handled by BaseJUnit4ClassRunner,
- // having ARGUMENT_LOG_ONLY in argument bundle here causes AndroidJUnitRunner
- // to use its own log-only class runner instead of BaseJUnit4ClassRunner.
- junit4Arguments.remove(ARGUMENT_LOG_ONLY);
-
- TestRequest listJUnit4TestRequest = createListTestRequest(junit4Arguments);
- results.putAll(executorBuilder.build().execute(listJUnit4TestRequest));
- listener.saveTestsToJson(
- InstrumentationRegistry.getArguments().getString(LIST_ALL_TESTS_FLAG));
- } catch (IOException | RuntimeException e) {
- String msg = "Fatal exception when running tests";
- Log.e(TAG, msg, e);
- // report the exception to instrumentation out
- results.putString(Instrumentation.REPORT_KEY_STREAMRESULT,
- msg + "\n" + Log.getStackTraceString(e));
- }
- finish(Activity.RESULT_OK, results);
- }
-
- private TestRequest createListTestRequest(Bundle arguments) {
- RunnerArgs runnerArgs =
- new RunnerArgs.Builder().fromManifest(this).fromBundle(arguments).build();
- TestRequestBuilder builder = new IncrementalInstallTestRequestBuilder(this, arguments);
- builder.addFromRunnerArgs(runnerArgs);
- builder.addApkToScan(getContext().getPackageCodePath());
- return builder.build();
- }
-
- static boolean shouldListTests(Bundle arguments) {
- return arguments != null && arguments.getString(LIST_ALL_TESTS_FLAG) != null;
- }
-
- /**
- * Wraps TestRequestBuilder to make it work with incremental install.
- */
- private static class IncrementalInstallTestRequestBuilder extends TestRequestBuilder {
- List<String> mExcludedPrefixes = new ArrayList<String>();
- boolean mHasClassList;
-
- public IncrementalInstallTestRequestBuilder(Instrumentation instr, Bundle bundle) {
- super(instr, bundle);
- }
-
- @Override
- public TestRequestBuilder addFromRunnerArgs(RunnerArgs runnerArgs) {
- mExcludedPrefixes.addAll(runnerArgs.notTestPackages);
- return super.addFromRunnerArgs(runnerArgs);
- }
-
- @Override
- public TestRequestBuilder addTestClass(String className) {
- mHasClassList = true;
- return super.addTestClass(className);
- }
-
- @Override
- public TestRequestBuilder addTestMethod(String testClassName, String testMethodName) {
- mHasClassList = true;
- return super.addTestMethod(testClassName, testMethodName);
- }
-
- @Override
- public TestRequest build() {
- // See crbug://841695. TestLoader.isTestClass is incorrectly deciding that
- // InstrumentationTestSuite is a test class.
- removeTestClass("android.test.InstrumentationTestSuite");
- // If a test class was requested, then no need to iterate class loader.
- if (mHasClassList) {
- return super.build();
- }
- maybeScanIncrementalClasspath();
- return super.build();
- }
-
- private void maybeScanIncrementalClasspath() {
- DexFile[] incrementalJars = null;
- try {
- Class<?> bootstrapClass =
- Class.forName("org.chromium.incrementalinstall.BootstrapApplication");
- incrementalJars =
- (DexFile[]) bootstrapClass.getDeclaredField("sIncrementalDexFiles")
- .get(null);
- } catch (Exception e) {
- // Not an incremental apk.
- }
- if (incrementalJars != null) {
- // builder.addApkToScan uses new DexFile(path) under the hood, which on Dalvik OS's
- // assumes that the optimized dex is in the default location (crashes).
- // Perform our own dex file scanning instead as a workaround.
- addTestClasses(incrementalJars, this);
- }
- }
-
- private boolean startsWithAny(String str, List<String> prefixes) {
- for (String prefix : prefixes) {
- if (str.startsWith(prefix)) {
- return true;
- }
- }
- return false;
- }
-
- private void addTestClasses(DexFile[] dexFiles, TestRequestBuilder builder) {
- Log.i(TAG, "Scanning incremental classpath.");
- try {
- Field excludedPackagesField =
- TestRequestBuilder.class.getDeclaredField("DEFAULT_EXCLUDED_PACKAGES");
- excludedPackagesField.setAccessible(true);
- mExcludedPrefixes.addAll(Arrays.asList((String[]) excludedPackagesField.get(null)));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- // Mirror TestRequestBuilder.getClassNamesFromClassPath().
- TestLoader loader = new TestLoader();
- for (DexFile dexFile : dexFiles) {
- Enumeration<String> classNames = dexFile.entries();
- while (classNames.hasMoreElements()) {
- String className = classNames.nextElement();
- if (!className.contains("$") && !startsWithAny(className, mExcludedPrefixes)
- && loader.loadIfTest(className) != null) {
- addTestClass(className);
- }
- }
- }
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java
deleted file mode 100644
index e5eb2731b7..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2017 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;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.support.v4.content.ContextCompat;
-
-import org.chromium.android.support.PackageManagerWrapper;
-import org.chromium.base.Log;
-import org.chromium.base.annotations.MainDex;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.Comparator;
-
-/**
- * Functionality common to the JUnit3 and JUnit4 runners.
- */
-@MainDex
-class BaseChromiumRunnerCommon {
- private static final String TAG = "base_test";
-
- /**
- * A ContextWrapper that allows multidex test APKs to extract secondary dexes into
- * the APK under test's data directory.
- */
- @MainDex
- static class MultiDexContextWrapper extends ContextWrapper {
- private Context mAppContext;
-
- MultiDexContextWrapper(Context instrContext, Context appContext) {
- super(instrContext);
- mAppContext = appContext;
- }
-
- @Override
- public File getFilesDir() {
- return mAppContext.getFilesDir();
- }
-
- @Override
- public SharedPreferences getSharedPreferences(String name, int mode) {
- return mAppContext.getSharedPreferences(name, mode);
- }
-
- @Override
- public PackageManager getPackageManager() {
- return new PackageManagerWrapper(super.getPackageManager()) {
- @Override
- public ApplicationInfo getApplicationInfo(String packageName, int flags) {
- try {
- ApplicationInfo ai = super.getApplicationInfo(packageName, flags);
- if (packageName.equals(getPackageName())) {
- File dataDir = new File(
- ContextCompat.getCodeCacheDir(mAppContext), "test-multidex");
- if (!dataDir.exists() && !dataDir.mkdirs()) {
- throw new IOException(String.format(
- "Unable to create test multidex directory \"%s\"",
- dataDir.getPath()));
- }
- ai.dataDir = dataDir.getPath();
- }
- return ai;
- } catch (Exception e) {
- Log.e(TAG, "Failed to get application info for %s", packageName, e);
- }
- return null;
- }
- };
- }
- }
-
- /**
- * Ensure all test dex entries precede app dex entries.
- *
- * @param cl ClassLoader to modify. Assumed to be a derivative of
- * {@link dalvik.system.BaseDexClassLoader}. If this isn't
- * the case, reordering will fail.
- */
- static void reorderDexPathElements(ClassLoader cl, Context context, Context targetContext) {
- try {
- Log.i(TAG,
- "Reordering dex files. If you're building a multidex test APK and see a "
- + "class resolving to an unexpected implementation, this may be why.");
- Field pathListField = findField(cl, "pathList");
- Object dexPathList = pathListField.get(cl);
- Field dexElementsField = findField(dexPathList, "dexElements");
- Object[] dexElementsList = (Object[]) dexElementsField.get(dexPathList);
- Arrays.sort(dexElementsList,
- new DexListReorderingComparator(
- context.getPackageName(), targetContext.getPackageName()));
- dexElementsField.set(dexPathList, dexElementsList);
- } catch (Exception e) {
- Log.e(TAG, "Failed to reorder dex elements for testing.", e);
- }
- }
-
- /**
- * Comparator for sorting dex list entries.
- *
- * Using this to sort a list of dex list entries will result in the following order:
- * - Strings that contain neither the test package nor the app package in lexicographical
- * order.
- * - Strings that contain the test package in lexicographical order.
- * - Strings that contain the app package but not the test package in lexicographical order.
- */
- private static class DexListReorderingComparator implements Comparator<Object>, Serializable {
- private String mTestPackage;
- private String mAppPackage;
-
- public DexListReorderingComparator(String testPackage, String appPackage) {
- mTestPackage = testPackage;
- mAppPackage = appPackage;
- }
-
- @Override
- public int compare(Object o1, Object o2) {
- String s1 = o1.toString();
- String s2 = o2.toString();
- if (s1.contains(mTestPackage)) {
- if (!s2.contains(mTestPackage)) {
- if (s2.contains(mAppPackage)) {
- return -1;
- } else {
- return 1;
- }
- }
- } else if (s1.contains(mAppPackage)) {
- if (s2.contains(mTestPackage)) {
- return 1;
- } else if (!s2.contains(mAppPackage)) {
- return 1;
- }
- } else if (s2.contains(mTestPackage) || s2.contains(mAppPackage)) {
- return -1;
- }
- return s1.compareTo(s2);
- }
- }
-
- private static Field findField(Object instance, String name) throws NoSuchFieldException {
- for (Class<?> clazz = instance.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
- try {
- Field f = clazz.getDeclaredField(name);
- f.setAccessible(true);
- return f;
- } catch (NoSuchFieldException e) {
- }
- }
- throw new NoSuchFieldException(
- "Unable to find field " + name + " in " + instance.getClass());
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
deleted file mode 100644
index 49f27b5089..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright 2016 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;
-
-import static org.chromium.base.test.BaseChromiumAndroidJUnitRunner.shouldListTests;
-
-import android.content.Context;
-import android.support.annotation.CallSuper;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
-import android.support.test.internal.util.AndroidRunnerParams;
-
-import org.junit.rules.MethodRule;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.Statement;
-
-import org.chromium.base.CommandLine;
-import org.chromium.base.ContextUtils;
-import org.chromium.base.Log;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
-import org.chromium.base.test.params.MethodParamAnnotationRule;
-import org.chromium.base.test.util.DisableIfSkipCheck;
-import org.chromium.base.test.util.MinAndroidSdkLevelSkipCheck;
-import org.chromium.base.test.util.RestrictionSkipCheck;
-import org.chromium.base.test.util.SkipCheck;
-
-import java.io.File;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A custom runner for JUnit4 tests that checks requirements to conditionally ignore tests.
- *
- * This ClassRunner imports from AndroidJUnit4ClassRunner which is a hidden but accessible
- * class. The reason is that default JUnit4 runner for Android is a final class,
- * AndroidJUnit4. We need to extends an inheritable class to change {@link #runChild}
- * and {@link #isIgnored} to add SkipChecks and PreTesthook.
- */
-public class BaseJUnit4ClassRunner extends AndroidJUnit4ClassRunner {
- private static final String TAG = "BaseJUnit4ClassRunnr";
-
- private static final String EXTRA_TRACE_FILE =
- "org.chromium.base.test.BaseJUnit4ClassRunner.TraceFile";
-
- /**
- * Create a BaseJUnit4ClassRunner to run {@code klass} and initialize values.
- *
- * To add more SkipCheck or PreTestHook in subclass, create Lists of checks and hooks,
- * pass them into the super constructors. If you want make a subclass extendable by other
- * class runners, you also have to create a constructor similar to the following one that
- * merges default checks or hooks with this checks and hooks passed in by constructor.
- *
- * <pre>
- * <code>
- * e.g.
- * public ChildRunner extends BaseJUnit4ClassRunner {
- * public ChildRunner(final Class<?> klass) {
- * throws InitializationError {
- * this(klass, Collections.emptyList(), Collections.emptyList(),
- * Collections.emptyList());
- * }
- *
- * public ChildRunner(
- * final Class<?> klass, List<SkipCheck> checks, List<PreTestHook> hook,
- * List<TestRule> rules) { throws InitializationError { super(klass, mergeList( checks,
- * getSkipChecks()), mergeList(hooks, getPreTestHooks()));
- * }
- *
- * public List<SkipCheck> getSkipChecks() {...}
- *
- * public List<PreTestHook> getPreTestHooks() {...}
- * </code>
- * </pre>
- *
- * @throws InitializationError if the test class malformed
- */
- public BaseJUnit4ClassRunner(final Class<?> klass) throws InitializationError {
- super(klass,
- new AndroidRunnerParams(InstrumentationRegistry.getInstrumentation(),
- InstrumentationRegistry.getArguments(), false, 0L, false));
-
- String traceOutput = InstrumentationRegistry.getArguments().getString(EXTRA_TRACE_FILE);
-
- if (traceOutput != null) {
- File traceOutputFile = new File(traceOutput);
- File traceOutputDir = traceOutputFile.getParentFile();
-
- if (traceOutputDir != null) {
- if (traceOutputDir.exists() || traceOutputDir.mkdirs()) {
- TestTraceEvent.enable(traceOutputFile);
- }
- }
- }
- }
-
- /**
- * Merge two List into a new ArrayList.
- *
- * Used to merge the default SkipChecks/PreTestHooks with the subclasses's
- * SkipChecks/PreTestHooks.
- */
- private static <T> List<T> mergeList(List<T> listA, List<T> listB) {
- List<T> l = new ArrayList<>(listA);
- l.addAll(listB);
- return l;
- }
-
- @SafeVarargs
- protected static <T> List<T> addToList(List<T> list, T... additionalEntries) {
- return mergeList(list, Arrays.asList(additionalEntries));
- }
-
- @Override
- protected void collectInitializationErrors(List<Throwable> errors) {
- super.collectInitializationErrors(errors);
- // Log any initialization errors to help debugging, as the host-side test runner can get
- // confused by the thrown exception.
- if (!errors.isEmpty()) {
- Log.e(TAG, "Initialization errors in %s: %s", getTestClass().getName(), errors);
- }
- }
-
- /**
- * Override this method to return a list of {@link SkipCheck}s}.
- *
- * Additional hooks can be added to the list using {@link #addToList}:
- * {@code return addToList(super.getSkipChecks(), check1, check2);}
- */
- @CallSuper
- protected List<SkipCheck> getSkipChecks() {
- return Arrays.asList(new RestrictionSkipCheck(InstrumentationRegistry.getTargetContext()),
- new MinAndroidSdkLevelSkipCheck(), new DisableIfSkipCheck());
- }
-
- /**
- * Override this method to return a list of {@link PreTestHook}s.
- *
- * Additional hooks can be added to the list using {@link #addToList}:
- * {@code return addToList(super.getPreTestHooks(), hook1, hook2);}
- * TODO(bauerb): Migrate PreTestHook to TestRule.
- */
- @CallSuper
- protected List<PreTestHook> getPreTestHooks() {
- return Collections.emptyList();
- }
-
- /**
- * Override this method to return a list of method rules that should be applied to all tests
- * run with this test runner.
- *
- * Additional rules can be added to the list using {@link #addToList}:
- * {@code return addToList(super.getDefaultMethodRules(), rule1, rule2);}
- */
- @CallSuper
- protected List<MethodRule> getDefaultMethodRules() {
- return Collections.singletonList(new MethodParamAnnotationRule());
- }
-
- /**
- * Override this method to return a list of rules that should be applied to all tests run with
- * this test runner.
- *
- * Additional rules can be added to the list using {@link #addToList}:
- * {@code return addToList(super.getDefaultTestRules(), rule1, rule2);}
- */
- @CallSuper
- protected List<TestRule> getDefaultTestRules() {
- return Collections.emptyList();
- }
-
- /**
- * Evaluate whether a FrameworkMethod is ignored based on {@code SkipCheck}s.
- */
- @Override
- protected boolean isIgnored(FrameworkMethod method) {
- return super.isIgnored(method) || shouldSkip(method);
- }
-
- @Override
- protected List<MethodRule> rules(Object target) {
- List<MethodRule> declaredRules = super.rules(target);
- List<MethodRule> defaultRules = getDefaultMethodRules();
- return mergeList(defaultRules, declaredRules);
- }
-
- @Override
- protected final List<TestRule> getTestRules(Object target) {
- List<TestRule> declaredRules = super.getTestRules(target);
- List<TestRule> defaultRules = getDefaultTestRules();
- return mergeList(declaredRules, defaultRules);
- }
-
- /**
- * Run test with or without execution based on bundle arguments.
- */
- @Override
- public void run(RunNotifier notifier) {
- ContextUtils.initApplicationContext(
- InstrumentationRegistry.getTargetContext().getApplicationContext());
- if (shouldListTests(InstrumentationRegistry.getArguments())) {
- for (Description child : getDescription().getChildren()) {
- notifier.fireTestStarted(child);
- notifier.fireTestFinished(child);
- }
- return;
- }
-
- if (!CommandLine.isInitialized()) {
- initCommandLineForTest();
- }
- super.run(notifier);
- }
-
- /**
- * Override this method to change how test class runner initiate commandline flags
- */
- protected void initCommandLineForTest() {
- CommandLine.init(null);
- }
-
- @Override
- protected void runChild(FrameworkMethod method, RunNotifier notifier) {
- String testName = method.getName();
- TestTraceEvent.begin(testName);
-
- runPreTestHooks(method);
-
- super.runChild(method, notifier);
-
- TestTraceEvent.end(testName);
-
- // A new instance of BaseJUnit4ClassRunner is created on the device
- // for each new method, so runChild will only be called once. Thus, we
- // can disable tracing, and dump the output, once we get here.
- TestTraceEvent.disable();
- }
-
- /**
- * Loop through all the {@code PreTestHook}s to run them
- */
- private void runPreTestHooks(FrameworkMethod frameworkMethod) {
- Method testMethod = frameworkMethod.getMethod();
- Context targetContext = InstrumentationRegistry.getTargetContext();
- for (PreTestHook hook : getPreTestHooks()) {
- hook.run(targetContext, testMethod);
- }
- }
-
- /**
- * Loop through all the {@code SkipCheck}s to confirm whether a test should be ignored
- */
- private boolean shouldSkip(FrameworkMethod method) {
- for (SkipCheck s : getSkipChecks()) {
- if (s.shouldSkip(method)) {
- return true;
- }
- }
- return false;
- }
-
- /*
- * Overriding this method to take screenshot of failure before tear down functions are run.
- */
- @Override
- protected Statement withAfters(FrameworkMethod method, Object test, Statement base) {
- return super.withAfters(method, test, new ScreenshotOnFailureStatement(base));
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
deleted file mode 100644
index a80e0cc4a0..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2015 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;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.SystemClock;
-
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-
-import org.chromium.base.Log;
-import org.chromium.base.test.util.SkipCheck;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A test result that can skip tests.
- */
-public class BaseTestResult extends TestResult {
- private static final String TAG = "base_test";
-
- private static final int SLEEP_INTERVAL_MS = 50;
- private static final int WAIT_DURATION_MS = 5000;
-
- private final Instrumentation mInstrumentation;
- private final List<SkipCheck> mSkipChecks;
- private final List<PreTestHook> mPreTestHooks;
-
- /**
- * Creates an instance of BaseTestResult.
- */
- public BaseTestResult(Instrumentation instrumentation) {
- mSkipChecks = new ArrayList<>();
- mPreTestHooks = new ArrayList<>();
- mInstrumentation = instrumentation;
- }
-
- /**
- * An interface for classes that have some code to run before a test. They run after
- * {@link SkipCheck}s. Provides access to the test method (and the annotations defined for it)
- * and the instrumentation context.
- */
- public interface PreTestHook {
- /**
- * @param targetContext the instrumentation context that will be used during the test.
- * @param testMethod the test method to be run.
- */
- public void run(Context targetContext, Method testMethod);
- }
-
- /**
- * Adds a check for whether a test should run.
- *
- * @param skipCheck The check to add.
- */
- public void addSkipCheck(SkipCheck skipCheck) {
- mSkipChecks.add(skipCheck);
- }
-
- /**
- * Adds hooks that will be executed before each test that runs.
- *
- * @param preTestHook The hook to add.
- */
- public void addPreTestHook(PreTestHook preTestHook) {
- mPreTestHooks.add(preTestHook);
- }
-
- protected boolean shouldSkip(TestCase test) {
- for (SkipCheck s : mSkipChecks) {
- if (s.shouldSkip(test)) return true;
- }
- return false;
- }
-
- private void runPreTestHooks(TestCase test) {
- try {
- Method testMethod = test.getClass().getMethod(test.getName());
- Context targetContext = getTargetContext();
-
- for (PreTestHook hook : mPreTestHooks) {
- hook.run(targetContext, testMethod);
- }
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "Unable to run pre test hooks.", e);
- }
- }
-
- @Override
- protected void run(TestCase test) {
- runPreTestHooks(test);
-
- if (shouldSkip(test)) {
- startTest(test);
-
- Bundle skipResult = new Bundle();
- skipResult.putString("class", test.getClass().getName());
- skipResult.putString("test", test.getName());
- skipResult.putBoolean("test_skipped", true);
- mInstrumentation.sendStatus(0, skipResult);
-
- endTest(test);
- } else {
- super.run(test);
- }
- }
-
- /**
- * Gets the target context.
- *
- * On older versions of Android, getTargetContext() may initially return null, so we have to
- * wait for it to become available.
- *
- * @return The target {@link Context} if available; null otherwise.
- */
- public Context getTargetContext() {
- Context targetContext = mInstrumentation.getTargetContext();
- try {
- long startTime = SystemClock.uptimeMillis();
- // TODO(jbudorick): Convert this to CriteriaHelper once that moves to base/.
- while (targetContext == null
- && SystemClock.uptimeMillis() - startTime < WAIT_DURATION_MS) {
- Thread.sleep(SLEEP_INTERVAL_MS);
- targetContext = mInstrumentation.getTargetContext();
- }
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted while attempting to initialize the command line.");
- }
- return targetContext;
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java b/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
deleted file mode 100644
index 397e8abf13..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2017 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;
-
-import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
-
-import org.junit.runners.model.Statement;
-
-import org.chromium.base.Log;
-
-import java.io.File;
-
-/**
- * Statement that captures screenshots if |base| statement fails.
- *
- * If --screenshot-path commandline flag is given, this |Statement|
- * will save a screenshot to the specified path in the case of a test failure.
- */
-public class ScreenshotOnFailureStatement extends Statement {
- private static final String TAG = "ScreenshotOnFail";
-
- private static final String EXTRA_SCREENSHOT_FILE =
- "org.chromium.base.test.ScreenshotOnFailureStatement.ScreenshotFile";
-
- private final Statement mBase;
-
- public ScreenshotOnFailureStatement(final Statement base) {
- mBase = base;
- }
-
- @Override
- public void evaluate() throws Throwable {
- try {
- mBase.evaluate();
- } catch (Throwable e) {
- takeScreenshot();
- throw e;
- }
- }
-
- private void takeScreenshot() {
- String screenshotFilePath =
- InstrumentationRegistry.getArguments().getString(EXTRA_SCREENSHOT_FILE);
- if (screenshotFilePath == null) {
- Log.d(TAG,
- String.format("Did not save screenshot of failure. Must specify %s "
- + "instrumentation argument to enable this feature.",
- EXTRA_SCREENSHOT_FILE));
- return;
- }
-
- UiDevice uiDevice = null;
- try {
- uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
- } catch (RuntimeException ex) {
- Log.d(TAG, "Failed to initialize UiDevice", ex);
- return;
- }
-
- File screenshotFile = new File(screenshotFilePath);
- File screenshotDir = screenshotFile.getParentFile();
- if (screenshotDir == null) {
- Log.d(TAG,
- String.format(
- "Failed to create parent directory for %s. Can't save screenshot.",
- screenshotFile));
- return;
- }
- if (!screenshotDir.exists()) {
- if (!screenshotDir.mkdirs()) {
- Log.d(TAG,
- String.format(
- "Failed to create %s. Can't save screenshot.", screenshotDir));
- return;
- }
- }
- Log.d(TAG, String.format("Saving screenshot of test failure, %s", screenshotFile));
- uiDevice.takeScreenshot(screenshotFile);
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/SetUpStatement.java b/base/test/android/javatests/src/org/chromium/base/test/SetUpStatement.java
deleted file mode 100644
index 30ac2b6c5c..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/SetUpStatement.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 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;
-
-import org.junit.rules.TestRule;
-import org.junit.runners.model.Statement;
-
-/**
- * Custom Statement for SetUpTestRules.
- *
- * Calls {@link SetUpTestRule#setUp} before evaluating {@link SetUpTestRule#base} if
- * {@link SetUpTestRule#shouldSetUp} is true
- */
-public class SetUpStatement extends Statement {
- private final Statement mBase;
- private final SetUpTestRule<? extends TestRule> mSetUpTestRule;
- private final boolean mShouldSetUp;
-
- public SetUpStatement(
- final Statement base, SetUpTestRule<? extends TestRule> callback, boolean shouldSetUp) {
- mBase = base;
- mSetUpTestRule = callback;
- mShouldSetUp = shouldSetUp;
- }
-
- @Override
- public void evaluate() throws Throwable {
- if (mShouldSetUp) {
- mSetUpTestRule.setUp();
- }
- mBase.evaluate();
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/SetUpTestRule.java b/base/test/android/javatests/src/org/chromium/base/test/SetUpTestRule.java
deleted file mode 100644
index 57dd8db552..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/SetUpTestRule.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 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;
-
-import org.junit.rules.TestRule;
-
-/**
- * An interface for TestRules that can be configured to automatically run set-up logic prior
- * to &#064;Before.
- *
- * TestRules that implement this interface should return a {@link SetUpStatement} from their {@link
- * TestRule#apply} method
- *
- * @param <T> TestRule type that implements this SetUpTestRule
- */
-public interface SetUpTestRule<T extends TestRule> {
- /**
- * Set whether the TestRule should run setUp automatically.
- *
- * So TestRule can be declared in test like this:
- * <code>
- * &#064;Rule TestRule mRule = new MySetUpTestRule().shouldSetUp(true);
- * </code>
- *
- * @return itself to chain up the calls for convenience
- */
- T shouldSetUp(boolean runSetUp);
-
- /**
- * Specify setUp action in this method
- */
- void setUp();
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java b/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
deleted file mode 100644
index ae91b44cf3..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2017 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;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Bundle;
-
-import org.chromium.base.process_launcher.ChildProcessConnection;
-
-/** An implementation of ChildProcessConnection that does not connect to a real service. */
-public class TestChildProcessConnection extends ChildProcessConnection {
- private static class MockChildServiceConnection
- implements ChildProcessConnection.ChildServiceConnection {
- private boolean mBound;
-
- @Override
- public boolean bind() {
- mBound = true;
- return true;
- }
-
- @Override
- public void unbind() {
- mBound = false;
- }
-
- @Override
- public boolean isBound() {
- return mBound;
- }
- }
-
- private int mPid;
- private boolean mConnected;
- private ServiceCallback mServiceCallback;
-
- /**
- * Creates a mock binding corresponding to real ManagedChildProcessConnection after the
- * connection is established: with initial binding bound and no strong binding.
- */
- public TestChildProcessConnection(ComponentName serviceName, boolean bindToCaller,
- boolean bindAsExternalService, Bundle serviceBundle) {
- super(null /* context */, serviceName, bindToCaller, bindAsExternalService, serviceBundle,
- new ChildServiceConnectionFactory() {
- @Override
- public ChildServiceConnection createConnection(Intent bindIntent, int bindFlags,
- ChildServiceConnectionDelegate delegate) {
- return new MockChildServiceConnection();
- }
- });
- }
-
- public void setPid(int pid) {
- mPid = pid;
- }
-
- @Override
- public int getPid() {
- return mPid;
- }
-
- // We don't have a real service so we have to mock the connection status.
- @Override
- public void start(boolean useStrongBinding, ServiceCallback serviceCallback) {
- super.start(useStrongBinding, serviceCallback);
- mConnected = true;
- mServiceCallback = serviceCallback;
- }
-
- @Override
- public void stop() {
- super.stop();
- mConnected = false;
- }
-
- @Override
- public boolean isConnected() {
- return mConnected;
- }
-
- public ServiceCallback getServiceCallback() {
- return mServiceCallback;
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java b/base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java
deleted file mode 100644
index 8cde57003c..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2017 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;
-
-import android.support.test.internal.runner.listener.InstrumentationRunListener;
-
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.junit.runner.Description;
-
-import org.chromium.base.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A RunListener that list out all the test information into a json file.
- */
-public class TestListInstrumentationRunListener extends InstrumentationRunListener {
- private static final String TAG = "TestListRunListener";
- private static final Set<String> SKIP_METHODS = new HashSet<>(
- Arrays.asList(new String[] {"toString", "hashCode", "annotationType", "equals"}));
-
- private final Map<Class<?>, JSONObject> mTestClassJsonMap = new HashMap<>();
-
- /**
- * Store the test method description to a Map at the beginning of a test run.
- */
- @Override
- public void testStarted(Description desc) throws Exception {
- if (mTestClassJsonMap.containsKey(desc.getTestClass())) {
- ((JSONArray) mTestClassJsonMap.get(desc.getTestClass()).get("methods"))
- .put(getTestMethodJSON(desc));
- } else {
- Class<?> testClass = desc.getTestClass();
- mTestClassJsonMap.put(desc.getTestClass(), new JSONObject()
- .put("class", testClass.getName())
- .put("superclass", testClass.getSuperclass().getName())
- .put("annotations",
- getAnnotationJSON(Arrays.asList(testClass.getAnnotations())))
- .put("methods", new JSONArray().put(getTestMethodJSON(desc))));
- }
- }
-
- /**
- * Create a JSONArray with all the test class JSONObjects and save it to listed output path.
- */
- public void saveTestsToJson(String outputPath) throws IOException {
- Writer writer = null;
- File file = new File(outputPath);
- try {
- writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
- JSONArray allTestClassesJSON = new JSONArray(mTestClassJsonMap.values());
- writer.write(allTestClassesJSON.toString());
- } catch (IOException e) {
- Log.e(TAG, "failed to write json to file", e);
- throw e;
- } finally {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException e) {
- // Intentionally ignore IOException when closing writer
- }
- }
- }
- }
-
- /**
- * Return a JSONOject that represent a Description of a method".
- */
- static JSONObject getTestMethodJSON(Description desc) throws Exception {
- return new JSONObject()
- .put("method", desc.getMethodName())
- .put("annotations", getAnnotationJSON(desc.getAnnotations()));
- }
-
- /**
- * Create a JSONObject that represent a collection of anntations.
- *
- * For example, for the following group of annotations for ExampleClass
- * <code>
- * @A
- * @B(message = "hello", level = 3)
- * public class ExampleClass() {}
- * </code>
- *
- * This method would return a JSONObject as such:
- * <code>
- * {
- * "A": {},
- * "B": {
- * "message": "hello",
- * "level": "3"
- * }
- * }
- * </code>
- *
- * The method accomplish this by though through each annotation and reflectively call the
- * annotation's method to get the element value, with exceptions to methods like "equals()"
- * or "hashCode".
- */
- static JSONObject getAnnotationJSON(Collection<Annotation> annotations)
- throws Exception {
- JSONObject annotationsJsons = new JSONObject();
- for (Annotation a : annotations) {
- JSONObject elementJsonObject = new JSONObject();
- for (Method method : a.annotationType().getMethods()) {
- if (SKIP_METHODS.contains(method.getName())) {
- continue;
- }
- try {
- Object value = method.invoke(a);
- if (value == null) {
- elementJsonObject.put(method.getName(), null);
- } else {
- elementJsonObject.put(method.getName(),
- value.getClass().isArray()
- ? new JSONArray(Arrays.asList((Object[]) value))
- : value.toString());
- }
- } catch (IllegalArgumentException e) {
- }
- }
- annotationsJsons.put(a.annotationType().getSimpleName(), elementJsonObject);
- }
- return annotationsJsons;
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java b/base/test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java
deleted file mode 100644
index 5e0f6b31f1..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2017 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;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import org.chromium.base.Log;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-/**
- * TestTraceEvent is a modified version of TraceEvent, intended for tracing test runs.
- */
-public class TestTraceEvent {
- private static final String TAG = "TestTraceEvent";
-
- /** The event types understood by the trace scripts. */
- private enum EventType {
- BEGIN("B"),
- END("E"),
- INSTANT("I");
-
- private final String mTypeStr;
-
- EventType(String typeStr) {
- mTypeStr = typeStr;
- }
-
- @Override
- public String toString() {
- return mTypeStr;
- }
- }
-
- // Locks internal fields.
- private static final Object sLock = new Object();
-
- private static File sOutputFile;
-
- private static boolean sEnabled;
-
- // A list of trace event strings.
- private static JSONArray sTraceStrings;
-
- /**
- * Enable tracing, and set a specific output file. If tracing was previously enabled and
- * disabled, that data is cleared.
- *
- * @param file Which file to append the trace data to.
- */
- public static void enable(File outputFile) {
- synchronized (sLock) {
- if (sEnabled) return;
-
- sEnabled = true;
- sOutputFile = outputFile;
- sTraceStrings = new JSONArray();
- }
- }
-
- /**
- * Disabling of tracing will dump trace data to the system log.
- */
- public static void disable() {
- synchronized (sLock) {
- if (!sEnabled) return;
-
- sEnabled = false;
- dumpTraceOutput();
- sTraceStrings = null;
- }
- }
-
- /**
- * @return True if tracing is enabled, false otherwise.
- */
- public static boolean isEnabled() {
- synchronized (sLock) {
- return sEnabled;
- }
- }
-
- /**
- * Record an "instant" trace event. E.g. "screen update happened".
- */
- public static void instant(String name) {
- synchronized (sLock) {
- if (!sEnabled) return;
-
- saveTraceString(name, name.hashCode(), EventType.INSTANT);
- }
- }
-
- /**
- * Record an "begin" trace event. Begin trace events should have a matching end event (recorded
- * by calling {@link #end(String)}).
- */
- public static void begin(String name) {
- synchronized (sLock) {
- if (!sEnabled) return;
-
- saveTraceString(name, name.hashCode(), EventType.BEGIN);
- }
- }
-
- /**
- * Record an "end" trace event, to match a begin event (recorded by calling {@link
- * #begin(String)}). The time delta between begin and end is usually interesting to graph code.
- */
- public static void end(String name) {
- synchronized (sLock) {
- if (!sEnabled) return;
-
- saveTraceString(name, name.hashCode(), EventType.END);
- }
- }
-
- /**
- * Save a trace event as a JSON dict.
- *
- * @param name The trace data.
- * @param id An identifier for the event, to be saved as the thread ID.
- * @param type the type of trace event (B, E, I).
- */
- private static void saveTraceString(String name, long id, EventType type) {
- // We use System.currentTimeMillis() because it agrees with the value of
- // the $EPOCHREALTIME environment variable. The Python test runner code
- // uses that variable to synchronize timing.
- long timeMicroseconds = System.currentTimeMillis() * 1000;
-
- try {
- JSONObject traceObj = new JSONObject();
- traceObj.put("cat", "Java");
- traceObj.put("ts", timeMicroseconds);
- traceObj.put("ph", type);
- traceObj.put("name", name);
- traceObj.put("tid", id);
-
- sTraceStrings.put(traceObj);
- } catch (JSONException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Dump all tracing data we have saved up to the log.
- * Output as JSON for parsing convenience.
- */
- private static void dumpTraceOutput() {
- try {
- PrintStream stream = new PrintStream(new FileOutputStream(sOutputFile, true));
- try {
- stream.print(sTraceStrings);
- } finally {
- if (stream != null) stream.close();
- }
- } catch (FileNotFoundException ex) {
- Log.e(TAG, "Unable to dump trace data to output file.");
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java b/base/test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java
deleted file mode 100644
index c0dcd469d2..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException;
-
-import java.util.List;
-
-/**
- * Class runner delegate that extends BaseJUnit4ClassRunner
- */
-public final class BaseJUnit4RunnerDelegate
- extends BaseJUnit4ClassRunner implements ParameterizedRunnerDelegate {
- private ParameterizedRunnerDelegateCommon mDelegateCommon;
-
- public BaseJUnit4RunnerDelegate(Class<?> klass,
- ParameterizedRunnerDelegateCommon delegateCommon) throws InitializationError {
- super(klass);
- mDelegateCommon = delegateCommon;
- }
-
- @Override
- public void collectInitializationErrors(List<Throwable> errors) {
- ParameterizedRunnerDelegateCommon.collectInitializationErrors(errors);
- }
-
- @Override
- public List<FrameworkMethod> computeTestMethods() {
- return mDelegateCommon.computeTestMethods();
- }
-
- @Override
- public Object createTest() throws ParameterizedTestInstantiationException {
- return mDelegateCommon.createTest();
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java b/base/test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java
deleted file mode 100644
index 7c948bb141..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-
-import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException;
-
-import java.util.List;
-
-/**
- * Parameterized class runner delegate that extends BlockJUnit4ClassRunner
- */
-public final class BlockJUnit4RunnerDelegate
- extends BlockJUnit4ClassRunner implements ParameterizedRunnerDelegate {
- private ParameterizedRunnerDelegateCommon mDelegateCommon;
-
- public BlockJUnit4RunnerDelegate(Class<?> klass,
- ParameterizedRunnerDelegateCommon delegateCommon) throws InitializationError {
- super(klass);
- mDelegateCommon = delegateCommon;
- }
-
- @Override
- public void collectInitializationErrors(List<Throwable> errors) {
- ParameterizedRunnerDelegateCommon.collectInitializationErrors(errors);
- }
-
- @Override
- public List<FrameworkMethod> computeTestMethods() {
- return mDelegateCommon.computeTestMethods();
- }
-
- @Override
- public Object createTest() throws ParameterizedTestInstantiationException {
- return mDelegateCommon.createTest();
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/MethodParamAnnotationRule.java b/base/test/android/javatests/src/org/chromium/base/test/params/MethodParamAnnotationRule.java
deleted file mode 100644
index 2986b96c08..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/MethodParamAnnotationRule.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.runners.model.Statement;
-
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterAfter;
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Processes {@link UseMethodParameterBefore} and {@link UseMethodParameterAfter} annotations to run
- * the corresponding methods. To use, add an instance to the test class and annotate it with
- * {@code @}{@link org.junit.Rule Rule}.
- */
-public class MethodParamAnnotationRule extends MethodParamRule {
- @Override
- protected Statement applyParameterAndValues(final Statement base, Object target,
- Class<? extends ParameterProvider> parameterProvider, List<Object> values) {
- final List<Method> beforeMethods = new ArrayList<>();
- final List<Method> afterMethods = new ArrayList<>();
- for (Method m : target.getClass().getDeclaredMethods()) {
- if (!m.getReturnType().equals(Void.TYPE)) continue;
- if (!Modifier.isPublic(m.getModifiers())) continue;
-
- UseMethodParameterBefore beforeAnnotation =
- m.getAnnotation(UseMethodParameterBefore.class);
- if (beforeAnnotation != null && beforeAnnotation.value().equals(parameterProvider)) {
- beforeMethods.add(m);
- }
-
- UseMethodParameterAfter afterAnnotation =
- m.getAnnotation(UseMethodParameterAfter.class);
- if (afterAnnotation != null && afterAnnotation.value().equals(parameterProvider)) {
- afterMethods.add(m);
- }
- }
-
- if (beforeMethods.isEmpty() && afterMethods.isEmpty()) return base;
-
- return new Statement() {
- @Override
- public void evaluate() throws Throwable {
- for (Method m : beforeMethods) {
- m.invoke(target, values.toArray());
- }
-
- base.evaluate();
-
- for (Method m : afterMethods) {
- m.invoke(target, values.toArray());
- }
- }
- };
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/MethodParamRule.java b/base/test/android/javatests/src/org/chromium/base/test/params/MethodParamRule.java
deleted file mode 100644
index 440831af2f..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/MethodParamRule.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.rules.MethodRule;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.Statement;
-
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
-
-import java.util.List;
-
-/**
- * Abstract base class for rules that are applied to test methods using
- * {@link org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter method parameters}.
- */
-public abstract class MethodParamRule implements MethodRule {
- @Override
- public Statement apply(final Statement base, FrameworkMethod method, Object target) {
- UseMethodParameter useParameterProvider = method.getAnnotation(UseMethodParameter.class);
- if (useParameterProvider == null) return base;
- Class<? extends ParameterProvider> parameterProvider = useParameterProvider.value();
-
- if (!(method instanceof ParameterizedFrameworkMethod)) return base;
- ParameterSet parameters = ((ParameterizedFrameworkMethod) method).getParameterSet();
- List<Object> values = parameters.getValues();
-
- return applyParameterAndValues(base, target, parameterProvider, values);
- }
-
- protected abstract Statement applyParameterAndValues(final Statement base, Object target,
- Class<? extends ParameterProvider> parameterProvider, List<Object> values);
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java
deleted file mode 100644
index 79183693ec..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2017 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.params;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotations for Parameterized Tests
- */
-public class ParameterAnnotations {
- /**
- * Annotation for test methods to indicate associated {@link ParameterProvider}.
- * Note: the class referred to must be public and have a public default constructor.
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- public @interface UseMethodParameter {
- Class<? extends ParameterProvider> value();
- }
-
- /**
- * Annotation for methods that should be called before running a test with method parameters.
- *
- * In order to use this, add a {@link MethodParamAnnotationRule} annotated with
- * {@code @}{@link org.junit.Rule Rule} to your test class.
- * @see ParameterProvider
- * @see UseMethodParameterAfter
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- public @interface UseMethodParameterBefore {
- Class<? extends ParameterProvider> value();
- }
-
- /**
- * Annotation for methods that should be called after running a test with method parameters.
- *
- * In order to use this, add a {@link MethodParamAnnotationRule} annotated with
- * {@code @}{@link org.junit.Rule Rule} to your test class.
- * @see ParameterProvider
- * @see UseMethodParameterBefore
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- public @interface UseMethodParameterAfter {
- Class<? extends ParameterProvider> value();
- }
-
- /**
- * Annotation for static field of a `List<ParameterSet>` for entire test class
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.FIELD)
- public @interface ClassParameter {}
-
- /**
- * Annotation for static field of a `List<ParameterSet>` of TestRule
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.FIELD)
- public @interface RuleParameter {}
-
- /**
- * Annotation for test class, it specifies which ParameterizeRunnerDelegate to use.
- *
- * The default ParameterizedRunnerDelegate is BaseJUnit4RunnerDelegate.class
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @interface UseRunnerDelegate {
- Class<? extends ParameterizedRunnerDelegate> value();
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java
deleted file mode 100644
index 1cdb576b05..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.Assert;
-
-import java.io.File;
-import java.net.URI;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Callable;
-
-/**
- * A set of parameters for one *SINGLE* test method or test class constructor.
- *
- * For example, <code>new ParameterSet().value("a", "b")</code> is intended for
- * a test method/constructor that takes in two string as arguments.
- * <code>public void testSimple(String a, String b) {...}</code>
- * or
- * <code>public MyTestClass(String a, String b) {...}</code>
- *
- * To parameterize testSimple or MyTestClass's tests, create multiple ParameterSets
- * <code>
- * static List<ParameterSet> sAllParameterSets = new ArrayList<>();
- * static {
- * sAllParameterSets.add(new ParameterSet().value("a", "b");
- * sAllParameterSets.add(new ParameterSet().value("c", "d");
- * }
- */
-public class ParameterSet {
- private List<Object> mValues;
- private String mName;
-
- public ParameterSet() {}
-
- public ParameterSet value(Object firstArg, Object... objects) {
- List<Object> parameterList = new ArrayList<Object>();
- parameterList.add(firstArg);
- parameterList.addAll(Arrays.asList(objects));
- Assert.assertTrue(
- "Can not create ParameterSet with no parameters", parameterList.size() != 0);
- mValues = validateAndCopy(parameterList);
- return this;
- }
-
- public ParameterSet name(String name) {
- mName = name;
- return this;
- }
-
- @Override
- public String toString() {
- if (mValues == null) {
- return "null";
- }
- return Arrays.toString(mValues.toArray());
- }
-
- private List<Object> validateAndCopy(List<Object> values) {
- List<Object> tempValues = new ArrayList<>();
- for (Object o : values) {
- if (o == null) {
- tempValues.add(null);
- } else {
- if (o.getClass().isPrimitive() || ACCEPTABLE_TYPES.contains(o.getClass())
- || o instanceof Callable) {
- tempValues.add(o);
- } else {
- // TODO(yolandyan): maybe come up with way to support
- // complex object while handling immutability at the
- // same time
- throw new IllegalArgumentException("Type \"%s\" is not supported in"
- + " parameterized testing at this time. Accepted types include"
- + " all primitive types along with "
- + Arrays.toString(ACCEPTABLE_TYPES.toArray(
- new String[ACCEPTABLE_TYPES.size()])));
- }
- }
- }
- return Collections.unmodifiableList(tempValues);
- }
-
- String getName() {
- if (mName == null) {
- return "";
- }
- return mName;
- }
-
- List<Object> getValues() {
- return mValues;
- }
-
- int size() {
- if (mValues == null) return 0;
- return mValues.size();
- }
-
- private static final Set<Class<?>> ACCEPTABLE_TYPES = getAcceptableTypes();
-
- /**
- * Any immutable class is acceptable.
- */
- private static Set<Class<?>> getAcceptableTypes() {
- Set<Class<?>> ret = new HashSet<Class<?>>();
- ret.add(Boolean.class);
- ret.add(Byte.class);
- ret.add(Character.class);
- ret.add(Class.class);
- ret.add(Double.class);
- ret.add(File.class);
- ret.add(Float.class);
- ret.add(Integer.class);
- ret.add(Long.class);
- ret.add(Short.class);
- ret.add(String.class);
- ret.add(URI.class);
- ret.add(URL.class);
- ret.add(Void.class);
- return ret;
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java
deleted file mode 100644
index f3333b5720..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.runners.model.FrameworkMethod;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Custom FrameworkMethod that includes a {@code ParameterSet} that
- * represents the parameters for this test method
- */
-public class ParameterizedFrameworkMethod extends FrameworkMethod {
- private ParameterSet mParameterSet;
- private String mName;
-
- public ParameterizedFrameworkMethod(
- Method method, ParameterSet parameterSet, String classParameterSetName) {
- super(method);
- mParameterSet = parameterSet;
- String postFix = "";
- if (classParameterSetName != null && !classParameterSetName.isEmpty()) {
- postFix += "_" + classParameterSetName;
- }
- if (parameterSet != null && !parameterSet.getName().isEmpty()) {
- postFix += "_" + parameterSet.getName();
- }
- mName = postFix.isEmpty() ? method.getName() : method.getName() + "_" + postFix;
- }
-
- @Override
- public String getName() {
- return mName;
- }
-
- @Override
- public Object invokeExplosively(Object target, Object... params) throws Throwable {
- if (mParameterSet != null) {
- return super.invokeExplosively(target, mParameterSet.getValues().toArray());
- }
- return super.invokeExplosively(target, params);
- }
-
- static List<FrameworkMethod> wrapAllFrameworkMethods(
- Collection<FrameworkMethod> frameworkMethods, String classParameterSetName) {
- List<FrameworkMethod> results = new ArrayList<>();
- for (FrameworkMethod frameworkMethod : frameworkMethods) {
- results.add(new ParameterizedFrameworkMethod(
- frameworkMethod.getMethod(), null, classParameterSetName));
- }
- return results;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof ParameterizedFrameworkMethod) {
- ParameterizedFrameworkMethod method = (ParameterizedFrameworkMethod) obj;
- return super.equals(obj) && method.getParameterSet().equals(getParameterSet())
- && method.getName().equals(getName());
- }
- return false;
- }
-
- /**
- * Override hashCode method to distinguish two ParameterizedFrameworkmethod with same
- * Method object.
- */
- @Override
- public int hashCode() {
- int result = 17;
- result = 31 * result + super.hashCode();
- result = 31 * result + getName().hashCode();
- if (getParameterSet() != null) {
- result = 31 * result + getParameterSet().hashCode();
- }
- return result;
- }
-
- Annotation[] getTestAnnotations() {
- // TODO(yolandyan): add annotation from the ParameterSet, enable
- // test writing to add SkipCheck for an individual parameter
- return getMethod().getAnnotations();
- }
-
- public ParameterSet getParameterSet() {
- return mParameterSet;
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java
deleted file mode 100644
index 834f26139f..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.Test;
-import org.junit.runner.Runner;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.Suite;
-import org.junit.runners.model.FrameworkField;
-import org.junit.runners.model.TestClass;
-
-import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
-import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
-import org.chromium.base.test.params.ParameterizedRunnerDelegateFactory.ParameterizedRunnerDelegateInstantiationException;
-
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * ParameterizedRunner generates a list of runners for each of class parameter set in a test class.
- *
- * ParameterizedRunner looks for {@code @ClassParameter} annotation in test class and
- * generates a list of ParameterizedRunnerDelegate runners for each ParameterSet.
- */
-public final class ParameterizedRunner extends Suite {
- private final List<Runner> mRunners;
-
- /**
- * Create a ParameterizedRunner to run test class
- *
- * @param klass the Class of the test class, test class should be atomic
- * (extends only Object)
- */
- public ParameterizedRunner(Class<?> klass) throws Throwable {
- super(klass, Collections.emptyList()); // pass in empty list of runners
- validate();
- mRunners = createRunners(getTestClass());
- }
-
- @Override
- protected List<Runner> getChildren() {
- return mRunners;
- }
-
- /**
- * ParentRunner calls collectInitializationErrors() to check for errors in Test class.
- * Parameterized tests are written in unconventional ways, therefore, this method is
- * overridden and validation is done seperately.
- */
- @Override
- protected void collectInitializationErrors(List<Throwable> errors) {
- // Do not call super collectInitializationErrors
- }
-
- private void validate() throws Throwable {
- validateNoNonStaticInnerClass();
- validateOnlyOneConstructor();
- validateInstanceMethods();
- validateOnlyOneClassParameterField();
- validateAtLeastOneParameterSetField();
- }
-
- private void validateNoNonStaticInnerClass() throws Exception {
- if (getTestClass().isANonStaticInnerClass()) {
- throw new Exception("The inner class " + getTestClass().getName() + " is not static.");
- }
- }
-
- private void validateOnlyOneConstructor() throws Exception {
- if (!hasOneConstructor()) {
- throw new Exception("Test class should have exactly one public constructor");
- }
- }
-
- private boolean hasOneConstructor() {
- return getTestClass().getJavaClass().getConstructors().length == 1;
- }
-
- private void validateOnlyOneClassParameterField() {
- if (getTestClass().getAnnotatedFields(ClassParameter.class).size() > 1) {
- throw new IllegalParameterArgumentException(String.format(Locale.getDefault(),
- "%s class has more than one @ClassParameter, only one is allowed",
- getTestClass().getName()));
- }
- }
-
- private void validateAtLeastOneParameterSetField() {
- if (getTestClass().getAnnotatedFields(ClassParameter.class).isEmpty()
- && getTestClass().getAnnotatedMethods(UseMethodParameter.class).isEmpty()) {
- throw new IllegalArgumentException(String.format(Locale.getDefault(),
- "%s has no field annotated with @ClassParameter or method annotated with"
- + "@UseMethodParameter; it should not use ParameterizedRunner",
- getTestClass().getName()));
- }
- }
-
- private void validateInstanceMethods() throws Exception {
- if (getTestClass().getAnnotatedMethods(Test.class).size() == 0) {
- throw new Exception("No runnable methods");
- }
- }
-
- /**
- * Return a list of runner delegates through ParameterizedRunnerDelegateFactory.
- *
- * For class parameter set: each class can only have one list of class parameter sets.
- * Each parameter set will be used to create one runner.
- *
- * For method parameter set: a single list method parameter sets is associated with
- * a string tag, an immutable map of string to parameter set list will be created and
- * passed into factory for each runner delegate to create multiple tests. Only one
- * Runner will be created for a method that uses @UseMethodParameter, regardless of the
- * number of ParameterSets in the associated list.
- *
- * @return a list of runners
- * @throws ParameterizedRunnerDelegateInstantiationException if runner delegate can not
- * be instantiated with constructor reflectively
- * @throws IllegalAccessError if the field in tests are not accessible
- */
- static List<Runner> createRunners(TestClass testClass)
- throws IllegalAccessException, ParameterizedRunnerDelegateInstantiationException {
- List<ParameterSet> classParameterSetList;
- if (testClass.getAnnotatedFields(ClassParameter.class).isEmpty()) {
- classParameterSetList = new ArrayList<>();
- classParameterSetList.add(null);
- } else {
- classParameterSetList = getParameterSetList(
- testClass.getAnnotatedFields(ClassParameter.class).get(0), testClass);
- validateWidth(classParameterSetList);
- }
-
- Class<? extends ParameterizedRunnerDelegate> runnerDelegateClass =
- getRunnerDelegateClass(testClass);
- ParameterizedRunnerDelegateFactory factory = new ParameterizedRunnerDelegateFactory();
- List<Runner> runnersForTestClass = new ArrayList<>();
- for (ParameterSet classParameterSet : classParameterSetList) {
- BlockJUnit4ClassRunner runner = (BlockJUnit4ClassRunner) factory.createRunner(
- testClass, classParameterSet, runnerDelegateClass);
- runnersForTestClass.add(runner);
- }
- return runnersForTestClass;
- }
-
- /**
- * Return an unmodifiable list of ParameterSet through a FrameworkField
- */
- private static List<ParameterSet> getParameterSetList(FrameworkField field, TestClass testClass)
- throws IllegalAccessException {
- field.getField().setAccessible(true);
- if (!Modifier.isStatic(field.getField().getModifiers())) {
- throw new IllegalParameterArgumentException(String.format(Locale.getDefault(),
- "ParameterSetList fields must be static, this field %s in %s is not",
- field.getName(), testClass.getName()));
- }
- if (!(field.get(testClass.getJavaClass()) instanceof List)) {
- throw new IllegalArgumentException(String.format(Locale.getDefault(),
- "Fields with @ClassParameter annotations must be an instance of List, "
- + "this field %s in %s is not list",
- field.getName(), testClass.getName()));
- }
- @SuppressWarnings("unchecked") // checked above
- List<ParameterSet> result = (List<ParameterSet>) field.get(testClass.getJavaClass());
- return Collections.unmodifiableList(result);
- }
-
- static void validateWidth(Iterable<ParameterSet> parameterSetList) {
- int lastSize = -1;
- for (ParameterSet set : parameterSetList) {
- if (set.size() == 0) {
- throw new IllegalParameterArgumentException(
- "No parameter is added to method ParameterSet");
- }
- if (lastSize == -1 || set.size() == lastSize) {
- lastSize = set.size();
- } else {
- throw new IllegalParameterArgumentException(String.format(Locale.getDefault(),
- "All ParameterSets in a list of ParameterSet must have equal"
- + " length. The current ParameterSet (%s) contains %d parameters,"
- + " while previous ParameterSet contains %d parameters",
- Arrays.toString(set.getValues().toArray()), set.size(), lastSize));
- }
- }
- }
-
- /**
- * Get the runner delegate class for the test class if {@code @UseRunnerDelegate} is used.
- * The default runner delegate is BaseJUnit4RunnerDelegate.class
- */
- private static Class<? extends ParameterizedRunnerDelegate> getRunnerDelegateClass(
- TestClass testClass) {
- if (testClass.getAnnotation(UseRunnerDelegate.class) != null) {
- return testClass.getAnnotation(UseRunnerDelegate.class).value();
- }
- return BaseJUnit4RunnerDelegate.class;
- }
-
- static class IllegalParameterArgumentException extends IllegalArgumentException {
- IllegalParameterArgumentException(String msg) {
- super(msg);
- }
- }
-
- public static class ParameterizedTestInstantiationException extends Exception {
- ParameterizedTestInstantiationException(
- TestClass testClass, String parameterSetString, Exception e) {
- super(String.format(
- "Test class %s can not be initiated, the provided parameters are %s,"
- + " the required parameter types are %s",
- testClass.getJavaClass().toString(), parameterSetString,
- Arrays.toString(testClass.getOnlyConstructor().getParameterTypes())),
- e);
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java
deleted file mode 100644
index d3698a95b4..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.runners.model.FrameworkMethod;
-
-import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException;
-
-import java.util.List;
-
-/**
- * This interface defines the methods that needs to be overriden for a Runner to
- * be used by ParameterizedRunner to generate individual runners for parameters.
- *
- * To create a ParameterizedRunnerDelegate, extends from any BlockJUnit4Runner
- * children class. You can copy all the implementation from
- * org.chromium.base.test.params.BaseJUnit4RunnerDelegate.
- */
-public interface ParameterizedRunnerDelegate {
- /**
- * Override to use DelegateCommon's implementation
- */
- void collectInitializationErrors(List<Throwable> errors);
-
- /**
- * Override to use DelegateCommon's implementation
- */
- List<FrameworkMethod> computeTestMethods();
-
- /**
- * Override to use DelegateCommon's implementation
- */
- Object createTest() throws ParameterizedTestInstantiationException;
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java
deleted file mode 100644
index f25e2b2ab9..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.TestClass;
-
-import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-
-/**
- * Parameterized runner delegate common that implements method that needed to be
- * delegated for parameterization purposes
- */
-public final class ParameterizedRunnerDelegateCommon {
- private final TestClass mTestClass;
- private final ParameterSet mClassParameterSet;
- private final List<FrameworkMethod> mParameterizedFrameworkMethodList;
-
- public ParameterizedRunnerDelegateCommon(TestClass testClass, ParameterSet classParameterSet,
- List<FrameworkMethod> parameterizedFrameworkMethods) {
- mTestClass = testClass;
- mClassParameterSet = classParameterSet;
- mParameterizedFrameworkMethodList = parameterizedFrameworkMethods;
- }
-
- /**
- * Do not do any validation here because running the default class runner's
- * collectInitializationErrors fail due to the overridden computeTestMethod relying on a local
- * member variable
- *
- * The validation needed for parameterized tests is already done by ParameterizedRunner.
- */
- public static void collectInitializationErrors(
- @SuppressWarnings("unused") List<Throwable> errors) {}
-
- public List<FrameworkMethod> computeTestMethods() {
- return mParameterizedFrameworkMethodList;
- }
-
- private void throwInstantiationException(Exception e)
- throws ParameterizedTestInstantiationException {
- String parameterSetString =
- mClassParameterSet == null ? "null" : mClassParameterSet.toString();
- throw new ParameterizedTestInstantiationException(mTestClass, parameterSetString, e);
- }
-
- public Object createTest() throws ParameterizedTestInstantiationException {
- try {
- if (mClassParameterSet == null) {
- return mTestClass.getOnlyConstructor().newInstance();
- }
- return mTestClass.getOnlyConstructor().newInstance(
- mClassParameterSet.getValues().toArray());
- } catch (InstantiationException e) {
- throwInstantiationException(e);
- } catch (IllegalAccessException e) {
- throwInstantiationException(e);
- } catch (InvocationTargetException e) {
- throwInstantiationException(e);
- }
- assert false;
- return null;
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java b/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java
deleted file mode 100644
index f829981c77..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.Test;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.TestClass;
-
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Factory to generate delegate class runners for ParameterizedRunner
- */
-public class ParameterizedRunnerDelegateFactory {
- /**
- * Create a runner that implements ParameterizedRunner and extends BlockJUnit4ClassRunner
- *
- * @param testClass the TestClass object for current test class
- * @param classParameterSet A parameter set for test constructor arguments
- * @param parameterizedRunnerDelegateClass the parameterized runner delegate class specified
- * through {@code @UseRunnerDelegate}
- */
- <T extends ParameterizedRunnerDelegate> T createRunner(TestClass testClass,
- ParameterSet classParameterSet, Class<T> parameterizedRunnerDelegateClass)
- throws ParameterizedRunnerDelegateInstantiationException {
- String testMethodPostfix = classParameterSet == null ? null : classParameterSet.getName();
- List<FrameworkMethod> unmodifiableFrameworkMethodList =
- generateUnmodifiableFrameworkMethodList(testClass, testMethodPostfix);
- ParameterizedRunnerDelegateCommon delegateCommon = new ParameterizedRunnerDelegateCommon(
- testClass, classParameterSet, unmodifiableFrameworkMethodList);
- try {
- return parameterizedRunnerDelegateClass
- .getDeclaredConstructor(Class.class, ParameterizedRunnerDelegateCommon.class)
- .newInstance(testClass.getJavaClass(), delegateCommon);
- } catch (Exception e) {
- throw new ParameterizedRunnerDelegateInstantiationException(
- parameterizedRunnerDelegateClass.toString(), e);
- }
- }
-
- /**
- * Match test methods annotated by @UseMethodParameter(X) with
- * ParameterSetList annotated by @MethodParameter(X)
- *
- * @param testClass a {@code TestClass} that wraps around the actual java
- * test class
- * @param postFix a name postfix for each test
- * @return a list of ParameterizedFrameworkMethod
- */
- static List<FrameworkMethod> generateUnmodifiableFrameworkMethodList(
- TestClass testClass, String postFix) {
- // Represent the list of all ParameterizedFrameworkMethod in this test class
- List<FrameworkMethod> returnList = new ArrayList<>();
-
- for (FrameworkMethod method : testClass.getAnnotatedMethods(Test.class)) {
- if (method.getMethod().isAnnotationPresent(UseMethodParameter.class)) {
- Iterable<ParameterSet> parameterSets =
- getParameters(method.getAnnotation(UseMethodParameter.class).value());
- returnList.addAll(createParameterizedMethods(method, parameterSets, postFix));
- } else {
- // If test method is not parameterized (does not have UseMethodParameter annotation)
- returnList.add(new ParameterizedFrameworkMethod(method.getMethod(), null, postFix));
- }
- }
-
- return Collections.unmodifiableList(returnList);
- }
-
- /**
- * Exception caused by instantiating the provided Runner delegate
- * Potentially caused by not overriding collecInitializationErrors() method
- * to be empty
- */
- public static class ParameterizedRunnerDelegateInstantiationException extends Exception {
- private ParameterizedRunnerDelegateInstantiationException(
- String runnerDelegateClass, Exception e) {
- super(String.format("Current class runner delegate %s can not be instantiated.",
- runnerDelegateClass),
- e);
- }
- }
-
- private static Iterable<ParameterSet> getParameters(Class<? extends ParameterProvider> clazz) {
- ParameterProvider parameterProvider;
- try {
- parameterProvider = clazz.getDeclaredConstructor().newInstance();
- } catch (IllegalAccessException e) {
- throw new IllegalStateException("Failed instantiating " + clazz.getCanonicalName(), e);
- } catch (InstantiationException e) {
- throw new IllegalStateException("Failed instantiating " + clazz.getCanonicalName(), e);
- } catch (NoSuchMethodException e) {
- throw new IllegalStateException("Failed instantiating " + clazz.getCanonicalName(), e);
- } catch (InvocationTargetException e) {
- throw new IllegalStateException("Failed instantiating " + clazz.getCanonicalName(), e);
- }
- return parameterProvider.getParameters();
- }
-
- private static List<FrameworkMethod> createParameterizedMethods(
- FrameworkMethod baseMethod, Iterable<ParameterSet> parameterSetList, String suffix) {
- ParameterizedRunner.validateWidth(parameterSetList);
- List<FrameworkMethod> returnList = new ArrayList<>();
- for (ParameterSet set : parameterSetList) {
- returnList.add(new ParameterizedFrameworkMethod(baseMethod.getMethod(), set, suffix));
- }
- return returnList;
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java b/base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java
deleted file mode 100644
index c8117f7fad..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2013 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 android.content.ComponentCallbacks;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.SharedPreferences;
-import android.test.mock.MockContentResolver;
-import android.test.mock.MockContext;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * ContextWrapper that adds functionality for SharedPreferences and a way to set and retrieve flags.
- */
-public class AdvancedMockContext extends ContextWrapper {
-
- private final MockContentResolver mMockContentResolver = new MockContentResolver();
-
- private final Map<String, SharedPreferences> mSharedPreferences =
- new HashMap<String, SharedPreferences>();
-
- private final Map<String, Boolean> mFlags = new HashMap<String, Boolean>();
-
- public AdvancedMockContext(Context base) {
- super(base);
- }
-
- public AdvancedMockContext() {
- super(new MockContext());
- }
-
- @Override
- public String getPackageName() {
- return getBaseContext().getPackageName();
- }
-
- @Override
- public Context getApplicationContext() {
- return this;
- }
-
- @Override
- public ContentResolver getContentResolver() {
- return mMockContentResolver;
- }
-
- public MockContentResolver getMockContentResolver() {
- return mMockContentResolver;
- }
-
- @Override
- public SharedPreferences getSharedPreferences(String name, int mode) {
- synchronized (mSharedPreferences) {
- if (!mSharedPreferences.containsKey(name)) {
- // Auto-create shared preferences to mimic Android Context behavior
- mSharedPreferences.put(name, new InMemorySharedPreferences());
- }
- return mSharedPreferences.get(name);
- }
- }
-
- @Override
- public void registerComponentCallbacks(ComponentCallbacks callback) {
- getBaseContext().registerComponentCallbacks(callback);
- }
-
- @Override
- public void unregisterComponentCallbacks(ComponentCallbacks callback) {
- getBaseContext().unregisterComponentCallbacks(callback);
- }
-
- public void addSharedPreferences(String name, Map<String, Object> data) {
- synchronized (mSharedPreferences) {
- mSharedPreferences.put(name, new InMemorySharedPreferences(data));
- }
- }
-
- public void setFlag(String key) {
- mFlags.put(key, true);
- }
-
- public void clearFlag(String key) {
- mFlags.remove(key);
- }
-
- public boolean isFlagSet(String key) {
- return mFlags.containsKey(key) && mFlags.get(key);
- }
-
- /**
- * Builder for maps of type Map<String, Object> to be used with
- * {@link #addSharedPreferences(String, java.util.Map)}.
- */
- public static class MapBuilder {
-
- private final Map<String, Object> mData = new HashMap<String, Object>();
-
- public static MapBuilder create() {
- return new MapBuilder();
- }
-
- public MapBuilder add(String key, Object value) {
- mData.put(key, value);
- return this;
- }
-
- public Map<String, Object> build() {
- return mData;
- }
-
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/CallbackHelper.java b/base/test/android/javatests/src/org/chromium/base/test/util/CallbackHelper.java
deleted file mode 100644
index bf064c4fce..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/CallbackHelper.java
+++ /dev/null
@@ -1,252 +0,0 @@
-// 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 static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
-
-import org.junit.Assert;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * A helper class that encapsulates listening and blocking for callbacks.
- *
- * Sample usage:
- *
- * // Let us assume that this interface is defined by some piece of production code and is used
- * // to communicate events that occur in that piece of code. Let us further assume that the
- * // production code runs on the main thread test code runs on a separate test thread.
- * // An instance that implements this interface would be injected by test code to ensure that the
- * // methods are being called on another thread.
- * interface Delegate {
- * void onOperationFailed(String errorMessage);
- * void onDataPersisted();
- * }
- *
- * // This is the inner class you'd write in your test case to later inject into the production
- * // code.
- * class TestDelegate implements Delegate {
- * // This is the preferred way to create a helper that stores the parameters it receives
- * // when called by production code.
- * public static class OnOperationFailedHelper extends CallbackHelper {
- * private String mErrorMessage;
- *
- * public void getErrorMessage() {
- * assert getCallCount() > 0;
- * return mErrorMessage;
- * }
- *
- * public void notifyCalled(String errorMessage) {
- * mErrorMessage = errorMessage;
- * // It's important to call this after all parameter assignments.
- * notifyCalled();
- * }
- * }
- *
- * // There should be one CallbackHelper instance per method.
- * private OnOperationFailedHelper mOnOperationFailedHelper;
- * private CallbackHelper mOnDataPersistedHelper;
- *
- * public OnOperationFailedHelper getOnOperationFailedHelper() {
- * return mOnOperationFailedHelper;
- * }
- *
- * public CallbackHelper getOnDataPersistedHelper() {
- * return mOnDataPersistedHelper;
- * }
- *
- * @Override
- * public void onOperationFailed(String errorMessage) {
- * mOnOperationFailedHelper.notifyCalled(errorMessage);
- * }
- *
- * @Override
- * public void onDataPersisted() {
- * mOnDataPersistedHelper.notifyCalled();
- * }
- * }
- *
- * // This is a sample test case.
- * public void testCase() throws Exception {
- * // Create the TestDelegate to inject into production code.
- * TestDelegate delegate = new TestDelegate();
- * // Create the production class instance that is being tested and inject the test delegate.
- * CodeUnderTest codeUnderTest = new CodeUnderTest();
- * codeUnderTest.setDelegate(delegate);
- *
- * // Typically you'd get the current call count before performing the operation you expect to
- * // trigger the callback. There can't be any callbacks 'in flight' at this moment, otherwise
- * // the call count is unpredictable and the test will be flaky.
- * int onOperationFailedCallCount = delegate.getOnOperationFailedHelper().getCallCount();
- * codeUnderTest.doSomethingThatEndsUpCallingOnOperationFailedFromAnotherThread();
- * // It's safe to do other stuff here, if needed.
- * ....
- * // Wait for the callback if it hadn't been called yet, otherwise return immediately. This
- * // can throw an exception if the callback doesn't arrive within the timeout.
- * delegate.getOnOperationFailedHelper().waitForCallback(onOperationFailedCallCount);
- * // Access to method parameters is now safe.
- * assertEquals("server error", delegate.getOnOperationFailedHelper().getErrorMessage());
- *
- * // Being able to pass the helper around lets us build methods which encapsulate commonly
- * // performed tasks.
- * doSomeOperationAndWait(codeUnerTest, delegate.getOnOperationFailedHelper());
- *
- * // The helper can be reused for as many calls as needed, just be sure to get the count each
- * // time.
- * onOperationFailedCallCount = delegate.getOnOperationFailedHelper().getCallCount();
- * codeUnderTest.doSomethingElseButStillFailOnAnotherThread();
- * delegate.getOnOperationFailedHelper().waitForCallback(onOperationFailedCallCount);
- *
- * // It is also possible to use more than one helper at a time.
- * onOperationFailedCallCount = delegate.getOnOperationFailedHelper().getCallCount();
- * int onDataPersistedCallCount = delegate.getOnDataPersistedHelper().getCallCount();
- * codeUnderTest.doSomethingThatPersistsDataButFailsInSomeOtherWayOnAnotherThread();
- * delegate.getOnDataPersistedHelper().waitForCallback(onDataPersistedCallCount);
- * delegate.getOnOperationFailedHelper().waitForCallback(onOperationFailedCallCount);
- * }
- *
- * // Shows how to turn an async operation + completion callback into a synchronous operation.
- * private void doSomeOperationAndWait(final CodeUnderTest underTest,
- * CallbackHelper operationHelper) throws InterruptedException, TimeoutException {
- * final int callCount = operationHelper.getCallCount();
- * getInstrumentation().runOnMainSync(new Runnable() {
- * @Override
- * public void run() {
- * // This schedules a call to a method on the injected TestDelegate. The TestDelegate
- * // implementation will then call operationHelper.notifyCalled().
- * underTest.operation();
- * }
- * });
- * operationHelper.waitForCallback(callCount);
- * }
- *
- */
-public class CallbackHelper {
- /** The default timeout (in seconds) for a callback to wait. */
- public static final long WAIT_TIMEOUT_SECONDS = scaleTimeout(5);
-
- private final Object mLock = new Object();
- private int mCallCount;
- private String mFailureString;
-
- /**
- * Gets the number of times the callback has been called.
- *
- * The call count can be used with the waitForCallback() method, indicating a point
- * in time after which the caller wishes to record calls to the callback.
- *
- * In order to wait for a callback caused by X, the call count should be obtained
- * before X occurs.
- *
- * NOTE: any call to the callback that occurs after the call count is obtained
- * will result in the corresponding wait call to resume execution. The call count
- * is intended to 'catch' callbacks that occur after X but before waitForCallback()
- * is called.
- */
- public int getCallCount() {
- synchronized (mLock) {
- return mCallCount;
- }
- }
-
- /**
- * Blocks until the callback is called the specified number of
- * times or throws an exception if we exceeded the specified time frame.
- *
- * This will wait for a callback to be called a specified number of times after
- * the point in time at which the call count was obtained. The method will return
- * immediately if a call occurred the specified number of times after the
- * call count was obtained but before the method was called, otherwise the method will
- * block until the specified call count is reached.
- *
- * @param msg The error message to use if the callback times out.
- * @param currentCallCount the value obtained by calling getCallCount().
- * @param numberOfCallsToWaitFor number of calls (counting since
- * currentCallCount was obtained) that we will wait for.
- * @param timeout timeout value. We will wait the specified amount of time for a single
- * callback to occur so the method call may block up to
- * <code>numberOfCallsToWaitFor * timeout</code> units.
- * @param unit timeout unit.
- * @throws InterruptedException
- * @throws TimeoutException Thrown if the method times out before onPageFinished is called.
- */
- public void waitForCallback(String msg, int currentCallCount, int numberOfCallsToWaitFor,
- long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
- assert mCallCount >= currentCallCount;
- assert numberOfCallsToWaitFor > 0;
- synchronized (mLock) {
- int callCountWhenDoneWaiting = currentCallCount + numberOfCallsToWaitFor;
- while (callCountWhenDoneWaiting > mCallCount) {
- int callCountBeforeWait = mCallCount;
- mLock.wait(unit.toMillis(timeout));
- if (mFailureString != null) {
- String s = mFailureString;
- mFailureString = null;
- Assert.fail(s);
- }
- if (callCountBeforeWait == mCallCount) {
- throw new TimeoutException(msg == null ? "waitForCallback timed out!" : msg);
- }
- }
- }
- }
-
- /**
- * @see #waitForCallback(String, int, int, long, TimeUnit)
- */
- public void waitForCallback(int currentCallCount, int numberOfCallsToWaitFor, long timeout,
- TimeUnit unit) throws InterruptedException, TimeoutException {
- waitForCallback(null, currentCallCount, numberOfCallsToWaitFor, timeout, unit);
- }
-
- /**
- * @see #waitForCallback(String, int, int, long, TimeUnit)
- */
- public void waitForCallback(int currentCallCount, int numberOfCallsToWaitFor)
- throws InterruptedException, TimeoutException {
- waitForCallback(null, currentCallCount, numberOfCallsToWaitFor,
- WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- }
-
- /**
- * @see #waitForCallback(String, int, int, long, TimeUnit)
- */
- public void waitForCallback(String msg, int currentCallCount)
- throws InterruptedException, TimeoutException {
- waitForCallback(msg, currentCallCount, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- }
-
- /**
- * @see #waitForCallback(String, int, int, long, TimeUnit)
- */
- public void waitForCallback(int currentCallCount)
- throws InterruptedException, TimeoutException {
- waitForCallback(null, currentCallCount, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- }
-
- /**
- * Should be called when the callback associated with this helper object is called.
- */
- public void notifyCalled() {
- synchronized (mLock) {
- mCallCount++;
- mLock.notifyAll();
- }
- }
-
- /**
- * Should be called when the callback associated with this helper object wants to
- * indicate a failure.
- *
- * @param s The failure message.
- */
- public void notifyFailed(String s) {
- synchronized (mLock) {
- mFailureString = s;
- mLock.notifyAll();
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
deleted file mode 100644
index 71ef8e91ff..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2015 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 android.text.TextUtils;
-
-import org.junit.Assert;
-import org.junit.Rule;
-
-import org.chromium.base.CommandLine;
-import org.chromium.base.CommandLineInitUtil;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Provides annotations related to command-line flag handling.
- *
- * Uses of these annotations on a derived class will take precedence over uses on its base classes,
- * so a derived class can add a command-line flag that a base class has removed (or vice versa).
- * Similarly, uses of these annotations on a test method will take precedence over uses on the
- * containing class.
- * <p>
- * These annonations may also be used on Junit4 Rule classes and on their base classes. Note,
- * however that the annotation processor only looks at the declared type of the Rule, not its actual
- * type, so in, for example:
- *
- * <pre>
- * &#64Rule
- * TestRule mRule = new ChromeActivityTestRule();
- * </pre>
- *
- * will only look for CommandLineFlags annotations on TestRule, not for CommandLineFlags annotations
- * on ChromeActivityTestRule.
- * <p>
- * In addition a rule may not remove flags added by an independently invoked rule, although it may
- * remove flags added by its base classes.
- * <p>
- * Uses of these annotations on the test class or methods take precedence over uses on Rule classes.
- * <p>
- * Note that this class should never be instantiated.
- */
-public final class CommandLineFlags {
- private static final String DISABLE_FEATURES = "disable-features";
- private static final String ENABLE_FEATURES = "enable-features";
-
- /**
- * Adds command-line flags to the {@link org.chromium.base.CommandLine} for this test.
- */
- @Inherited
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD, ElementType.TYPE})
- public @interface Add {
- String[] value();
- }
-
- /**
- * Removes command-line flags from the {@link org.chromium.base.CommandLine} from this test.
- *
- * Note that this can only remove flags added via {@link Add} above.
- */
- @Inherited
- @Retention(RetentionPolicy.RUNTIME)
- @Target({ElementType.METHOD, ElementType.TYPE})
- public @interface Remove {
- String[] value();
- }
-
- /**
- * Sets up the CommandLine with the appropriate flags.
- *
- * This will add the difference of the sets of flags specified by {@link CommandLineFlags.Add}
- * and {@link CommandLineFlags.Remove} to the {@link org.chromium.base.CommandLine}. Note that
- * trying to remove a flag set externally, i.e. by the command-line flags file, will not work.
- */
- public static void setUp(AnnotatedElement element) {
- CommandLine.reset();
- CommandLineInitUtil.initCommandLine(getTestCmdLineFile());
- Set<String> enableFeatures = new HashSet<String>();
- Set<String> disableFeatures = new HashSet<String>();
- Set<String> flags = getFlags(element);
- for (String flag : flags) {
- String[] parsedFlags = flag.split("=", 2);
- if (parsedFlags.length == 1) {
- CommandLine.getInstance().appendSwitch(flag);
- } else if (ENABLE_FEATURES.equals(parsedFlags[0])) {
- // We collect enable/disable features flags separately and aggregate them because
- // they may be specified multiple times, in which case the values will trample each
- // other.
- Collections.addAll(enableFeatures, parsedFlags[1].split(","));
- } else if (DISABLE_FEATURES.equals(parsedFlags[0])) {
- Collections.addAll(disableFeatures, parsedFlags[1].split(","));
- } else {
- CommandLine.getInstance().appendSwitchWithValue(parsedFlags[0], parsedFlags[1]);
- }
- }
-
- if (enableFeatures.size() > 0) {
- CommandLine.getInstance().appendSwitchWithValue(
- ENABLE_FEATURES, TextUtils.join(",", enableFeatures));
- }
- if (disableFeatures.size() > 0) {
- CommandLine.getInstance().appendSwitchWithValue(
- DISABLE_FEATURES, TextUtils.join(",", disableFeatures));
- }
- }
-
- private static Set<String> getFlags(AnnotatedElement type) {
- Set<String> rule_flags = new HashSet<>();
- updateFlagsForElement(type, rule_flags);
- return rule_flags;
- }
-
- private static void updateFlagsForElement(AnnotatedElement element, Set<String> flags) {
- if (element instanceof Class<?>) {
- // Get flags from rules within the class.
- for (Field field : ((Class<?>) element).getFields()) {
- if (field.isAnnotationPresent(Rule.class)) {
- // The order in which fields are returned is undefined, so, for consistency,
- // a rule must not remove a flag added by a different rule. Ensure this by
- // initially getting the flags into a new set.
- Set<String> rule_flags = getFlags(field.getType());
- flags.addAll(rule_flags);
- }
- }
- for (Method method : ((Class<?>) element).getMethods()) {
- if (method.isAnnotationPresent(Rule.class)) {
- // The order in which methods are returned is undefined, so, for consistency,
- // a rule must not remove a flag added by a different rule. Ensure this by
- // initially getting the flags into a new set.
- Set<String> rule_flags = getFlags(method.getReturnType());
- flags.addAll(rule_flags);
- }
- }
- }
-
- // Add the flags from the parent. Override any flags defined by the rules.
- AnnotatedElement parent = (element instanceof Method)
- ? ((Method) element).getDeclaringClass()
- : ((Class<?>) element).getSuperclass();
- if (parent != null) updateFlagsForElement(parent, flags);
-
- // Flags on the element itself override all other flag sources.
- if (element.isAnnotationPresent(CommandLineFlags.Add.class)) {
- flags.addAll(
- Arrays.asList(element.getAnnotation(CommandLineFlags.Add.class).value()));
- }
-
- if (element.isAnnotationPresent(CommandLineFlags.Remove.class)) {
- List<String> flagsToRemove =
- Arrays.asList(element.getAnnotation(CommandLineFlags.Remove.class).value());
- for (String flagToRemove : flagsToRemove) {
- // If your test fails here, you have tried to remove a command-line flag via
- // CommandLineFlags.Remove that was loaded into CommandLine via something other
- // than CommandLineFlags.Add (probably the command-line flag file).
- Assert.assertFalse("Unable to remove command-line flag \"" + flagToRemove + "\".",
- CommandLine.getInstance().hasSwitch(flagToRemove));
- }
- flags.removeAll(flagsToRemove);
- }
- }
-
- private CommandLineFlags() {
- throw new AssertionError("CommandLineFlags is a non-instantiable class");
- }
-
- public static PreTestHook getRegistrationHook() {
- return (targetContext, testMethod) -> CommandLineFlags.setUp(testMethod);
- }
-
- public static String getTestCmdLineFile() {
- return "test-cmdline-file";
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java b/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java
deleted file mode 100644
index c0303b68d4..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 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;
-
-/**
- * Annotations to support conditional test disabling.
- *
- * These annotations should only be used to disable tests that are temporarily failing
- * in some configurations. If a test should never run at all in some configurations, use
- * {@link Restriction}.
- */
-public class DisableIf {
-
- /** Conditional disabling based on {@link android.os.Build}.
- */
- @Target({ElementType.METHOD, ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- public static @interface Build {
- String message() default "";
-
- int sdk_is_greater_than() default 0;
- int sdk_is_less_than() default Integer.MAX_VALUE;
-
- String supported_abis_includes() default "";
-
- String hardware_is() default "";
-
- String product_name_includes() default "";
- }
-
- @Target({ElementType.METHOD, ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- public static @interface Device {
- /**
- * @return A list of disabled types.
- */
- public String[] type();
- }
-
- /* Objects of this type should not be created. */
- private DisableIf() {}
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/DisableIfSkipCheck.java b/base/test/android/javatests/src/org/chromium/base/test/util/DisableIfSkipCheck.java
deleted file mode 100644
index e46b9799a6..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/DisableIfSkipCheck.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2015 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 android.os.Build;
-
-import org.junit.runners.model.FrameworkMethod;
-
-import org.chromium.base.Log;
-
-import java.util.Arrays;
-
-/**
- * Checks for conditional disables.
- *
- * Currently, this only includes checks against a few {@link android.os.Build} values.
- */
-public class DisableIfSkipCheck extends SkipCheck {
-
- private static final String TAG = "cr_base_test";
-
- @Override
- public boolean shouldSkip(FrameworkMethod method) {
- if (method == null) return true;
- for (DisableIf.Build v : AnnotationProcessingUtils.getAnnotations(
- method.getMethod(), DisableIf.Build.class)) {
- if (abi(v) && hardware(v) && product(v) && sdk(v)) {
- if (!v.message().isEmpty()) {
- Log.i(TAG, "%s is disabled: %s", method.getName(), v.message());
- }
- return true;
- }
- }
-
- for (DisableIf.Device d : AnnotationProcessingUtils.getAnnotations(
- method.getMethod(), DisableIf.Device.class)) {
- for (String deviceType : d.type()) {
- if (deviceTypeApplies(deviceType)) {
- Log.i(TAG, "Test " + method.getDeclaringClass().getName() + "#"
- + method.getName() + " disabled because of "
- + d);
- return true;
- }
- }
- }
-
- return false;
- }
-
- @SuppressWarnings("deprecation")
- private boolean abi(DisableIf.Build v) {
- if (v.supported_abis_includes().isEmpty()) return true;
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return Arrays.asList(Build.SUPPORTED_ABIS).contains(
- v.supported_abis_includes());
- } else {
- return Build.CPU_ABI.equals(v.supported_abis_includes())
- || Build.CPU_ABI2.equals(v.supported_abis_includes());
- }
- }
-
- private boolean hardware(DisableIf.Build v) {
- return v.hardware_is().isEmpty() || Build.HARDWARE.equals(v.hardware_is());
- }
-
- private boolean product(DisableIf.Build v) {
- return v.product_name_includes().isEmpty()
- || Build.PRODUCT.contains(v.product_name_includes());
- }
-
- private boolean sdk(DisableIf.Build v) {
- return Build.VERSION.SDK_INT > v.sdk_is_greater_than()
- && Build.VERSION.SDK_INT < v.sdk_is_less_than();
- }
-
- protected boolean deviceTypeApplies(String type) {
- return false;
- }
-
-}
-
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java b/base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java
deleted file mode 100644
index a3e4e8ee7f..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 is for disabled tests.
- * <p>
- * Tests with this annotation will not be run on any of the normal bots.
- * Please note that they might eventually run on a special bot.
- */
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface DisabledTest {
- String message() default "";
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java b/base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java
deleted file mode 100644
index af483ec3f9..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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 is for enormous tests.
- * <p>
- * Examples of enormous tests are tests that depend on external web sites or
- * tests that are long running.
- * <p>
- * Such tests are likely NOT reliable enough to run on tree closing bots and
- * should only be run on FYI bots.
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface EnormousTest {
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/Feature.java b/base/test/android/javatests/src/org/chromium/base/test/util/Feature.java
deleted file mode 100644
index 1bc9226441..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/Feature.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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;
-
-/**
- * The java instrumentation tests are normally fairly large (in terms of
- * dependencies), and the test suite ends up containing a large amount of
- * tests that are not trivial to filter / group just by their names.
- * Instead, we use this annotation: each test should be annotated as:
- * @Feature({"Foo", "Bar"})
- * in order for the test runner scripts to be able to filter and group
- * them accordingly (for instance, this enable us to run all tests that exercise
- * feature Foo).
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Feature {
- /**
- * @return A list of feature names.
- */
- public String[] value();
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java b/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java
deleted file mode 100644
index 83f8e9f43d..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 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 is for flaky tests.
- * <p>
- * Tests with this annotation will not be run on any of the normal bots.
- * Please note that they might eventually run on a special bot.
- */
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface FlakyTest {
- String message() default "";
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java b/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java
deleted file mode 100644
index 2587d724a5..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2013 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 android.content.SharedPreferences;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * An implementation of SharedPreferences that can be used in tests.
- * <p/>
- * It keeps all state in memory, and there is no difference between apply() and commit().
- */
-public class InMemorySharedPreferences implements SharedPreferences {
-
- // Guarded on its own monitor.
- private final Map<String, Object> mData;
-
- public InMemorySharedPreferences() {
- mData = new HashMap<String, Object>();
- }
-
- public InMemorySharedPreferences(Map<String, Object> data) {
- mData = data;
- }
-
- @Override
- public Map<String, ?> getAll() {
- synchronized (mData) {
- return Collections.unmodifiableMap(mData);
- }
- }
-
- @Override
- public String getString(String key, String defValue) {
- synchronized (mData) {
- if (mData.containsKey(key)) {
- return (String) mData.get(key);
- }
- }
- return defValue;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Set<String> getStringSet(String key, Set<String> defValues) {
- synchronized (mData) {
- if (mData.containsKey(key)) {
- return Collections.unmodifiableSet((Set<String>) mData.get(key));
- }
- }
- return defValues;
- }
-
- @Override
- public int getInt(String key, int defValue) {
- synchronized (mData) {
- if (mData.containsKey(key)) {
- return (Integer) mData.get(key);
- }
- }
- return defValue;
- }
-
- @Override
- public long getLong(String key, long defValue) {
- synchronized (mData) {
- if (mData.containsKey(key)) {
- return (Long) mData.get(key);
- }
- }
- return defValue;
- }
-
- @Override
- public float getFloat(String key, float defValue) {
- synchronized (mData) {
- if (mData.containsKey(key)) {
- return (Float) mData.get(key);
- }
- }
- return defValue;
- }
-
- @Override
- public boolean getBoolean(String key, boolean defValue) {
- synchronized (mData) {
- if (mData.containsKey(key)) {
- return (Boolean) mData.get(key);
- }
- }
- return defValue;
- }
-
- @Override
- public boolean contains(String key) {
- synchronized (mData) {
- return mData.containsKey(key);
- }
- }
-
- @Override
- public SharedPreferences.Editor edit() {
- return new InMemoryEditor();
- }
-
- @Override
- public void registerOnSharedPreferenceChangeListener(
- SharedPreferences.OnSharedPreferenceChangeListener
- listener) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void unregisterOnSharedPreferenceChangeListener(
- SharedPreferences.OnSharedPreferenceChangeListener listener) {
- throw new UnsupportedOperationException();
- }
-
- private class InMemoryEditor implements SharedPreferences.Editor {
-
- // All guarded by |mChanges|
- private boolean mClearCalled;
- private volatile boolean mApplyCalled;
- private final Map<String, Object> mChanges = new HashMap<String, Object>();
-
- @Override
- public SharedPreferences.Editor putString(String key, String value) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- mChanges.put(key, value);
- return this;
- }
- }
-
- @Override
- public SharedPreferences.Editor putStringSet(String key, Set<String> values) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- mChanges.put(key, values);
- return this;
- }
- }
-
- @Override
- public SharedPreferences.Editor putInt(String key, int value) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- mChanges.put(key, value);
- return this;
- }
- }
-
- @Override
- public SharedPreferences.Editor putLong(String key, long value) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- mChanges.put(key, value);
- return this;
- }
- }
-
- @Override
- public SharedPreferences.Editor putFloat(String key, float value) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- mChanges.put(key, value);
- return this;
- }
- }
-
- @Override
- public SharedPreferences.Editor putBoolean(String key, boolean value) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- mChanges.put(key, value);
- return this;
- }
- }
-
- @Override
- public SharedPreferences.Editor remove(String key) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- // Magic value for removes
- mChanges.put(key, this);
- return this;
- }
- }
-
- @Override
- public SharedPreferences.Editor clear() {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- mClearCalled = true;
- return this;
- }
- }
-
- @Override
- public boolean commit() {
- apply();
- return true;
- }
-
- @Override
- public void apply() {
- synchronized (mData) {
- synchronized (mChanges) {
- if (mApplyCalled) throw new IllegalStateException();
- if (mClearCalled) {
- mData.clear();
- }
- for (Map.Entry<String, Object> entry : mChanges.entrySet()) {
- String key = entry.getKey();
- Object value = entry.getValue();
- if (value == this) {
- // Special value for removal
- mData.remove(key);
- } else {
- mData.put(key, value);
- }
- }
- // The real shared prefs clears out the temporaries allowing the caller to
- // reuse the Editor instance, however this is undocumented behavior and subtle
- // to read, so instead we just ban any future use of this instance.
- mApplyCalled = true;
- }
- }
- }
- }
-
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java b/base/test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java
deleted file mode 100644
index 20cfd9d620..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 android.app.Instrumentation;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-/**
- * Utility methods built around the android.app.Instrumentation class.
- */
-public final class InstrumentationUtils {
-
- private InstrumentationUtils() {
- }
-
- public static <R> R runOnMainSyncAndGetResult(Instrumentation instrumentation,
- Callable<R> callable) throws Throwable {
- FutureTask<R> task = new FutureTask<R>(callable);
- instrumentation.runOnMainSync(task);
- try {
- return task.get();
- } catch (ExecutionException e) {
- // Unwrap the cause of the exception and re-throw it.
- throw e.getCause();
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java b/base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java
deleted file mode 100644
index 8b6550d62d..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 is for integration tests.
- * <p>
- * Examples of integration tests are tests that rely on real instances of the
- * application's services and components (e.g. Search) to test the system as
- * a whole. These tests may use additional command-line flags to configure the
- * existing backends to use.
- * <p>
- * Such tests are likely NOT reliable enough to run on tree closing bots and
- * should only be run on FYI bots.
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface IntegrationTest {
-} \ No newline at end of file
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/Manual.java b/base/test/android/javatests/src/org/chromium/base/test/util/Manual.java
deleted file mode 100644
index 31f3977bef..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/Manual.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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/base/test/android/javatests/src/org/chromium/base/test/util/Matchers.java b/base/test/android/javatests/src/org/chromium/base/test/util/Matchers.java
deleted file mode 100644
index fc9d68907b..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/Matchers.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 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 org.hamcrest.CoreMatchers;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-
-/**
- * Helper class containing Hamcrest matchers.
- */
-public class Matchers extends CoreMatchers {
- private static class GreaterThanOrEqualTo<T extends Comparable<T>>
- extends TypeSafeMatcher<T> {
-
- private final T mComparisonValue;
-
- public GreaterThanOrEqualTo(T comparisonValue) {
- mComparisonValue = comparisonValue;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("greater than or equal to ").appendValue(mComparisonValue);
- }
-
- @Override
- protected boolean matchesSafely(T item) {
- return item.compareTo(mComparisonValue) >= 0;
- }
- }
-
- /**
- * @param <T> A Comparable type.
- * @param comparisonValue The value to be compared against.
- * @return A matcher that expects the value to be greater than the |comparisonValue|.
- */
- public static <T extends Comparable<T>> Matcher<T> greaterThanOrEqualTo(T comparisonValue) {
- return new GreaterThanOrEqualTo<>(comparisonValue);
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java b/base/test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java
deleted file mode 100644
index c4664d68b0..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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 org.chromium.base.metrics.RecordHistogram;
-
-/**
- * Helpers for testing UMA metrics.
- */
-public class MetricsUtils {
- /**
- * Helper class that snapshots the given bucket of the given UMA histogram on its creation,
- * allowing to inspect the number of samples recorded during its lifetime.
- */
- public static class HistogramDelta {
- private final String mHistogram;
- private final int mSampleValue;
-
- private final int mInitialCount;
-
- private int get() {
- return RecordHistogram.getHistogramValueCountForTesting(mHistogram, mSampleValue);
- }
-
- /**
- * Snapshots the given bucket of the given histogram.
- * @param histogram name of the histogram to snapshot
- * @param sampleValue the bucket that contains this value will be snapshot
- */
- public HistogramDelta(String histogram, int sampleValue) {
- mHistogram = histogram;
- mSampleValue = sampleValue;
- mInitialCount = get();
- }
-
- /** Returns the number of samples of the snapshot bucket recorded since creation */
- public int getDelta() {
- return get() - mInitialCount;
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java b/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java
deleted file mode 100644
index 13e25786a7..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java
+++ /dev/null
@@ -1,19 +0,0 @@
-// 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.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Inherited
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface MinAndroidSdkLevel {
- int value() default 0;
-}
-
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheck.java b/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheck.java
deleted file mode 100644
index 8b07c0f19b..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheck.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2016 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 android.os.Build;
-
-import org.junit.runners.model.FrameworkMethod;
-
-import org.chromium.base.Log;
-
-/**
- * Checks the device's SDK level against any specified minimum requirement.
- */
-public class MinAndroidSdkLevelSkipCheck extends SkipCheck {
-
- private static final String TAG = "base_test";
-
- /**
- * If {@link MinAndroidSdkLevel} is present, checks its value
- * against the device's SDK level.
- *
- * @param testCase The test to check.
- * @return true if the device's SDK level is below the specified minimum.
- */
- @Override
- public boolean shouldSkip(FrameworkMethod frameworkMethod) {
- int minSdkLevel = 0;
- for (MinAndroidSdkLevel m : AnnotationProcessingUtils.getAnnotations(
- frameworkMethod.getMethod(), MinAndroidSdkLevel.class)) {
- minSdkLevel = Math.max(minSdkLevel, m.value());
- }
- if (Build.VERSION.SDK_INT < minSdkLevel) {
- Log.i(TAG, "Test " + frameworkMethod.getDeclaringClass().getName() + "#"
- + frameworkMethod.getName() + " is not enabled at SDK level "
- + Build.VERSION.SDK_INT + ".");
- return true;
- }
- return false;
- }
-
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java b/base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java
deleted file mode 100644
index f39bfbd783..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 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;
-
-/**
- * An annotation for listing restrictions for a test method. For example, if a test method is only
- * applicable on a phone with small memory:
- * @Restriction({RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_SMALL_MEMORY})
- * Test classes are free to define restrictions and enforce them using reflection at runtime.
- */
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Restriction {
- /** Specifies the test is only valid on low end devices that have less memory. */
- public static final String RESTRICTION_TYPE_LOW_END_DEVICE = "Low_End_Device";
-
- /** Specifies the test is only valid on non-low end devices. */
- public static final String RESTRICTION_TYPE_NON_LOW_END_DEVICE = "Non_Low_End_Device";
-
- /** Specifies the test is only valid on a device that can reach the internet. */
- public static final String RESTRICTION_TYPE_INTERNET = "Internet";
-
- /** Specifies the test is only valid on a device that has a camera. */
- public static final String RESTRICTION_TYPE_HAS_CAMERA = "Has_Camera";
-
- /**
- * @return A list of restrictions.
- */
- public String[] value();
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/RestrictionSkipCheck.java b/base/test/android/javatests/src/org/chromium/base/test/util/RestrictionSkipCheck.java
deleted file mode 100644
index a27dd1fe08..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/RestrictionSkipCheck.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2016 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 android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.text.TextUtils;
-
-import org.junit.runners.model.FrameworkMethod;
-
-import org.chromium.base.Log;
-import org.chromium.base.SysUtils;
-
-/**
- * Checks if any restrictions exist and skip the test if it meets those restrictions.
- */
-public class RestrictionSkipCheck extends SkipCheck {
-
- private static final String TAG = "base_test";
-
- private final Context mTargetContext;
-
- public RestrictionSkipCheck(Context targetContext) {
- mTargetContext = targetContext;
- }
-
- protected Context getTargetContext() {
- return mTargetContext;
- }
-
- @Override
- public boolean shouldSkip(FrameworkMethod frameworkMethod) {
- if (frameworkMethod == null) return true;
-
- for (Restriction restriction : AnnotationProcessingUtils.getAnnotations(
- frameworkMethod.getMethod(), Restriction.class)) {
- for (String restrictionVal : restriction.value()) {
- if (restrictionApplies(restrictionVal)) {
- Log.i(TAG, "Test " + frameworkMethod.getDeclaringClass().getName() + "#"
- + frameworkMethod.getName() + " skipped because of restriction "
- + restriction);
- return true;
- }
- }
- }
- return false;
- }
-
- protected boolean restrictionApplies(String restriction) {
- if (TextUtils.equals(restriction, Restriction.RESTRICTION_TYPE_LOW_END_DEVICE)
- && !SysUtils.isLowEndDevice()) {
- return true;
- }
- if (TextUtils.equals(restriction, Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE)
- && SysUtils.isLowEndDevice()) {
- return true;
- }
- if (TextUtils.equals(restriction, Restriction.RESTRICTION_TYPE_INTERNET)
- && !isNetworkAvailable()) {
- return true;
- }
- if (TextUtils.equals(restriction, Restriction.RESTRICTION_TYPE_HAS_CAMERA)
- && !SysUtils.hasCamera(mTargetContext)) {
- return true;
- }
- return false;
- }
-
- private boolean isNetworkAvailable() {
- final ConnectivityManager connectivityManager = (ConnectivityManager)
- mTargetContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- final NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
- return activeNetworkInfo != null && activeNetworkInfo.isConnected();
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/RetryOnFailure.java b/base/test/android/javatests/src/org/chromium/base/test/util/RetryOnFailure.java
deleted file mode 100644
index eb98008d00..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/RetryOnFailure.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 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;
-
-// Note this annotation may be a NOOP. Check http://crbug.com/797002 for latest status (also see
-// http://crbug.com/619055). Current default behavior is to retry all tests on failure.
-/**
- * Mark a test as flaky and should be retried on failure. The test is
- * considered passed by the test script if any retry succeeds.
- *
- * Long term, this should be merged with @FlakyTest. But @FlakyTest means
- * has specific meaning that is currently different from RetryOnFailure.
- */
-@Target({ElementType.METHOD, ElementType.TYPE})
-@Retention(RetentionPolicy.RUNTIME)
-public @interface RetryOnFailure {
- String message() default "";
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/ScalableTimeout.java b/base/test/android/javatests/src/org/chromium/base/test/util/ScalableTimeout.java
deleted file mode 100644
index 7a815c09a4..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/ScalableTimeout.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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;
-
-/**
- * Utility class for scaling various timeouts by a common factor.
- * For example, to run tests under slow memory tools, you might do
- * something like this:
- * adb shell "echo 20.0 > /data/local/tmp/chrome_timeout_scale"
- */
-public class ScalableTimeout {
- private static Double sTimeoutScale;
- public static final String PROPERTY_FILE = "/data/local/tmp/chrome_timeout_scale";
-
- public static long scaleTimeout(long timeout) {
- if (sTimeoutScale == null) {
- try {
- char[] data = TestFileUtil.readUtf8File(PROPERTY_FILE, 32);
- sTimeoutScale = Double.parseDouble(new String(data));
- } catch (Exception e) {
- // NumberFormatException, FileNotFoundException, IOException
- sTimeoutScale = 1.0;
- }
- }
- return (long) (timeout * sTimeoutScale);
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/SkipCheck.java b/base/test/android/javatests/src/org/chromium/base/test/util/SkipCheck.java
deleted file mode 100644
index d1dd7be17f..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/SkipCheck.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 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 junit.framework.TestCase;
-
-import org.junit.runners.model.FrameworkMethod;
-
-import org.chromium.base.Log;
-
-import java.lang.reflect.Method;
-
-/**
- * Check whether a test case should be skipped.
- */
-public abstract class SkipCheck {
-
- private static final String TAG = "base_test";
-
- /**
- *
- * Checks whether the given test method should be skipped.
- *
- * @param testMethod The test method to check.
- * @return Whether the test case should be skipped.
- */
- public abstract boolean shouldSkip(FrameworkMethod testMethod);
-
- /**
- *
- * Checks whether the given test case should be skipped.
- *
- * @param testCase The test case to check.
- * @return Whether the test case should be skipped.
- */
- public boolean shouldSkip(TestCase testCase) {
- try {
- Method m = testCase.getClass().getMethod(testCase.getName(), (Class[]) null);
- return shouldSkip(new FrameworkMethod(m));
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "Unable to find %s in %s", testCase.getName(),
- testCase.getClass().getName(), e);
- return false;
- }
- }
-}
-
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java b/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
deleted file mode 100644
index 6d891210fc..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.Arrays;
-
-/**
- * Utility class for dealing with files for test.
- */
-public class TestFileUtil {
- public static void createNewHtmlFile(String name, String title, String body)
- throws IOException {
- createNewHtmlFile(new File(name), title, body);
- }
-
- public static void createNewHtmlFile(File file, String title, String body)
- throws IOException {
- if (!file.createNewFile()) {
- throw new IOException("File \"" + file.getAbsolutePath() + "\" already exists");
- }
-
- Writer writer = null;
- try {
- writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
- writer.write("<html><meta charset=\"UTF-8\" />"
- + " <head><title>" + title + "</title></head>"
- + " <body>"
- + (body != null ? body : "")
- + " </body>"
- + " </html>");
- } finally {
- if (writer != null) {
- writer.close();
- }
- }
- }
-
- public static void deleteFile(String name) {
- deleteFile(new File(name));
- }
-
- public static void deleteFile(File file) {
- boolean deleted = file.delete();
- assert (deleted || !file.exists());
- }
-
- /**
- * @param fileName the file to read in.
- * @param sizeLimit cap on the file size: will throw an exception if exceeded
- * @return Array of chars read from the file
- * @throws FileNotFoundException file does not exceed
- * @throws IOException error encountered accessing the file
- */
- public static char[] readUtf8File(String fileName, int sizeLimit) throws
- FileNotFoundException, IOException {
- Reader reader = null;
- try {
- File f = new File(fileName);
- if (f.length() > sizeLimit) {
- throw new IOException("File " + fileName + " length " + f.length()
- + " exceeds limit " + sizeLimit);
- }
- char[] buffer = new char[(int) f.length()];
- reader = new InputStreamReader(new FileInputStream(f), "UTF-8");
- int charsRead = reader.read(buffer);
- // Debug check that we've exhausted the input stream (will fail e.g. if the
- // file grew after we inspected its length).
- assert !reader.ready();
- return charsRead < buffer.length ? Arrays.copyOfRange(buffer, 0, charsRead) : buffer;
- } finally {
- if (reader != null) reader.close();
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/TestThread.java b/base/test/android/javatests/src/org/chromium/base/test/util/TestThread.java
deleted file mode 100644
index 4f6296924c..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/TestThread.java
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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 android.os.Handler;
-import android.os.Looper;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * This class is usefull when writing instrumentation tests that exercise code that posts tasks
- * (to the same thread).
- * Since the test code is run in a single thread, the posted tasks are never executed.
- * The TestThread class lets you run that code on a specific thread synchronously and flush the
- * message loop on that thread.
- *
- * Example of test using this:
- *
- * public void testMyAwesomeClass() {
- * TestThread testThread = new TestThread();
- * testThread.startAndWaitForReadyState();
- *
- * testThread.runOnTestThreadSyncAndProcessPendingTasks(new Runnable() {
- * @Override
- * public void run() {
- * MyAwesomeClass.doStuffAsync();
- * }
- * });
- * // Once we get there we know doStuffAsync has been executed and all the tasks it posted.
- * assertTrue(MyAwesomeClass.stuffWasDone());
- * }
- *
- * Notes:
- * - this is only for tasks posted to the same thread. Anyway if you were posting to a different
- * thread, you'd probably need to set that other thread up.
- * - this only supports tasks posted using Handler.post(), it won't work with postDelayed and
- * postAtTime.
- * - if your test instanciates an object and that object is the one doing the posting of tasks, you
- * probably want to instanciate it on the test thread as it might create the Handler it posts
- * tasks to in the constructor.
- */
-
-public class TestThread extends Thread {
- private final Object mThreadReadyLock;
- private AtomicBoolean mThreadReady;
- private Handler mMainThreadHandler;
- private Handler mTestThreadHandler;
-
- public TestThread() {
- mMainThreadHandler = new Handler();
- // We can't use the AtomicBoolean as the lock or findbugs will freak out...
- mThreadReadyLock = new Object();
- mThreadReady = new AtomicBoolean();
- }
-
- @Override
- public void run() {
- Looper.prepare();
- mTestThreadHandler = new Handler();
- mTestThreadHandler.post(new Runnable() {
- @Override
- public void run() {
- synchronized (mThreadReadyLock) {
- mThreadReady.set(true);
- mThreadReadyLock.notify();
- }
- }
- });
- Looper.loop();
- }
-
- /**
- * Starts this TestThread and blocks until it's ready to accept calls.
- */
- public void startAndWaitForReadyState() {
- checkOnMainThread();
- start();
- synchronized (mThreadReadyLock) {
- try {
- // Note the mThreadReady and while are not really needed.
- // There are there so findbugs don't report warnings.
- while (!mThreadReady.get()) {
- mThreadReadyLock.wait();
- }
- } catch (InterruptedException ie) {
- System.err.println("Error starting TestThread.");
- ie.printStackTrace();
- }
- }
- }
-
- /**
- * Runs the passed Runnable synchronously on the TestThread and returns when all pending
- * runnables have been excuted.
- * Should be called from the main thread.
- */
- public void runOnTestThreadSyncAndProcessPendingTasks(Runnable r) {
- checkOnMainThread();
-
- runOnTestThreadSync(r);
-
- // Run another task, when it's done it means all pendings tasks have executed.
- runOnTestThreadSync(null);
- }
-
- /**
- * Runs the passed Runnable on the test thread and blocks until it has finished executing.
- * Should be called from the main thread.
- * @param r The runnable to be executed.
- */
- public void runOnTestThreadSync(final Runnable r) {
- checkOnMainThread();
- final Object lock = new Object();
- // Task executed is not really needed since we are only on one thread, it is here to appease
- // findbugs.
- final AtomicBoolean taskExecuted = new AtomicBoolean();
- mTestThreadHandler.post(new Runnable() {
- @Override
- public void run() {
- if (r != null) r.run();
- synchronized (lock) {
- taskExecuted.set(true);
- lock.notify();
- }
- }
- });
- synchronized (lock) {
- try {
- while (!taskExecuted.get()) {
- lock.wait();
- }
- } catch (InterruptedException ie) {
- ie.printStackTrace();
- }
- }
- }
-
- private void checkOnMainThread() {
- assert Looper.myLooper() == mMainThreadHandler.getLooper();
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/TimeoutScale.java b/base/test/android/javatests/src/org/chromium/base/test/util/TimeoutScale.java
deleted file mode 100644
index 5aee05e73a..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/TimeoutScale.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 scale a specific test timeout.
- */
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface TimeoutScale {
- /**
- * @return A number to scale the test timeout.
- */
- public int value();
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java b/base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
deleted file mode 100644
index 9ca3fcc33c..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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 org.junit.Assert;
-
-import org.chromium.base.PathUtils;
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.MainDex;
-
-/**
- * Collection of URL utilities.
- */
-@MainDex
-public class UrlUtils {
- private static final String DATA_DIR = "/chrome/test/data/";
-
- /**
- * Construct the full path of a test data file.
- * @param path Pathname relative to external/chrome/test/data
- */
- public static String getTestFilePath(String path) {
- // TODO(jbudorick): Remove DATA_DIR once everything has been isolated. crbug/400499
- return getIsolatedTestFilePath(DATA_DIR + path);
- }
-
- // TODO(jbudorick): Remove this function once everything has been isolated and switched back
- // to getTestFilePath. crbug/400499
- /**
- * Construct the full path of a test data file.
- * @param path Pathname relative to external/
- */
- public static String getIsolatedTestFilePath(String path) {
- return getIsolatedTestRoot() + "/" + path;
- }
-
- /**
- * Returns the root of the test data directory.
- */
- @CalledByNative
- public static String getIsolatedTestRoot() {
- return PathUtils.getExternalStorageDirectory() + "/chromium_tests_root";
- }
-
- /**
- * Construct a suitable URL for loading a test data file.
- * @param path Pathname relative to external/chrome/test/data
- */
- public static String getTestFileUrl(String path) {
- return "file://" + getTestFilePath(path);
- }
-
- // TODO(jbudorick): Remove this function once everything has been isolated and switched back
- // to getTestFileUrl. crbug/400499
- /**
- * Construct a suitable URL for loading a test data file.
- * @param path Pathname relative to external/
- */
- public static String getIsolatedTestFileUrl(String path) {
- return "file://" + getIsolatedTestFilePath(path);
- }
-
- /**
- * Construct a data:text/html URI for loading from an inline HTML.
- * @param html An unencoded HTML
- * @return String An URI that contains the given HTML
- */
- public static String encodeHtmlDataUri(String html) {
- try {
- // URLEncoder encodes into application/x-www-form-encoded, so
- // ' '->'+' needs to be undone and replaced with ' '->'%20'
- // to match the Data URI requirements.
- String encoded =
- "data:text/html;utf-8," + java.net.URLEncoder.encode(html, "UTF-8");
- encoded = encoded.replace("+", "%20");
- return encoded;
- } catch (java.io.UnsupportedEncodingException e) {
- Assert.fail("Unsupported encoding: " + e.getMessage());
- return null;
- }
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/UserActionTester.java b/base/test/android/javatests/src/org/chromium/base/test/util/UserActionTester.java
deleted file mode 100644
index 88e3551131..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/UserActionTester.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2017 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 org.chromium.base.ThreadUtils;
-import org.chromium.base.metrics.RecordUserAction;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A util class that records UserActions.
- */
-public class UserActionTester implements RecordUserAction.UserActionCallback {
- private List<String> mActions;
-
- public UserActionTester() {
- mActions = new ArrayList<>();
- ThreadUtils.runOnUiThreadBlocking(new Runnable() {
- @Override
- public void run() {
- RecordUserAction.setActionCallbackForTesting(UserActionTester.this);
- }
- });
- }
-
- public void tearDown() {
- ThreadUtils.runOnUiThreadBlocking(new Runnable() {
- @Override
- public void run() {
- RecordUserAction.removeActionCallbackForTesting();
- }
- });
- }
-
- @Override
- public void onActionRecorded(String action) {
- mActions.add(action);
- }
-
- public List<String> getActions() {
- return mActions;
- }
-
- @Override
- public String toString() {
- return "Actions: " + mActions.toString();
- }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java
deleted file mode 100644
index e6f5506899..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 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.parameter;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * The annotation for parametering CommandLineFlags in JUnit3 instrumentation tests.
- *
- * E.g. if you add the following annotation to your test class:
- *
- * <code>
- * @CommandLineParameter({"", FLAG_A, FLAG_B})
- * public class MyTestClass
- * </code>
- *
- * The test harness would run the test 3 times with each of the flag added to commandline
- * file.
- */
-
-@Inherited
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface CommandLineParameter {
- String[] value() default {};
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java b/base/test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java
deleted file mode 100644
index 2181031617..0000000000
--- a/base/test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 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.parameter;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * BaseJUnit4ClassRunner and host side test harness skips commandline parameterization for test
- * classes or methods annotated with SkipCommandLineParameterization.
- *
- * This usually used by test that only runs in WebView javatests that only runs in sandboxed mode
- * or single process mode.
- */
-
-@Inherited
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.METHOD, ElementType.TYPE})
-public @interface SkipCommandLineParameterization {}
diff --git a/base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java b/base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java
deleted file mode 100644
index 3ca756ad9a..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 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;
-
-import org.junit.runners.model.InitializationError;
-import org.robolectric.DefaultTestLifecycle;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.TestLifecycle;
-
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.CommandLine;
-import org.chromium.base.ContextUtils;
-import org.chromium.testing.local.LocalRobolectricTestRunner;
-
-import java.lang.reflect.Method;
-
-/**
- * A Robolectric Test Runner that initializes base globals.
- */
-public class BaseRobolectricTestRunner extends LocalRobolectricTestRunner {
- /**
- * Enables a per-test setUp / tearDown hook.
- */
- public static class BaseTestLifecycle extends DefaultTestLifecycle {
- @Override
- public void beforeTest(Method method) {
- ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
- CommandLine.init(null);
- super.beforeTest(method);
- }
-
- @Override
- public void afterTest(Method method) {
- ApplicationStatus.destroyForJUnitTests();
- super.afterTest(method);
- }
- }
-
- public BaseRobolectricTestRunner(Class<?> testClass) throws InitializationError {
- super(testClass);
- }
-
- @Override
- protected Class<? extends TestLifecycle> getTestLifecycleClass() {
- return BaseTestLifecycle.class;
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java b/base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java
deleted file mode 100644
index 722bd1acfe..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 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;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.Statement;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Test SetUpStatement is working as intended with SetUpTestRule.
- */
-@RunWith(BlockJUnit4ClassRunner.class)
-public class SetUpStatementTest {
- private Statement mBase;
- private SetUpTestRule<TestRule> mRule;
- private List<Integer> mList;
-
- @Before
- public void setUp() {
- mBase = new Statement() {
- @Override
- public void evaluate() {
- mList.add(1);
- }
- };
- mList = new ArrayList<>();
- mRule = new SetUpTestRule<TestRule>() {
- @Override
- public void setUp() {
- mList.add(0);
- }
-
- @Override
- public TestRule shouldSetUp(boolean toSetUp) {
- return null;
- }
- };
- }
-
- @Test
- public void testSetUpStatementShouldSetUp() throws Throwable {
- SetUpStatement statement = new SetUpStatement(mBase, mRule, true);
- statement.evaluate();
- Integer[] expected = {0, 1};
- Assert.assertArrayEquals(expected, mList.toArray());
- }
-
- @Test
- public void testSetUpStatementShouldNotSetUp() throws Throwable {
- SetUpStatement statement = new SetUpStatement(mBase, mRule, false);
- statement.evaluate();
- Integer[] expected = {1};
- Assert.assertArrayEquals(expected, mList.toArray());
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java b/base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java
deleted file mode 100644
index 63fa5601fb..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2017 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;
-
-import static org.chromium.base.test.TestListInstrumentationRunListener.getAnnotationJSON;
-import static org.chromium.base.test.TestListInstrumentationRunListener.getTestMethodJSON;
-
-import org.json.JSONObject;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.Description;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.util.CommandLineFlags;
-
-import java.util.Arrays;
-
-/**
- * Robolectric test to ensure static methods in TestListInstrumentationRunListener works properly.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class TestListInstrumentationRunListenerTest {
- @CommandLineFlags.Add("hello")
- private static class ParentClass {
- public void testA() {}
-
- @CommandLineFlags.Add("world")
- public void testB() {}
- }
-
- @CommandLineFlags.Remove("hello")
- private static class ChildClass extends ParentClass {
- }
-
- @Test
- public void testGetTestMethodJSON_testA() throws Throwable {
- Description desc = Description.createTestDescription(
- ParentClass.class, "testA",
- ParentClass.class.getMethod("testA").getAnnotations());
- JSONObject json = getTestMethodJSON(desc);
- String expectedJsonString =
- "{"
- + "'method': 'testA',"
- + "'annotations': {}"
- + "}";
- expectedJsonString = expectedJsonString
- .replaceAll("\\s", "")
- .replaceAll("'", "\"");
- Assert.assertEquals(expectedJsonString, json.toString());
- }
-
- @Test
- public void testGetTestMethodJSON_testB() throws Throwable {
- Description desc = Description.createTestDescription(
- ParentClass.class, "testB",
- ParentClass.class.getMethod("testB").getAnnotations());
- JSONObject json = getTestMethodJSON(desc);
- String expectedJsonString =
- "{"
- + "'method': 'testB',"
- + "'annotations': {"
- + " 'Add': {"
- + " 'value': ['world']"
- + " }"
- + " }"
- + "}";
- expectedJsonString = expectedJsonString
- .replaceAll("\\s", "")
- .replaceAll("'", "\"");
- Assert.assertEquals(expectedJsonString, json.toString());
- }
-
-
- @Test
- public void testGetTestMethodJSONForInheritedClass() throws Throwable {
- Description desc = Description.createTestDescription(
- ChildClass.class, "testB",
- ChildClass.class.getMethod("testB").getAnnotations());
- JSONObject json = getTestMethodJSON(desc);
- String expectedJsonString =
- "{"
- + "'method': 'testB',"
- + "'annotations': {"
- + " 'Add': {"
- + " 'value': ['world']"
- + " }"
- + " }"
- + "}";
- expectedJsonString = expectedJsonString
- .replaceAll("\\s", "")
- .replaceAll("'", "\"");
- Assert.assertEquals(expectedJsonString, json.toString());
- }
-
- @Test
- public void testGetAnnotationJSONForParentClass() throws Throwable {
- JSONObject json = getAnnotationJSON(Arrays.asList(ParentClass.class.getAnnotations()));
- String expectedJsonString = "{'Add':{'value':['hello']}}";
- expectedJsonString = expectedJsonString
- .replaceAll("\\s", "")
- .replaceAll("'", "\"");
- Assert.assertEquals(expectedJsonString, json.toString());
- }
-
- @Test
- public void testGetAnnotationJSONForChildClass() throws Throwable {
- JSONObject json = getAnnotationJSON(Arrays.asList(ChildClass.class.getAnnotations()));
- String expectedJsonString = "{'Add':{'value':['hello']},'Remove':{'value':['hello']}}";
- expectedJsonString = expectedJsonString
- .replaceAll("\\s", "")
- .replaceAll("'", "\"");
- Assert.assertEquals(expectedJsonString, json.toString());
- }
-}
-
diff --git a/base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java b/base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java
deleted file mode 100644
index c75e7948f0..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/asynctask/BackgroundShadowAsyncTask.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2015 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.asynctask;
-
-import static org.junit.Assert.fail;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowApplication;
-
-import org.chromium.base.AsyncTask;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- * Executes async tasks on a background thread and waits on the result on the main thread.
- * This is useful for users of AsyncTask on Roboelectric who check if the code is actually being
- * run on a background thread (i.e. through the use of {@link ThreadUtils#runningOnUiThread()}).
- * @param <Params> type for execute function parameters
- * @param <Progress> type for reporting Progress
- * @param <Result> type for reporting result
- */
-@Implements(AsyncTask.class)
-public class BackgroundShadowAsyncTask<Params, Progress, Result>
- extends ShadowAsyncTask<Params, Progress, Result> {
- private static final ExecutorService sExecutorService = Executors.newSingleThreadExecutor();
-
- @Override
- @Implementation
- @SafeVarargs
- public final AsyncTask<Params, Progress, Result> execute(final Params... params) {
- try {
- return sExecutorService
- .submit(new Callable<AsyncTask<Params, Progress, Result>>() {
- @Override
- public AsyncTask<Params, Progress, Result> call() throws Exception {
- return BackgroundShadowAsyncTask.super.execute(params);
- }
- })
- .get();
- } catch (Exception ex) {
- fail(ex.getMessage());
- return null;
- }
- }
-
- @Override
- @Implementation
- public final Result get() {
- try {
- runBackgroundTasks();
- return BackgroundShadowAsyncTask.super.get();
- } catch (Exception e) {
- return null;
- }
- }
-
- public static void runBackgroundTasks() throws Exception {
- sExecutorService
- .submit(new Runnable() {
- @Override
- public void run() {
- ShadowApplication.runBackgroundTasks();
- }
- })
- .get();
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java b/base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java
deleted file mode 100644
index bd581c1377..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/asynctask/CustomShadowAsyncTask.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 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.asynctask;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
-import org.chromium.base.AsyncTask;
-
-import java.util.concurrent.Executor;
-
-/**
- * Forces async tasks to execute with the default executor.
- * This works around Robolectric not working out of the box with custom executors.
- *
- * @param <Params>
- * @param <Progress>
- * @param <Result>
- */
-@Implements(AsyncTask.class)
-public class CustomShadowAsyncTask<Params, Progress, Result>
- extends ShadowAsyncTask<Params, Progress, Result> {
- @SafeVarargs
- @Override
- @Implementation
- public final AsyncTask<Params, Progress, Result> executeOnExecutor(
- Executor executor, Params... params) {
- return super.execute(params);
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java
deleted file mode 100644
index 6ffccad44b..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.MethodRule;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterAfter;
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore;
-import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Example test that uses ParameterizedRunner
- */
-@RunWith(ParameterizedRunner.class)
-@UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
-public class ExampleParameterizedTest {
- @ClassParameter
- private static List<ParameterSet> sClassParams =
- Arrays.asList(new ParameterSet().value("hello", "world").name("HelloWorld"),
- new ParameterSet().value("Xxxx", "Yyyy").name("XxxxYyyy"),
- new ParameterSet().value("aa", "yy").name("AaYy"));
-
- public static class MethodParamsA implements ParameterProvider {
- private static List<ParameterSet> sMethodParamA =
- Arrays.asList(new ParameterSet().value(1, 2).name("OneTwo"),
- new ParameterSet().value(2, 3).name("TwoThree"),
- new ParameterSet().value(3, 4).name("ThreeFour"));
-
- @Override
- public List<ParameterSet> getParameters() {
- return sMethodParamA;
- }
- }
-
- public static class MethodParamsB implements ParameterProvider {
- private static List<ParameterSet> sMethodParamB =
- Arrays.asList(new ParameterSet().value("a", "b").name("Ab"),
- new ParameterSet().value("b", "c").name("Bc"),
- new ParameterSet().value("c", "d").name("Cd"),
- new ParameterSet().value("d", "e").name("De"));
-
- @Override
- public List<ParameterSet> getParameters() {
- return sMethodParamB;
- }
- }
-
- private String mStringA;
- private String mStringB;
-
- public ExampleParameterizedTest(String a, String b) {
- mStringA = a;
- mStringB = b;
- }
-
- @Test
- public void testSimple() {
- Assert.assertEquals(
- "A and B string length aren't equal", mStringA.length(), mStringB.length());
- }
-
- @Rule
- public MethodRule mMethodParamAnnotationProcessor = new MethodParamAnnotationRule();
-
- private Integer mSum;
-
- @UseMethodParameterBefore(MethodParamsA.class)
- public void setupWithOnlyA(int intA, int intB) {
- mSum = intA + intB;
- }
-
- @Test
- @UseMethodParameter(MethodParamsA.class)
- public void testWithOnlyA(int intA, int intB) {
- Assert.assertEquals(intA + 1, intB);
- Assert.assertEquals(mSum, Integer.valueOf(intA + intB));
- mSum = null;
- }
-
- private String mConcatenation;
-
- @Test
- @UseMethodParameter(MethodParamsB.class)
- public void testWithOnlyB(String a, String b) {
- Assert.assertTrue(!a.equals(b));
- mConcatenation = a + b;
- }
-
- @UseMethodParameterAfter(MethodParamsB.class)
- public void teardownWithOnlyB(String a, String b) {
- Assert.assertEquals(mConcatenation, a + b);
- mConcatenation = null;
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java
deleted file mode 100644
index 6d854c57e6..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2018 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.params;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.TestClass;
-
-import org.chromium.base.test.params.ParameterizedRunner.ParameterizedTestInstantiationException;
-
-import java.util.Collections;
-
-@RunWith(BlockJUnit4ClassRunner.class)
-public class ParameterizedRunnerDelegateCommonTest {
- /**
- * Create a test object using the list of class parameter set
- *
- * @param testClass the {@link TestClass} object for current test class
- * @param classParameterSet the parameter set needed for the test class constructor
- */
- private static Object createTest(TestClass testClass, ParameterSet classParameterSet)
- throws ParameterizedTestInstantiationException {
- return new ParameterizedRunnerDelegateCommon(
- testClass, classParameterSet, Collections.emptyList())
- .createTest();
- }
-
- static class BadTestClassWithMoreThanOneConstructor {
- public BadTestClassWithMoreThanOneConstructor() {}
- @SuppressWarnings("unused")
- public BadTestClassWithMoreThanOneConstructor(String argument) {}
- }
-
- static class BadTestClassWithTwoArgumentConstructor {
- @SuppressWarnings("unused")
- public BadTestClassWithTwoArgumentConstructor(int a, int b) {}
- }
-
- static abstract class BadTestClassAbstract {
- public BadTestClassAbstract() {}
- }
-
- static class BadTestClassConstructorThrows {
- public BadTestClassConstructorThrows() {
- throw new RuntimeException();
- }
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testCreateTestWithMoreThanOneConstructor() throws Throwable {
- TestClass testClass = new TestClass(BadTestClassWithMoreThanOneConstructor.class);
- createTest(testClass, null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testCreateTestWithIncorrectArguments() throws Throwable {
- TestClass testClass = new TestClass(BadTestClassWithTwoArgumentConstructor.class);
- ParameterSet pSet = new ParameterSet().value(1, 2, 3);
- createTest(testClass, pSet);
- }
-
- @Test(expected = ParameterizedTestInstantiationException.class)
- public void testCreateTestWithAbstractClass() throws ParameterizedTestInstantiationException {
- TestClass testClass = new TestClass(BadTestClassAbstract.class);
- createTest(testClass, null);
- }
-
- @Test(expected = ParameterizedTestInstantiationException.class)
- public void testCreateTestWithThrowingConstructor()
- throws ParameterizedTestInstantiationException {
- TestClass testClass = new TestClass(BadTestClassConstructorThrows.class);
- createTest(testClass, null);
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java
deleted file mode 100644
index 723382d71d..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.TestClass;
-
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
-import org.chromium.base.test.params.ParameterizedRunnerDelegateFactory.ParameterizedRunnerDelegateInstantiationException;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Test for org.chromium.base.test.params.ParameterizedRunnerDelegateFactory
- */
-@RunWith(BlockJUnit4ClassRunner.class)
-public class ParameterizedRunnerDelegateFactoryTest {
- /**
- * This RunnerDelegate calls `super.collectInitializationErrors()` and would
- * cause BlockJUnit4ClassRunner to validate test classes.
- */
- public static class BadExampleRunnerDelegate
- extends BlockJUnit4ClassRunner implements ParameterizedRunnerDelegate {
- public static class LalaTestClass {}
-
- private final List<FrameworkMethod> mParameterizedFrameworkMethodList;
-
- BadExampleRunnerDelegate(Class<?> klass,
- List<FrameworkMethod> parameterizedFrameworkMethods) throws InitializationError {
- super(klass);
- mParameterizedFrameworkMethodList = parameterizedFrameworkMethods;
- }
-
- @Override
- public void collectInitializationErrors(List<Throwable> errors) {
- super.collectInitializationErrors(errors); // This is wrong!!
- }
-
- @Override
- public List<FrameworkMethod> computeTestMethods() {
- return mParameterizedFrameworkMethodList;
- }
-
- @Override
- public Object createTest() {
- return null;
- }
- }
-
- static class ExampleTestClass {
- static class MethodParamsA implements ParameterProvider {
- @Override
- public Iterable<ParameterSet> getParameters() {
- return Arrays.asList(
- new ParameterSet().value("a").name("testWithValue_a"),
- new ParameterSet().value("b").name("testWithValue_b")
- );
- }
- }
-
- @SuppressWarnings("unused")
- @UseMethodParameter(MethodParamsA.class)
- @Test
- public void testA(String a) {}
-
- static class MethodParamsB implements ParameterProvider {
- @Override
- public Iterable<ParameterSet> getParameters() {
- return Arrays.asList(
- new ParameterSet().value(1).name("testWithValue_1"),
- new ParameterSet().value(2).name("testWithValue_2"),
- new ParameterSet().value(3).name("testWithValue_3")
- );
- }
- }
-
- @SuppressWarnings("unused")
- @UseMethodParameter(MethodParamsB.class)
- @Test
- public void testB(int b) {}
-
- @Test
- public void testByMyself() {}
- }
-
- /**
- * This test validates ParameterizedRunnerDelegateFactory throws exception when
- * a runner delegate does not override the collectInitializationErrors method.
- */
- @Test(expected = ParameterizedRunnerDelegateInstantiationException.class)
- public void testBadRunnerDelegateWithIncorrectValidationCall() throws Throwable {
- ParameterizedRunnerDelegateFactory factory = new ParameterizedRunnerDelegateFactory();
- TestClass testClass = new TestClass(BadExampleRunnerDelegate.LalaTestClass.class);
- factory.createRunner(testClass, null, BadExampleRunnerDelegate.class);
- }
-
- @Test
- public void testGenerateParameterizedFrameworkMethod() throws Throwable {
- List<FrameworkMethod> methods =
- ParameterizedRunnerDelegateFactory.generateUnmodifiableFrameworkMethodList(
- new TestClass(ExampleTestClass.class), "");
-
- Assert.assertEquals(methods.size(), 6);
-
- Map<String, Method> expectedTests = new HashMap<>();
- Method testMethodA = ExampleTestClass.class.getDeclaredMethod("testA", String.class);
- Method testMethodB = ExampleTestClass.class.getDeclaredMethod("testB", int.class);
- Method testMethodByMyself = ExampleTestClass.class.getDeclaredMethod("testByMyself");
- expectedTests.put("testA__testWithValue_a", testMethodA);
- expectedTests.put("testA__testWithValue_b", testMethodA);
- expectedTests.put("testB__testWithValue_1", testMethodB);
- expectedTests.put("testB__testWithValue_2", testMethodB);
- expectedTests.put("testB__testWithValue_3", testMethodB);
- expectedTests.put("testByMyself", testMethodByMyself);
- for (FrameworkMethod method : methods) {
- Assert.assertNotNull(expectedTests.get(method.getName()));
- Assert.assertEquals(expectedTests.get(method.getName()), method.getMethod());
- expectedTests.remove(method.getName());
- }
- Assert.assertTrue(expectedTests.isEmpty());
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java
deleted file mode 100644
index 170ff69eaf..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.BlockJUnit4ClassRunner;
-
-import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
-import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
-import org.chromium.base.test.params.ParameterizedRunner.IllegalParameterArgumentException;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Test for org.chromium.base.test.params.ParameterizedRunner
- */
-@RunWith(BlockJUnit4ClassRunner.class)
-public class ParameterizedRunnerTest {
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class BadTestClassWithMoreThanOneConstructor {
- @ClassParameter
- static List<ParameterSet> sClassParams = new ArrayList<>();
-
- public BadTestClassWithMoreThanOneConstructor() {}
-
- public BadTestClassWithMoreThanOneConstructor(String x) {}
- }
-
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class BadTestClassWithNonListParameters {
- @ClassParameter
- static String[] sMethodParamA = {"1", "2"};
-
- @Test
- public void test() {}
- }
-
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class BadTestClassWithoutNeedForParameterization {
- @Test
- public void test() {}
- }
-
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class BadTestClassWithNonStaticParameterSetList {
- @ClassParameter
- public List<ParameterSet> mClassParams = new ArrayList<>();
-
- @Test
- public void test() {}
- }
-
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class BadTestClassWithMultipleClassParameter {
- @ClassParameter
- private static List<ParameterSet> sParamA = new ArrayList<>();
-
- @ClassParameter
- private static List<ParameterSet> sParamB = new ArrayList<>();
- }
-
- @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class)
- public void testEmptyParameterSet() {
- List<ParameterSet> paramList = new ArrayList<>();
- paramList.add(new ParameterSet());
- ParameterizedRunner.validateWidth(paramList);
- }
-
- @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class)
- public void testUnequalWidthParameterSetList() {
- List<ParameterSet> paramList = new ArrayList<>();
- paramList.add(new ParameterSet().value(1, 2));
- paramList.add(new ParameterSet().value(3, 4, 5));
- ParameterizedRunner.validateWidth(paramList);
- }
-
- @Test(expected = ParameterizedRunner.IllegalParameterArgumentException.class)
- public void testUnequalWidthParameterSetListWithNull() {
- List<ParameterSet> paramList = new ArrayList<>();
- paramList.add(new ParameterSet().value(null));
- paramList.add(new ParameterSet().value(1, 2));
- ParameterizedRunner.validateWidth(paramList);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testBadClassWithNonListParameters() throws Throwable {
- new ParameterizedRunner(BadTestClassWithNonListParameters.class);
- }
-
- @Test(expected = IllegalParameterArgumentException.class)
- public void testBadClassWithNonStaticParameterSetList() throws Throwable {
- new ParameterizedRunner(BadTestClassWithNonStaticParameterSetList.class);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testBadClassWithoutNeedForParameterization() throws Throwable {
- new ParameterizedRunner(BadTestClassWithoutNeedForParameterization.class);
- }
-
- @Test(expected = Exception.class)
- public void testBadClassWithMoreThanOneConstructor() throws Throwable {
- new ParameterizedRunner(BadTestClassWithMoreThanOneConstructor.class);
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java b/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java
deleted file mode 100644
index e79f5c5304..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2017 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.params;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runner.Runner;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.TestClass;
-
-import org.chromium.base.test.params.ParameterAnnotations.ClassParameter;
-import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameter;
-import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Test for verify the names and test method Description works properly
- */
-@RunWith(BlockJUnit4ClassRunner.class)
-public class ParameterizedTestNameTest {
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class TestClassWithClassParameterAppendName {
- @ClassParameter
- static List<ParameterSet> sAllName = Arrays.asList(
- new ParameterSet().value("hello").name("Hello"),
- new ParameterSet().value("world").name("World")
- );
-
- public TestClassWithClassParameterAppendName(String a) {}
-
- @Test
- public void test() {}
- }
-
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class TestClassWithClassParameterDefaultName {
- @ClassParameter
- static List<ParameterSet> sAllName = Arrays.asList(
- new ParameterSet().value("hello"),
- new ParameterSet().value("world")
- );
-
- public TestClassWithClassParameterDefaultName(String a) {}
-
- @Test
- public void test() {}
- }
-
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class TestClassWithMethodParameter {
- static class AppendNameParams implements ParameterProvider {
- @Override
- public Iterable<ParameterSet> getParameters() {
- return Arrays.asList(
- new ParameterSet().value("hello").name("Hello"),
- new ParameterSet().value("world").name("World")
- );
- }
- }
-
- static class DefaultNameParams implements ParameterProvider {
- @Override
- public Iterable<ParameterSet> getParameters() {
- return Arrays.asList(
- new ParameterSet().value("hello"),
- new ParameterSet().value("world")
- );
- }
- }
-
- @UseMethodParameter(AppendNameParams.class)
- @Test
- public void test(String a) {}
-
- @UseMethodParameter(DefaultNameParams.class)
- @Test
- public void testDefaultName(String b) {}
- }
-
- @UseRunnerDelegate(BlockJUnit4RunnerDelegate.class)
- public static class TestClassWithMixedParameter {
- @ClassParameter
- static List<ParameterSet> sAllName = Arrays.asList(
- new ParameterSet().value("hello").name("Hello"),
- new ParameterSet().value("world").name("World")
- );
-
- static class AppendNameParams implements ParameterProvider {
- @Override
- public Iterable<ParameterSet> getParameters() {
- return Arrays.asList(
- new ParameterSet().value("1").name("A"),
- new ParameterSet().value("2").name("B")
- );
- }
- }
-
- public TestClassWithMixedParameter(String a) {}
-
- @UseMethodParameter(AppendNameParams.class)
- @Test
- public void testA(String a) {}
-
- @Test
- public void test() {}
- }
-
- @Test
- public void testClassParameterAppendName() throws Throwable {
- List<Runner> runners = ParameterizedRunner.createRunners(
- new TestClass(TestClassWithClassParameterAppendName.class));
- List<String> expectedTestNames =
- new LinkedList<String>(Arrays.asList("test__Hello", "test__World"));
- List<String> computedMethodNames = new ArrayList<>();
- for (Runner r : runners) {
- BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
- for (FrameworkMethod method : castedRunner.computeTestMethods()) {
- computedMethodNames.add(method.getName());
- Assert.assertTrue("This test name is not expected: " + method.getName(),
- expectedTestNames.contains(method.getName()));
- expectedTestNames.remove(method.getName());
- method.getName();
- }
- }
- Assert.assertTrue(
- String.format(
- "These names were provided: %s, these expected names are not found: %s",
- Arrays.toString(computedMethodNames.toArray()),
- Arrays.toString(expectedTestNames.toArray())),
- expectedTestNames.isEmpty());
- }
-
- @Test
- public void testClassParameterDefaultName() throws Throwable {
- List<Runner> runners = ParameterizedRunner.createRunners(
- new TestClass(TestClassWithClassParameterDefaultName.class));
- List<String> expectedTestNames = new LinkedList<String>(Arrays.asList("test", "test"));
- for (Runner r : runners) {
- @SuppressWarnings("unchecked")
- BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
- for (FrameworkMethod method : castedRunner.computeTestMethods()) {
- Assert.assertTrue("This test name is not expected: " + method.getName(),
- expectedTestNames.contains(method.getName()));
- expectedTestNames.remove(method.getName());
- method.getName();
- }
- }
- Assert.assertTrue("These expected names are not found: "
- + Arrays.toString(expectedTestNames.toArray()),
- expectedTestNames.isEmpty());
- }
-
- @Test
- public void testMethodParameter() throws Throwable {
- List<Runner> runners = ParameterizedRunner.createRunners(
- new TestClass(TestClassWithMethodParameter.class));
- List<String> expectedTestNames = new LinkedList<String>(
- Arrays.asList("test__Hello", "test__World", "testDefaultName", "testDefaultName"));
- for (Runner r : runners) {
- BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
- for (FrameworkMethod method : castedRunner.computeTestMethods()) {
- Assert.assertTrue("This test name is not expected: " + method.getName(),
- expectedTestNames.contains(method.getName()));
- expectedTestNames.remove(method.getName());
- method.getName();
- }
- }
- Assert.assertTrue("These expected names are not found: "
- + Arrays.toString(expectedTestNames.toArray()),
- expectedTestNames.isEmpty());
- }
-
- @Test
- public void testMixedParameterTestA() throws Throwable {
- List<Runner> runners =
- ParameterizedRunner.createRunners(new TestClass(TestClassWithMixedParameter.class));
- List<String> expectedTestNames =
- new LinkedList<String>(Arrays.asList("testA__Hello_A", "testA__World_A",
- "testA__Hello_B", "testA__World_B", "test__Hello", "test__World"));
- for (Runner r : runners) {
- BlockJUnit4RunnerDelegate castedRunner = (BlockJUnit4RunnerDelegate) r;
- for (FrameworkMethod method : castedRunner.computeTestMethods()) {
- Assert.assertTrue("This test name is not expected: " + method.getName(),
- expectedTestNames.contains(method.getName()));
- expectedTestNames.remove(method.getName());
- method.getName();
- }
- }
- Assert.assertTrue("These expected names are not found: "
- + Arrays.toString(expectedTestNames.toArray()),
- expectedTestNames.isEmpty());
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java b/base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java
deleted file mode 100644
index a147435355..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2015 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 android.os.Build;
-
-import junit.framework.TestCase;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-import org.robolectric.util.ReflectionHelpers;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-/** Unit tests for the DisableIf annotation and its SkipCheck implementation. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 21)
-public class DisableIfTest {
- @Test
- public void testSdkIsLessThanAndIsLessThan() {
- TestCase sdkIsLessThan = new TestCase("sdkIsLessThan") {
- @DisableIf.Build(sdk_is_less_than = 22)
- public void sdkIsLessThan() {}
- };
- Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sdkIsLessThan));
- }
-
- @Test
- public void testSdkIsLessThanButIsEqual() {
- TestCase sdkIsEqual = new TestCase("sdkIsEqual") {
- @DisableIf.Build(sdk_is_less_than = 21)
- public void sdkIsEqual() {}
- };
- Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsEqual));
- }
-
- @Test
- public void testSdkIsLessThanButIsGreaterThan() {
- TestCase sdkIsGreaterThan = new TestCase("sdkIsGreaterThan") {
- @DisableIf.Build(sdk_is_less_than = 20)
- public void sdkIsGreaterThan() {}
- };
- Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsGreaterThan));
- }
-
- @Test
- public void testSdkIsGreaterThanButIsLessThan() {
- TestCase sdkIsLessThan = new TestCase("sdkIsLessThan") {
- @DisableIf.Build(sdk_is_greater_than = 22)
- public void sdkIsLessThan() {}
- };
- Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsLessThan));
- }
-
- @Test
- public void testSdkIsGreaterThanButIsEqual() {
- TestCase sdkIsEqual = new TestCase("sdkIsEqual") {
- @DisableIf.Build(sdk_is_greater_than = 21)
- public void sdkIsEqual() {}
- };
- Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(sdkIsEqual));
- }
-
- @Test
- public void testSdkIsGreaterThanAndIsGreaterThan() {
- TestCase sdkIsGreaterThan = new TestCase("sdkIsGreaterThan") {
- @DisableIf.Build(sdk_is_greater_than = 20)
- public void sdkIsGreaterThan() {}
- };
- Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sdkIsGreaterThan));
- }
-
- @Test
- public void testSupportedAbiIncludesAndCpuAbiMatches() {
- TestCase supportedAbisCpuAbiMatch = new TestCase("supportedAbisCpuAbiMatch") {
- @DisableIf.Build(supported_abis_includes = "foo")
- public void supportedAbisCpuAbiMatch() {}
- };
- String[] originalAbis = Build.SUPPORTED_ABIS;
- try {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS",
- new String[] {"foo", "bar"});
- Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(supportedAbisCpuAbiMatch));
- } finally {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
- }
- }
-
- @Test
- public void testSupportedAbiIncludesAndCpuAbi2Matches() {
- TestCase supportedAbisCpuAbi2Match = new TestCase("supportedAbisCpuAbi2Match") {
- @DisableIf.Build(supported_abis_includes = "bar")
- public void supportedAbisCpuAbi2Match() {}
- };
- String[] originalAbis = Build.SUPPORTED_ABIS;
- try {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS",
- new String[] {"foo", "bar"});
- Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(supportedAbisCpuAbi2Match));
- } finally {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
- }
- }
-
- @Test
- public void testSupportedAbiIncludesButNoMatch() {
- TestCase supportedAbisNoMatch = new TestCase("supportedAbisNoMatch") {
- @DisableIf.Build(supported_abis_includes = "baz")
- public void supportedAbisNoMatch() {}
- };
- String[] originalAbis = Build.SUPPORTED_ABIS;
- try {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS",
- new String[] {"foo", "bar"});
- Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(supportedAbisNoMatch));
- } finally {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
- }
- }
-
- @Test
- public void testHardwareIsMatches() {
- TestCase hardwareIsMatches = new TestCase("hardwareIsMatches") {
- @DisableIf.Build(hardware_is = "hammerhead")
- public void hardwareIsMatches() {}
- };
- String originalHardware = Build.HARDWARE;
- try {
- ReflectionHelpers.setStaticField(Build.class, "HARDWARE", "hammerhead");
- Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(hardwareIsMatches));
- } finally {
- ReflectionHelpers.setStaticField(Build.class, "HARDWARE", originalHardware);
- }
- }
-
- @Test
- public void testHardwareIsDoesntMatch() {
- TestCase hardwareIsDoesntMatch = new TestCase("hardwareIsDoesntMatch") {
- @DisableIf.Build(hardware_is = "hammerhead")
- public void hardwareIsDoesntMatch() {}
- };
- String originalHardware = Build.HARDWARE;
- try {
- ReflectionHelpers.setStaticField(Build.class, "HARDWARE", "mako");
- Assert.assertFalse(new DisableIfSkipCheck().shouldSkip(hardwareIsDoesntMatch));
- } finally {
- ReflectionHelpers.setStaticField(Build.class, "HARDWARE", originalHardware);
- }
- }
-
- @DisableIf.Build(supported_abis_includes = "foo")
- private static class DisableIfSuperclassTestCase extends TestCase {
- public DisableIfSuperclassTestCase(String name) {
- super(name);
- }
- }
-
- @DisableIf.Build(hardware_is = "hammerhead")
- private static class DisableIfTestCase extends DisableIfSuperclassTestCase {
- public DisableIfTestCase(String name) {
- super(name);
- }
- public void sampleTestMethod() {}
- }
-
- @Test
- public void testDisableClass() {
- TestCase sampleTestMethod = new DisableIfTestCase("sampleTestMethod");
- String originalHardware = Build.HARDWARE;
- try {
- ReflectionHelpers.setStaticField(Build.class, "HARDWARE", "hammerhead");
- Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sampleTestMethod));
- } finally {
- ReflectionHelpers.setStaticField(Build.class, "HARDWARE", originalHardware);
- }
- }
-
- @Test
- public void testDisableSuperClass() {
- TestCase sampleTestMethod = new DisableIfTestCase("sampleTestMethod");
- String[] originalAbis = Build.SUPPORTED_ABIS;
- try {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", new String[] {"foo"});
- Assert.assertTrue(new DisableIfSkipCheck().shouldSkip(sampleTestMethod));
- } finally {
- ReflectionHelpers.setStaticField(Build.class, "SUPPORTED_ABIS", originalAbis);
- }
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java b/base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java
deleted file mode 100644
index 2236646938..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2016 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 static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.isIn;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.Description;
-import org.junit.runner.RunWith;
-import org.junit.runners.model.FrameworkMethod;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-/** Unit tests for MinAndroidSdkLevelSkipCheck. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 18)
-public class MinAndroidSdkLevelSkipCheckTest {
- public static class UnannotatedBaseClass {
- @Test @MinAndroidSdkLevel(17) public void min17Method() {}
- @Test @MinAndroidSdkLevel(20) public void min20Method() {}
- }
-
- @MinAndroidSdkLevel(17)
- public static class Min17Class extends UnannotatedBaseClass {
- @Test public void unannotatedMethod() {}
- }
-
- @MinAndroidSdkLevel(20)
- public static class Min20Class extends UnannotatedBaseClass {
- @Test public void unannotatedMethod() {}
- }
-
- public static class ExtendsMin17Class extends Min17Class {
- @Override
- @Test public void unannotatedMethod() {}
- }
-
- public static class ExtendsMin20Class extends Min20Class {
- @Override
- @Test public void unannotatedMethod() {}
- }
-
- private MinAndroidSdkLevelSkipCheck mSkipCheck = new MinAndroidSdkLevelSkipCheck();
-
- @Rule
- public TestRunnerTestRule mTestRunnerTestRule =
- new TestRunnerTestRule(BaseJUnit4ClassRunner.class);
-
- private void expectShouldSkip(Class<?> testClass, String methodName, boolean shouldSkip)
- throws Exception {
- Assert.assertThat(
- mSkipCheck.shouldSkip(new FrameworkMethod(testClass.getMethod(methodName))),
- equalTo(shouldSkip));
- TestRunnerTestRule.TestLog runListener = mTestRunnerTestRule.runTest(testClass);
- Assert.assertThat(Description.createTestDescription(testClass, methodName),
- isIn(shouldSkip ? runListener.skippedTests : runListener.runTests));
- }
-
- @Test
- public void testAnnotatedMethodAboveMin() throws Exception {
- expectShouldSkip(UnannotatedBaseClass.class, "min17Method", false);
- }
-
- @Test
- public void testAnnotatedMethodBelowMin() throws Exception {
- expectShouldSkip(UnannotatedBaseClass.class, "min20Method", true);
- }
-
- @Test
- public void testAnnotatedClassAboveMin() throws Exception {
- expectShouldSkip(Min17Class.class, "unannotatedMethod", false);
- }
-
- @Test
- public void testAnnotatedClassBelowMin() throws Exception {
- expectShouldSkip(Min20Class.class, "unannotatedMethod", true);
- }
-
- @Test
- public void testAnnotatedSuperclassAboveMin() throws Exception {
- expectShouldSkip(ExtendsMin17Class.class, "unannotatedMethod", false);
- }
-
- @Test
- public void testAnnotatedSuperclassBelowMin() throws Exception {
- expectShouldSkip(ExtendsMin20Class.class, "unannotatedMethod", true);
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java b/base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java
deleted file mode 100644
index 86285de3f0..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2016 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 android.text.TextUtils;
-
-import junit.framework.TestCase;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-/** Unit tests for RestrictionSkipCheck. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class RestrictionSkipCheckTest {
- private static final String TEST_RESTRICTION_APPLIES =
- "org.chromium.base.test.util.RestrictionSkipCheckTest.TEST_RESTRICTION_APPLIES";
- private static final String TEST_RESTRICTION_DOES_NOT_APPLY =
- "org.chromium.base.test.util.RestrictionSkipCheckTest.TEST_RESTRICTION_DOES_NOT_APPLY";
-
- private static class TestRestrictionSkipCheck extends RestrictionSkipCheck {
- public TestRestrictionSkipCheck() {
- super(null);
- }
- @Override
- protected boolean restrictionApplies(String restriction) {
- return TextUtils.equals(restriction, TEST_RESTRICTION_APPLIES);
- }
- }
-
- private static class UnannotatedBaseClass extends TestCase {
- public UnannotatedBaseClass(String name) {
- super(name);
- }
- @Restriction({TEST_RESTRICTION_APPLIES}) public void restrictedMethod() {}
- @Restriction({TEST_RESTRICTION_DOES_NOT_APPLY}) public void unrestrictedMethod() {}
- }
-
- @Restriction({TEST_RESTRICTION_APPLIES})
- private static class RestrictedClass extends UnannotatedBaseClass {
- public RestrictedClass(String name) {
- super(name);
- }
- public void unannotatedMethod() {}
- }
-
- @Restriction({TEST_RESTRICTION_DOES_NOT_APPLY})
- private static class UnrestrictedClass extends UnannotatedBaseClass {
- public UnrestrictedClass(String name) {
- super(name);
- }
- public void unannotatedMethod() {}
- }
-
- @Restriction({
- TEST_RESTRICTION_APPLIES,
- TEST_RESTRICTION_DOES_NOT_APPLY})
- private static class MultipleRestrictionsRestrictedClass extends UnannotatedBaseClass {
- public MultipleRestrictionsRestrictedClass(String name) {
- super(name);
- }
- public void unannotatedMethod() {}
- }
-
- private static class ExtendsRestrictedClass extends RestrictedClass {
- public ExtendsRestrictedClass(String name) {
- super(name);
- }
- @Override
- public void unannotatedMethod() {}
- }
-
- private static class ExtendsUnrestrictedClass extends UnrestrictedClass {
- public ExtendsUnrestrictedClass(String name) {
- super(name);
- }
- @Override
- public void unannotatedMethod() {}
- }
-
- @Test
- public void testMethodRestricted() {
- Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
- new UnannotatedBaseClass("restrictedMethod")));
- }
-
- @Test
- public void testMethodUnrestricted() {
- Assert.assertFalse(new TestRestrictionSkipCheck().shouldSkip(
- new UnannotatedBaseClass("unrestrictedMethod")));
- }
-
- @Test
- public void testClassRestricted() {
- Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
- new RestrictedClass("unannotatedMethod")));
- }
-
- @Test
- public void testClassUnrestricted() {
- Assert.assertFalse(new TestRestrictionSkipCheck().shouldSkip(
- new UnrestrictedClass("unannotatedMethod")));
- }
-
- @Test
- public void testMultipleRestrictionsClassRestricted() {
- Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
- new MultipleRestrictionsRestrictedClass("unannotatedMethod")));
- }
-
- @Test
- public void testSuperclassRestricted() {
- Assert.assertTrue(new TestRestrictionSkipCheck().shouldSkip(
- new ExtendsRestrictedClass("unannotatedMethod")));
- }
-
- @Test
- public void testSuperclassUnrestricted() {
- Assert.assertFalse(new TestRestrictionSkipCheck().shouldSkip(
- new ExtendsUnrestrictedClass("unannotatedMethod")));
- }
-}
-
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java b/base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java
deleted file mode 100644
index 51c7516e71..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2016 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 junit.framework.TestCase;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.model.FrameworkMethod;
-import org.robolectric.annotation.Config;
-
-import org.chromium.base.test.BaseRobolectricTestRunner;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Method;
-import java.util.List;
-
-/** Unit tests for SkipCheck. */
-@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
-public class SkipCheckTest {
- private static class TestableSkipCheck extends SkipCheck {
- public static <T extends Annotation> List<T> getAnnotationsForTesting(
- AnnotatedElement element, Class<T> annotationClass) {
- return AnnotationProcessingUtils.getAnnotations(element, annotationClass);
- }
-
- @Override
- public boolean shouldSkip(FrameworkMethod m) {
- return false;
- }
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- private @interface TestAnnotation {}
-
- @TestAnnotation
- private class AnnotatedBaseClass {
- public void unannotatedMethod() {}
- @TestAnnotation public void annotatedMethod() {}
- }
-
- private class ExtendsAnnotatedBaseClass extends AnnotatedBaseClass {
- public void anotherUnannotatedMethod() {}
- }
-
- private class ExtendsTestCaseClass extends TestCase {
- public ExtendsTestCaseClass(String name) {
- super(name);
- }
- public void testMethodA() {}
- }
-
- private class UnannotatedBaseClass {
- public void unannotatedMethod() {}
- @TestAnnotation public void annotatedMethod() {}
- }
-
- @Test
- public void getAnnotationsForClassNone() {
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- UnannotatedBaseClass.class, TestAnnotation.class);
- Assert.assertEquals(0, annotations.size());
- }
-
- @Test
- public void getAnnotationsForClassOnClass() {
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- AnnotatedBaseClass.class, TestAnnotation.class);
- Assert.assertEquals(1, annotations.size());
- }
-
- @Test
- public void getAnnotationsForClassOnSuperclass() {
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- ExtendsAnnotatedBaseClass.class, TestAnnotation.class);
- Assert.assertEquals(1, annotations.size());
- }
-
- @Test
- public void getAnnotationsForMethodNone() throws NoSuchMethodException {
- Method testMethod = UnannotatedBaseClass.class.getMethod("unannotatedMethod",
- (Class[]) null);
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- testMethod, TestAnnotation.class);
- Assert.assertEquals(0, annotations.size());
- }
-
- @Test
- public void getAnnotationsForMethodOnMethod() throws NoSuchMethodException {
- Method testMethod = UnannotatedBaseClass.class.getMethod("annotatedMethod",
- (Class[]) null);
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- testMethod, TestAnnotation.class);
- Assert.assertEquals(1, annotations.size());
- }
-
- @Test
- public void getAnnotationsForMethodOnClass() throws NoSuchMethodException {
- Method testMethod = AnnotatedBaseClass.class.getMethod("unannotatedMethod",
- (Class[]) null);
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- testMethod, TestAnnotation.class);
- Assert.assertEquals(1, annotations.size());
- }
-
- @Test
- public void getAnnotationsForMethodOnSuperclass() throws NoSuchMethodException {
- Method testMethod = ExtendsAnnotatedBaseClass.class.getMethod("unannotatedMethod",
- (Class[]) null);
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- testMethod, TestAnnotation.class);
- Assert.assertEquals(1, annotations.size());
- }
-
- @Test
- public void getAnnotationsOverlapping() throws NoSuchMethodException {
- Method testMethod = AnnotatedBaseClass.class.getMethod("annotatedMethod",
- (Class[]) null);
- List<TestAnnotation> annotations = TestableSkipCheck.getAnnotationsForTesting(
- testMethod, TestAnnotation.class);
- Assert.assertEquals(2, annotations.size());
- }
-}
diff --git a/base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java b/base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java
deleted file mode 100644
index 64805c124e..0000000000
--- a/base/test/android/junit/src/org/chromium/base/test/util/TestRunnerTestRule.java
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2018 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 static org.hamcrest.Matchers.isIn;
-import static org.junit.Assert.fail;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
-
-import org.junit.Assert;
-import org.junit.rules.ExternalResource;
-import org.junit.runner.Description;
-import org.junit.runner.Runner;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunListener;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RuntimeEnvironment;
-
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Helper rule to allow executing test runners in tests.
- *
- * Quis probat ipsas probas?
- */
-class TestRunnerTestRule extends ExternalResource {
- final Class<? extends BlockJUnit4ClassRunner> mRunnerClass;
-
- /**
- * @param runnerClass The runner class to run the test
- */
- TestRunnerTestRule(Class<? extends BlockJUnit4ClassRunner> runnerClass) {
- mRunnerClass = runnerClass;
- }
-
- @Override
- protected void before() throws Throwable {
- // Register a fake Instrumentation so that class runners for instrumentation tests
- // can be run even in Robolectric tests.
- Instrumentation instrumentation = new Instrumentation() {
- @Override
- public Context getTargetContext() {
- return RuntimeEnvironment.application;
- }
- };
- InstrumentationRegistry.registerInstance(instrumentation, new Bundle());
- }
-
- @Override
- protected void after() {
- InstrumentationRegistry.registerInstance(null, new Bundle());
- }
-
- /**
- * A struct-like class containing lists of run and skipped tests.
- */
- public static class TestLog {
- public final List<Description> runTests = new ArrayList<>();
- public final List<Description> skippedTests = new ArrayList<>();
- }
-
- /**
- * Creates a new test runner and executes the test in the given {@code testClass} on it,
- * returning lists of tests that were run and tests that were skipped.
- * @param testClass The test class
- * @return A {@link TestLog} that contains lists of run and skipped tests.
- */
- public TestLog runTest(Class<?> testClass) throws InvocationTargetException,
- NoSuchMethodException, InstantiationException,
- IllegalAccessException {
- TestLog testLog = new TestLog();
-
- // TODO(bauerb): Using Mockito mock() or spy() throws a ClassCastException.
- RunListener runListener = new RunListener() {
- @Override
- public void testStarted(Description description) throws Exception {
- testLog.runTests.add(description);
- }
-
- @Override
- public void testFinished(Description description) throws Exception {
- Assert.assertThat(description, isIn(testLog.runTests));
- }
-
- @Override
- public void testFailure(Failure failure) throws Exception {
- fail(failure.toString());
- }
-
- @Override
- public void testAssumptionFailure(Failure failure) {
- fail(failure.toString());
- }
-
- @Override
- public void testIgnored(Description description) throws Exception {
- testLog.skippedTests.add(description);
- }
- };
- RunNotifier runNotifier = new RunNotifier();
- runNotifier.addListener(runListener);
- Runner runner;
- try {
- runner = mRunnerClass.getConstructor(Class.class).newInstance(testClass);
- } catch (InvocationTargetException e) {
- // If constructing the runner caused initialization errors, unwrap them from the
- // InvocationTargetException.
- Throwable cause = e.getCause();
- if (!(cause instanceof InitializationError)) throw e;
- List<Throwable> causes = ((InitializationError) cause).getCauses();
-
- // If there was exactly one initialization error, rewrap that one.
- if (causes.size() == 1) {
- throw new InvocationTargetException(causes.get(0), "Initialization error");
- }
-
- // Otherwise, serialize all initialization errors to a string and throw that.
- throw new AssertionError(causes.toString());
- }
- runner.run(runNotifier);
- return testLog;
- }
-}
diff --git a/base/test/fuzzed_data_provider.cc b/base/test/fuzzed_data_provider.cc
deleted file mode 100644
index b2d443a9b9..0000000000
--- a/base/test/fuzzed_data_provider.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2016 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/fuzzed_data_provider.h"
-
-#include <algorithm>
-#include <limits>
-
-#include "base/logging.h"
-
-namespace base {
-
-FuzzedDataProvider::FuzzedDataProvider(const uint8_t* data, size_t size)
- : remaining_data_(reinterpret_cast<const char*>(data), size) {}
-
-FuzzedDataProvider::~FuzzedDataProvider() = default;
-
-std::string FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
- num_bytes = std::min(num_bytes, remaining_data_.length());
- StringPiece result(remaining_data_.data(), num_bytes);
- remaining_data_ = remaining_data_.substr(num_bytes);
- return result.as_string();
-}
-
-std::string FuzzedDataProvider::ConsumeRemainingBytes() {
- return ConsumeBytes(remaining_data_.length());
-}
-
-uint32_t FuzzedDataProvider::ConsumeUint32InRange(uint32_t min, uint32_t max) {
- CHECK_LE(min, max);
-
- uint32_t range = max - min;
- uint32_t offset = 0;
- uint32_t result = 0;
-
- while (offset < 32 && (range >> offset) > 0 && !remaining_data_.empty()) {
- // Pull bytes off the end of the seed data. Experimentally, this seems to
- // allow the fuzzer to more easily explore the input space. This makes
- // sense, since it works by modifying inputs that caused new code to run,
- // and this data is often used to encode length of data read by
- // ConsumeBytes. Separating out read lengths makes it easier modify the
- // contents of the data that is actually read.
- uint8_t next_byte = remaining_data_.back();
- remaining_data_.remove_suffix(1);
- result = (result << 8) | next_byte;
- offset += 8;
- }
-
- // Avoid division by 0, in the case |range + 1| results in overflow.
- if (range == std::numeric_limits<uint32_t>::max())
- return result;
-
- return min + result % (range + 1);
-}
-
-std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
- // Reads bytes from start of |remaining_data_|. Maps "\\" to "\", and maps "\"
- // followed by anything else to the end of the string. As a result of this
- // logic, a fuzzer can insert characters into the string, and the string will
- // be lengthened to include those new characters, resulting in a more stable
- // fuzzer than picking the length of a string independently from picking its
- // contents.
- std::string out;
- for (size_t i = 0; i < max_length && !remaining_data_.empty(); ++i) {
- char next = remaining_data_[0];
- remaining_data_.remove_prefix(1);
- if (next == '\\' && !remaining_data_.empty()) {
- next = remaining_data_[0];
- remaining_data_.remove_prefix(1);
- if (next != '\\')
- return out;
- }
- out += next;
- }
- return out;
-}
-
-int FuzzedDataProvider::ConsumeInt32InRange(int min, int max) {
- CHECK_LE(min, max);
-
- uint32_t range = max - min;
- return min + ConsumeUint32InRange(0, range);
-}
-
-bool FuzzedDataProvider::ConsumeBool() {
- return (ConsumeUint8() & 0x01) == 0x01;
-}
-
-uint8_t FuzzedDataProvider::ConsumeUint8() {
- return ConsumeUint32InRange(0, 0xFF);
-}
-
-uint16_t FuzzedDataProvider::ConsumeUint16() {
- return ConsumeUint32InRange(0, 0xFFFF);
-}
-
-} // namespace base
diff --git a/base/test/fuzzed_data_provider.h b/base/test/fuzzed_data_provider.h
deleted file mode 100644
index 425c820a21..0000000000
--- a/base/test/fuzzed_data_provider.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TEST_FUZZED_DATA_PROVIDER_H_
-#define BASE_TEST_FUZZED_DATA_PROVIDER_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-
-namespace base {
-
-// Utility class to break up fuzzer input for multiple consumers. Whenever run
-// on the same input, provides the same output, as long as its methods are
-// called in the same order, with the same arguments.
-class FuzzedDataProvider {
- public:
- // |data| is an array of length |size| that the FuzzedDataProvider wraps to
- // provide more granular access. |data| must outlive the FuzzedDataProvider.
- FuzzedDataProvider(const uint8_t* data, size_t size);
- ~FuzzedDataProvider();
-
- // Returns a std::string containing |num_bytes| of input data. If fewer than
- // |num_bytes| of data remain, returns a shorter std::string containing all
- // of the data that's left.
- std::string ConsumeBytes(size_t num_bytes);
-
- // Returns a std::string containing all remaining bytes of the input data.
- std::string ConsumeRemainingBytes();
-
- // Returns a std::string of length from 0 to |max_length|. When it runs out of
- // input data, returns what remains of the input. Designed to be more stable
- // with respect to a fuzzer inserting characters than just picking a random
- // length and then consuming that many bytes with ConsumeBytes().
- std::string ConsumeRandomLengthString(size_t max_length);
-
- // Returns a number in the range [min, max] by consuming bytes from the input
- // data. The value might not be uniformly distributed in the given range. If
- // there's no input data left, always returns |min|. |min| must be less than
- // or equal to |max|.
- uint32_t ConsumeUint32InRange(uint32_t min, uint32_t max);
- int ConsumeInt32InRange(int min, int max);
-
- // Returns a bool, or false when no data remains.
- bool ConsumeBool();
-
- // Returns a uint8_t from the input or 0 if nothing remains. This is
- // equivalent to ConsumeUint32InRange(0, 0xFF).
- uint8_t ConsumeUint8();
-
- // Returns a uint16_t from the input. If fewer than 2 bytes of data remain
- // will fill the most significant bytes with 0. This is equivalent to
- // ConsumeUint32InRange(0, 0xFFFF).
- uint16_t ConsumeUint16();
-
- // Returns a value from |array|, consuming as many bytes as needed to do so.
- // |array| must be a fixed-size array. Equivalent to
- // array[ConsumeUint32InRange(sizeof(array)-1)];
- template <typename Type, size_t size>
- Type PickValueInArray(Type (&array)[size]) {
- return array[ConsumeUint32InRange(0, size - 1)];
- }
-
- // Reports the remaining bytes available for fuzzed input.
- size_t remaining_bytes() { return remaining_data_.length(); }
-
- private:
- StringPiece remaining_data_;
-
- DISALLOW_COPY_AND_ASSIGN(FuzzedDataProvider);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_FUZZED_DATA_PROVIDER_H_
diff --git a/base/test/gtest_xml_unittest_result_printer.cc b/base/test/gtest_xml_unittest_result_printer.cc
deleted file mode 100644
index 558a9867b4..0000000000
--- a/base/test/gtest_xml_unittest_result_printer.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright 2015 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/gtest_xml_unittest_result_printer.h"
-
-#include "base/base64.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/test/test_switches.h"
-#include "base/time/time.h"
-
-namespace base {
-
-namespace {
-const int kDefaultTestPartResultsLimit = 10;
-
-const char kTestPartLesultsLimitExceeded[] =
- "Test part results limit exceeded. Use --test-launcher-test-part-limit to "
- "increase or disable limit.";
-} // namespace
-
-XmlUnitTestResultPrinter::XmlUnitTestResultPrinter()
- : output_file_(nullptr), open_failed_(false) {}
-
-XmlUnitTestResultPrinter::~XmlUnitTestResultPrinter() {
- if (output_file_ && !open_failed_) {
- fprintf(output_file_, "</testsuites>\n");
- fflush(output_file_);
- CloseFile(output_file_);
- }
-}
-
-bool XmlUnitTestResultPrinter::Initialize(const FilePath& output_file_path) {
- DCHECK(!output_file_);
- output_file_ = OpenFile(output_file_path, "w");
- if (!output_file_) {
- // If the file open fails, we set the output location to stderr. This is
- // because in current usage our caller CHECKs the result of this function.
- // But that in turn causes a LogMessage that comes back to this object,
- // which in turn causes a (double) crash. By pointing at stderr, there might
- // be some indication what's going wrong. See https://crbug.com/736783.
- output_file_ = stderr;
- open_failed_ = true;
- return false;
- }
-
- fprintf(output_file_,
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<testsuites>\n");
- fflush(output_file_);
-
- return true;
-}
-
-void XmlUnitTestResultPrinter::OnAssert(const char* file,
- int line,
- const std::string& summary,
- const std::string& message) {
- WriteTestPartResult(file, line, testing::TestPartResult::kFatalFailure,
- summary, message);
-}
-
-void XmlUnitTestResultPrinter::OnTestCaseStart(
- const testing::TestCase& test_case) {
- fprintf(output_file_, " <testsuite>\n");
- fflush(output_file_);
-}
-
-void XmlUnitTestResultPrinter::OnTestStart(
- const testing::TestInfo& test_info) {
- // This is our custom extension - it helps to recognize which test was
- // running when the test binary crashed. Note that we cannot even open the
- // <testcase> tag here - it requires e.g. run time of the test to be known.
- fprintf(output_file_,
- " <x-teststart name=\"%s\" classname=\"%s\" />\n",
- test_info.name(),
- test_info.test_case_name());
- fflush(output_file_);
-}
-
-void XmlUnitTestResultPrinter::OnTestEnd(const testing::TestInfo& test_info) {
- fprintf(output_file_,
- " <testcase name=\"%s\" status=\"run\" time=\"%.3f\""
- " classname=\"%s\">\n",
- test_info.name(),
- static_cast<double>(test_info.result()->elapsed_time()) /
- Time::kMillisecondsPerSecond,
- test_info.test_case_name());
- if (test_info.result()->Failed()) {
- fprintf(output_file_,
- " <failure message=\"\" type=\"\"></failure>\n");
- }
-
- int limit = test_info.result()->total_part_count();
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTestLauncherTestPartResultsLimit)) {
- std::string limit_str =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTestLauncherTestPartResultsLimit);
- int test_part_results_limit = std::strtol(limit_str.c_str(), nullptr, 10);
- if (test_part_results_limit >= 0)
- limit = std::min(limit, test_part_results_limit);
- } else {
- limit = std::min(limit, kDefaultTestPartResultsLimit);
- }
-
- for (int i = 0; i < limit; ++i) {
- const auto& test_part_result = test_info.result()->GetTestPartResult(i);
- WriteTestPartResult(test_part_result.file_name(),
- test_part_result.line_number(), test_part_result.type(),
- test_part_result.summary(), test_part_result.message());
- }
-
- if (test_info.result()->total_part_count() > limit) {
- WriteTestPartResult(
- "<unknown>", 0, testing::TestPartResult::kNonFatalFailure,
- kTestPartLesultsLimitExceeded, kTestPartLesultsLimitExceeded);
- }
-
- fprintf(output_file_, " </testcase>\n");
- fflush(output_file_);
-}
-
-void XmlUnitTestResultPrinter::OnTestCaseEnd(
- const testing::TestCase& test_case) {
- fprintf(output_file_, " </testsuite>\n");
- fflush(output_file_);
-}
-
-void XmlUnitTestResultPrinter::WriteTestPartResult(
- const char* file,
- int line,
- testing::TestPartResult::Type result_type,
- const std::string& summary,
- const std::string& message) {
- const char* type = "unknown";
- switch (result_type) {
- case testing::TestPartResult::kSuccess:
- type = "success";
- break;
- case testing::TestPartResult::kNonFatalFailure:
- type = "failure";
- break;
- case testing::TestPartResult::kFatalFailure:
- type = "fatal_failure";
- break;
- }
- std::string summary_encoded;
- Base64Encode(summary, &summary_encoded);
- std::string message_encoded;
- Base64Encode(message, &message_encoded);
- fprintf(output_file_,
- " <x-test-result-part type=\"%s\" file=\"%s\" line=\"%d\">\n"
- " <summary>%s</summary>\n"
- " <message>%s</message>\n"
- " </x-test-result-part>\n",
- type, file, line, summary_encoded.c_str(), message_encoded.c_str());
- fflush(output_file_);
-}
-
-} // namespace base
diff --git a/base/test/gtest_xml_unittest_result_printer.h b/base/test/gtest_xml_unittest_result_printer.h
deleted file mode 100644
index 93403822cf..0000000000
--- a/base/test/gtest_xml_unittest_result_printer.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_GTEST_XML_UNITTEST_RESULT_PRINTER_H_
-#define BASE_TEST_GTEST_XML_UNITTEST_RESULT_PRINTER_H_
-
-#include <stdio.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class FilePath;
-
-// Generates an XML output file. Format is very close to GTest, but has
-// extensions needed by the test launcher.
-class XmlUnitTestResultPrinter : public testing::EmptyTestEventListener {
- public:
- XmlUnitTestResultPrinter();
- ~XmlUnitTestResultPrinter() override;
-
- // Must be called before adding as a listener. Returns true on success.
- bool Initialize(const FilePath& output_file_path) WARN_UNUSED_RESULT;
-
- // CHECK/DCHECK failed. Print file/line and message to the xml.
- void OnAssert(const char* file,
- int line,
- const std::string& summary,
- const std::string& message);
-
- private:
- // testing::EmptyTestEventListener:
- void OnTestCaseStart(const testing::TestCase& test_case) override;
- void OnTestStart(const testing::TestInfo& test_info) override;
- void OnTestEnd(const testing::TestInfo& test_info) override;
- void OnTestCaseEnd(const testing::TestCase& test_case) override;
-
- void WriteTestPartResult(const char* file,
- int line,
- testing::TestPartResult::Type type,
- const std::string& summary,
- const std::string& message);
-
- FILE* output_file_;
- bool open_failed_;
-
- DISALLOW_COPY_AND_ASSIGN(XmlUnitTestResultPrinter);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_GTEST_XML_UNITTEST_RESULT_PRINTER_H_
diff --git a/base/test/gtest_xml_util.cc b/base/test/gtest_xml_util.cc
deleted file mode 100644
index 37104e88ae..0000000000
--- a/base/test/gtest_xml_util.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2013 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/gtest_xml_util.h"
-
-#include <stdint.h>
-
-#include "base/base64.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/gtest_util.h"
-#include "base/test/launcher/test_launcher.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-
-namespace base {
-
-namespace {
-
-// This is used for the xml parser to report errors. This assumes the context
-// is a pointer to a std::string where the error message should be appended.
-static void XmlErrorFunc(void *context, const char *message, ...) {
- va_list args;
- va_start(args, message);
- std::string* error = static_cast<std::string*>(context);
- StringAppendV(error, message, args);
- va_end(args);
-}
-
-} // namespace
-
-bool ProcessGTestOutput(const base::FilePath& output_file,
- std::vector<TestResult>* results,
- bool* crashed) {
- DCHECK(results);
-
- std::string xml_contents;
- if (!ReadFileToString(output_file, &xml_contents))
- return false;
-
- // Silence XML errors - otherwise they go to stderr.
- std::string xml_errors;
- ScopedXmlErrorFunc error_func(&xml_errors, &XmlErrorFunc);
-
- XmlReader xml_reader;
- if (!xml_reader.Load(xml_contents))
- return false;
-
- enum {
- STATE_INIT,
- STATE_TESTSUITE,
- STATE_TESTCASE,
- STATE_TEST_RESULT,
- STATE_FAILURE,
- STATE_END,
- } state = STATE_INIT;
-
- while (xml_reader.Read()) {
- xml_reader.SkipToElement();
- std::string node_name(xml_reader.NodeName());
-
- switch (state) {
- case STATE_INIT:
- if (node_name == "testsuites" && !xml_reader.IsClosingElement())
- state = STATE_TESTSUITE;
- else
- return false;
- break;
- case STATE_TESTSUITE:
- if (node_name == "testsuites" && xml_reader.IsClosingElement())
- state = STATE_END;
- else if (node_name == "testsuite" && !xml_reader.IsClosingElement())
- state = STATE_TESTCASE;
- else
- return false;
- break;
- case STATE_TESTCASE:
- if (node_name == "testsuite" && xml_reader.IsClosingElement()) {
- state = STATE_TESTSUITE;
- } else if (node_name == "x-teststart" &&
- !xml_reader.IsClosingElement()) {
- // This is our custom extension that helps recognize which test was
- // running when the test binary crashed.
- TestResult result;
-
- std::string test_case_name;
- if (!xml_reader.NodeAttribute("classname", &test_case_name))
- return false;
- std::string test_name;
- if (!xml_reader.NodeAttribute("name", &test_name))
- return false;
- result.full_name = FormatFullTestName(test_case_name, test_name);
-
- result.elapsed_time = TimeDelta();
-
- // Assume the test crashed - we can correct that later.
- result.status = TestResult::TEST_CRASH;
-
- results->push_back(result);
- } else if (node_name == "testcase" && !xml_reader.IsClosingElement()) {
- std::string test_status;
- if (!xml_reader.NodeAttribute("status", &test_status))
- return false;
-
- if (test_status != "run" && test_status != "notrun")
- return false;
- if (test_status != "run")
- break;
-
- TestResult result;
-
- std::string test_case_name;
- if (!xml_reader.NodeAttribute("classname", &test_case_name))
- return false;
- std::string test_name;
- if (!xml_reader.NodeAttribute("name", &test_name))
- return false;
- result.full_name = test_case_name + "." + test_name;
-
- std::string test_time_str;
- if (!xml_reader.NodeAttribute("time", &test_time_str))
- return false;
- result.elapsed_time = TimeDelta::FromMicroseconds(
- static_cast<int64_t>(strtod(test_time_str.c_str(), nullptr) *
- Time::kMicrosecondsPerSecond));
-
- result.status = TestResult::TEST_SUCCESS;
-
- if (!results->empty() &&
- results->back().full_name == result.full_name &&
- results->back().status == TestResult::TEST_CRASH) {
- // Erase the fail-safe "crashed" result - now we know the test did
- // not crash.
- results->pop_back();
- }
-
- results->push_back(result);
- } else if (node_name == "failure" && !xml_reader.IsClosingElement()) {
- std::string failure_message;
- if (!xml_reader.NodeAttribute("message", &failure_message))
- return false;
-
- DCHECK(!results->empty());
- results->back().status = TestResult::TEST_FAILURE;
-
- state = STATE_FAILURE;
- } else if (node_name == "testcase" && xml_reader.IsClosingElement()) {
- // Deliberately empty.
- } else if (node_name == "x-test-result-part" &&
- !xml_reader.IsClosingElement()) {
- std::string result_type;
- if (!xml_reader.NodeAttribute("type", &result_type))
- return false;
-
- std::string file_name;
- if (!xml_reader.NodeAttribute("file", &file_name))
- return false;
-
- std::string line_number_str;
- if (!xml_reader.NodeAttribute("line", &line_number_str))
- return false;
-
- int line_number;
- if (!StringToInt(line_number_str, &line_number))
- return false;
-
- TestResultPart::Type type;
- if (!TestResultPart::TypeFromString(result_type, &type))
- return false;
-
- TestResultPart test_result_part;
- test_result_part.type = type;
- test_result_part.file_name = file_name,
- test_result_part.line_number = line_number;
- DCHECK(!results->empty());
- results->back().test_result_parts.push_back(test_result_part);
-
- state = STATE_TEST_RESULT;
- } else {
- return false;
- }
- break;
- case STATE_TEST_RESULT:
- if (node_name == "summary" && !xml_reader.IsClosingElement()) {
- std::string summary;
- if (!xml_reader.ReadElementContent(&summary))
- return false;
-
- if (!Base64Decode(summary, &summary))
- return false;
-
- DCHECK(!results->empty());
- DCHECK(!results->back().test_result_parts.empty());
- results->back().test_result_parts.back().summary = summary;
- } else if (node_name == "summary" && xml_reader.IsClosingElement()) {
- } else if (node_name == "message" && !xml_reader.IsClosingElement()) {
- std::string message;
- if (!xml_reader.ReadElementContent(&message))
- return false;
-
- if (!Base64Decode(message, &message))
- return false;
-
- DCHECK(!results->empty());
- DCHECK(!results->back().test_result_parts.empty());
- results->back().test_result_parts.back().message = message;
- } else if (node_name == "message" && xml_reader.IsClosingElement()) {
- } else if (node_name == "x-test-result-part" &&
- xml_reader.IsClosingElement()) {
- state = STATE_TESTCASE;
- } else {
- return false;
- }
- break;
- case STATE_FAILURE:
- if (node_name == "failure" && xml_reader.IsClosingElement())
- state = STATE_TESTCASE;
- else
- return false;
- break;
- case STATE_END:
- // If we are here and there are still XML elements, the file has wrong
- // format.
- return false;
- }
- }
-
- *crashed = (state != STATE_END);
- return true;
-}
-
-} // namespace base
diff --git a/base/test/gtest_xml_util.h b/base/test/gtest_xml_util.h
deleted file mode 100644
index b023f80da1..0000000000
--- a/base/test/gtest_xml_util.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_GTEST_XML_UTIL_H_
-#define BASE_TEST_GTEST_XML_UTIL_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-
-namespace base {
-
-class FilePath;
-struct TestResult;
-
-// Produces a vector of test results based on GTest output file.
-// Returns true iff the output file exists and has been successfully parsed.
-// On successful return |crashed| is set to true if the test results
-// are valid but incomplete.
-bool ProcessGTestOutput(const base::FilePath& output_file,
- std::vector<TestResult>* results,
- bool* crashed) WARN_UNUSED_RESULT;
-
-} // namespace base
-
-#endif // BASE_TEST_GTEST_XML_UTIL_H_
diff --git a/base/test/icu_test_util.cc b/base/test/icu_test_util.cc
deleted file mode 100644
index a6f3e55665..0000000000
--- a/base/test/icu_test_util.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2015 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/icu_test_util.h"
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/i18n/icu_util.h"
-#include "base/i18n/rtl.h"
-#include "third_party/icu/source/common/unicode/uloc.h"
-
-namespace base {
-namespace test {
-
-ScopedRestoreICUDefaultLocale::ScopedRestoreICUDefaultLocale()
- : ScopedRestoreICUDefaultLocale(std::string()) {}
-
-ScopedRestoreICUDefaultLocale::ScopedRestoreICUDefaultLocale(
- const std::string& locale)
- : default_locale_(uloc_getDefault()) {
- if (!locale.empty())
- i18n::SetICUDefaultLocale(locale.data());
-}
-
-ScopedRestoreICUDefaultLocale::~ScopedRestoreICUDefaultLocale() {
- i18n::SetICUDefaultLocale(default_locale_.data());
-}
-
-void InitializeICUForTesting() {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTestDoNotInitializeIcu)) {
- i18n::AllowMultipleInitializeCallsForTesting();
- i18n::InitializeICU();
- }
-}
-
-} // namespace test
-} // namespace base
diff --git a/base/test/icu_test_util.h b/base/test/icu_test_util.h
deleted file mode 100644
index 1a6e47d3ab..0000000000
--- a/base/test/icu_test_util.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TEST_ICU_TEST_UTIL_H_
-#define BASE_TEST_ICU_TEST_UTIL_H_
-
-#include <string>
-
-#include "base/macros.h"
-
-namespace base {
-namespace test {
-
-// In unit tests, prefer ScopedRestoreICUDefaultLocale over
-// calling base::i18n::SetICUDefaultLocale() directly. This scoper makes it
-// harder to accidentally forget to reset the locale.
-class ScopedRestoreICUDefaultLocale {
- public:
- ScopedRestoreICUDefaultLocale();
- explicit ScopedRestoreICUDefaultLocale(const std::string& locale);
- ~ScopedRestoreICUDefaultLocale();
-
- private:
- const std::string default_locale_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedRestoreICUDefaultLocale);
-};
-
-void InitializeICUForTesting();
-
-} // namespace test
-} // namespace base
-
-#endif // BASE_TEST_ICU_TEST_UTIL_H_
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
deleted file mode 100644
index ddd9a4dc18..0000000000
--- a/base/test/launcher/test_launcher.cc
+++ /dev/null
@@ -1,1345 +0,0 @@
-// Copyright 2013 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 <stdio.h>
-
-#include <algorithm>
-#include <map>
-#include <random>
-#include <utility>
-
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/format_macros.h"
-#include "base/hash.h"
-#include "base/lazy_instance.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/pattern.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringize_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/sys_info.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "base/test/gtest_util.h"
-#include "base/test/launcher/test_launcher_tracer.h"
-#include "base/test/launcher/test_results_tracker.h"
-#include "base/test/test_switches.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include <fcntl.h>
-
-#include "base/files/file_descriptor_watcher_posix.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
-#endif
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
-#if defined(OS_FUCHSIA)
-#include <lib/zx/job.h>
-#include "base/fuchsia/default_job.h"
-#include "base/fuchsia/fuchsia_logging.h"
-#endif
-
-namespace base {
-
-// See https://groups.google.com/a/chromium.org/d/msg/chromium-dev/nkdTP7sstSc/uT3FaE_sgkAJ .
-using ::operator<<;
-
-// The environment variable name for the total number of test shards.
-const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
-// The environment variable name for the test shard index.
-const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
-
-namespace {
-
-// Global tag for test runs where the results are incomplete or unreliable
-// for any reason, e.g. early exit because of too many broken tests.
-const char kUnreliableResultsTag[] = "UNRELIABLE_RESULTS";
-
-// Maximum time of no output after which we print list of processes still
-// running. This deliberately doesn't use TestTimeouts (which is otherwise
-// a recommended solution), because they can be increased. This would defeat
-// the purpose of this timeout, which is 1) to avoid buildbot "no output for
-// X seconds" timeout killing the process 2) help communicate status of
-// the test launcher to people looking at the output (no output for a long
-// time is mysterious and gives no info about what is happening) 3) help
-// debugging in case the process hangs anyway.
-constexpr TimeDelta kOutputTimeout = TimeDelta::FromSeconds(15);
-
-// Limit of output snippet lines when printing to stdout.
-// Avoids flooding the logs with amount of output that gums up
-// the infrastructure.
-const size_t kOutputSnippetLinesLimit = 5000;
-
-// Limit of output snippet size. Exceeding this limit
-// results in truncating the output and failing the test.
-const size_t kOutputSnippetBytesLimit = 300 * 1024;
-
-// Limit of seed values for gtest shuffling. Arbitrary, but based on
-// gtest's similarly arbitrary choice.
-const uint32_t kRandomSeedUpperBound = 100000;
-
-// Set of live launch test processes with corresponding lock (it is allowed
-// for callers to launch processes on different threads).
-Lock* GetLiveProcessesLock() {
- static auto* lock = new Lock;
- return lock;
-}
-
-std::map<ProcessHandle, CommandLine>* GetLiveProcesses() {
- static auto* map = new std::map<ProcessHandle, CommandLine>;
- return map;
-}
-
-// Performance trace generator.
-TestLauncherTracer* GetTestLauncherTracer() {
- static auto* tracer = new TestLauncherTracer;
- return tracer;
-}
-
-// Creates and starts a TaskScheduler with |num_parallel_jobs| dedicated to
-// foreground blocking tasks (corresponds to the traits used to launch and wait
-// for child processes).
-void CreateAndStartTaskScheduler(int num_parallel_jobs) {
- // These values are taken from TaskScheduler::StartWithDefaultParams(), which
- // is not used directly to allow a custom number of threads in the foreground
- // blocking pool.
- constexpr int kMaxBackgroundThreads = 1;
- constexpr int kMaxBackgroundBlockingThreads = 2;
- const int max_foreground_threads =
- std::max(1, base::SysInfo::NumberOfProcessors());
- constexpr base::TimeDelta kSuggestedReclaimTime =
- base::TimeDelta::FromSeconds(30);
- base::TaskScheduler::Create("TestLauncher");
- base::TaskScheduler::GetInstance()->Start(
- {{kMaxBackgroundThreads, kSuggestedReclaimTime},
- {kMaxBackgroundBlockingThreads, kSuggestedReclaimTime},
- {max_foreground_threads, kSuggestedReclaimTime},
- {num_parallel_jobs, kSuggestedReclaimTime}});
-}
-
-#if defined(OS_POSIX)
-// Self-pipe that makes it possible to do complex shutdown handling
-// outside of the signal handler.
-int g_shutdown_pipe[2] = { -1, -1 };
-
-void ShutdownPipeSignalHandler(int signal) {
- HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1));
-}
-
-void KillSpawnedTestProcesses() {
- // Keep the lock until exiting the process to prevent further processes
- // from being spawned.
- AutoLock lock(*GetLiveProcessesLock());
-
- fprintf(stdout, "Sending SIGTERM to %" PRIuS " child processes... ",
- GetLiveProcesses()->size());
- fflush(stdout);
-
- for (const auto& pair : *GetLiveProcesses()) {
- // Send the signal to entire process group.
- kill((-1) * (pair.first), SIGTERM);
- }
-
- fprintf(stdout,
- "done.\nGiving processes a chance to terminate cleanly... ");
- fflush(stdout);
-
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(500));
-
- fprintf(stdout, "done.\n");
- fflush(stdout);
-
- fprintf(stdout, "Sending SIGKILL to %" PRIuS " child processes... ",
- GetLiveProcesses()->size());
- fflush(stdout);
-
- for (const auto& pair : *GetLiveProcesses()) {
- // Send the signal to entire process group.
- kill((-1) * (pair.first), SIGKILL);
- }
-
- fprintf(stdout, "done.\n");
- fflush(stdout);
-}
-#endif // defined(OS_POSIX)
-
-// Parses the environment variable var as an Int32. If it is unset, returns
-// true. If it is set, unsets it then converts it to Int32 before
-// returning it in |result|. Returns true on success.
-bool TakeInt32FromEnvironment(const char* const var, int32_t* result) {
- std::unique_ptr<Environment> env(Environment::Create());
- std::string str_val;
-
- if (!env->GetVar(var, &str_val))
- return true;
-
- if (!env->UnSetVar(var)) {
- LOG(ERROR) << "Invalid environment: we could not unset " << var << ".\n";
- return false;
- }
-
- if (!StringToInt(str_val, result)) {
- LOG(ERROR) << "Invalid environment: " << var << " is not an integer.\n";
- return false;
- }
-
- return true;
-}
-
-// Unsets the environment variable |name| and returns true on success.
-// Also returns true if the variable just doesn't exist.
-bool UnsetEnvironmentVariableIfExists(const std::string& name) {
- std::unique_ptr<Environment> env(Environment::Create());
- std::string str_val;
- if (!env->GetVar(name, &str_val))
- return true;
- return env->UnSetVar(name);
-}
-
-// Returns true if bot mode has been requested, i.e. defaults optimized
-// for continuous integration bots. This way developers don't have to remember
-// special command-line flags.
-bool BotModeEnabled() {
- std::unique_ptr<Environment> env(Environment::Create());
- return CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTestLauncherBotMode) ||
- env->HasVar("CHROMIUM_TEST_LAUNCHER_BOT_MODE");
-}
-
-// Returns command line command line after gtest-specific processing
-// and applying |wrapper|.
-CommandLine PrepareCommandLineForGTest(const CommandLine& command_line,
- const std::string& wrapper) {
- CommandLine new_command_line(command_line.GetProgram());
- CommandLine::SwitchMap switches = command_line.GetSwitches();
-
- // Handled by the launcher process.
- switches.erase(kGTestRepeatFlag);
- switches.erase(kGTestShuffleFlag);
- switches.erase(kGTestRandomSeedFlag);
-
- // Don't try to write the final XML report in child processes.
- switches.erase(kGTestOutputFlag);
-
- for (CommandLine::SwitchMap::const_iterator iter = switches.begin();
- iter != switches.end(); ++iter) {
- new_command_line.AppendSwitchNative((*iter).first, (*iter).second);
- }
-
- // Prepend wrapper after last CommandLine quasi-copy operation. CommandLine
- // does not really support removing switches well, and trying to do that
- // on a CommandLine with a wrapper is known to break.
- // TODO(phajdan.jr): Give it a try to support CommandLine removing switches.
-#if defined(OS_WIN)
- new_command_line.PrependWrapper(ASCIIToUTF16(wrapper));
-#else
- new_command_line.PrependWrapper(wrapper);
-#endif
-
- return new_command_line;
-}
-
-// Launches a child process using |command_line|. If the child process is still
-// running after |timeout|, it is terminated and |*was_timeout| is set to true.
-// Returns exit code of the process.
-int LaunchChildTestProcessWithOptions(const CommandLine& command_line,
- const LaunchOptions& options,
- int flags,
- TimeDelta timeout,
- ProcessLifetimeObserver* observer,
- bool* was_timeout) {
- TimeTicks start_time(TimeTicks::Now());
-
-#if defined(OS_POSIX)
- // Make sure an option we rely on is present - see LaunchChildGTestProcess.
- DCHECK(options.new_process_group);
-#endif
-
- LaunchOptions new_options(options);
-
-#if defined(OS_WIN)
- DCHECK(!new_options.job_handle);
-
- win::ScopedHandle job_handle;
- if (flags & TestLauncher::USE_JOB_OBJECTS) {
- job_handle.Set(CreateJobObject(NULL, NULL));
- if (!job_handle.IsValid()) {
- LOG(ERROR) << "Could not create JobObject.";
- return -1;
- }
-
- DWORD job_flags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
-
- // Allow break-away from job since sandbox and few other places rely on it
- // on Windows versions prior to Windows 8 (which supports nested jobs).
- if (win::GetVersion() < win::VERSION_WIN8 &&
- flags & TestLauncher::ALLOW_BREAKAWAY_FROM_JOB) {
- job_flags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK;
- }
-
- if (!SetJobObjectLimitFlags(job_handle.Get(), job_flags)) {
- LOG(ERROR) << "Could not SetJobObjectLimitFlags.";
- return -1;
- }
-
- new_options.job_handle = job_handle.Get();
- }
-#elif defined(OS_FUCHSIA)
- DCHECK(!new_options.job_handle);
-
- zx::job job_handle;
- zx_status_t result = zx::job::create(*GetDefaultJob(), 0, &job_handle);
- ZX_CHECK(ZX_OK == result, result) << "zx_job_create";
- new_options.job_handle = job_handle.get();
-#endif // defined(OS_FUCHSIA)
-
-#if defined(OS_LINUX)
- // To prevent accidental privilege sharing to an untrusted child, processes
- // are started with PR_SET_NO_NEW_PRIVS. Do not set that here, since this
- // new child will be privileged and trusted.
- new_options.allow_new_privs = true;
-#endif
-
- Process process;
-
- {
- // Note how we grab the lock before the process possibly gets created.
- // This ensures that when the lock is held, ALL the processes are registered
- // in the set.
- AutoLock lock(*GetLiveProcessesLock());
-
-#if defined(OS_WIN)
- // Allow the handle used to capture stdio and stdout to be inherited by the
- // child. Note that this is done under GetLiveProcessesLock() to ensure that
- // only the desired child receives the handle.
- if (new_options.stdout_handle) {
- ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT,
- HANDLE_FLAG_INHERIT);
- }
-#endif
-
- process = LaunchProcess(command_line, new_options);
-
-#if defined(OS_WIN)
- // Revoke inheritance so that the handle isn't leaked into other children.
- // Note that this is done under GetLiveProcessesLock() to ensure that only
- // the desired child receives the handle.
- if (new_options.stdout_handle)
- ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, 0);
-#endif
-
- if (!process.IsValid())
- return -1;
-
- // TODO(rvargas) crbug.com/417532: Don't store process handles.
- GetLiveProcesses()->insert(std::make_pair(process.Handle(), command_line));
- }
-
- if (observer)
- observer->OnLaunched(process.Handle(), process.Pid());
-
- int exit_code = 0;
- bool did_exit = false;
-
- {
- base::ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
- did_exit = process.WaitForExitWithTimeout(timeout, &exit_code);
- }
-
- if (!did_exit) {
- if (observer)
- observer->OnTimedOut(command_line);
-
- *was_timeout = true;
- exit_code = -1; // Set a non-zero exit code to signal a failure.
-
- {
- base::ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
- // Ensure that the process terminates.
- process.Terminate(-1, true);
- }
- }
-
- {
- // Note how we grab the log before issuing a possibly broad process kill.
- // Other code parts that grab the log kill processes, so avoid trying
- // to do that twice and trigger all kinds of log messages.
- AutoLock lock(*GetLiveProcessesLock());
-
-#if defined(OS_FUCHSIA)
- zx_status_t status = job_handle.kill();
- ZX_CHECK(status == ZX_OK, status);
-#elif defined(OS_POSIX)
- if (exit_code != 0) {
- // On POSIX, in case the test does not exit cleanly, either due to a crash
- // or due to it timing out, we need to clean up any child processes that
- // it might have created. On Windows, child processes are automatically
- // cleaned up using JobObjects.
- KillProcessGroup(process.Handle());
- }
-#endif
-
- GetLiveProcesses()->erase(process.Handle());
- }
-
- GetTestLauncherTracer()->RecordProcessExecution(
- start_time, TimeTicks::Now() - start_time);
-
- return exit_code;
-}
-
-void DoLaunchChildTestProcess(
- const CommandLine& command_line,
- TimeDelta timeout,
- const TestLauncher::LaunchOptions& test_launch_options,
- bool redirect_stdio,
- SingleThreadTaskRunner* task_runner,
- std::unique_ptr<ProcessLifetimeObserver> observer) {
- TimeTicks start_time = TimeTicks::Now();
-
- ScopedFILE output_file;
- FilePath output_filename;
- if (redirect_stdio) {
- FILE* raw_output_file = CreateAndOpenTemporaryFile(&output_filename);
- output_file.reset(raw_output_file);
- CHECK(output_file);
- }
-
- LaunchOptions options;
-#if defined(OS_WIN)
-
- options.inherit_mode = test_launch_options.inherit_mode;
- options.handles_to_inherit = test_launch_options.handles_to_inherit;
- if (redirect_stdio) {
- HANDLE handle =
- reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(output_file.get())));
- CHECK_NE(INVALID_HANDLE_VALUE, handle);
- options.stdin_handle = INVALID_HANDLE_VALUE;
- options.stdout_handle = handle;
- options.stderr_handle = handle;
- // See LaunchOptions.stdout_handle comments for why this compares against
- // FILE_TYPE_CHAR.
- if (options.inherit_mode == base::LaunchOptions::Inherit::kSpecific &&
- GetFileType(handle) != FILE_TYPE_CHAR) {
- options.handles_to_inherit.push_back(handle);
- }
- }
-
-#else // if !defined(OS_WIN)
-
- options.fds_to_remap = test_launch_options.fds_to_remap;
- if (redirect_stdio) {
- int output_file_fd = fileno(output_file.get());
- CHECK_LE(0, output_file_fd);
- options.fds_to_remap.push_back(
- std::make_pair(output_file_fd, STDOUT_FILENO));
- options.fds_to_remap.push_back(
- std::make_pair(output_file_fd, STDERR_FILENO));
- }
-
-#if !defined(OS_FUCHSIA)
- options.new_process_group = true;
-#endif
-#if defined(OS_LINUX)
- options.kill_on_parent_death = true;
-#endif
-
-#endif // !defined(OS_WIN)
-
- bool was_timeout = false;
- int exit_code = LaunchChildTestProcessWithOptions(
- command_line, options, test_launch_options.flags, timeout, observer.get(),
- &was_timeout);
-
- std::string output_file_contents;
- if (redirect_stdio) {
- fflush(output_file.get());
- output_file.reset();
- // Reading the file can sometimes fail when the process was killed midflight
- // (e.g. on test suite timeout): https://crbug.com/826408. Attempt to read
- // the output file anyways, but do not crash on failure in this case.
- CHECK(ReadFileToString(output_filename, &output_file_contents) ||
- exit_code != 0);
-
- if (!DeleteFile(output_filename, false)) {
- // This needs to be non-fatal at least for Windows.
- LOG(WARNING) << "Failed to delete " << output_filename.AsUTF8Unsafe();
- }
- }
-
- // Invoke OnCompleted on the thread it was originating from, not on a worker
- // pool thread.
- task_runner->PostTask(
- FROM_HERE,
- BindOnce(&ProcessLifetimeObserver::OnCompleted, std::move(observer),
- exit_code, TimeTicks::Now() - start_time, was_timeout,
- output_file_contents));
-}
-
-} // namespace
-
-const char kGTestBreakOnFailure[] = "gtest_break_on_failure";
-const char kGTestFilterFlag[] = "gtest_filter";
-const char kGTestFlagfileFlag[] = "gtest_flagfile";
-const char kGTestHelpFlag[] = "gtest_help";
-const char kGTestListTestsFlag[] = "gtest_list_tests";
-const char kGTestRepeatFlag[] = "gtest_repeat";
-const char kGTestRunDisabledTestsFlag[] = "gtest_also_run_disabled_tests";
-const char kGTestOutputFlag[] = "gtest_output";
-const char kGTestShuffleFlag[] = "gtest_shuffle";
-const char kGTestRandomSeedFlag[] = "gtest_random_seed";
-
-TestLauncherDelegate::~TestLauncherDelegate() = default;
-
-TestLauncher::LaunchOptions::LaunchOptions() = default;
-TestLauncher::LaunchOptions::LaunchOptions(const LaunchOptions& other) =
- default;
-TestLauncher::LaunchOptions::~LaunchOptions() = default;
-
-TestLauncher::TestLauncher(TestLauncherDelegate* launcher_delegate,
- size_t parallel_jobs)
- : launcher_delegate_(launcher_delegate),
- total_shards_(1),
- shard_index_(0),
- cycles_(1),
- test_found_count_(0),
- test_started_count_(0),
- test_finished_count_(0),
- test_success_count_(0),
- test_broken_count_(0),
- retry_count_(0),
- retry_limit_(0),
- force_run_broken_tests_(false),
- run_result_(true),
- shuffle_(false),
- shuffle_seed_(0),
- watchdog_timer_(FROM_HERE,
- kOutputTimeout,
- this,
- &TestLauncher::OnOutputTimeout),
- parallel_jobs_(parallel_jobs) {}
-
-TestLauncher::~TestLauncher() {
- if (base::TaskScheduler::GetInstance()) {
- base::TaskScheduler::GetInstance()->Shutdown();
- }
-}
-
-bool TestLauncher::Run() {
- if (!Init())
- return false;
-
- // Value of |cycles_| changes after each iteration. Keep track of the
- // original value.
- int requested_cycles = cycles_;
-
-#if defined(OS_POSIX)
- CHECK_EQ(0, pipe(g_shutdown_pipe));
-
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- sigemptyset(&action.sa_mask);
- action.sa_handler = &ShutdownPipeSignalHandler;
-
- CHECK_EQ(0, sigaction(SIGINT, &action, nullptr));
- CHECK_EQ(0, sigaction(SIGQUIT, &action, nullptr));
- CHECK_EQ(0, sigaction(SIGTERM, &action, nullptr));
-
- auto controller = base::FileDescriptorWatcher::WatchReadable(
- g_shutdown_pipe[0],
- base::Bind(&TestLauncher::OnShutdownPipeReadable, Unretained(this)));
-#endif // defined(OS_POSIX)
-
- // Start the watchdog timer.
- watchdog_timer_.Reset();
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&TestLauncher::RunTestIteration, Unretained(this)));
-
- RunLoop().Run();
-
- if (requested_cycles != 1)
- results_tracker_.PrintSummaryOfAllIterations();
-
- MaybeSaveSummaryAsJSON(std::vector<std::string>());
-
- return run_result_;
-}
-
-void TestLauncher::LaunchChildGTestProcess(
- const CommandLine& command_line,
- const std::string& wrapper,
- TimeDelta timeout,
- const LaunchOptions& options,
- std::unique_ptr<ProcessLifetimeObserver> observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Record the exact command line used to launch the child.
- CommandLine new_command_line(
- PrepareCommandLineForGTest(command_line, wrapper));
-
- // When running in parallel mode we need to redirect stdio to avoid mixed-up
- // output. We also always redirect on the bots to get the test output into
- // JSON summary.
- bool redirect_stdio = (parallel_jobs_ > 1) || BotModeEnabled();
-
- PostTaskWithTraits(
- FROM_HERE, {MayBlock(), TaskShutdownBehavior::BLOCK_SHUTDOWN},
- BindOnce(&DoLaunchChildTestProcess, new_command_line, timeout, options,
- redirect_stdio, RetainedRef(ThreadTaskRunnerHandle::Get()),
- std::move(observer)));
-}
-
-void TestLauncher::OnTestFinished(const TestResult& original_result) {
- ++test_finished_count_;
-
- TestResult result(original_result);
-
- if (result.output_snippet.length() > kOutputSnippetBytesLimit) {
- if (result.status == TestResult::TEST_SUCCESS)
- result.status = TestResult::TEST_EXCESSIVE_OUTPUT;
-
- // Keep the top and bottom of the log and truncate the middle part.
- result.output_snippet =
- result.output_snippet.substr(0, kOutputSnippetBytesLimit / 2) + "\n" +
- StringPrintf("<truncated (%" PRIuS " bytes)>\n",
- result.output_snippet.length()) +
- result.output_snippet.substr(result.output_snippet.length() -
- kOutputSnippetBytesLimit / 2) +
- "\n";
- }
-
- bool print_snippet = false;
- std::string print_test_stdio("auto");
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTestLauncherPrintTestStdio)) {
- print_test_stdio = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTestLauncherPrintTestStdio);
- }
- if (print_test_stdio == "auto") {
- print_snippet = (result.status != TestResult::TEST_SUCCESS);
- } else if (print_test_stdio == "always") {
- print_snippet = true;
- } else if (print_test_stdio == "never") {
- print_snippet = false;
- } else {
- LOG(WARNING) << "Invalid value of " << switches::kTestLauncherPrintTestStdio
- << ": " << print_test_stdio;
- }
- if (print_snippet) {
- std::vector<base::StringPiece> snippet_lines =
- SplitStringPiece(result.output_snippet, "\n", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_ALL);
- if (snippet_lines.size() > kOutputSnippetLinesLimit) {
- size_t truncated_size = snippet_lines.size() - kOutputSnippetLinesLimit;
- snippet_lines.erase(
- snippet_lines.begin(),
- snippet_lines.begin() + truncated_size);
- snippet_lines.insert(snippet_lines.begin(), "<truncated>");
- }
- fprintf(stdout, "%s", base::JoinString(snippet_lines, "\n").c_str());
- fflush(stdout);
- }
-
- if (result.status == TestResult::TEST_SUCCESS) {
- ++test_success_count_;
- } else {
- tests_to_retry_.insert(result.full_name);
- }
-
- results_tracker_.AddTestResult(result);
-
- // TODO(phajdan.jr): Align counter (padding).
- std::string status_line(
- StringPrintf("[%" PRIuS "/%" PRIuS "] %s ",
- test_finished_count_,
- test_started_count_,
- result.full_name.c_str()));
- if (result.completed()) {
- status_line.append(StringPrintf("(%" PRId64 " ms)",
- result.elapsed_time.InMilliseconds()));
- } else if (result.status == TestResult::TEST_TIMEOUT) {
- status_line.append("(TIMED OUT)");
- } else if (result.status == TestResult::TEST_CRASH) {
- status_line.append("(CRASHED)");
- } else if (result.status == TestResult::TEST_SKIPPED) {
- status_line.append("(SKIPPED)");
- } else if (result.status == TestResult::TEST_UNKNOWN) {
- status_line.append("(UNKNOWN)");
- } else {
- // Fail very loudly so it's not ignored.
- CHECK(false) << "Unhandled test result status: " << result.status;
- }
- fprintf(stdout, "%s\n", status_line.c_str());
- fflush(stdout);
-
- // We just printed a status line, reset the watchdog timer.
- watchdog_timer_.Reset();
-
- // Do not waste time on timeouts. We include tests with unknown results here
- // because sometimes (e.g. hang in between unit tests) that's how a timeout
- // gets reported.
- if (result.status == TestResult::TEST_TIMEOUT ||
- result.status == TestResult::TEST_UNKNOWN) {
- test_broken_count_++;
- }
- size_t broken_threshold =
- std::max(static_cast<size_t>(20), test_found_count_ / 10);
- if (!force_run_broken_tests_ && test_broken_count_ >= broken_threshold) {
- fprintf(stdout, "Too many badly broken tests (%" PRIuS "), exiting now.\n",
- test_broken_count_);
- fflush(stdout);
-
-#if defined(OS_POSIX)
- KillSpawnedTestProcesses();
-#endif // defined(OS_POSIX)
-
- MaybeSaveSummaryAsJSON({"BROKEN_TEST_EARLY_EXIT", kUnreliableResultsTag});
-
- exit(1);
- }
-
- if (test_finished_count_ != test_started_count_)
- return;
-
- if (tests_to_retry_.empty() || retry_count_ >= retry_limit_) {
- OnTestIterationFinished();
- return;
- }
-
- if (!force_run_broken_tests_ && tests_to_retry_.size() >= broken_threshold) {
- fprintf(stdout,
- "Too many failing tests (%" PRIuS "), skipping retries.\n",
- tests_to_retry_.size());
- fflush(stdout);
-
- results_tracker_.AddGlobalTag("BROKEN_TEST_SKIPPED_RETRIES");
- results_tracker_.AddGlobalTag(kUnreliableResultsTag);
-
- OnTestIterationFinished();
- return;
- }
-
- retry_count_++;
-
- std::vector<std::string> test_names(tests_to_retry_.begin(),
- tests_to_retry_.end());
-
- tests_to_retry_.clear();
-
- size_t retry_started_count = launcher_delegate_->RetryTests(this, test_names);
- if (retry_started_count == 0) {
- // Signal failure, but continue to run all requested test iterations.
- // With the summary of all iterations at the end this is a good default.
- run_result_ = false;
-
- OnTestIterationFinished();
- return;
- }
-
- fprintf(stdout, "Retrying %" PRIuS " test%s (retry #%" PRIuS ")\n",
- retry_started_count,
- retry_started_count > 1 ? "s" : "",
- retry_count_);
- fflush(stdout);
-
- test_started_count_ += retry_started_count;
-}
-
-// Helper used to parse test filter files. Syntax is documented in
-// //testing/buildbot/filters/README.md .
-bool LoadFilterFile(const FilePath& file_path,
- std::vector<std::string>* positive_filter,
- std::vector<std::string>* negative_filter) {
- std::string file_content;
- if (!ReadFileToString(file_path, &file_content)) {
- LOG(ERROR) << "Failed to read the filter file.";
- return false;
- }
-
- std::vector<std::string> filter_lines = SplitString(
- file_content, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- int line_num = 0;
- for (const std::string& filter_line : filter_lines) {
- line_num++;
-
- size_t hash_pos = filter_line.find('#');
-
- // In case when # symbol is not in the beginning of the line and is not
- // proceeded with a space then it's likely that the comment was
- // unintentional.
- if (hash_pos != std::string::npos && hash_pos > 0 &&
- filter_line[hash_pos - 1] != ' ') {
- LOG(WARNING) << "Content of line " << line_num << " in " << file_path
- << " after # is treated as a comment, " << filter_line;
- }
-
- // Strip comments and whitespace from each line.
- std::string trimmed_line =
- TrimWhitespaceASCII(filter_line.substr(0, hash_pos), TRIM_ALL)
- .as_string();
-
- if (trimmed_line.substr(0, 2) == "//") {
- LOG(ERROR) << "Line " << line_num << " in " << file_path
- << " starts with //, use # for comments.";
- return false;
- }
-
- // Treat a line starting with '//' as a comment.
- if (trimmed_line.empty())
- continue;
-
- if (trimmed_line[0] == '-')
- negative_filter->push_back(trimmed_line.substr(1));
- else
- positive_filter->push_back(trimmed_line);
- }
-
- return true;
-}
-
-bool TestLauncher::Init() {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
-
- // Initialize sharding. Command line takes precedence over legacy environment
- // variables.
- if (command_line->HasSwitch(switches::kTestLauncherTotalShards) &&
- command_line->HasSwitch(switches::kTestLauncherShardIndex)) {
- if (!StringToInt(
- command_line->GetSwitchValueASCII(
- switches::kTestLauncherTotalShards),
- &total_shards_)) {
- LOG(ERROR) << "Invalid value for " << switches::kTestLauncherTotalShards;
- return false;
- }
- if (!StringToInt(
- command_line->GetSwitchValueASCII(
- switches::kTestLauncherShardIndex),
- &shard_index_)) {
- LOG(ERROR) << "Invalid value for " << switches::kTestLauncherShardIndex;
- return false;
- }
- fprintf(stdout,
- "Using sharding settings from command line. This is shard %d/%d\n",
- shard_index_, total_shards_);
- fflush(stdout);
- } else {
- if (!TakeInt32FromEnvironment(kTestTotalShards, &total_shards_))
- return false;
- if (!TakeInt32FromEnvironment(kTestShardIndex, &shard_index_))
- return false;
- fprintf(stdout,
- "Using sharding settings from environment. This is shard %d/%d\n",
- shard_index_, total_shards_);
- fflush(stdout);
- }
- if (shard_index_ < 0 ||
- total_shards_ < 0 ||
- shard_index_ >= total_shards_) {
- LOG(ERROR) << "Invalid sharding settings: we require 0 <= "
- << kTestShardIndex << " < " << kTestTotalShards
- << ", but you have " << kTestShardIndex << "=" << shard_index_
- << ", " << kTestTotalShards << "=" << total_shards_ << ".\n";
- return false;
- }
-
- // Make sure we don't pass any sharding-related environment to the child
- // processes. This test launcher implements the sharding completely.
- CHECK(UnsetEnvironmentVariableIfExists("GTEST_TOTAL_SHARDS"));
- CHECK(UnsetEnvironmentVariableIfExists("GTEST_SHARD_INDEX"));
-
- if (command_line->HasSwitch(kGTestRepeatFlag) &&
- !StringToInt(command_line->GetSwitchValueASCII(kGTestRepeatFlag),
- &cycles_)) {
- LOG(ERROR) << "Invalid value for " << kGTestRepeatFlag;
- return false;
- }
-
- if (command_line->HasSwitch(switches::kTestLauncherRetryLimit)) {
- int retry_limit = -1;
- if (!StringToInt(command_line->GetSwitchValueASCII(
- switches::kTestLauncherRetryLimit), &retry_limit) ||
- retry_limit < 0) {
- LOG(ERROR) << "Invalid value for " << switches::kTestLauncherRetryLimit;
- return false;
- }
-
- retry_limit_ = retry_limit;
- } else if (!command_line->HasSwitch(kGTestFilterFlag) || BotModeEnabled()) {
- // Retry failures 3 times by default if we are running all of the tests or
- // in bot mode.
- retry_limit_ = 3;
- }
-
- if (command_line->HasSwitch(switches::kTestLauncherForceRunBrokenTests))
- force_run_broken_tests_ = true;
-
- // Some of the TestLauncherDelegate implementations don't call into gtest
- // until they've already split into test-specific processes. This results
- // in gtest's native shuffle implementation attempting to shuffle one test.
- // Shuffling the list of tests in the test launcher (before the delegate
- // gets involved) ensures that the entire shard is shuffled.
- if (command_line->HasSwitch(kGTestShuffleFlag)) {
- shuffle_ = true;
-
- if (command_line->HasSwitch(kGTestRandomSeedFlag)) {
- const std::string custom_seed_str =
- command_line->GetSwitchValueASCII(kGTestRandomSeedFlag);
- uint32_t custom_seed = 0;
- if (!StringToUint(custom_seed_str, &custom_seed)) {
- LOG(ERROR) << "Unable to parse seed \"" << custom_seed_str << "\".";
- return false;
- }
- if (custom_seed >= kRandomSeedUpperBound) {
- LOG(ERROR) << "Seed " << custom_seed << " outside of expected range "
- << "[0, " << kRandomSeedUpperBound << ")";
- return false;
- }
- shuffle_seed_ = custom_seed;
- } else {
- std::uniform_int_distribution<uint32_t> dist(0, kRandomSeedUpperBound);
- std::random_device random_dev;
- shuffle_seed_ = dist(random_dev);
- }
- } else if (command_line->HasSwitch(kGTestRandomSeedFlag)) {
- LOG(ERROR) << kGTestRandomSeedFlag << " requires " << kGTestShuffleFlag;
- return false;
- }
-
- fprintf(stdout, "Using %" PRIuS " parallel jobs.\n", parallel_jobs_);
- fflush(stdout);
-
- CreateAndStartTaskScheduler(static_cast<int>(parallel_jobs_));
-
- std::vector<std::string> positive_file_filter;
- std::vector<std::string> positive_gtest_filter;
-
- if (command_line->HasSwitch(switches::kTestLauncherFilterFile)) {
- base::FilePath filter_file_path = base::MakeAbsoluteFilePath(
- command_line->GetSwitchValuePath(switches::kTestLauncherFilterFile));
- if (!LoadFilterFile(filter_file_path, &positive_file_filter,
- &negative_test_filter_))
- return false;
- }
-
- // Split --gtest_filter at '-', if there is one, to separate into
- // positive filter and negative filter portions.
- std::string filter = command_line->GetSwitchValueASCII(kGTestFilterFlag);
- size_t dash_pos = filter.find('-');
- if (dash_pos == std::string::npos) {
- positive_gtest_filter =
- SplitString(filter, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- } else {
- // Everything up to the dash.
- positive_gtest_filter =
- SplitString(filter.substr(0, dash_pos), ":", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL);
-
- // Everything after the dash.
- for (std::string pattern :
- SplitString(filter.substr(dash_pos + 1), ":", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL)) {
- negative_test_filter_.push_back(pattern);
- }
- }
-
- if (!launcher_delegate_->GetTests(&tests_)) {
- LOG(ERROR) << "Failed to get list of tests.";
- return false;
- }
-
- CombinePositiveTestFilters(std::move(positive_gtest_filter),
- std::move(positive_file_filter));
-
- if (!results_tracker_.Init(*command_line)) {
- LOG(ERROR) << "Failed to initialize test results tracker.";
- return 1;
- }
-
-#if defined(NDEBUG)
- results_tracker_.AddGlobalTag("MODE_RELEASE");
-#else
- results_tracker_.AddGlobalTag("MODE_DEBUG");
-#endif
-
- // Operating systems (sorted alphabetically).
- // Note that they can deliberately overlap, e.g. OS_LINUX is a subset
- // of OS_POSIX.
-#if defined(OS_ANDROID)
- results_tracker_.AddGlobalTag("OS_ANDROID");
-#endif
-
-#if defined(OS_BSD)
- results_tracker_.AddGlobalTag("OS_BSD");
-#endif
-
-#if defined(OS_FREEBSD)
- results_tracker_.AddGlobalTag("OS_FREEBSD");
-#endif
-
-#if defined(OS_FUCHSIA)
- results_tracker_.AddGlobalTag("OS_FUCHSIA");
-#endif
-
-#if defined(OS_IOS)
- results_tracker_.AddGlobalTag("OS_IOS");
-#endif
-
-#if defined(OS_LINUX)
- results_tracker_.AddGlobalTag("OS_LINUX");
-#endif
-
-#if defined(OS_MACOSX)
- results_tracker_.AddGlobalTag("OS_MACOSX");
-#endif
-
-#if defined(OS_NACL)
- results_tracker_.AddGlobalTag("OS_NACL");
-#endif
-
-#if defined(OS_OPENBSD)
- results_tracker_.AddGlobalTag("OS_OPENBSD");
-#endif
-
-#if defined(OS_POSIX)
- results_tracker_.AddGlobalTag("OS_POSIX");
-#endif
-
-#if defined(OS_SOLARIS)
- results_tracker_.AddGlobalTag("OS_SOLARIS");
-#endif
-
-#if defined(OS_WIN)
- results_tracker_.AddGlobalTag("OS_WIN");
-#endif
-
- // CPU-related tags.
-#if defined(ARCH_CPU_32_BITS)
- results_tracker_.AddGlobalTag("CPU_32_BITS");
-#endif
-
-#if defined(ARCH_CPU_64_BITS)
- results_tracker_.AddGlobalTag("CPU_64_BITS");
-#endif
-
- return true;
-}
-
-void TestLauncher::CombinePositiveTestFilters(
- std::vector<std::string> filter_a,
- std::vector<std::string> filter_b) {
- has_at_least_one_positive_filter_ = !filter_a.empty() || !filter_b.empty();
- if (!has_at_least_one_positive_filter_) {
- return;
- }
- // If two positive filters are present, only run tests that match a pattern
- // in both filters.
- if (!filter_a.empty() && !filter_b.empty()) {
- for (size_t i = 0; i < tests_.size(); i++) {
- std::string test_name =
- FormatFullTestName(tests_[i].test_case_name, tests_[i].test_name);
- bool found_a = false;
- bool found_b = false;
- for (size_t k = 0; k < filter_a.size(); ++k) {
- found_a = found_a || MatchPattern(test_name, filter_a[k]);
- }
- for (size_t k = 0; k < filter_b.size(); ++k) {
- found_b = found_b || MatchPattern(test_name, filter_b[k]);
- }
- if (found_a && found_b) {
- positive_test_filter_.push_back(test_name);
- }
- }
- } else if (!filter_a.empty()) {
- positive_test_filter_ = std::move(filter_a);
- } else {
- positive_test_filter_ = std::move(filter_b);
- }
-}
-
-void TestLauncher::RunTests() {
- std::vector<std::string> test_names;
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- for (const TestIdentifier& test_id : tests_) {
- std::string test_name =
- FormatFullTestName(test_id.test_case_name, test_id.test_name);
-
- results_tracker_.AddTest(test_name);
-
- if (test_name.find("DISABLED") != std::string::npos) {
- results_tracker_.AddDisabledTest(test_name);
-
- // Skip disabled tests unless explicitly requested.
- if (!command_line->HasSwitch(kGTestRunDisabledTestsFlag))
- continue;
- }
-
- if (!launcher_delegate_->ShouldRunTest(test_id.test_case_name,
- test_id.test_name)) {
- continue;
- }
-
- // Count tests in the binary, before we apply filter and sharding.
- test_found_count_++;
-
- std::string test_name_no_disabled =
- TestNameWithoutDisabledPrefix(test_name);
-
- // Skip the test that doesn't match the filter (if given).
- if (has_at_least_one_positive_filter_) {
- bool found = false;
- for (auto filter : positive_test_filter_) {
- if (MatchPattern(test_name, filter) ||
- MatchPattern(test_name_no_disabled, filter)) {
- found = true;
- break;
- }
- }
-
- if (!found)
- continue;
- }
- if (!negative_test_filter_.empty()) {
- bool excluded = false;
- for (auto filter : negative_test_filter_) {
- if (MatchPattern(test_name, filter) ||
- MatchPattern(test_name_no_disabled, filter)) {
- excluded = true;
- break;
- }
- }
-
- if (excluded)
- continue;
- }
-
- if (Hash(test_name) % total_shards_ != static_cast<uint32_t>(shard_index_))
- continue;
-
- // Report test locations after applying all filters, so that we report test
- // locations only for those tests that were run as part of this shard.
- results_tracker_.AddTestLocation(test_name, test_id.file, test_id.line);
-
- test_names.push_back(test_name);
- }
-
- if (shuffle_) {
- std::mt19937 randomizer;
- randomizer.seed(shuffle_seed_);
- std::shuffle(test_names.begin(), test_names.end(), randomizer);
-
- fprintf(stdout, "Randomizing with seed %u\n", shuffle_seed_);
- fflush(stdout);
- }
-
- // Save an early test summary in case the launcher crashes or gets killed.
- MaybeSaveSummaryAsJSON({"EARLY_SUMMARY", kUnreliableResultsTag});
-
- test_started_count_ = launcher_delegate_->RunTests(this, test_names);
-
- if (test_started_count_ == 0) {
- fprintf(stdout, "0 tests run\n");
- fflush(stdout);
-
- // No tests have actually been started, so kick off the next iteration.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&TestLauncher::RunTestIteration, Unretained(this)));
- }
-}
-
-void TestLauncher::RunTestIteration() {
- const bool stop_on_failure =
- CommandLine::ForCurrentProcess()->HasSwitch(kGTestBreakOnFailure);
- if (cycles_ == 0 ||
- (stop_on_failure && test_success_count_ != test_finished_count_)) {
- RunLoop::QuitCurrentWhenIdleDeprecated();
- return;
- }
-
- // Special value "-1" means "repeat indefinitely".
- cycles_ = (cycles_ == -1) ? cycles_ : cycles_ - 1;
-
- test_found_count_ = 0;
- test_started_count_ = 0;
- test_finished_count_ = 0;
- test_success_count_ = 0;
- test_broken_count_ = 0;
- retry_count_ = 0;
- tests_to_retry_.clear();
- results_tracker_.OnTestIterationStarting();
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&TestLauncher::RunTests, Unretained(this)));
-}
-
-#if defined(OS_POSIX)
-// I/O watcher for the reading end of the self-pipe above.
-// Terminates any launched child processes and exits the process.
-void TestLauncher::OnShutdownPipeReadable() {
- fprintf(stdout, "\nCaught signal. Killing spawned test processes...\n");
- fflush(stdout);
-
- KillSpawnedTestProcesses();
-
- MaybeSaveSummaryAsJSON({"CAUGHT_TERMINATION_SIGNAL", kUnreliableResultsTag});
-
- // The signal would normally kill the process, so exit now.
- _exit(1);
-}
-#endif // defined(OS_POSIX)
-
-void TestLauncher::MaybeSaveSummaryAsJSON(
- const std::vector<std::string>& additional_tags) {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) {
- FilePath summary_path(command_line->GetSwitchValuePath(
- switches::kTestLauncherSummaryOutput));
- if (!results_tracker_.SaveSummaryAsJSON(summary_path, additional_tags)) {
- LOG(ERROR) << "Failed to save test launcher output summary.";
- }
- }
- if (command_line->HasSwitch(switches::kTestLauncherTrace)) {
- FilePath trace_path(
- command_line->GetSwitchValuePath(switches::kTestLauncherTrace));
- if (!GetTestLauncherTracer()->Dump(trace_path)) {
- LOG(ERROR) << "Failed to save test launcher trace.";
- }
- }
-}
-
-void TestLauncher::OnTestIterationFinished() {
- TestResultsTracker::TestStatusMap tests_by_status(
- results_tracker_.GetTestStatusMapForCurrentIteration());
- if (!tests_by_status[TestResult::TEST_UNKNOWN].empty())
- results_tracker_.AddGlobalTag(kUnreliableResultsTag);
-
- // When we retry tests, success is determined by having nothing more
- // to retry (everything eventually passed), as opposed to having
- // no failures at all.
- if (tests_to_retry_.empty()) {
- fprintf(stdout, "SUCCESS: all tests passed.\n");
- fflush(stdout);
- } else {
- // Signal failure, but continue to run all requested test iterations.
- // With the summary of all iterations at the end this is a good default.
- run_result_ = false;
- }
-
- results_tracker_.PrintSummaryOfCurrentIteration();
-
- // Kick off the next iteration.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&TestLauncher::RunTestIteration, Unretained(this)));
-}
-
-void TestLauncher::OnOutputTimeout() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- AutoLock lock(*GetLiveProcessesLock());
-
- fprintf(stdout, "Still waiting for the following processes to finish:\n");
-
- for (const auto& pair : *GetLiveProcesses()) {
-#if defined(OS_WIN)
- fwprintf(stdout, L"\t%s\n", pair.second.GetCommandLineString().c_str());
-#else
- fprintf(stdout, "\t%s\n", pair.second.GetCommandLineString().c_str());
-#endif
- }
-
- fflush(stdout);
-
- // Arm the timer again - otherwise it would fire only once.
- watchdog_timer_.Reset();
-}
-
-size_t NumParallelJobs() {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kTestLauncherJobs)) {
- // If the number of test launcher jobs was specified, return that number.
- size_t jobs = 0U;
-
- if (!StringToSizeT(
- command_line->GetSwitchValueASCII(switches::kTestLauncherJobs),
- &jobs) ||
- !jobs) {
- LOG(ERROR) << "Invalid value for " << switches::kTestLauncherJobs;
- return 0U;
- }
- return jobs;
- }
- if (command_line->HasSwitch(kGTestFilterFlag) && !BotModeEnabled()) {
- // Do not run jobs in parallel by default if we are running a subset of
- // the tests and if bot mode is off.
- return 1U;
- }
-
- // Default to the number of processor cores.
- return base::checked_cast<size_t>(SysInfo::NumberOfProcessors());
-}
-
-std::string GetTestOutputSnippet(const TestResult& result,
- const std::string& full_output) {
- size_t run_pos = full_output.find(std::string("[ RUN ] ") +
- result.full_name);
- if (run_pos == std::string::npos)
- return std::string();
-
- size_t end_pos = full_output.find(std::string("[ FAILED ] ") +
- result.full_name,
- run_pos);
- // Only clip the snippet to the "OK" message if the test really
- // succeeded. It still might have e.g. crashed after printing it.
- if (end_pos == std::string::npos &&
- result.status == TestResult::TEST_SUCCESS) {
- end_pos = full_output.find(std::string("[ OK ] ") +
- result.full_name,
- run_pos);
- }
- if (end_pos != std::string::npos) {
- size_t newline_pos = full_output.find("\n", end_pos);
- if (newline_pos != std::string::npos)
- end_pos = newline_pos + 1;
- }
-
- std::string snippet(full_output.substr(run_pos));
- if (end_pos != std::string::npos)
- snippet = full_output.substr(run_pos, end_pos - run_pos);
-
- return snippet;
-}
-
-} // namespace base
diff --git a/base/test/launcher/test_launcher.h b/base/test/launcher/test_launcher.h
deleted file mode 100644
index 9ac45ba689..0000000000
--- a/base/test/launcher/test_launcher.h
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_LAUNCHER_TEST_LAUNCHER_H_
-#define BASE_TEST_LAUNCHER_TEST_LAUNCHER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/process/launch.h"
-#include "base/test/gtest_util.h"
-#include "base/test/launcher/test_result.h"
-#include "base/test/launcher/test_results_tracker.h"
-#include "base/threading/thread_checker.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "build/build_config.h"
-
-namespace base {
-
-class CommandLine;
-struct LaunchOptions;
-class TestLauncher;
-
-// Constants for GTest command-line flags.
-extern const char kGTestFilterFlag[];
-extern const char kGTestFlagfileFlag[];
-extern const char kGTestHelpFlag[];
-extern const char kGTestListTestsFlag[];
-extern const char kGTestRepeatFlag[];
-extern const char kGTestRunDisabledTestsFlag[];
-extern const char kGTestOutputFlag[];
-extern const char kGTestShuffleFlag[];
-extern const char kGTestRandomSeedFlag[];
-
-// Interface for use with LaunchTests that abstracts away exact details
-// which tests and how are run.
-class TestLauncherDelegate {
- public:
- // Called to get names of tests available for running. The delegate
- // must put the result in |output| and return true on success.
- virtual bool GetTests(std::vector<TestIdentifier>* output) = 0;
-
- // Called before a test is considered for running. If it returns false,
- // the test is not run. If it returns true, the test will be run provided
- // it is part of the current shard.
- virtual bool ShouldRunTest(const std::string& test_case_name,
- const std::string& test_name) = 0;
-
- // Called to make the delegate run the specified tests. The delegate must
- // return the number of actual tests it's going to run (can be smaller,
- // equal to, or larger than size of |test_names|). It must also call
- // |test_launcher|'s OnTestFinished method once per every run test,
- // regardless of its success.
- virtual size_t RunTests(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) = 0;
-
- // Called to make the delegate retry the specified tests. The delegate must
- // return the number of actual tests it's going to retry (can be smaller,
- // equal to, or larger than size of |test_names|). It must also call
- // |test_launcher|'s OnTestFinished method once per every retried test,
- // regardless of its success.
- virtual size_t RetryTests(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) = 0;
-
- protected:
- virtual ~TestLauncherDelegate();
-};
-
-// An observer of child process lifetime events generated by
-// LaunchChildGTestProcess.
-class ProcessLifetimeObserver {
- public:
- virtual ~ProcessLifetimeObserver() = default;
-
- // Invoked once the child process is started. |handle| is a handle to the
- // child process and |id| is its pid. NOTE: this method is invoked on the
- // thread the process is launched on immediately after it is launched. The
- // caller owns the ProcessHandle.
- virtual void OnLaunched(ProcessHandle handle, ProcessId id) {}
-
- // Invoked when a test process exceeds its runtime, immediately before it is
- // terminated. |command_line| is the command line used to launch the process.
- // NOTE: this method is invoked on the thread the process is launched on.
- virtual void OnTimedOut(const CommandLine& command_line) {}
-
- // Invoked after a child process finishes, reporting the process |exit_code|,
- // child process |elapsed_time|, whether or not the process was terminated as
- // a result of a timeout, and the output of the child (stdout and stderr
- // together). NOTE: this method is invoked on the same thread as
- // LaunchChildGTestProcess.
- virtual void OnCompleted(int exit_code,
- TimeDelta elapsed_time,
- bool was_timeout,
- const std::string& output) {}
-
- protected:
- ProcessLifetimeObserver() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ProcessLifetimeObserver);
-};
-
-// Launches tests using a TestLauncherDelegate.
-class TestLauncher {
- public:
- // Flags controlling behavior of LaunchChildGTestProcess.
- enum LaunchChildGTestProcessFlags {
- // Allows usage of job objects on Windows. Helps properly clean up child
- // processes.
- USE_JOB_OBJECTS = (1 << 0),
-
- // Allows breakaway from job on Windows. May result in some child processes
- // not being properly terminated after launcher dies if these processes
- // fail to cooperate.
- ALLOW_BREAKAWAY_FROM_JOB = (1 << 1),
- };
-
- struct LaunchOptions {
- LaunchOptions();
- LaunchOptions(const LaunchOptions& other);
- ~LaunchOptions();
-
- int flags = 0;
- // These mirror values in base::LaunchOptions, see it for details.
-#if defined(OS_WIN)
- base::LaunchOptions::Inherit inherit_mode =
- base::LaunchOptions::Inherit::kSpecific;
- base::HandlesToInheritVector handles_to_inherit;
-#else
- FileHandleMappingVector fds_to_remap;
-#endif
- };
-
- // Constructor. |parallel_jobs| is the limit of simultaneous parallel test
- // jobs.
- TestLauncher(TestLauncherDelegate* launcher_delegate, size_t parallel_jobs);
- ~TestLauncher();
-
- // Runs the launcher. Must be called at most once.
- bool Run() WARN_UNUSED_RESULT;
-
- // Launches a child process (assumed to be gtest-based binary) using
- // |command_line|. If |wrapper| is not empty, it is prepended to the final
- // command line. |observer|, if not null, is used to convey process lifetime
- // events to the caller. |observer| is destroyed after its OnCompleted
- // method is invoked.
- void LaunchChildGTestProcess(
- const CommandLine& command_line,
- const std::string& wrapper,
- TimeDelta timeout,
- const LaunchOptions& options,
- std::unique_ptr<ProcessLifetimeObserver> observer);
-
- // Called when a test has finished running.
- void OnTestFinished(const TestResult& result);
-
- private:
- bool Init() WARN_UNUSED_RESULT;
-
- // Runs all tests in current iteration.
- void RunTests();
-
- void CombinePositiveTestFilters(std::vector<std::string> filter_a,
- std::vector<std::string> filter_b);
-
- void RunTestIteration();
-
-#if defined(OS_POSIX)
- void OnShutdownPipeReadable();
-#endif
-
- // Saves test results summary as JSON if requested from command line.
- void MaybeSaveSummaryAsJSON(const std::vector<std::string>& additional_tags);
-
- // Called when a test iteration is finished.
- void OnTestIterationFinished();
-
- // Called by the delay timer when no output was made for a while.
- void OnOutputTimeout();
-
- // Make sure we don't accidentally call the wrong methods e.g. on the worker
- // pool thread. Should be the first member so that it's destroyed last: when
- // destroying other members, especially the worker pool, we may check the code
- // is running on the correct thread.
- ThreadChecker thread_checker_;
-
- TestLauncherDelegate* launcher_delegate_;
-
- // Support for outer sharding, just like gtest does.
- int32_t total_shards_; // Total number of outer shards, at least one.
- int32_t shard_index_; // Index of shard the launcher is to run.
-
- int cycles_; // Number of remaining test iterations, or -1 for infinite.
-
- // Test filters (empty means no filter).
- bool has_at_least_one_positive_filter_;
- std::vector<std::string> positive_test_filter_;
- std::vector<std::string> negative_test_filter_;
-
- // Tests to use (cached result of TestLauncherDelegate::GetTests).
- std::vector<TestIdentifier> tests_;
-
- // Number of tests found in this binary.
- size_t test_found_count_;
-
- // Number of tests started in this iteration.
- size_t test_started_count_;
-
- // Number of tests finished in this iteration.
- size_t test_finished_count_;
-
- // Number of tests successfully finished in this iteration.
- size_t test_success_count_;
-
- // Number of tests either timing out or having an unknown result,
- // likely indicating a more systemic problem if widespread.
- size_t test_broken_count_;
-
- // Number of retries in this iteration.
- size_t retry_count_;
-
- // Maximum number of retries per iteration.
- size_t retry_limit_;
-
- // If true will not early exit nor skip retries even if too many tests are
- // broken.
- bool force_run_broken_tests_;
-
- // Tests to retry in this iteration.
- std::set<std::string> tests_to_retry_;
-
- // Result to be returned from Run.
- bool run_result_;
-
- // Support for test shuffling, just like gtest does.
- bool shuffle_;
- uint32_t shuffle_seed_;
-
- TestResultsTracker results_tracker_;
-
- // Watchdog timer to make sure we do not go without output for too long.
- DelayTimer watchdog_timer_;
-
- // Number of jobs to run in parallel.
- size_t parallel_jobs_;
-
- DISALLOW_COPY_AND_ASSIGN(TestLauncher);
-};
-
-// Return the number of parallel jobs to use, or 0U in case of error.
-size_t NumParallelJobs();
-
-// Extract part from |full_output| that applies to |result|.
-std::string GetTestOutputSnippet(const TestResult& result,
- const std::string& full_output);
-
-} // namespace base
-
-#endif // BASE_TEST_LAUNCHER_TEST_LAUNCHER_H_
diff --git a/base/test/launcher/test_launcher_tracer.cc b/base/test/launcher/test_launcher_tracer.cc
deleted file mode 100644
index d525df7523..0000000000
--- a/base/test/launcher/test_launcher_tracer.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 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_tracer.h"
-
-#include "base/json/json_file_value_serializer.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-
-namespace base {
-
-TestLauncherTracer::TestLauncherTracer()
- : trace_start_time_(TimeTicks::Now()) {}
-
-TestLauncherTracer::~TestLauncherTracer() = default;
-
-void TestLauncherTracer::RecordProcessExecution(TimeTicks start_time,
- TimeDelta duration) {
- AutoLock lock(lock_);
-
- Event event;
- event.name = StringPrintf("process #%zu", events_.size());
- event.timestamp = start_time;
- event.duration = duration;
- event.thread_id = PlatformThread::CurrentId();
- events_.push_back(event);
-}
-
-bool TestLauncherTracer::Dump(const FilePath& path) {
- AutoLock lock(lock_);
-
- std::unique_ptr<ListValue> json_events(new ListValue);
- for (const Event& event : events_) {
- std::unique_ptr<DictionaryValue> json_event(new DictionaryValue);
- json_event->SetString("name", event.name);
- json_event->SetString("ph", "X");
- json_event->SetInteger(
- "ts", (event.timestamp - trace_start_time_).InMicroseconds());
- json_event->SetInteger("dur", event.duration.InMicroseconds());
- json_event->SetInteger("tid", event.thread_id);
-
- // Add fake values required by the trace viewer.
- json_event->SetInteger("pid", 0);
-
- json_events->Append(std::move(json_event));
- }
-
- JSONFileValueSerializer serializer(path);
- return serializer.Serialize(*json_events);
-}
-
-} // namespace base
diff --git a/base/test/launcher/test_launcher_tracer.h b/base/test/launcher/test_launcher_tracer.h
deleted file mode 100644
index 58bc1b071e..0000000000
--- a/base/test/launcher/test_launcher_tracer.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TEST_LAUNCHER_TEST_LAUNCHER_TRACER_H_
-#define BASE_TEST_LAUNCHER_TEST_LAUNCHER_TRACER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-
-namespace base {
-
-class FilePath;
-
-// Records traces of test execution, e.g. to analyze performance.
-// Thread safe.
-class TestLauncherTracer {
- public:
- TestLauncherTracer();
- ~TestLauncherTracer();
-
- // Records an event corresponding to test process execution.
- void RecordProcessExecution(TimeTicks start_time, TimeDelta duration);
-
- // Dumps trace data as JSON. Returns true on success.
- bool Dump(const FilePath& path) WARN_UNUSED_RESULT;
-
- private:
- // Simplified version of base::TraceEvent.
- struct Event {
- std::string name; // Displayed name.
- TimeTicks timestamp; // Timestamp when this event began.
- TimeDelta duration; // How long was this event.
- PlatformThreadId thread_id; // Thread ID where event was reported.
- };
-
- // Timestamp when tracing started.
- TimeTicks trace_start_time_;
-
- // Log of trace events.
- std::vector<Event> events_;
-
- // Lock to protect all member variables.
- Lock lock_;
-
- DISALLOW_COPY_AND_ASSIGN(TestLauncherTracer);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_LAUNCHER_TEST_LAUNCHER_TRACER_H_
diff --git a/base/test/launcher/test_result.cc b/base/test/launcher/test_result.cc
deleted file mode 100644
index 9f37a2b96d..0000000000
--- a/base/test/launcher/test_result.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2013 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_result.h"
-
-#include <stddef.h>
-
-#include "base/logging.h"
-
-namespace base {
-
-TestResultPart::TestResultPart() = default;
-TestResultPart::~TestResultPart() = default;
-
-TestResultPart::TestResultPart(const TestResultPart& other) = default;
-TestResultPart::TestResultPart(TestResultPart&& other) = default;
-TestResultPart& TestResultPart::operator=(const TestResultPart& other) =
- default;
-TestResultPart& TestResultPart::operator=(TestResultPart&& other) = default;
-
-// static
-bool TestResultPart::TypeFromString(const std::string& str, Type* type) {
- if (str == "success")
- *type = kSuccess;
- else if (str == "failure")
- *type = kNonFatalFailure;
- else if (str == "fatal_failure")
- *type = kFatalFailure;
- else
- return false;
- return true;
-}
-
-std::string TestResultPart::TypeAsString() const {
- switch (type) {
- case kSuccess:
- return "success";
- case kNonFatalFailure:
- return "failure";
- case kFatalFailure:
- return "fatal_failure";
- default:
- NOTREACHED();
- }
- return "unknown";
-}
-
-TestResult::TestResult() : status(TEST_UNKNOWN) {
-}
-
-TestResult::~TestResult() = default;
-
-TestResult::TestResult(const TestResult& other) = default;
-TestResult::TestResult(TestResult&& other) = default;
-TestResult& TestResult::operator=(const TestResult& other) = default;
-TestResult& TestResult::operator=(TestResult&& other) = default;
-
-std::string TestResult::StatusAsString() const {
- switch (status) {
- case TEST_UNKNOWN:
- return "UNKNOWN";
- case TEST_SUCCESS:
- return "SUCCESS";
- case TEST_FAILURE:
- return "FAILURE";
- case TEST_FAILURE_ON_EXIT:
- return "FAILURE_ON_EXIT";
- case TEST_CRASH:
- return "CRASH";
- case TEST_TIMEOUT:
- return "TIMEOUT";
- case TEST_SKIPPED:
- return "SKIPPED";
- case TEST_EXCESSIVE_OUTPUT:
- return "EXCESSIVE_OUTPUT";
- // Rely on compiler warnings to ensure all possible values are handled.
- }
-
- NOTREACHED();
- return std::string();
-}
-
-std::string TestResult::GetTestName() const {
- size_t dot_pos = full_name.find('.');
- CHECK_NE(dot_pos, std::string::npos);
- return full_name.substr(dot_pos + 1);
-}
-
-std::string TestResult::GetTestCaseName() const {
- size_t dot_pos = full_name.find('.');
- CHECK_NE(dot_pos, std::string::npos);
- return full_name.substr(0, dot_pos);
-}
-
-} // namespace base
diff --git a/base/test/launcher/test_result.h b/base/test/launcher/test_result.h
deleted file mode 100644
index 07338b372f..0000000000
--- a/base/test/launcher/test_result.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_LAUNCHER_TEST_RESULT_H_
-#define BASE_TEST_LAUNCHER_TEST_RESULT_H_
-
-#include <string>
-#include <vector>
-
-#include "base/time/time.h"
-
-namespace base {
-
-// Structure contains result of a single EXPECT/ASSERT/SUCCESS.
-struct TestResultPart {
- enum Type {
- kSuccess, // SUCCESS
- kNonFatalFailure, // EXPECT
- kFatalFailure, // ASSERT
- };
- Type type;
-
- TestResultPart();
- ~TestResultPart();
-
- TestResultPart(const TestResultPart& other);
- TestResultPart(TestResultPart&& other);
- TestResultPart& operator=(const TestResultPart& other);
- TestResultPart& operator=(TestResultPart&& other);
-
- // Convert type to string and back.
- static bool TypeFromString(const std::string& str, Type* type);
- std::string TypeAsString() const;
-
- // Filename and line of EXPECT/ASSERT.
- std::string file_name;
- int line_number;
-
- // Message without stacktrace, etc.
- std::string summary;
-
- // Complete message.
- std::string message;
-};
-
-// Structure containing result of a single test.
-struct TestResult {
- enum Status {
- TEST_UNKNOWN, // Status not set.
- TEST_SUCCESS, // Test passed.
- TEST_FAILURE, // Assertion failure (e.g. EXPECT_TRUE, not DCHECK).
- TEST_FAILURE_ON_EXIT, // Passed but executable exit code was non-zero.
- TEST_TIMEOUT, // Test timed out and was killed.
- TEST_CRASH, // Test crashed (includes CHECK/DCHECK failures).
- TEST_SKIPPED, // Test skipped (not run at all).
- TEST_EXCESSIVE_OUTPUT, // Test exceeded output limit.
- };
-
- TestResult();
- ~TestResult();
-
- TestResult(const TestResult& other);
- TestResult(TestResult&& other);
- TestResult& operator=(const TestResult& other);
- TestResult& operator=(TestResult&& other);
-
- // Returns the test status as string (e.g. for display).
- std::string StatusAsString() const;
-
- // Returns the test name (e.g. "B" for "A.B").
- std::string GetTestName() const;
-
- // Returns the test case name (e.g. "A" for "A.B").
- std::string GetTestCaseName() const;
-
- // Returns true if the test has completed (i.e. the test binary exited
- // normally, possibly with an exit code indicating failure, but didn't crash
- // or time out in the middle of the test).
- bool completed() const {
- return status == TEST_SUCCESS ||
- status == TEST_FAILURE ||
- status == TEST_FAILURE_ON_EXIT ||
- status == TEST_EXCESSIVE_OUTPUT;
- }
-
- // Full name of the test (e.g. "A.B").
- std::string full_name;
-
- Status status;
-
- // Time it took to run the test.
- base::TimeDelta elapsed_time;
-
- // Output of just this test (optional).
- std::string output_snippet;
-
- // Information about failed expectations.
- std::vector<TestResultPart> test_result_parts;
-};
-
-} // namespace base
-
-#endif // BASE_TEST_LAUNCHER_TEST_RESULT_H_
diff --git a/base/test/launcher/test_results_tracker.cc b/base/test/launcher/test_results_tracker.cc
deleted file mode 100644
index a7e590c2ed..0000000000
--- a/base/test/launcher/test_results_tracker.cc
+++ /dev/null
@@ -1,541 +0,0 @@
-// Copyright 2013 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_results_tracker.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/base64.h"
-#include "base/command_line.h"
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/format_macros.h"
-#include "base/json/json_writer.h"
-#include "base/json/string_escape.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/gtest_util.h"
-#include "base/test/launcher/test_launcher.h"
-#include "base/time/time.h"
-#include "base/values.h"
-
-namespace base {
-
-namespace {
-
-// The default output file for XML output.
-const FilePath::CharType kDefaultOutputFile[] = FILE_PATH_LITERAL(
- "test_detail.xml");
-
-// Converts the given epoch time in milliseconds to a date string in the ISO
-// 8601 format, without the timezone information.
-// TODO(xyzzyz): Find a good place in Chromium to put it and refactor all uses
-// to point to it.
-std::string FormatTimeAsIso8601(Time time) {
- Time::Exploded exploded;
- time.UTCExplode(&exploded);
- return StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
- exploded.year,
- exploded.month,
- exploded.day_of_month,
- exploded.hour,
- exploded.minute,
- exploded.second);
-}
-
-struct TestSuiteResultsAggregator {
- TestSuiteResultsAggregator()
- : tests(0), failures(0), disabled(0), errors(0) {}
-
- void Add(const TestResult& result) {
- tests++;
- elapsed_time += result.elapsed_time;
-
- switch (result.status) {
- case TestResult::TEST_SUCCESS:
- break;
- case TestResult::TEST_FAILURE:
- failures++;
- break;
- case TestResult::TEST_EXCESSIVE_OUTPUT:
- case TestResult::TEST_FAILURE_ON_EXIT:
- case TestResult::TEST_TIMEOUT:
- case TestResult::TEST_CRASH:
- case TestResult::TEST_UNKNOWN:
- errors++;
- break;
- case TestResult::TEST_SKIPPED:
- disabled++;
- break;
- }
- }
-
- int tests;
- int failures;
- int disabled;
- int errors;
-
- TimeDelta elapsed_time;
-};
-
-} // namespace
-
-TestResultsTracker::TestResultsTracker() : iteration_(-1), out_(nullptr) {}
-
-TestResultsTracker::~TestResultsTracker() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!out_)
- return;
-
- // Maps test case names to test results.
- typedef std::map<std::string, std::vector<TestResult> > TestCaseMap;
- TestCaseMap test_case_map;
-
- TestSuiteResultsAggregator all_tests_aggregator;
- for (const PerIterationData::ResultsMap::value_type& i
- : per_iteration_data_[iteration_].results) {
- // Use the last test result as the final one.
- TestResult result = i.second.test_results.back();
- test_case_map[result.GetTestCaseName()].push_back(result);
- all_tests_aggregator.Add(result);
- }
-
- fprintf(out_, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- fprintf(out_,
- "<testsuites name=\"AllTests\" tests=\"%d\" failures=\"%d\""
- " disabled=\"%d\" errors=\"%d\" time=\"%.3f\" timestamp=\"%s\">\n",
- all_tests_aggregator.tests, all_tests_aggregator.failures,
- all_tests_aggregator.disabled, all_tests_aggregator.errors,
- all_tests_aggregator.elapsed_time.InSecondsF(),
- FormatTimeAsIso8601(Time::Now()).c_str());
-
- for (const TestCaseMap::value_type& i : test_case_map) {
- const std::string testsuite_name = i.first;
- const std::vector<TestResult>& results = i.second;
-
- TestSuiteResultsAggregator aggregator;
- for (const TestResult& result : results) {
- aggregator.Add(result);
- }
- fprintf(out_,
- " <testsuite name=\"%s\" tests=\"%d\" "
- "failures=\"%d\" disabled=\"%d\" errors=\"%d\" time=\"%.3f\" "
- "timestamp=\"%s\">\n",
- testsuite_name.c_str(), aggregator.tests, aggregator.failures,
- aggregator.disabled, aggregator.errors,
- aggregator.elapsed_time.InSecondsF(),
- FormatTimeAsIso8601(Time::Now()).c_str());
-
- for (const TestResult& result : results) {
- fprintf(out_, " <testcase name=\"%s\" status=\"run\" time=\"%.3f\""
- " classname=\"%s\">\n",
- result.GetTestName().c_str(),
- result.elapsed_time.InSecondsF(),
- result.GetTestCaseName().c_str());
- if (result.status != TestResult::TEST_SUCCESS) {
- // The actual failure message is not propagated up to here, as it's too
- // much work to escape it properly, and in case of failure, almost
- // always one needs to look into full log anyway.
- fprintf(out_, " <failure message=\"\" type=\"\"></failure>\n");
- }
- fprintf(out_, " </testcase>\n");
- }
- fprintf(out_, " </testsuite>\n");
- }
-
- fprintf(out_, "</testsuites>\n");
- fclose(out_);
-}
-
-bool TestResultsTracker::Init(const CommandLine& command_line) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Prevent initializing twice.
- if (out_) {
- NOTREACHED();
- return false;
- }
-
- if (!command_line.HasSwitch(kGTestOutputFlag))
- return true;
-
- std::string flag = command_line.GetSwitchValueASCII(kGTestOutputFlag);
- size_t colon_pos = flag.find(':');
- FilePath path;
- if (colon_pos != std::string::npos) {
- FilePath flag_path =
- command_line.GetSwitchValuePath(kGTestOutputFlag);
- FilePath::StringType path_string = flag_path.value();
- path = FilePath(path_string.substr(colon_pos + 1));
- // If the given path ends with '/', consider it is a directory.
- // Note: This does NOT check that a directory (or file) actually exists
- // (the behavior is same as what gtest does).
- if (path.EndsWithSeparator()) {
- FilePath executable = command_line.GetProgram().BaseName();
- path = path.Append(executable.ReplaceExtension(
- FilePath::StringType(FILE_PATH_LITERAL("xml"))));
- }
- }
- if (path.value().empty())
- path = FilePath(kDefaultOutputFile);
- FilePath dir_name = path.DirName();
- if (!DirectoryExists(dir_name)) {
- LOG(WARNING) << "The output directory does not exist. "
- << "Creating the directory: " << dir_name.value();
- // Create the directory if necessary (because the gtest does the same).
- if (!CreateDirectory(dir_name)) {
- LOG(ERROR) << "Failed to created directory " << dir_name.value();
- return false;
- }
- }
- out_ = OpenFile(path, "w");
- if (!out_) {
- LOG(ERROR) << "Cannot open output file: "
- << path.value() << ".";
- return false;
- }
-
- return true;
-}
-
-void TestResultsTracker::OnTestIterationStarting() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Start with a fresh state for new iteration.
- iteration_++;
- per_iteration_data_.push_back(PerIterationData());
-}
-
-void TestResultsTracker::AddTest(const std::string& test_name) {
- // Record disabled test names without DISABLED_ prefix so that they are easy
- // to compare with regular test names, e.g. before or after disabling.
- all_tests_.insert(TestNameWithoutDisabledPrefix(test_name));
-}
-
-void TestResultsTracker::AddDisabledTest(const std::string& test_name) {
- // Record disabled test names without DISABLED_ prefix so that they are easy
- // to compare with regular test names, e.g. before or after disabling.
- disabled_tests_.insert(TestNameWithoutDisabledPrefix(test_name));
-}
-
-void TestResultsTracker::AddTestLocation(const std::string& test_name,
- const std::string& file,
- int line) {
- test_locations_.insert(std::make_pair(test_name, CodeLocation(file, line)));
-}
-
-void TestResultsTracker::AddTestResult(const TestResult& result) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Record disabled test names without DISABLED_ prefix so that they are easy
- // to compare with regular test names, e.g. before or after disabling.
- per_iteration_data_[iteration_].results[
- TestNameWithoutDisabledPrefix(result.full_name)].test_results.push_back(
- result);
-}
-
-void TestResultsTracker::PrintSummaryOfCurrentIteration() const {
- TestStatusMap tests_by_status(GetTestStatusMapForCurrentIteration());
-
- PrintTests(tests_by_status[TestResult::TEST_FAILURE].begin(),
- tests_by_status[TestResult::TEST_FAILURE].end(),
- "failed");
- PrintTests(tests_by_status[TestResult::TEST_FAILURE_ON_EXIT].begin(),
- tests_by_status[TestResult::TEST_FAILURE_ON_EXIT].end(),
- "failed on exit");
- PrintTests(tests_by_status[TestResult::TEST_EXCESSIVE_OUTPUT].begin(),
- tests_by_status[TestResult::TEST_EXCESSIVE_OUTPUT].end(),
- "produced excessive output");
- PrintTests(tests_by_status[TestResult::TEST_TIMEOUT].begin(),
- tests_by_status[TestResult::TEST_TIMEOUT].end(),
- "timed out");
- PrintTests(tests_by_status[TestResult::TEST_CRASH].begin(),
- tests_by_status[TestResult::TEST_CRASH].end(),
- "crashed");
- PrintTests(tests_by_status[TestResult::TEST_SKIPPED].begin(),
- tests_by_status[TestResult::TEST_SKIPPED].end(),
- "skipped");
- PrintTests(tests_by_status[TestResult::TEST_UNKNOWN].begin(),
- tests_by_status[TestResult::TEST_UNKNOWN].end(),
- "had unknown result");
-}
-
-void TestResultsTracker::PrintSummaryOfAllIterations() const {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- TestStatusMap tests_by_status(GetTestStatusMapForAllIterations());
-
- fprintf(stdout, "Summary of all test iterations:\n");
- fflush(stdout);
-
- PrintTests(tests_by_status[TestResult::TEST_FAILURE].begin(),
- tests_by_status[TestResult::TEST_FAILURE].end(),
- "failed");
- PrintTests(tests_by_status[TestResult::TEST_FAILURE_ON_EXIT].begin(),
- tests_by_status[TestResult::TEST_FAILURE_ON_EXIT].end(),
- "failed on exit");
- PrintTests(tests_by_status[TestResult::TEST_EXCESSIVE_OUTPUT].begin(),
- tests_by_status[TestResult::TEST_EXCESSIVE_OUTPUT].end(),
- "produced excessive output");
- PrintTests(tests_by_status[TestResult::TEST_TIMEOUT].begin(),
- tests_by_status[TestResult::TEST_TIMEOUT].end(),
- "timed out");
- PrintTests(tests_by_status[TestResult::TEST_CRASH].begin(),
- tests_by_status[TestResult::TEST_CRASH].end(),
- "crashed");
- PrintTests(tests_by_status[TestResult::TEST_SKIPPED].begin(),
- tests_by_status[TestResult::TEST_SKIPPED].end(),
- "skipped");
- PrintTests(tests_by_status[TestResult::TEST_UNKNOWN].begin(),
- tests_by_status[TestResult::TEST_UNKNOWN].end(),
- "had unknown result");
-
- fprintf(stdout, "End of the summary.\n");
- fflush(stdout);
-}
-
-void TestResultsTracker::AddGlobalTag(const std::string& tag) {
- global_tags_.insert(tag);
-}
-
-bool TestResultsTracker::SaveSummaryAsJSON(
- const FilePath& path,
- const std::vector<std::string>& additional_tags) const {
- std::unique_ptr<DictionaryValue> summary_root(new DictionaryValue);
-
- std::unique_ptr<ListValue> global_tags(new ListValue);
- for (const auto& global_tag : global_tags_) {
- global_tags->AppendString(global_tag);
- }
- for (const auto& tag : additional_tags) {
- global_tags->AppendString(tag);
- }
- summary_root->Set("global_tags", std::move(global_tags));
-
- std::unique_ptr<ListValue> all_tests(new ListValue);
- for (const auto& test : all_tests_) {
- all_tests->AppendString(test);
- }
- summary_root->Set("all_tests", std::move(all_tests));
-
- std::unique_ptr<ListValue> disabled_tests(new ListValue);
- for (const auto& disabled_test : disabled_tests_) {
- disabled_tests->AppendString(disabled_test);
- }
- summary_root->Set("disabled_tests", std::move(disabled_tests));
-
- std::unique_ptr<ListValue> per_iteration_data(new ListValue);
-
- for (int i = 0; i <= iteration_; i++) {
- std::unique_ptr<DictionaryValue> current_iteration_data(
- new DictionaryValue);
-
- for (PerIterationData::ResultsMap::const_iterator j =
- per_iteration_data_[i].results.begin();
- j != per_iteration_data_[i].results.end();
- ++j) {
- std::unique_ptr<ListValue> test_results(new ListValue);
-
- for (size_t k = 0; k < j->second.test_results.size(); k++) {
- const TestResult& test_result = j->second.test_results[k];
-
- std::unique_ptr<DictionaryValue> test_result_value(new DictionaryValue);
-
- test_result_value->SetString("status", test_result.StatusAsString());
- test_result_value->SetInteger(
- "elapsed_time_ms",
- static_cast<int>(test_result.elapsed_time.InMilliseconds()));
-
- bool lossless_snippet = false;
- if (IsStringUTF8(test_result.output_snippet)) {
- test_result_value->SetString(
- "output_snippet", test_result.output_snippet);
- lossless_snippet = true;
- } else {
- test_result_value->SetString(
- "output_snippet",
- "<non-UTF-8 snippet, see output_snippet_base64>");
- }
-
- // TODO(phajdan.jr): Fix typo in JSON key (losless -> lossless)
- // making sure not to break any consumers of this data.
- test_result_value->SetBoolean("losless_snippet", lossless_snippet);
-
- // Also include the raw version (base64-encoded so that it can be safely
- // JSON-serialized - there are no guarantees about character encoding
- // of the snippet). This can be very useful piece of information when
- // debugging a test failure related to character encoding.
- std::string base64_output_snippet;
- Base64Encode(test_result.output_snippet, &base64_output_snippet);
- test_result_value->SetString("output_snippet_base64",
- base64_output_snippet);
-
- std::unique_ptr<ListValue> test_result_parts(new ListValue);
- for (const TestResultPart& result_part :
- test_result.test_result_parts) {
- std::unique_ptr<DictionaryValue> result_part_value(
- new DictionaryValue);
- result_part_value->SetString("type", result_part.TypeAsString());
- result_part_value->SetString("file", result_part.file_name);
- result_part_value->SetInteger("line", result_part.line_number);
-
- bool lossless_summary = IsStringUTF8(result_part.summary);
- if (lossless_summary) {
- result_part_value->SetString("summary", result_part.summary);
- } else {
- result_part_value->SetString(
- "summary", "<non-UTF-8 snippet, see summary_base64>");
- }
- result_part_value->SetBoolean("lossless_summary", lossless_summary);
-
- std::string encoded_summary;
- Base64Encode(result_part.summary, &encoded_summary);
- result_part_value->SetString("summary_base64", encoded_summary);
-
- bool lossless_message = IsStringUTF8(result_part.message);
- if (lossless_message) {
- result_part_value->SetString("message", result_part.message);
- } else {
- result_part_value->SetString(
- "message", "<non-UTF-8 snippet, see message_base64>");
- }
- result_part_value->SetBoolean("lossless_message", lossless_message);
-
- std::string encoded_message;
- Base64Encode(result_part.message, &encoded_message);
- result_part_value->SetString("message_base64", encoded_message);
-
- test_result_parts->Append(std::move(result_part_value));
- }
- test_result_value->Set("result_parts", std::move(test_result_parts));
-
- test_results->Append(std::move(test_result_value));
- }
-
- current_iteration_data->SetWithoutPathExpansion(j->first,
- std::move(test_results));
- }
- per_iteration_data->Append(std::move(current_iteration_data));
- }
- summary_root->Set("per_iteration_data", std::move(per_iteration_data));
-
- std::unique_ptr<DictionaryValue> test_locations(new DictionaryValue);
- for (const auto& item : test_locations_) {
- std::string test_name = item.first;
- CodeLocation location = item.second;
- std::unique_ptr<DictionaryValue> location_value(new DictionaryValue);
- location_value->SetString("file", location.file);
- location_value->SetInteger("line", location.line);
- test_locations->SetWithoutPathExpansion(test_name,
- std::move(location_value));
- }
- summary_root->Set("test_locations", std::move(test_locations));
-
- std::string json;
- if (!JSONWriter::Write(*summary_root, &json))
- return false;
-
- File output(path, File::FLAG_CREATE_ALWAYS | File::FLAG_WRITE);
- if (!output.IsValid())
- return false;
-
- int json_size = static_cast<int>(json.size());
- if (output.WriteAtCurrentPos(json.data(), json_size) != json_size) {
- return false;
- }
-
- // File::Flush() will call fsync(). This is important on Fuchsia to ensure
- // that the file is written to the disk - the system running under qemu will
- // shutdown shortly after the test completes. On Fuchsia fsync() times out
- // after 15 seconds. Apparently this may not be enough in some cases,
- // particularly when running net_unittests on buildbots, see
- // https://crbug.com/796318. Try calling fsync() more than once to workaround
- // this issue.
- //
- // TODO(sergeyu): Figure out a better solution.
- int flush_attempts_left = 4;
- while (flush_attempts_left-- > 0) {
- if (output.Flush())
- return true;
- LOG(ERROR) << "fsync() failed when saving test output summary. "
- << ((flush_attempts_left > 0) ? "Retrying." : " Giving up.");
- }
-
- return false;
-}
-
-TestResultsTracker::TestStatusMap
- TestResultsTracker::GetTestStatusMapForCurrentIteration() const {
- TestStatusMap tests_by_status;
- GetTestStatusForIteration(iteration_, &tests_by_status);
- return tests_by_status;
-}
-
-TestResultsTracker::TestStatusMap
- TestResultsTracker::GetTestStatusMapForAllIterations() const {
- TestStatusMap tests_by_status;
- for (int i = 0; i <= iteration_; i++)
- GetTestStatusForIteration(i, &tests_by_status);
- return tests_by_status;
-}
-
-void TestResultsTracker::GetTestStatusForIteration(
- int iteration, TestStatusMap* map) const {
- for (PerIterationData::ResultsMap::const_iterator j =
- per_iteration_data_[iteration].results.begin();
- j != per_iteration_data_[iteration].results.end();
- ++j) {
- // Use the last test result as the final one.
- const TestResult& result = j->second.test_results.back();
- (*map)[result.status].insert(result.full_name);
- }
-}
-
-// Utility function to print a list of test names. Uses iterator to be
-// compatible with different containers, like vector and set.
-template<typename InputIterator>
-void TestResultsTracker::PrintTests(InputIterator first,
- InputIterator last,
- const std::string& description) const {
- size_t count = std::distance(first, last);
- if (count == 0)
- return;
-
- fprintf(stdout,
- "%" PRIuS " test%s %s:\n",
- count,
- count != 1 ? "s" : "",
- description.c_str());
- for (InputIterator it = first; it != last; ++it) {
- const std::string& test_name = *it;
- const auto location_it = test_locations_.find(test_name);
- DCHECK(location_it != test_locations_.end()) << test_name;
- const CodeLocation& location = location_it->second;
- fprintf(stdout, " %s (%s:%d)\n", test_name.c_str(),
- location.file.c_str(), location.line);
- }
- fflush(stdout);
-}
-
-TestResultsTracker::AggregateTestResult::AggregateTestResult() = default;
-
-TestResultsTracker::AggregateTestResult::AggregateTestResult(
- const AggregateTestResult& other) = default;
-
-TestResultsTracker::AggregateTestResult::~AggregateTestResult() = default;
-
-TestResultsTracker::PerIterationData::PerIterationData() = default;
-
-TestResultsTracker::PerIterationData::PerIterationData(
- const PerIterationData& other) = default;
-
-TestResultsTracker::PerIterationData::~PerIterationData() = default;
-
-} // namespace base
diff --git a/base/test/launcher/test_results_tracker.h b/base/test/launcher/test_results_tracker.h
deleted file mode 100644
index d89821d2af..0000000000
--- a/base/test/launcher/test_results_tracker.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_LAUNCHER_TEST_RESULTS_TRACKER_H_
-#define BASE_TEST_LAUNCHER_TEST_RESULTS_TRACKER_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/test/launcher/test_result.h"
-#include "base/threading/thread_checker.h"
-
-namespace base {
-
-class CommandLine;
-class FilePath;
-
-// A helper class to output results.
-// Note: as currently XML is the only supported format by gtest, we don't
-// check output format (e.g. "xml:" prefix) here and output an XML file
-// unconditionally.
-// Note: we don't output per-test-case or total summary info like
-// total failed_test_count, disabled_test_count, elapsed_time and so on.
-// Only each test (testcase element in the XML) will have the correct
-// failed/disabled/elapsed_time information. Each test won't include
-// detailed failure messages either.
-class TestResultsTracker {
- public:
- TestResultsTracker();
- ~TestResultsTracker();
-
- // Initialize the result tracker. Must be called exactly once before
- // calling any other methods. Returns true on success.
- bool Init(const CommandLine& command_line) WARN_UNUSED_RESULT;
-
- // Called when a test iteration is starting.
- void OnTestIterationStarting();
-
- // Adds |test_name| to the set of discovered tests (this includes all tests
- // present in the executable, not necessarily run).
- void AddTest(const std::string& test_name);
-
- // Adds |test_name| to the set of disabled tests.
- void AddDisabledTest(const std::string& test_name);
-
- // Adds location for the |test_name|.
- void AddTestLocation(const std::string& test_name,
- const std::string& file,
- int line);
-
- // Adds |result| to the stored test results.
- void AddTestResult(const TestResult& result);
-
- // Prints a summary of current test iteration to stdout.
- void PrintSummaryOfCurrentIteration() const;
-
- // Prints a summary of all test iterations (not just the last one) to stdout.
- void PrintSummaryOfAllIterations() const;
-
- // Adds a string tag to the JSON summary. This is intended to indicate
- // conditions that affect the entire test run, as opposed to individual tests.
- void AddGlobalTag(const std::string& tag);
-
- // Saves a JSON summary of all test iterations results to |path|. Adds
- // |additional_tags| to the summary (just for this invocation). Returns
- // true on success.
- bool SaveSummaryAsJSON(
- const FilePath& path,
- const std::vector<std::string>& additional_tags) const WARN_UNUSED_RESULT;
-
- // Map where keys are test result statuses, and values are sets of tests
- // which finished with that status.
- typedef std::map<TestResult::Status, std::set<std::string> > TestStatusMap;
-
- // Returns a test status map (see above) for current test iteration.
- TestStatusMap GetTestStatusMapForCurrentIteration() const;
-
- // Returns a test status map (see above) for all test iterations.
- TestStatusMap GetTestStatusMapForAllIterations() const;
-
- private:
- void GetTestStatusForIteration(int iteration, TestStatusMap* map) const;
-
- template<typename InputIterator>
- void PrintTests(InputIterator first,
- InputIterator last,
- const std::string& description) const;
-
- struct AggregateTestResult {
- AggregateTestResult();
- AggregateTestResult(const AggregateTestResult& other);
- ~AggregateTestResult();
-
- std::vector<TestResult> test_results;
- };
-
- struct PerIterationData {
- PerIterationData();
- PerIterationData(const PerIterationData& other);
- ~PerIterationData();
-
- // Aggregate test results grouped by full test name.
- typedef std::map<std::string, AggregateTestResult> ResultsMap;
- ResultsMap results;
- };
-
- struct CodeLocation {
- CodeLocation(const std::string& f, int l) : file(f), line(l) {
- }
-
- std::string file;
- int line;
- };
-
- ThreadChecker thread_checker_;
-
- // Set of global tags, i.e. strings indicating conditions that apply to
- // the entire test run.
- std::set<std::string> global_tags_;
-
- // Set of all test names discovered in the current executable.
- std::set<std::string> all_tests_;
-
- std::map<std::string, CodeLocation> test_locations_;
-
- // Set of all disabled tests in the current executable.
- std::set<std::string> disabled_tests_;
-
- // Store test results for each iteration.
- std::vector<PerIterationData> per_iteration_data_;
-
- // Index of current iteration (starting from 0). -1 before the first
- // iteration.
- int iteration_;
-
- // File handle of output file (can be NULL if no file).
- FILE* out_;
-
- DISALLOW_COPY_AND_ASSIGN(TestResultsTracker);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_LAUNCHER_TEST_RESULTS_TRACKER_H_
diff --git a/base/test/launcher/unit_test_launcher.cc b/base/test/launcher/unit_test_launcher.cc
deleted file mode 100644
index 1d4439c681..0000000000
--- a/base/test/launcher/unit_test_launcher.cc
+++ /dev/null
@@ -1,750 +0,0 @@
-// Copyright 2013 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/unit_test_launcher.h"
-
-#include <map>
-#include <memory>
-#include <utility>
-
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/debug/debugger.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/format_macros.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/sequence_checker.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/sys_info.h"
-#include "base/test/gtest_xml_util.h"
-#include "base/test/launcher/test_launcher.h"
-#include "base/test/test_switches.h"
-#include "base/test/test_timeouts.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include "base/files/file_descriptor_watcher_posix.h"
-#endif
-
-namespace base {
-
-namespace {
-
-// This constant controls how many tests are run in a single batch by default.
-const size_t kDefaultTestBatchLimit = 10;
-
-const char kHelpFlag[] = "help";
-
-// Flag to run all tests in a single process.
-const char kSingleProcessTestsFlag[] = "single-process-tests";
-
-void PrintUsage() {
- fprintf(stdout,
- "Runs tests using the gtest framework, each batch of tests being\n"
- "run in their own process. Supported command-line flags:\n"
- "\n"
- " Common flags:\n"
- " --gtest_filter=...\n"
- " Runs a subset of tests (see --gtest_help for more info).\n"
- "\n"
- " --help\n"
- " Shows this message.\n"
- "\n"
- " --gtest_help\n"
- " Shows the gtest help message.\n"
- "\n"
- " --test-launcher-jobs=N\n"
- " Sets the number of parallel test jobs to N.\n"
- "\n"
- " --single-process-tests\n"
- " Runs the tests and the launcher in the same process. Useful\n"
- " for debugging a specific test in a debugger.\n"
- "\n"
- " Other flags:\n"
- " --test-launcher-filter-file=PATH\n"
- " Like --gtest_filter, but read the test filter from PATH.\n"
- " One pattern per line; lines starting with '-' are exclusions.\n"
- " See also //testing/buildbot/filters/README.md file.\n"
- "\n"
- " --test-launcher-batch-limit=N\n"
- " Sets the limit of test batch to run in a single process to N.\n"
- "\n"
- " --test-launcher-debug-launcher\n"
- " Disables autodetection of debuggers and similar tools,\n"
- " making it possible to use them to debug launcher itself.\n"
- "\n"
- " --test-launcher-retry-limit=N\n"
- " Sets the limit of test retries on failures to N.\n"
- "\n"
- " --test-launcher-summary-output=PATH\n"
- " Saves a JSON machine-readable summary of the run.\n"
- "\n"
- " --test-launcher-print-test-stdio=auto|always|never\n"
- " Controls when full test output is printed.\n"
- " auto means to print it when the test failed.\n"
- "\n"
- " --test-launcher-test-part-results-limit=N\n"
- " Sets the limit of failed EXPECT/ASSERT entries in the xml and\n"
- " JSON outputs per test to N (default N=10). Negative value \n"
- " will disable this limit.\n"
- "\n"
- " --test-launcher-total-shards=N\n"
- " Sets the total number of shards to N.\n"
- "\n"
- " --test-launcher-shard-index=N\n"
- " Sets the shard index to run to N (from 0 to TOTAL - 1).\n");
- fflush(stdout);
-}
-
-class DefaultUnitTestPlatformDelegate : public UnitTestPlatformDelegate {
- public:
- DefaultUnitTestPlatformDelegate() = default;
-
- private:
- // UnitTestPlatformDelegate:
- bool GetTests(std::vector<TestIdentifier>* output) override {
- *output = GetCompiledInTests();
- return true;
- }
-
- bool CreateResultsFile(base::FilePath* path) override {
- if (!CreateNewTempDirectory(FilePath::StringType(), path))
- return false;
- *path = path->AppendASCII("test_results.xml");
- return true;
- }
-
- bool CreateTemporaryFile(base::FilePath* path) override {
- if (!temp_dir_.IsValid() && !temp_dir_.CreateUniqueTempDir())
- return false;
- return CreateTemporaryFileInDir(temp_dir_.GetPath(), path);
- }
-
- CommandLine GetCommandLineForChildGTestProcess(
- const std::vector<std::string>& test_names,
- const base::FilePath& output_file,
- const base::FilePath& flag_file) override {
- CommandLine new_cmd_line(*CommandLine::ForCurrentProcess());
-
- CHECK(base::PathExists(flag_file));
-
- std::string long_flags(
- std::string("--") + kGTestFilterFlag + "=" +
- JoinString(test_names, ":"));
- CHECK_EQ(static_cast<int>(long_flags.size()),
- WriteFile(flag_file, long_flags.data(),
- static_cast<int>(long_flags.size())));
-
- new_cmd_line.AppendSwitchPath(switches::kTestLauncherOutput, output_file);
- new_cmd_line.AppendSwitchPath(kGTestFlagfileFlag, flag_file);
- new_cmd_line.AppendSwitch(kSingleProcessTestsFlag);
-
- return new_cmd_line;
- }
-
- std::string GetWrapperForChildGTestProcess() override {
- return std::string();
- }
-
- void RelaunchTests(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names,
- int launch_flags) override {
- // Relaunch requested tests in parallel, but only use single
- // test per batch for more precise results (crashes, etc).
- for (const std::string& test_name : test_names) {
- std::vector<std::string> batch;
- batch.push_back(test_name);
- RunUnitTestsBatch(test_launcher, this, batch, launch_flags);
- }
- }
-
- ScopedTempDir temp_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(DefaultUnitTestPlatformDelegate);
-};
-
-bool GetSwitchValueAsInt(const std::string& switch_name, int* result) {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switch_name))
- return true;
-
- std::string switch_value =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switch_name);
- if (!StringToInt(switch_value, result) || *result < 0) {
- LOG(ERROR) << "Invalid value for " << switch_name << ": " << switch_value;
- return false;
- }
-
- return true;
-}
-
-int LaunchUnitTestsInternal(RunTestSuiteCallback run_test_suite,
- size_t parallel_jobs,
- int default_batch_limit,
- bool use_job_objects,
- OnceClosure gtest_init) {
-#if defined(OS_ANDROID)
- // We can't easily fork on Android, just run the test suite directly.
- return std::move(run_test_suite).Run();
-#else
- bool force_single_process = false;
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTestLauncherDebugLauncher)) {
- fprintf(stdout, "Forcing test launcher debugging mode.\n");
- fflush(stdout);
- } else {
- if (base::debug::BeingDebugged()) {
- fprintf(stdout,
- "Debugger detected, switching to single process mode.\n"
- "Pass --test-launcher-debug-launcher to debug the launcher "
- "itself.\n");
- fflush(stdout);
- force_single_process = true;
- }
- }
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(kGTestHelpFlag) ||
- CommandLine::ForCurrentProcess()->HasSwitch(kGTestListTestsFlag) ||
- CommandLine::ForCurrentProcess()->HasSwitch(kSingleProcessTestsFlag) ||
- CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTestChildProcess) ||
- force_single_process) {
- return std::move(run_test_suite).Run();
- }
-#endif
-
- if (CommandLine::ForCurrentProcess()->HasSwitch(kHelpFlag)) {
- PrintUsage();
- return 0;
- }
-
- TimeTicks start_time(TimeTicks::Now());
-
- std::move(gtest_init).Run();
- TestTimeouts::Initialize();
-
- int batch_limit = default_batch_limit;
- if (!GetSwitchValueAsInt(switches::kTestLauncherBatchLimit, &batch_limit))
- return 1;
-
- fprintf(stdout,
- "IMPORTANT DEBUGGING NOTE: batches of tests are run inside their\n"
- "own process. For debugging a test inside a debugger, use the\n"
- "--gtest_filter=<your_test_name> flag along with\n"
- "--single-process-tests.\n");
- fflush(stdout);
-
- MessageLoopForIO message_loop;
-#if defined(OS_POSIX)
- FileDescriptorWatcher file_descriptor_watcher(&message_loop);
-#endif
-
- DefaultUnitTestPlatformDelegate platform_delegate;
- UnitTestLauncherDelegate delegate(
- &platform_delegate, batch_limit, use_job_objects);
- TestLauncher launcher(&delegate, parallel_jobs);
- bool success = launcher.Run();
-
- fprintf(stdout, "Tests took %" PRId64 " seconds.\n",
- (TimeTicks::Now() - start_time).InSeconds());
- fflush(stdout);
-
- return (success ? 0 : 1);
-}
-
-void InitGoogleTestChar(int* argc, char** argv) {
- testing::InitGoogleTest(argc, argv);
-}
-
-#if defined(OS_WIN)
-void InitGoogleTestWChar(int* argc, wchar_t** argv) {
- testing::InitGoogleTest(argc, argv);
-}
-#endif // defined(OS_WIN)
-
-// Interprets test results and reports to the test launcher. Returns true
-// on success.
-bool ProcessTestResults(
- TestLauncher* test_launcher,
- const std::vector<std::string>& test_names,
- const base::FilePath& output_file,
- const std::string& output,
- int exit_code,
- bool was_timeout,
- std::vector<std::string>* tests_to_relaunch) {
- std::vector<TestResult> test_results;
- bool crashed = false;
- bool have_test_results =
- ProcessGTestOutput(output_file, &test_results, &crashed);
-
- bool called_any_callback = false;
-
- if (have_test_results) {
- // TODO(phajdan.jr): Check for duplicates and mismatches between
- // the results we got from XML file and tests we intended to run.
- std::map<std::string, TestResult> results_map;
- for (size_t i = 0; i < test_results.size(); i++)
- results_map[test_results[i].full_name] = test_results[i];
-
- bool had_interrupted_test = false;
-
- // Results to be reported back to the test launcher.
- std::vector<TestResult> final_results;
-
- for (size_t i = 0; i < test_names.size(); i++) {
- if (ContainsKey(results_map, test_names[i])) {
- TestResult test_result = results_map[test_names[i]];
- if (test_result.status == TestResult::TEST_CRASH) {
- had_interrupted_test = true;
-
- if (was_timeout) {
- // Fix up the test status: we forcibly kill the child process
- // after the timeout, so from XML results it looks just like
- // a crash.
- test_result.status = TestResult::TEST_TIMEOUT;
- }
- } else if (test_result.status == TestResult::TEST_SUCCESS ||
- test_result.status == TestResult::TEST_FAILURE) {
- // We run multiple tests in a batch with a timeout applied
- // to the entire batch. It is possible that with other tests
- // running quickly some tests take longer than the per-test timeout.
- // For consistent handling of tests independent of order and other
- // factors, mark them as timing out.
- if (test_result.elapsed_time >
- TestTimeouts::test_launcher_timeout()) {
- test_result.status = TestResult::TEST_TIMEOUT;
- }
- }
- test_result.output_snippet = GetTestOutputSnippet(test_result, output);
- final_results.push_back(test_result);
- } else if (had_interrupted_test) {
- tests_to_relaunch->push_back(test_names[i]);
- } else {
- // TODO(phajdan.jr): Explicitly pass the info that the test didn't
- // run for a mysterious reason.
- LOG(ERROR) << "no test result for " << test_names[i];
- TestResult test_result;
- test_result.full_name = test_names[i];
- test_result.status = TestResult::TEST_UNKNOWN;
- test_result.output_snippet = GetTestOutputSnippet(test_result, output);
- final_results.push_back(test_result);
- }
- }
-
- // TODO(phajdan.jr): Handle the case where processing XML output
- // indicates a crash but none of the test results is marked as crashing.
-
- if (final_results.empty())
- return false;
-
- bool has_non_success_test = false;
- for (size_t i = 0; i < final_results.size(); i++) {
- if (final_results[i].status != TestResult::TEST_SUCCESS) {
- has_non_success_test = true;
- break;
- }
- }
-
- if (!has_non_success_test && exit_code != 0) {
- // This is a bit surprising case: all tests are marked as successful,
- // but the exit code was not zero. This can happen e.g. under memory
- // tools that report leaks this way. Mark all tests as a failure on exit,
- // and for more precise info they'd need to be retried serially.
- for (size_t i = 0; i < final_results.size(); i++)
- final_results[i].status = TestResult::TEST_FAILURE_ON_EXIT;
- }
-
- for (size_t i = 0; i < final_results.size(); i++) {
- // Fix the output snippet after possible changes to the test result.
- final_results[i].output_snippet =
- GetTestOutputSnippet(final_results[i], output);
- test_launcher->OnTestFinished(final_results[i]);
- called_any_callback = true;
- }
- } else {
- fprintf(stdout,
- "Failed to get out-of-band test success data, "
- "dumping full stdio below:\n%s\n",
- output.c_str());
- fflush(stdout);
-
- // We do not have reliable details about test results (parsing test
- // stdout is known to be unreliable).
- if (test_names.size() == 1) {
- // There is only one test. Try to determine status by exit code.
- const std::string& test_name = test_names.front();
- TestResult test_result;
- test_result.full_name = test_name;
-
- if (was_timeout) {
- test_result.status = TestResult::TEST_TIMEOUT;
- } else if (exit_code != 0) {
- test_result.status = TestResult::TEST_FAILURE;
- } else {
- // It's strange case when test executed successfully,
- // but we failed to read machine-readable report for it.
- test_result.status = TestResult::TEST_UNKNOWN;
- }
-
- test_launcher->OnTestFinished(test_result);
- called_any_callback = true;
- } else {
- // There is more than one test. Retry them individually.
- for (const std::string& test_name : test_names)
- tests_to_relaunch->push_back(test_name);
- }
- }
-
- return called_any_callback;
-}
-
-class UnitTestProcessLifetimeObserver : public ProcessLifetimeObserver {
- public:
- ~UnitTestProcessLifetimeObserver() override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- }
-
- TestLauncher* test_launcher() { return test_launcher_; }
- UnitTestPlatformDelegate* platform_delegate() { return platform_delegate_; }
- const std::vector<std::string>& test_names() { return test_names_; }
- int launch_flags() { return launch_flags_; }
- const FilePath& output_file() { return output_file_; }
- const FilePath& flag_file() { return flag_file_; }
-
- protected:
- UnitTestProcessLifetimeObserver(TestLauncher* test_launcher,
- UnitTestPlatformDelegate* platform_delegate,
- const std::vector<std::string>& test_names,
- int launch_flags,
- const FilePath& output_file,
- const FilePath& flag_file)
- : ProcessLifetimeObserver(),
- test_launcher_(test_launcher),
- platform_delegate_(platform_delegate),
- test_names_(test_names),
- launch_flags_(launch_flags),
- output_file_(output_file),
- flag_file_(flag_file) {}
-
- SEQUENCE_CHECKER(sequence_checker_);
-
- private:
- TestLauncher* const test_launcher_;
- UnitTestPlatformDelegate* const platform_delegate_;
- const std::vector<std::string> test_names_;
- const int launch_flags_;
- const FilePath output_file_;
- const FilePath flag_file_;
-
- DISALLOW_COPY_AND_ASSIGN(UnitTestProcessLifetimeObserver);
-};
-
-class ParallelUnitTestProcessLifetimeObserver
- : public UnitTestProcessLifetimeObserver {
- public:
- ParallelUnitTestProcessLifetimeObserver(
- TestLauncher* test_launcher,
- UnitTestPlatformDelegate* platform_delegate,
- const std::vector<std::string>& test_names,
- int launch_flags,
- const FilePath& output_file,
- const FilePath& flag_file)
- : UnitTestProcessLifetimeObserver(test_launcher,
- platform_delegate,
- test_names,
- launch_flags,
- output_file,
- flag_file) {}
- ~ParallelUnitTestProcessLifetimeObserver() override = default;
-
- private:
- // ProcessLifetimeObserver:
- void OnCompleted(int exit_code,
- TimeDelta elapsed_time,
- bool was_timeout,
- const std::string& output) override;
-
- DISALLOW_COPY_AND_ASSIGN(ParallelUnitTestProcessLifetimeObserver);
-};
-
-void ParallelUnitTestProcessLifetimeObserver::OnCompleted(
- int exit_code,
- TimeDelta elapsed_time,
- bool was_timeout,
- const std::string& output) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::vector<std::string> tests_to_relaunch;
- ProcessTestResults(test_launcher(), test_names(), output_file(), output,
- exit_code, was_timeout, &tests_to_relaunch);
-
- if (!tests_to_relaunch.empty()) {
- platform_delegate()->RelaunchTests(test_launcher(), tests_to_relaunch,
- launch_flags());
- }
-
- // The temporary file's directory is also temporary.
- DeleteFile(output_file().DirName(), true);
- if (!flag_file().empty())
- DeleteFile(flag_file(), false);
-}
-
-class SerialUnitTestProcessLifetimeObserver
- : public UnitTestProcessLifetimeObserver {
- public:
- SerialUnitTestProcessLifetimeObserver(
- TestLauncher* test_launcher,
- UnitTestPlatformDelegate* platform_delegate,
- const std::vector<std::string>& test_names,
- int launch_flags,
- const FilePath& output_file,
- const FilePath& flag_file,
- std::vector<std::string>&& next_test_names)
- : UnitTestProcessLifetimeObserver(test_launcher,
- platform_delegate,
- test_names,
- launch_flags,
- output_file,
- flag_file),
- next_test_names_(std::move(next_test_names)) {}
- ~SerialUnitTestProcessLifetimeObserver() override = default;
-
- private:
- // ProcessLifetimeObserver:
- void OnCompleted(int exit_code,
- TimeDelta elapsed_time,
- bool was_timeout,
- const std::string& output) override;
-
- std::vector<std::string> next_test_names_;
-
- DISALLOW_COPY_AND_ASSIGN(SerialUnitTestProcessLifetimeObserver);
-};
-
-void SerialUnitTestProcessLifetimeObserver::OnCompleted(
- int exit_code,
- TimeDelta elapsed_time,
- bool was_timeout,
- const std::string& output) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- std::vector<std::string> tests_to_relaunch;
- bool called_any_callbacks =
- ProcessTestResults(test_launcher(), test_names(), output_file(), output,
- exit_code, was_timeout, &tests_to_relaunch);
-
- // There is only one test, there cannot be other tests to relaunch
- // due to a crash.
- DCHECK(tests_to_relaunch.empty());
-
- // There is only one test, we should have called back with its result.
- DCHECK(called_any_callbacks);
-
- // The temporary file's directory is also temporary.
- DeleteFile(output_file().DirName(), true);
-
- if (!flag_file().empty())
- DeleteFile(flag_file(), false);
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&RunUnitTestsSerially, test_launcher(), platform_delegate(),
- std::move(next_test_names_), launch_flags()));
-}
-
-} // namespace
-
-int LaunchUnitTests(int argc,
- char** argv,
- RunTestSuiteCallback run_test_suite) {
- CommandLine::Init(argc, argv);
- size_t parallel_jobs = NumParallelJobs();
- if (parallel_jobs == 0U) {
- return 1;
- }
- return LaunchUnitTestsInternal(std::move(run_test_suite), parallel_jobs,
- kDefaultTestBatchLimit, true,
- BindOnce(&InitGoogleTestChar, &argc, argv));
-}
-
-int LaunchUnitTestsSerially(int argc,
- char** argv,
- RunTestSuiteCallback run_test_suite) {
- CommandLine::Init(argc, argv);
- return LaunchUnitTestsInternal(std::move(run_test_suite), 1U,
- kDefaultTestBatchLimit, true,
- BindOnce(&InitGoogleTestChar, &argc, argv));
-}
-
-int LaunchUnitTestsWithOptions(int argc,
- char** argv,
- size_t parallel_jobs,
- int default_batch_limit,
- bool use_job_objects,
- RunTestSuiteCallback run_test_suite) {
- CommandLine::Init(argc, argv);
- return LaunchUnitTestsInternal(std::move(run_test_suite), parallel_jobs,
- default_batch_limit, use_job_objects,
- BindOnce(&InitGoogleTestChar, &argc, argv));
-}
-
-#if defined(OS_WIN)
-int LaunchUnitTests(int argc,
- wchar_t** argv,
- bool use_job_objects,
- RunTestSuiteCallback run_test_suite) {
- // Windows CommandLine::Init ignores argv anyway.
- CommandLine::Init(argc, NULL);
- size_t parallel_jobs = NumParallelJobs();
- if (parallel_jobs == 0U) {
- return 1;
- }
- return LaunchUnitTestsInternal(std::move(run_test_suite), parallel_jobs,
- kDefaultTestBatchLimit, use_job_objects,
- BindOnce(&InitGoogleTestWChar, &argc, argv));
-}
-#endif // defined(OS_WIN)
-
-void RunUnitTestsSerially(
- TestLauncher* test_launcher,
- UnitTestPlatformDelegate* platform_delegate,
- const std::vector<std::string>& test_names,
- int launch_flags) {
- if (test_names.empty())
- return;
-
- // Create a dedicated temporary directory to store the xml result data
- // per run to ensure clean state and make it possible to launch multiple
- // processes in parallel.
- FilePath output_file;
- CHECK(platform_delegate->CreateResultsFile(&output_file));
- FilePath flag_file;
- platform_delegate->CreateTemporaryFile(&flag_file);
-
- auto observer = std::make_unique<SerialUnitTestProcessLifetimeObserver>(
- test_launcher, platform_delegate,
- std::vector<std::string>(1, test_names.back()), launch_flags, output_file,
- flag_file,
- std::vector<std::string>(test_names.begin(), test_names.end() - 1));
-
- CommandLine cmd_line(platform_delegate->GetCommandLineForChildGTestProcess(
- observer->test_names(), output_file, flag_file));
-
- TestLauncher::LaunchOptions launch_options;
- launch_options.flags = launch_flags;
- test_launcher->LaunchChildGTestProcess(
- cmd_line, platform_delegate->GetWrapperForChildGTestProcess(),
- TestTimeouts::test_launcher_timeout(), launch_options,
- std::move(observer));
-}
-
-void RunUnitTestsBatch(
- TestLauncher* test_launcher,
- UnitTestPlatformDelegate* platform_delegate,
- const std::vector<std::string>& test_names,
- int launch_flags) {
- if (test_names.empty())
- return;
-
- // Create a dedicated temporary directory to store the xml result data
- // per run to ensure clean state and make it possible to launch multiple
- // processes in parallel.
- FilePath output_file;
- CHECK(platform_delegate->CreateResultsFile(&output_file));
- FilePath flag_file;
- platform_delegate->CreateTemporaryFile(&flag_file);
-
- auto observer = std::make_unique<ParallelUnitTestProcessLifetimeObserver>(
- test_launcher, platform_delegate, test_names, launch_flags, output_file,
- flag_file);
-
- CommandLine cmd_line(platform_delegate->GetCommandLineForChildGTestProcess(
- test_names, output_file, flag_file));
-
- // Adjust the timeout depending on how many tests we're running
- // (note that e.g. the last batch of tests will be smaller).
- // TODO(phajdan.jr): Consider an adaptive timeout, which can change
- // depending on how many tests ran and how many remain.
- // Note: do NOT parse child's stdout to do that, it's known to be
- // unreliable (e.g. buffering issues can mix up the output).
- TimeDelta timeout = test_names.size() * TestTimeouts::test_launcher_timeout();
-
- TestLauncher::LaunchOptions options;
- options.flags = launch_flags;
- test_launcher->LaunchChildGTestProcess(
- cmd_line, platform_delegate->GetWrapperForChildGTestProcess(), timeout,
- options, std::move(observer));
-}
-
-UnitTestLauncherDelegate::UnitTestLauncherDelegate(
- UnitTestPlatformDelegate* platform_delegate,
- size_t batch_limit,
- bool use_job_objects)
- : platform_delegate_(platform_delegate),
- batch_limit_(batch_limit),
- use_job_objects_(use_job_objects) {
-}
-
-UnitTestLauncherDelegate::~UnitTestLauncherDelegate() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-bool UnitTestLauncherDelegate::GetTests(std::vector<TestIdentifier>* output) {
- DCHECK(thread_checker_.CalledOnValidThread());
- return platform_delegate_->GetTests(output);
-}
-
-bool UnitTestLauncherDelegate::ShouldRunTest(const std::string& test_case_name,
- const std::string& test_name) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // There is no additional logic to disable specific tests.
- return true;
-}
-
-size_t UnitTestLauncherDelegate::RunTests(
- TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- int launch_flags = use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0;
-
- std::vector<std::string> batch;
- for (size_t i = 0; i < test_names.size(); i++) {
- batch.push_back(test_names[i]);
-
- // Use 0 to indicate unlimited batch size.
- if (batch.size() >= batch_limit_ && batch_limit_ != 0) {
- RunUnitTestsBatch(test_launcher, platform_delegate_, batch, launch_flags);
- batch.clear();
- }
- }
-
- RunUnitTestsBatch(test_launcher, platform_delegate_, batch, launch_flags);
-
- return test_names.size();
-}
-
-size_t UnitTestLauncherDelegate::RetryTests(
- TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) {
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&RunUnitTestsSerially, test_launcher, platform_delegate_,
- test_names,
- use_job_objects_ ? TestLauncher::USE_JOB_OBJECTS : 0));
- return test_names.size();
-}
-
-} // namespace base
diff --git a/base/test/launcher/unit_test_launcher.h b/base/test/launcher/unit_test_launcher.h
deleted file mode 100644
index 0d1c21e084..0000000000
--- a/base/test/launcher/unit_test_launcher.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_LAUNCHER_UNIT_TEST_LAUNCHER_H_
-#define BASE_TEST_LAUNCHER_UNIT_TEST_LAUNCHER_H_
-
-#include <stddef.h>
-
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/test/launcher/test_launcher.h"
-#include "build/build_config.h"
-
-namespace base {
-
-// Callback that runs a test suite and returns exit code.
-using RunTestSuiteCallback = OnceCallback<int(void)>;
-
-// Launches unit tests in given test suite. Returns exit code.
-int LaunchUnitTests(int argc, char** argv, RunTestSuiteCallback run_test_suite);
-
-// Same as above, but always runs tests serially.
-int LaunchUnitTestsSerially(int argc,
- char** argv,
- RunTestSuiteCallback run_test_suite);
-
-// Launches unit tests in given test suite. Returns exit code.
-// |parallel_jobs| is the number of parallel test jobs.
-// |default_batch_limit| is the default size of test batch
-// (use 0 to disable batching).
-// |use_job_objects| determines whether to use job objects.
-int LaunchUnitTestsWithOptions(int argc,
- char** argv,
- size_t parallel_jobs,
- int default_batch_limit,
- bool use_job_objects,
- RunTestSuiteCallback run_test_suite);
-
-#if defined(OS_WIN)
-// Launches unit tests in given test suite. Returns exit code.
-// |use_job_objects| determines whether to use job objects.
-int LaunchUnitTests(int argc,
- wchar_t** argv,
- bool use_job_objects,
- RunTestSuiteCallback run_test_suite);
-#endif // defined(OS_WIN)
-
-// Delegate to abstract away platform differences for unit tests.
-class UnitTestPlatformDelegate {
- public:
- // Called to get names of tests available for running. The delegate
- // must put the result in |output| and return true on success.
- virtual bool GetTests(std::vector<TestIdentifier>* output) = 0;
-
- // Called to create a temporary for storing test results. The delegate
- // must put the resulting path in |path| and return true on success.
- virtual bool CreateResultsFile(base::FilePath* path) = 0;
-
- // Called to create a new temporary file. The delegate must put the resulting
- // path in |path| and return true on success.
- virtual bool CreateTemporaryFile(base::FilePath* path) = 0;
-
- // Returns command line for child GTest process based on the command line
- // of current process. |test_names| is a vector of test full names
- // (e.g. "A.B"), |output_file| is path to the GTest XML output file.
- virtual CommandLine GetCommandLineForChildGTestProcess(
- const std::vector<std::string>& test_names,
- const base::FilePath& output_file,
- const base::FilePath& flag_file) = 0;
-
- // Returns wrapper to use for child GTest process. Empty string means
- // no wrapper.
- virtual std::string GetWrapperForChildGTestProcess() = 0;
-
- // Relaunch tests, e.g. after a crash.
- virtual void RelaunchTests(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names,
- int launch_flags) = 0;
-
- protected:
- ~UnitTestPlatformDelegate() = default;
-};
-
-// Runs tests serially, each in its own process.
-void RunUnitTestsSerially(TestLauncher* test_launcher,
- UnitTestPlatformDelegate* platform_delegate,
- const std::vector<std::string>& test_names,
- int launch_flags);
-
-// Runs tests in batches (each batch in its own process).
-void RunUnitTestsBatch(TestLauncher* test_launcher,
- UnitTestPlatformDelegate* platform_delegate,
- const std::vector<std::string>& test_names,
- int launch_flags);
-
-// Test launcher delegate for unit tests (mostly to support batching).
-class UnitTestLauncherDelegate : public TestLauncherDelegate {
- public:
- UnitTestLauncherDelegate(UnitTestPlatformDelegate* delegate,
- size_t batch_limit,
- bool use_job_objects);
- ~UnitTestLauncherDelegate() override;
-
- private:
- // TestLauncherDelegate:
- bool GetTests(std::vector<TestIdentifier>* output) override;
- bool ShouldRunTest(const std::string& test_case_name,
- const std::string& test_name) override;
- size_t RunTests(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) override;
- size_t RetryTests(TestLauncher* test_launcher,
- const std::vector<std::string>& test_names) override;
-
- ThreadChecker thread_checker_;
-
- UnitTestPlatformDelegate* platform_delegate_;
-
- // Maximum number of tests to run in a single batch.
- size_t batch_limit_;
-
- // Determines whether we use job objects on Windows.
- bool use_job_objects_;
-
- DISALLOW_COPY_AND_ASSIGN(UnitTestLauncherDelegate);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_LAUNCHER_UNIT_TEST_LAUNCHER_H_
diff --git a/base/test/malloc_wrapper.cc b/base/test/malloc_wrapper.cc
deleted file mode 100644
index eb280a3eee..0000000000
--- a/base/test/malloc_wrapper.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2015 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 "malloc_wrapper.h"
-
-#include <stdlib.h>
-
-void* MallocWrapper(size_t size) {
- return malloc(size);
-}
diff --git a/base/test/malloc_wrapper.h b/base/test/malloc_wrapper.h
deleted file mode 100644
index d06228d37d..0000000000
--- a/base/test/malloc_wrapper.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TEST_MALLOC_WRAPPER_H_
-#define BASE_TEST_MALLOC_WRAPPER_H_
-
-#include <stddef.h>
-
-// BASE_EXPORT depends on COMPONENT_BUILD.
-// This will always be a separate shared library, so don't use BASE_EXPORT here.
-#if defined(WIN32)
-#define MALLOC_WRAPPER_EXPORT __declspec(dllexport)
-#else
-#define MALLOC_WRAPPER_EXPORT __attribute__((visibility("default")))
-#endif // defined(WIN32)
-
-// Calls malloc directly.
-MALLOC_WRAPPER_EXPORT void* MallocWrapper(size_t size);
-
-#endif // BASE_TEST_MALLOC_WRAPPER_H_
diff --git a/base/test/metrics/histogram_tester_unittest.cc b/base/test/metrics/histogram_tester_unittest.cc
deleted file mode 100644
index e9b9f20fbc..0000000000
--- a/base/test/metrics/histogram_tester_unittest.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// 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/metrics/histogram_tester.h"
-
-#include <memory>
-#include <string>
-
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/histogram_samples.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::ElementsAre;
-using ::testing::IsEmpty;
-
-namespace {
-
-const char kHistogram1[] = "Test1";
-const char kHistogram2[] = "Test2";
-const char kHistogram3[] = "Test3";
-const char kHistogram4[] = "Test4";
-const char kHistogram5[] = "Test5";
-
-} // namespace
-
-namespace base {
-
-typedef testing::Test HistogramTesterTest;
-
-TEST_F(HistogramTesterTest, Scope) {
- // Record a histogram before the creation of the recorder.
- UMA_HISTOGRAM_BOOLEAN(kHistogram1, true);
-
- HistogramTester tester;
-
- // Verify that no histogram is recorded.
- tester.ExpectTotalCount(kHistogram1, 0);
-
- // Record a histogram after the creation of the recorder.
- UMA_HISTOGRAM_BOOLEAN(kHistogram1, true);
-
- // Verify that one histogram is recorded.
- std::unique_ptr<HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation(kHistogram1));
- EXPECT_TRUE(samples);
- EXPECT_EQ(1, samples->TotalCount());
-}
-
-TEST_F(HistogramTesterTest, GetHistogramSamplesSinceCreationNotNull) {
- // Chose the histogram name uniquely, to ensure nothing was recorded for it so
- // far.
- static const char kHistogram[] =
- "GetHistogramSamplesSinceCreationNotNullHistogram";
- HistogramTester tester;
-
- // Verify that the returned samples are empty but not null.
- std::unique_ptr<HistogramSamples> samples(
- tester.GetHistogramSamplesSinceCreation(kHistogram1));
- EXPECT_TRUE(samples);
- tester.ExpectTotalCount(kHistogram, 0);
-}
-
-TEST_F(HistogramTesterTest, TestUniqueSample) {
- HistogramTester tester;
-
- // Record into a sample thrice
- UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
- UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
- UMA_HISTOGRAM_COUNTS_100(kHistogram2, 2);
-
- tester.ExpectUniqueSample(kHistogram2, 2, 3);
-}
-
-TEST_F(HistogramTesterTest, TestBucketsSample) {
- HistogramTester tester;
-
- // Record into a sample twice
- UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
- UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
- UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
- UMA_HISTOGRAM_COUNTS_100(kHistogram3, 2);
- UMA_HISTOGRAM_COUNTS_100(kHistogram3, 3);
-
- tester.ExpectBucketCount(kHistogram3, 2, 4);
- tester.ExpectBucketCount(kHistogram3, 3, 1);
-
- tester.ExpectTotalCount(kHistogram3, 5);
-}
-
-TEST_F(HistogramTesterTest, TestBucketsSampleWithScope) {
- // Record into a sample twice, once before the tester creation and once after.
- UMA_HISTOGRAM_COUNTS_100(kHistogram4, 2);
-
- HistogramTester tester;
- UMA_HISTOGRAM_COUNTS_100(kHistogram4, 3);
-
- tester.ExpectBucketCount(kHistogram4, 2, 0);
- tester.ExpectBucketCount(kHistogram4, 3, 1);
-
- tester.ExpectTotalCount(kHistogram4, 1);
-}
-
-TEST_F(HistogramTesterTest, TestGetAllSamples) {
- HistogramTester tester;
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 2, 5);
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5);
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5);
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 5, 5);
-
- EXPECT_THAT(tester.GetAllSamples(kHistogram5),
- ElementsAre(Bucket(2, 1), Bucket(3, 2), Bucket(5, 1)));
-}
-
-TEST_F(HistogramTesterTest, TestGetAllSamples_NoSamples) {
- HistogramTester tester;
- EXPECT_THAT(tester.GetAllSamples(kHistogram5), IsEmpty());
-}
-
-TEST_F(HistogramTesterTest, TestGetTotalCountsForPrefix) {
- HistogramTester tester;
- UMA_HISTOGRAM_ENUMERATION("Test1.Test2.Test3", 2, 5);
-
- // Regression check for bug https://crbug.com/659977.
- EXPECT_TRUE(tester.GetTotalCountsForPrefix("Test2.").empty());
-
- EXPECT_EQ(1u, tester.GetTotalCountsForPrefix("Test1.").size());
-}
-
-TEST_F(HistogramTesterTest, TestGetAllChangedHistograms) {
- // Record into a sample twice, once before the tester creation.
- UMA_HISTOGRAM_COUNTS_100(kHistogram1, true);
- UMA_HISTOGRAM_COUNTS_100(kHistogram4, 4);
-
- HistogramTester tester;
- UMA_HISTOGRAM_COUNTS_100(kHistogram4, 3);
-
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 2, 5);
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 3, 5);
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 4, 5);
- UMA_HISTOGRAM_ENUMERATION(kHistogram5, 5, 5);
-
- UMA_HISTOGRAM_ENUMERATION("Test1.Test2.Test3", 2, 5);
- std::string results = tester.GetAllHistogramsRecorded();
-
- EXPECT_EQ(std::string::npos, results.find("Histogram: Test1 recorded"));
- EXPECT_NE(std::string::npos,
- results.find("Histogram: Test4 recorded 1 new samples"));
- EXPECT_NE(std::string::npos,
- results.find("Histogram: Test5 recorded 4 new samples"));
- EXPECT_NE(
- std::string::npos,
- results.find("Histogram: Test1.Test2.Test3 recorded 1 new samples"));
-}
-
-} // namespace base
diff --git a/base/test/metrics/user_action_tester.cc b/base/test/metrics/user_action_tester.cc
deleted file mode 100644
index a845bca78d..0000000000
--- a/base/test/metrics/user_action_tester.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 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/metrics/user_action_tester.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/test/test_simple_task_runner.h"
-
-namespace base {
-
-UserActionTester::UserActionTester()
- : task_runner_(new base::TestSimpleTaskRunner),
- action_callback_(
- base::Bind(&UserActionTester::OnUserAction, base::Unretained(this))) {
- base::SetRecordActionTaskRunner(task_runner_);
- base::AddActionCallback(action_callback_);
-}
-
-UserActionTester::~UserActionTester() {
- base::RemoveActionCallback(action_callback_);
-}
-
-int UserActionTester::GetActionCount(const std::string& user_action) const {
- UserActionCountMap::const_iterator iter = count_map_.find(user_action);
- return iter == count_map_.end() ? 0 : iter->second;
-}
-
-void UserActionTester::ResetCounts() {
- count_map_.clear();
-}
-
-void UserActionTester::OnUserAction(const std::string& user_action) {
- ++(count_map_[user_action]);
-}
-
-} // namespace base
diff --git a/base/test/metrics/user_action_tester.h b/base/test/metrics/user_action_tester.h
deleted file mode 100644
index a422c9a8e9..0000000000
--- a/base/test/metrics/user_action_tester.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TEST_METRICS_USER_ACTION_TESTER_H_
-#define BASE_TEST_METRICS_USER_ACTION_TESTER_H_
-
-#include <map>
-#include <string>
-
-#include "base/macros.h"
-#include "base/metrics/user_metrics.h"
-
-namespace base {
-
-// This class observes and collects user action notifications that are sent
-// by the tests, so that they can be examined afterwards for correctness.
-// Note: This class is NOT thread-safe.
-class UserActionTester {
- public:
- UserActionTester();
- ~UserActionTester();
-
- // Returns the number of times the given |user_action| occurred.
- int GetActionCount(const std::string& user_action) const;
-
- // Resets all user action counts to 0.
- void ResetCounts();
-
- private:
- typedef std::map<std::string, int> UserActionCountMap;
-
- // The callback that is notified when a user actions occurs.
- void OnUserAction(const std::string& user_action);
-
- // A map that tracks the number of times a user action has occurred.
- UserActionCountMap count_map_;
-
- // A test task runner used by user metrics.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- // The callback that is added to the global action callback list.
- base::ActionCallback action_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(UserActionTester);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_METRICS_USER_ACTION_TESTER_H_
diff --git a/base/test/metrics/user_action_tester_unittest.cc b/base/test/metrics/user_action_tester_unittest.cc
deleted file mode 100644
index 14557d24e4..0000000000
--- a/base/test/metrics/user_action_tester_unittest.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015 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/metrics/user_action_tester.h"
-
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-const char kUserAction1[] = "user.action.1";
-const char kUserAction2[] = "user.action.2";
-const char kUserAction3[] = "user.action.3";
-
-// Record an action and cause all ActionCallback observers to be notified.
-void RecordAction(const char user_action[]) {
- base::RecordAction(base::UserMetricsAction(user_action));
-}
-
-} // namespace
-
-// Verify user action counts are zero initially.
-TEST(UserActionTesterTest, GetActionCountWhenNoActionsHaveBeenRecorded) {
- UserActionTester user_action_tester;
- EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction1));
-}
-
-// Verify user action counts are tracked properly.
-TEST(UserActionTesterTest, GetActionCountWhenActionsHaveBeenRecorded) {
- UserActionTester user_action_tester;
-
- RecordAction(kUserAction1);
- RecordAction(kUserAction2);
- RecordAction(kUserAction2);
-
- EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
- EXPECT_EQ(2, user_action_tester.GetActionCount(kUserAction2));
- EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction3));
-}
-
-// Verify no seg faults occur when resetting action counts when none have been
-// recorded.
-TEST(UserActionTesterTest, ResetCountsWhenNoActionsHaveBeenRecorded) {
- UserActionTester user_action_tester;
- user_action_tester.ResetCounts();
-}
-
-// Verify user action counts are set to zero on a ResetCounts.
-TEST(UserActionTesterTest, ResetCountsWhenActionsHaveBeenRecorded) {
- UserActionTester user_action_tester;
-
- RecordAction(kUserAction1);
- RecordAction(kUserAction1);
- RecordAction(kUserAction2);
- user_action_tester.ResetCounts();
-
- EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction1));
- EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction2));
- EXPECT_EQ(0, user_action_tester.GetActionCount(kUserAction3));
-}
-
-// Verify the UserActionsTester is notified when base::RecordAction is called.
-TEST(UserActionTesterTest, VerifyUserActionTesterListensForUserActions) {
- UserActionTester user_action_tester;
-
- base::RecordAction(base::UserMetricsAction(kUserAction1));
-
- EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
-}
-
-// Verify the UserActionsTester is notified when base::RecordComputedAction is
-// called.
-TEST(UserActionTesterTest,
- VerifyUserActionTesterListensForComputedUserActions) {
- UserActionTester user_action_tester;
-
- base::RecordComputedAction(kUserAction1);
-
- EXPECT_EQ(1, user_action_tester.GetActionCount(kUserAction1));
-}
-
-} // namespace base
diff --git a/base/test/mock_callback.h b/base/test/mock_callback.h
deleted file mode 100644
index 7ac4d3467e..0000000000
--- a/base/test/mock_callback.h
+++ /dev/null
@@ -1,366 +0,0 @@
-// This file was GENERATED by command:
-// pump.py mock_callback.h.pump
-// DO NOT EDIT BY HAND!!!
-
-// Copyright 2017 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.
-
-// Analogous to GMock's built-in MockFunction, but for base::Callback instead of
-// std::function. It takes the full callback type as a parameter, so that it can
-// support both OnceCallback and RepeatingCallback.
-//
-// Use:
-// using FooCallback = base::Callback<int(std::string)>;
-//
-// TEST(FooTest, RunsCallbackWithBarArgument) {
-// base::MockCallback<FooCallback> callback;
-// EXPECT_CALL(callback, Run("bar")).WillOnce(Return(1));
-// Foo(callback.Get());
-// }
-//
-// Can be used with StrictMock and NiceMock. Caller must ensure that it outlives
-// any base::Callback obtained from it.
-
-#ifndef BASE_TEST_MOCK_CALLBACK_H_
-#define BASE_TEST_MOCK_CALLBACK_H_
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace base {
-
-// clang-format off
-
-template <typename F>
-class MockCallback;
-
-template <typename R>
-class MockCallback<Callback<R()>> {
- public:
- MockCallback() = default;
- MOCK_METHOD0_T(Run, R());
-
- Callback<R()> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R>
-class MockCallback<OnceCallback<R()>> {
- public:
- MockCallback() = default;
- MOCK_METHOD0_T(Run, R());
-
- OnceCallback<R()> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1>
-class MockCallback<Callback<R(A1)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD1_T(Run, R(A1));
-
- Callback<R(A1)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1>
-class MockCallback<OnceCallback<R(A1)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD1_T(Run, R(A1));
-
- OnceCallback<R(A1)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2>
-class MockCallback<Callback<R(A1, A2)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD2_T(Run, R(A1, A2));
-
- Callback<R(A1, A2)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2>
-class MockCallback<OnceCallback<R(A1, A2)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD2_T(Run, R(A1, A2));
-
- OnceCallback<R(A1, A2)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-class MockCallback<Callback<R(A1, A2, A3)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD3_T(Run, R(A1, A2, A3));
-
- Callback<R(A1, A2, A3)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3>
-class MockCallback<OnceCallback<R(A1, A2, A3)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD3_T(Run, R(A1, A2, A3));
-
- OnceCallback<R(A1, A2, A3)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class MockCallback<Callback<R(A1, A2, A3, A4)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD4_T(Run, R(A1, A2, A3, A4));
-
- Callback<R(A1, A2, A3, A4)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class MockCallback<OnceCallback<R(A1, A2, A3, A4)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD4_T(Run, R(A1, A2, A3, A4));
-
- OnceCallback<R(A1, A2, A3, A4)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5>
-class MockCallback<Callback<R(A1, A2, A3, A4, A5)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD5_T(Run, R(A1, A2, A3, A4, A5));
-
- Callback<R(A1, A2, A3, A4, A5)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5>
-class MockCallback<OnceCallback<R(A1, A2, A3, A4, A5)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD5_T(Run, R(A1, A2, A3, A4, A5));
-
- OnceCallback<R(A1, A2, A3, A4, A5)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6>
-class MockCallback<Callback<R(A1, A2, A3, A4, A5, A6)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD6_T(Run, R(A1, A2, A3, A4, A5, A6));
-
- Callback<R(A1, A2, A3, A4, A5, A6)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6>
-class MockCallback<OnceCallback<R(A1, A2, A3, A4, A5, A6)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD6_T(Run, R(A1, A2, A3, A4, A5, A6));
-
- OnceCallback<R(A1, A2, A3, A4, A5, A6)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7>
-class MockCallback<Callback<R(A1, A2, A3, A4, A5, A6, A7)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD7_T(Run, R(A1, A2, A3, A4, A5, A6, A7));
-
- Callback<R(A1, A2, A3, A4, A5, A6, A7)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7>
-class MockCallback<OnceCallback<R(A1, A2, A3, A4, A5, A6, A7)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD7_T(Run, R(A1, A2, A3, A4, A5, A6, A7));
-
- OnceCallback<R(A1, A2, A3, A4, A5, A6, A7)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7, typename A8>
-class MockCallback<Callback<R(A1, A2, A3, A4, A5, A6, A7, A8)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD8_T(Run, R(A1, A2, A3, A4, A5, A6, A7, A8));
-
- Callback<R(A1, A2, A3, A4, A5, A6, A7, A8)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7, typename A8>
-class MockCallback<OnceCallback<R(A1, A2, A3, A4, A5, A6, A7, A8)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD8_T(Run, R(A1, A2, A3, A4, A5, A6, A7, A8));
-
- OnceCallback<R(A1, A2, A3, A4, A5, A6, A7, A8)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7, typename A8, typename A9>
-class MockCallback<Callback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD9_T(Run, R(A1, A2, A3, A4, A5, A6, A7, A8, A9));
-
- Callback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7, typename A8, typename A9>
-class MockCallback<OnceCallback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD9_T(Run, R(A1, A2, A3, A4, A5, A6, A7, A8, A9));
-
- OnceCallback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7, typename A8, typename A9,
- typename A10>
-class MockCallback<Callback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD10_T(Run, R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10));
-
- Callback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R, typename A1, typename A2, typename A3, typename A4,
- typename A5, typename A6, typename A7, typename A8, typename A9,
- typename A10>
-class MockCallback<OnceCallback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>> {
- public:
- MockCallback() = default;
- MOCK_METHOD10_T(Run, R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10));
-
- OnceCallback<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-// clang-format on
-
-} // namespace base
-
-#endif // BASE_TEST_MOCK_CALLBACK_H_
diff --git a/base/test/mock_callback.h.pump b/base/test/mock_callback.h.pump
deleted file mode 100644
index 3372789db5..0000000000
--- a/base/test/mock_callback.h.pump
+++ /dev/null
@@ -1,85 +0,0 @@
-$$ This is a pump file for generating file templates. Pump is a python
-$$ script that is part of the Google Test suite of utilities. Description
-$$ can be found here:
-$$
-$$ https://github.com/google/googletest/blob/master/googletest/docs/PumpManual.md
-$$
-$$ MAX_ARITY controls the number of arguments that MockCallback supports.
-$$ It is choosen to match the number GMock supports.
-$var MAX_ARITY = 10
-$$
-// Copyright 2017 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.
-
-// Analogous to GMock's built-in MockFunction, but for base::Callback instead of
-// std::function. It takes the full callback type as a parameter, so that it can
-// support both OnceCallback and RepeatingCallback.
-//
-// Use:
-// using FooCallback = base::Callback<int(std::string)>;
-//
-// TEST(FooTest, RunsCallbackWithBarArgument) {
-// base::MockCallback<FooCallback> callback;
-// EXPECT_CALL(callback, Run("bar")).WillOnce(Return(1));
-// Foo(callback.Get());
-// }
-//
-// Can be used with StrictMock and NiceMock. Caller must ensure that it outlives
-// any base::Callback obtained from it.
-
-#ifndef BASE_TEST_MOCK_CALLBACK_H_
-#define BASE_TEST_MOCK_CALLBACK_H_
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace base {
-
-// clang-format off
-
-template <typename F>
-class MockCallback;
-
-$range i 0..MAX_ARITY
-$for i [[
-$range j 1..i
-$var run_type = [[R($for j, [[A$j]])]]
-
-template <typename R$for j [[, typename A$j]]>
-class MockCallback<Callback<$run_type>> {
- public:
- MockCallback() = default;
- MOCK_METHOD$(i)_T(Run, $run_type);
-
- Callback<$run_type> Get() {
- return Bind(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-template <typename R$for j [[, typename A$j]]>
-class MockCallback<OnceCallback<$run_type>> {
- public:
- MockCallback() = default;
- MOCK_METHOD$(i)_T(Run, $run_type);
-
- OnceCallback<$run_type> Get() {
- return BindOnce(&MockCallback::Run, Unretained(this));
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockCallback);
-};
-
-]]
-
-// clang-format on
-
-} // namespace base
-
-#endif // BASE_TEST_MOCK_CALLBACK_H_
diff --git a/base/test/mock_callback_unittest.cc b/base/test/mock_callback_unittest.cc
deleted file mode 100644
index c5f109f0e4..0000000000
--- a/base/test/mock_callback_unittest.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 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/mock_callback.h"
-
-#include "base/callback.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using testing::InSequence;
-using testing::Return;
-
-namespace base {
-namespace {
-
-TEST(MockCallbackTest, ZeroArgs) {
- MockCallback<Closure> mock_closure;
- EXPECT_CALL(mock_closure, Run());
- mock_closure.Get().Run();
-
- MockCallback<Callback<int()>> mock_int_callback;
- {
- InSequence sequence;
- EXPECT_CALL(mock_int_callback, Run()).WillOnce(Return(42));
- EXPECT_CALL(mock_int_callback, Run()).WillOnce(Return(88));
- }
- EXPECT_EQ(42, mock_int_callback.Get().Run());
- EXPECT_EQ(88, mock_int_callback.Get().Run());
-}
-
-TEST(MockCallbackTest, WithArgs) {
- MockCallback<Callback<int(int, int)>> mock_two_int_callback;
- EXPECT_CALL(mock_two_int_callback, Run(1, 2)).WillOnce(Return(42));
- EXPECT_CALL(mock_two_int_callback, Run(0, 0)).WillRepeatedly(Return(-1));
- Callback<int(int, int)> two_int_callback = mock_two_int_callback.Get();
- EXPECT_EQ(-1, two_int_callback.Run(0, 0));
- EXPECT_EQ(42, two_int_callback.Run(1, 2));
- EXPECT_EQ(-1, two_int_callback.Run(0, 0));
-}
-
-TEST(MockCallbackTest, ZeroArgsOnce) {
- MockCallback<OnceClosure> mock_closure;
- EXPECT_CALL(mock_closure, Run());
- mock_closure.Get().Run();
-
- MockCallback<OnceCallback<int()>> mock_int_callback;
- EXPECT_CALL(mock_int_callback, Run()).WillOnce(Return(88));
- EXPECT_EQ(88, mock_int_callback.Get().Run());
-}
-
-TEST(MockCallbackTest, WithArgsOnce) {
- MockCallback<OnceCallback<int(int, int)>> mock_two_int_callback;
- EXPECT_CALL(mock_two_int_callback, Run(1, 2)).WillOnce(Return(42));
- OnceCallback<int(int, int)> two_int_callback = mock_two_int_callback.Get();
- EXPECT_EQ(42, std::move(two_int_callback).Run(1, 2));
-}
-
-} // namespace
-} // namespace base
diff --git a/base/test/mock_devices_changed_observer.cc b/base/test/mock_devices_changed_observer.cc
deleted file mode 100644
index 9fc57cd93e..0000000000
--- a/base/test/mock_devices_changed_observer.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/mock_devices_changed_observer.h"
-
-namespace base {
-
-MockDevicesChangedObserver::MockDevicesChangedObserver() = default;
-
-MockDevicesChangedObserver::~MockDevicesChangedObserver() = default;
-
-} // namespace base
diff --git a/base/test/mock_devices_changed_observer.h b/base/test/mock_devices_changed_observer.h
deleted file mode 100644
index 0734fb4f6a..0000000000
--- a/base/test/mock_devices_changed_observer.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_TEST_MOCK_DEVICES_CHANGED_OBSERVER_H_
-#define BASE_TEST_MOCK_DEVICES_CHANGED_OBSERVER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/system_monitor/system_monitor.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace base {
-
-class MockDevicesChangedObserver
- : public base::SystemMonitor::DevicesChangedObserver {
- public:
- MockDevicesChangedObserver();
- ~MockDevicesChangedObserver() override;
-
- MOCK_METHOD1(OnDevicesChanged,
- void(base::SystemMonitor::DeviceType device_type));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockDevicesChangedObserver);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_MOCK_DEVICES_CHANGED_OBSERVER_H_
diff --git a/base/test/mock_log.cc b/base/test/mock_log.cc
deleted file mode 100644
index a09000d8ed..0000000000
--- a/base/test/mock_log.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2015 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/mock_log.h"
-
-namespace base {
-namespace test {
-
-// static
-MockLog* MockLog::g_instance_ = nullptr;
-Lock MockLog::g_lock;
-
-MockLog::MockLog() : is_capturing_logs_(false) {
-}
-
-MockLog::~MockLog() {
- if (is_capturing_logs_) {
- StopCapturingLogs();
- }
-}
-
-void MockLog::StartCapturingLogs() {
- AutoLock scoped_lock(g_lock);
-
- // We don't use CHECK(), which can generate a new LOG message, and
- // thus can confuse MockLog objects or other registered
- // LogSinks.
- RAW_CHECK(!is_capturing_logs_);
- RAW_CHECK(!g_instance_);
-
- is_capturing_logs_ = true;
- g_instance_ = this;
- previous_handler_ = logging::GetLogMessageHandler();
- logging::SetLogMessageHandler(LogMessageHandler);
-}
-
-void MockLog::StopCapturingLogs() {
- AutoLock scoped_lock(g_lock);
-
- // We don't use CHECK(), which can generate a new LOG message, and
- // thus can confuse MockLog objects or other registered
- // LogSinks.
- RAW_CHECK(is_capturing_logs_);
- RAW_CHECK(g_instance_ == this);
-
- is_capturing_logs_ = false;
- logging::SetLogMessageHandler(previous_handler_);
- g_instance_ = nullptr;
-}
-
-// static
-bool MockLog::LogMessageHandler(int severity,
- const char* file,
- int line,
- size_t message_start,
- const std::string& str) {
- // gMock guarantees thread-safety for calling a mocked method
- // (https://github.com/google/googlemock/blob/master/googlemock/docs/CookBook.md#using-google-mock-and-threads)
- // but we also need to make sure that Start/StopCapturingLogs are synchronized
- // with LogMessageHandler.
- AutoLock scoped_lock(g_lock);
-
- return g_instance_->Log(severity, file, line, message_start, str);
-}
-
-} // namespace test
-} // namespace base
diff --git a/base/test/mock_log.h b/base/test/mock_log.h
deleted file mode 100644
index cda2fcd625..0000000000
--- a/base/test/mock_log.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TEST_MOCK_LOG_H_
-#define BASE_TEST_MOCK_LOG_H_
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace base {
-namespace test {
-
-// A MockLog object intercepts LOG() messages issued during its lifespan. Using
-// this together with gMock, it's very easy to test how a piece of code calls
-// LOG(). The typical usage:
-//
-// TEST(FooTest, LogsCorrectly) {
-// MockLog log;
-//
-// // We expect the WARNING "Something bad!" exactly twice.
-// EXPECT_CALL(log, Log(WARNING, _, "Something bad!"))
-// .Times(2);
-//
-// // We allow foo.cc to call LOG(INFO) any number of times.
-// EXPECT_CALL(log, Log(INFO, HasSubstr("/foo.cc"), _))
-// .Times(AnyNumber());
-//
-// log.StartCapturingLogs(); // Call this after done setting expectations.
-// Foo(); // Exercises the code under test.
-// }
-//
-// CAVEAT: base/logging does not allow a thread to call LOG() again when it's
-// already inside a LOG() call. Doing so will cause a deadlock. Therefore,
-// it's the user's responsibility to not call LOG() in an action triggered by
-// MockLog::Log(). You may call RAW_LOG() instead.
-class MockLog {
- public:
- // Creates a MockLog object that is not capturing logs. If it were to start
- // to capture logs, it could be a problem if some other threads already exist
- // and are logging, as the user hasn't had a chance to set up expectation on
- // this object yet (calling a mock method before setting the expectation is
- // UNDEFINED behavior).
- MockLog();
-
- // When the object is destructed, it stops intercepting logs.
- ~MockLog();
-
- // Starts log capturing if the object isn't already doing so.
- // Otherwise crashes.
- void StartCapturingLogs();
-
- // Stops log capturing if the object is capturing logs. Otherwise crashes.
- void StopCapturingLogs();
-
- // Log method is invoked for every log message before it's sent to other log
- // destinations (if any). The method should return true to signal that it
- // handled the message and the message should not be sent to other log
- // destinations.
- MOCK_METHOD5(Log,
- bool(int severity,
- const char* file,
- int line,
- size_t message_start,
- const std::string& str));
-
- private:
- // The currently active mock log.
- static MockLog* g_instance_;
-
- // Lock protecting access to g_instance_.
- static Lock g_lock;
-
- // Static function which is set as the logging message handler.
- // Called once for each message.
- static bool LogMessageHandler(int severity,
- const char* file,
- int line,
- size_t message_start,
- const std::string& str);
-
- // True if this object is currently capturing logs.
- bool is_capturing_logs_;
-
- // The previous handler to restore when the MockLog is destroyed.
- logging::LogMessageHandlerFunction previous_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(MockLog);
-};
-
-} // namespace test
-} // namespace base
-
-#endif // BASE_TEST_MOCK_LOG_H_
diff --git a/base/test/multiprocess_test.cc b/base/test/multiprocess_test.cc
index c6ee420cb1..48af3226a0 100644
--- a/base/test/multiprocess_test.cc
+++ b/base/test/multiprocess_test.cc
@@ -13,7 +13,7 @@
namespace base {
-#if !defined(OS_ANDROID) && !defined(__ANDROID_HOST__)
+#if !defined(OS_ANDROID) && !defined(__ANDROID__) && !defined(__ANDROID_HOST__)
Process SpawnMultiProcessTestChild(const std::string& procname,
const CommandLine& base_command_line,
const LaunchOptions& options) {
@@ -39,7 +39,7 @@ bool TerminateMultiProcessTestChild(const Process& process,
return process.Terminate(exit_code, wait);
}
-#endif // !OS_ANDROID && !__ANDROID_HOST__
+#endif // !OS_ANDROID && !__ANDROID__ && !__ANDROID_HOST__
CommandLine GetMultiProcessTestChildBaseCommandLine() {
base::ScopedAllowBlockingForTesting allow_blocking;
diff --git a/base/test/native_library_test_utils.cc b/base/test/native_library_test_utils.cc
deleted file mode 100644
index adcb1b01e9..0000000000
--- a/base/test/native_library_test_utils.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 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/native_library_test_utils.h"
-
-namespace {
-
-int g_static_value = 0;
-
-} // namespace
-
-extern "C" {
-
-int g_native_library_exported_value = 0;
-
-int NativeLibraryTestIncrement() { return ++g_static_value; }
-
-} // extern "C"
diff --git a/base/test/native_library_test_utils.h b/base/test/native_library_test_utils.h
deleted file mode 100644
index e26fd1a04e..0000000000
--- a/base/test/native_library_test_utils.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TEST_NATIVE_LIBRARY_TEST_UTILS_H_
-#define BASE_TEST_NATIVE_LIBRARY_TEST_UTILS_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#define NATIVE_LIBRARY_TEST_ALWAYS_EXPORT __declspec(dllexport)
-#else
-#define NATIVE_LIBRARY_TEST_ALWAYS_EXPORT __attribute__((visibility("default")))
-#endif
-
-extern "C" {
-
-extern NATIVE_LIBRARY_TEST_ALWAYS_EXPORT int g_native_library_exported_value;
-
-// A function which increments an internal counter value and returns its value.
-// The first call returns 1, then 2, etc.
-NATIVE_LIBRARY_TEST_ALWAYS_EXPORT int NativeLibraryTestIncrement();
-
-} // extern "C"
-
-#endif // BASE_TEST_NATIVE_LIBRARY_TEST_UTILS_H_
diff --git a/base/test/null_task_runner.cc b/base/test/null_task_runner.cc
deleted file mode 100644
index dfa26fa313..0000000000
--- a/base/test/null_task_runner.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/null_task_runner.h"
-
-namespace base {
-
-NullTaskRunner::NullTaskRunner() = default;
-
-NullTaskRunner::~NullTaskRunner() = default;
-
-bool NullTaskRunner::PostDelayedTask(const Location& from_here,
- OnceClosure task,
- base::TimeDelta delay) {
- return false;
-}
-
-bool NullTaskRunner::PostNonNestableDelayedTask(const Location& from_here,
- OnceClosure task,
- base::TimeDelta delay) {
- return false;
-}
-
-bool NullTaskRunner::RunsTasksInCurrentSequence() const {
- return true;
-}
-
-} // namespace base
diff --git a/base/test/null_task_runner.h b/base/test/null_task_runner.h
deleted file mode 100644
index c11ab6b0c6..0000000000
--- a/base/test/null_task_runner.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_TEST_NULL_TASK_RUNNER_H_
-#define BASE_TEST_NULL_TASK_RUNNER_H_
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-
-namespace base {
-
-// Helper class for tests that need to provide an implementation of a
-// *TaskRunner class but don't actually care about tasks being run.
-
-class NullTaskRunner : public base::SingleThreadTaskRunner {
- public:
- NullTaskRunner();
-
- bool PostDelayedTask(const Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override;
- bool PostNonNestableDelayedTask(const Location& from_here,
- base::OnceClosure task,
- base::TimeDelta delay) override;
- // Always returns true to avoid triggering DCHECKs.
- bool RunsTasksInCurrentSequence() const override;
-
- protected:
- ~NullTaskRunner() override;
-
- DISALLOW_COPY_AND_ASSIGN(NullTaskRunner);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_NULL_TASK_RUNNER_H_
diff --git a/base/test/perf_log.cc b/base/test/perf_log.cc
deleted file mode 100644
index 9212f4b355..0000000000
--- a/base/test/perf_log.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 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/perf_log.h"
-
-#include "base/files/file_util.h"
-#include "base/logging.h"
-
-namespace base {
-
-static FILE* perf_log_file = nullptr;
-
-bool InitPerfLog(const FilePath& log_file) {
- if (perf_log_file) {
- // trying to initialize twice
- NOTREACHED();
- return false;
- }
-
- perf_log_file = OpenFile(log_file, "w");
- return perf_log_file != nullptr;
-}
-
-void FinalizePerfLog() {
- if (!perf_log_file) {
- // trying to cleanup without initializing
- NOTREACHED();
- return;
- }
- base::CloseFile(perf_log_file);
-}
-
-void LogPerfResult(const char* test_name, double value, const char* units) {
- if (!perf_log_file) {
- NOTREACHED();
- return;
- }
-
- fprintf(perf_log_file, "%s\t%g\t%s\n", test_name, value, units);
- printf("%s\t%g\t%s\n", test_name, value, units);
- fflush(stdout);
-}
-
-} // namespace base
diff --git a/base/test/perf_log.h b/base/test/perf_log.h
deleted file mode 100644
index 5d6ed9f8ba..0000000000
--- a/base/test/perf_log.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_PERF_LOG_H_
-#define BASE_TEST_PERF_LOG_H_
-
-namespace base {
-
-class FilePath;
-
-// Initializes and finalizes the perf log. These functions should be
-// called at the beginning and end (respectively) of running all the
-// performance tests. The init function returns true on success.
-bool InitPerfLog(const FilePath& log_path);
-void FinalizePerfLog();
-
-// Writes to the perf result log the given 'value' resulting from the
-// named 'test'. The units are to aid in reading the log by people.
-void LogPerfResult(const char* test_name, double value, const char* units);
-
-} // namespace base
-
-#endif // BASE_TEST_PERF_LOG_H_
diff --git a/base/test/perf_test_suite.cc b/base/test/perf_test_suite.cc
deleted file mode 100644
index 2e2cdbb751..0000000000
--- a/base/test/perf_test_suite.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2010 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/perf_test_suite.h"
-
-#include "base/command_line.h"
-#include "base/debug/debugger.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/process/launch.h"
-#include "base/strings/string_util.h"
-#include "base/test/perf_log.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-PerfTestSuite::PerfTestSuite(int argc, char** argv) : TestSuite(argc, argv) {}
-
-void PerfTestSuite::Initialize() {
- TestSuite::Initialize();
-
- // Initialize the perf timer log
- FilePath log_path =
- CommandLine::ForCurrentProcess()->GetSwitchValuePath("log-file");
- if (log_path.empty()) {
- PathService::Get(FILE_EXE, &log_path);
-#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
- base::FilePath tmp_dir;
- PathService::Get(base::DIR_CACHE, &tmp_dir);
- log_path = tmp_dir.Append(log_path.BaseName());
-#endif
- log_path = log_path.ReplaceExtension(FILE_PATH_LITERAL("log"));
- log_path = log_path.InsertBeforeExtension(FILE_PATH_LITERAL("_perf"));
- }
- ASSERT_TRUE(InitPerfLog(log_path));
-
- // Raise to high priority to have more precise measurements. Since we don't
- // aim at 1% precision, it is not necessary to run at realtime level.
- if (!debug::BeingDebugged())
- RaiseProcessToHighPriority();
-}
-
-void PerfTestSuite::Shutdown() {
- TestSuite::Shutdown();
- FinalizePerfLog();
-}
-
-} // namespace base
diff --git a/base/test/perf_test_suite.h b/base/test/perf_test_suite.h
deleted file mode 100644
index 52528f0ac4..0000000000
--- a/base/test/perf_test_suite.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_TEST_PERF_TEST_SUITE_H_
-#define BASE_TEST_PERF_TEST_SUITE_H_
-
-#include "base/test/test_suite.h"
-
-namespace base {
-
-class PerfTestSuite : public TestSuite {
- public:
- PerfTestSuite(int argc, char** argv);
-
- void Initialize() override;
- void Shutdown() override;
-};
-
-} // namespace base
-
-#endif // BASE_TEST_PERF_TEST_SUITE_H_
diff --git a/base/test/perf_time_logger.cc b/base/test/perf_time_logger.cc
deleted file mode 100644
index c05ba51b7d..0000000000
--- a/base/test/perf_time_logger.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 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/perf_time_logger.h"
-
-#include "base/test/perf_log.h"
-
-namespace base {
-
-PerfTimeLogger::PerfTimeLogger(const char* test_name)
- : logged_(false), test_name_(test_name) {}
-
-PerfTimeLogger::~PerfTimeLogger() {
- if (!logged_)
- Done();
-}
-
-void PerfTimeLogger::Done() {
- // we use a floating-point millisecond value because it is more
- // intuitive than microseconds and we want more precision than
- // integer milliseconds
- LogPerfResult(test_name_.c_str(), timer_.Elapsed().InMillisecondsF(), "ms");
- logged_ = true;
-}
-
-} // namespace base
diff --git a/base/test/perf_time_logger.h b/base/test/perf_time_logger.h
deleted file mode 100644
index a5f3e8a70c..0000000000
--- a/base/test/perf_time_logger.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_PERF_TIME_LOGGER_H_
-#define BASE_TEST_PERF_TIME_LOGGER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/timer/elapsed_timer.h"
-
-namespace base {
-
-// Automates calling LogPerfResult for the common case where you want
-// to measure the time that something took. Call Done() when the test
-// is complete if you do extra work after the test or there are stack
-// objects with potentially expensive constructors. Otherwise, this
-// class with automatically log on destruction.
-class PerfTimeLogger {
- public:
- explicit PerfTimeLogger(const char* test_name);
- ~PerfTimeLogger();
-
- void Done();
-
- private:
- bool logged_;
- std::string test_name_;
- ElapsedTimer timer_;
-
- DISALLOW_COPY_AND_ASSIGN(PerfTimeLogger);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_PERF_TIME_LOGGER_H_
diff --git a/base/test/power_monitor_test_base.cc b/base/test/power_monitor_test_base.cc
deleted file mode 100644
index f3625662bf..0000000000
--- a/base/test/power_monitor_test_base.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2013 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/power_monitor_test_base.h"
-
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_source.h"
-#include "base/run_loop.h"
-
-namespace base {
-
-PowerMonitorTestSource::PowerMonitorTestSource()
- : test_on_battery_power_(false) {
- DCHECK(MessageLoopCurrent::Get())
- << "PowerMonitorTestSource requires a MessageLoop.";
-}
-
-PowerMonitorTestSource::~PowerMonitorTestSource() = default;
-
-void PowerMonitorTestSource::Shutdown() {}
-
-void PowerMonitorTestSource::GeneratePowerStateEvent(bool on_battery_power) {
- test_on_battery_power_ = on_battery_power;
- ProcessPowerEvent(POWER_STATE_EVENT);
- RunLoop().RunUntilIdle();
-}
-
-void PowerMonitorTestSource::GenerateSuspendEvent() {
- ProcessPowerEvent(SUSPEND_EVENT);
- RunLoop().RunUntilIdle();
-}
-
-void PowerMonitorTestSource::GenerateResumeEvent() {
- ProcessPowerEvent(RESUME_EVENT);
- RunLoop().RunUntilIdle();
-}
-
-bool PowerMonitorTestSource::IsOnBatteryPowerImpl() {
- return test_on_battery_power_;
-};
-
-PowerMonitorTestObserver::PowerMonitorTestObserver()
- : last_power_state_(false),
- power_state_changes_(0),
- suspends_(0),
- resumes_(0) {
-}
-
-PowerMonitorTestObserver::~PowerMonitorTestObserver() = default;
-
-// PowerObserver callbacks.
-void PowerMonitorTestObserver::OnPowerStateChange(bool on_battery_power) {
- last_power_state_ = on_battery_power;
- power_state_changes_++;
-}
-
-void PowerMonitorTestObserver::OnSuspend() {
- suspends_++;
-}
-
-void PowerMonitorTestObserver::OnResume() {
- resumes_++;
-}
-
-} // namespace base
diff --git a/base/test/power_monitor_test_base.h b/base/test/power_monitor_test_base.h
deleted file mode 100644
index 9b14fb0721..0000000000
--- a/base/test/power_monitor_test_base.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TEST_POWER_MONITOR_TEST_BASE_H_
-#define BASE_TEST_POWER_MONITOR_TEST_BASE_H_
-
-#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_source.h"
-
-namespace base {
-
-class PowerMonitorTestSource : public PowerMonitorSource {
- public:
- PowerMonitorTestSource();
- ~PowerMonitorTestSource() override;
- void Shutdown() override;
-
- void GeneratePowerStateEvent(bool on_battery_power);
- void GenerateSuspendEvent();
- void GenerateResumeEvent();
-
- protected:
- bool IsOnBatteryPowerImpl() override;
-
- bool test_on_battery_power_;
-};
-
-class PowerMonitorTestObserver : public PowerObserver {
- public:
- PowerMonitorTestObserver();
- ~PowerMonitorTestObserver() override;
-
- // PowerObserver callbacks.
- void OnPowerStateChange(bool on_battery_power) override;
- void OnSuspend() override;
- void OnResume() override;
-
- // Test status counts.
- bool last_power_state() { return last_power_state_; }
- int power_state_changes() { return power_state_changes_; }
- int suspends() { return suspends_; }
- int resumes() { return resumes_; }
-
- private:
- bool last_power_state_; // Last power state we were notified of.
- int power_state_changes_; // Count of OnPowerStateChange notifications.
- int suspends_; // Count of OnSuspend notifications.
- int resumes_; // Count of OnResume notifications.
-};
-
-} // namespace base
-
-#endif // BASE_TEST_POWER_MONITOR_TEST_BASE_H_
diff --git a/base/test/run_all_base_unittests.cc b/base/test/run_all_base_unittests.cc
deleted file mode 100644
index da52310fb5..0000000000
--- a/base/test/run_all_base_unittests.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2016 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/bind.h"
-#include "base/test/launcher/unit_test_launcher.h"
-#include "base/test/test_suite.h"
-#include "build/build_config.h"
-
-int main(int argc, char** argv) {
- base::TestSuite test_suite(argc, argv);
- return base::LaunchUnitTests(
- argc, argv,
- base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite)));
-}
diff --git a/base/test/run_all_perftests.cc b/base/test/run_all_perftests.cc
deleted file mode 100644
index 6e38109376..0000000000
--- a/base/test/run_all_perftests.cc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/perf_test_suite.h"
-
-int main(int argc, char** argv) {
- return base::PerfTestSuite(argc, argv).Run();
-}
diff --git a/base/test/run_all_unittests.cc b/base/test/run_all_unittests.cc
deleted file mode 100644
index 0ad84ed53d..0000000000
--- a/base/test/run_all_unittests.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/bind.h"
-#include "base/test/launcher/unit_test_launcher.h"
-#include "base/test/test_suite.h"
-#include "build/build_config.h"
-
-int main(int argc, char** argv) {
- base::TestSuite test_suite(argc, argv);
- return base::LaunchUnitTests(
- argc, argv,
- base::BindOnce(&base::TestSuite::Run, base::Unretained(&test_suite)));
-}
diff --git a/base/test/scoped_command_line.cc b/base/test/scoped_command_line.cc
deleted file mode 100644
index c74d243f44..0000000000
--- a/base/test/scoped_command_line.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 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/scoped_command_line.h"
-
-namespace base {
-namespace test {
-
-ScopedCommandLine::ScopedCommandLine()
- : original_command_line_(*base::CommandLine::ForCurrentProcess()) {}
-
-ScopedCommandLine::~ScopedCommandLine() {
- *base::CommandLine::ForCurrentProcess() = original_command_line_;
-}
-
-CommandLine* ScopedCommandLine::GetProcessCommandLine() {
- return base::CommandLine::ForCurrentProcess();
-}
-
-} // namespace test
-} // namespace base
diff --git a/base/test/scoped_command_line.h b/base/test/scoped_command_line.h
deleted file mode 100644
index dea0c6ac1e..0000000000
--- a/base/test/scoped_command_line.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TEST_SCOPED_COMMAND_LINE_H_
-#define BASE_TEST_SCOPED_COMMAND_LINE_H_
-
-#include "base/command_line.h"
-
-namespace base {
-namespace test {
-
-// Helper class to restore the original command line at the end of the scope.
-// NOTE: In most unit tests, the command line is automatically restored per
-// test, so this class is not necessary if the command line applies to
-// the entire single test.
-class ScopedCommandLine final {
- public:
- ScopedCommandLine();
- ~ScopedCommandLine();
-
- // Gets the command line for the current process.
- // NOTE: Do not name this GetCommandLine as this will conflict with Windows's
- // GetCommandLine and get renamed to GetCommandLineW.
- CommandLine* GetProcessCommandLine();
-
- private:
- const CommandLine original_command_line_;
-};
-
-} // namespace test
-} // namespace base
-
-#endif // BASE_TEST_SCOPED_COMMAND_LINE_H_
diff --git a/base/test/scoped_mock_time_message_loop_task_runner.cc b/base/test/scoped_mock_time_message_loop_task_runner.cc
deleted file mode 100644
index 8e855e58fa..0000000000
--- a/base/test/scoped_mock_time_message_loop_task_runner.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 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/scoped_mock_time_message_loop_task_runner.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/run_loop.h"
-#include "base/test/test_pending_task.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-
-namespace base {
-
-ScopedMockTimeMessageLoopTaskRunner::ScopedMockTimeMessageLoopTaskRunner()
- : task_runner_(new TestMockTimeTaskRunner),
- previous_task_runner_(ThreadTaskRunnerHandle::Get()) {
- DCHECK(MessageLoopCurrent::Get());
- // To ensure that we process any initialization tasks posted to the
- // MessageLoop by a test fixture before replacing its TaskRunner.
- RunLoop().RunUntilIdle();
- MessageLoopCurrent::Get()->SetTaskRunner(task_runner_);
-}
-
-ScopedMockTimeMessageLoopTaskRunner::~ScopedMockTimeMessageLoopTaskRunner() {
- DCHECK(previous_task_runner_->RunsTasksInCurrentSequence());
- DCHECK_EQ(task_runner_, ThreadTaskRunnerHandle::Get());
- for (auto& pending_task : task_runner_->TakePendingTasks()) {
- previous_task_runner_->PostDelayedTask(
- pending_task.location, std::move(pending_task.task),
- pending_task.GetTimeToRun() - task_runner_->NowTicks());
- }
- MessageLoopCurrent::Get()->SetTaskRunner(std::move(previous_task_runner_));
-}
-
-} // namespace base
diff --git a/base/test/scoped_mock_time_message_loop_task_runner.h b/base/test/scoped_mock_time_message_loop_task_runner.h
deleted file mode 100644
index 2a034ee8f8..0000000000
--- a/base/test/scoped_mock_time_message_loop_task_runner.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TEST_SCOPED_MOCK_TIME_MESSAGE_LOOP_TASK_RUNNER_H_
-#define BASE_TEST_SCOPED_MOCK_TIME_MESSAGE_LOOP_TASK_RUNNER_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/test/test_mock_time_task_runner.h"
-
-namespace base {
-
-class SingleThreadTaskRunner;
-
-// A scoped wrapper around TestMockTimeTaskRunner that replaces
-// MessageLoopCurrent::Get()'s task runner (and consequently
-// ThreadTaskRunnerHandle) with a TestMockTimeTaskRunner and resets it back at
-// the end of its scope.
-//
-// Note: RunLoop() will not work in the scope of a
-// ScopedMockTimeMessageLoopTaskRunner, the underlying TestMockTimeTaskRunner's
-// methods must be used instead to pump tasks.
-//
-// DEPRECATED: Use a TestMockTimeTaskRunner::Type::kBoundToThread instead of a
-// MessageLoop + ScopedMockTimeMessageLoopTaskRunner.
-// TODO(gab): Remove usage of this API and delete it.
-class ScopedMockTimeMessageLoopTaskRunner {
- public:
- ScopedMockTimeMessageLoopTaskRunner();
- ~ScopedMockTimeMessageLoopTaskRunner();
-
- TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }
- TestMockTimeTaskRunner* operator->() { return task_runner_.get(); }
-
- private:
- const scoped_refptr<TestMockTimeTaskRunner> task_runner_;
- scoped_refptr<SingleThreadTaskRunner> previous_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedMockTimeMessageLoopTaskRunner);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_SCOPED_MOCK_TIME_MESSAGE_LOOP_TASK_RUNNER_H_
diff --git a/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc b/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc
deleted file mode 100644
index b08323d380..0000000000
--- a/base/test/scoped_mock_time_message_loop_task_runner_unittest.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2015 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/scoped_mock_time_message_loop_task_runner.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback_forward.h"
-#include "base/containers/circular_deque.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/test/test_pending_task.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-TaskRunner* GetCurrentTaskRunner() {
- return MessageLoopCurrent::Get()->task_runner().get();
-}
-
-void AssignTrue(bool* out) {
- *out = true;
-}
-
-// Pops a task from the front of |pending_tasks| and returns it.
-TestPendingTask PopFront(base::circular_deque<TestPendingTask>* pending_tasks) {
- TestPendingTask task = std::move(pending_tasks->front());
- pending_tasks->pop_front();
- return task;
-}
-
-class ScopedMockTimeMessageLoopTaskRunnerTest : public testing::Test {
- public:
- ScopedMockTimeMessageLoopTaskRunnerTest()
- : original_task_runner_(new TestMockTimeTaskRunner()) {
- MessageLoopCurrent::Get()->SetTaskRunner(original_task_runner_);
- }
-
- protected:
- TestMockTimeTaskRunner* original_task_runner() {
- return original_task_runner_.get();
- }
-
- private:
- scoped_refptr<TestMockTimeTaskRunner> original_task_runner_;
-
- MessageLoop message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedMockTimeMessageLoopTaskRunnerTest);
-};
-
-// Verifies a new TaskRunner is installed while a
-// ScopedMockTimeMessageLoopTaskRunner exists and the previous one is installed
-// after destruction.
-TEST_F(ScopedMockTimeMessageLoopTaskRunnerTest, CurrentTaskRunners) {
- auto scoped_task_runner_ =
- std::make_unique<ScopedMockTimeMessageLoopTaskRunner>();
- EXPECT_EQ(scoped_task_runner_->task_runner(), GetCurrentTaskRunner());
- scoped_task_runner_.reset();
- EXPECT_EQ(original_task_runner(), GetCurrentTaskRunner());
-}
-
-TEST_F(ScopedMockTimeMessageLoopTaskRunnerTest,
- IncompleteTasksAreCopiedToPreviousTaskRunnerAfterDestruction) {
- auto scoped_task_runner_ =
- std::make_unique<ScopedMockTimeMessageLoopTaskRunner>();
-
- bool task_10_has_run = false;
- bool task_11_has_run = false;
-
- Closure task_1 = DoNothing();
- Closure task_2 = DoNothing();
- Closure task_10 = Bind(&AssignTrue, &task_10_has_run);
- Closure task_11 = Bind(&AssignTrue, &task_11_has_run);
-
- constexpr TimeDelta task_1_delay = TimeDelta::FromSeconds(1);
- constexpr TimeDelta task_2_delay = TimeDelta::FromSeconds(2);
- constexpr TimeDelta task_10_delay = TimeDelta::FromSeconds(10);
- constexpr TimeDelta task_11_delay = TimeDelta::FromSeconds(11);
-
- constexpr TimeDelta step_time_by = TimeDelta::FromSeconds(5);
-
- GetCurrentTaskRunner()->PostDelayedTask(FROM_HERE, task_1, task_1_delay);
- GetCurrentTaskRunner()->PostDelayedTask(FROM_HERE, task_2, task_2_delay);
- GetCurrentTaskRunner()->PostDelayedTask(FROM_HERE, task_10, task_10_delay);
- GetCurrentTaskRunner()->PostDelayedTask(FROM_HERE, task_11, task_11_delay);
-
- scoped_task_runner_->task_runner()->FastForwardBy(step_time_by);
-
- scoped_task_runner_.reset();
-
- base::circular_deque<TestPendingTask> pending_tasks =
- original_task_runner()->TakePendingTasks();
-
- EXPECT_EQ(2U, pending_tasks.size());
-
- TestPendingTask pending_task = PopFront(&pending_tasks);
- EXPECT_FALSE(task_10_has_run);
- std::move(pending_task.task).Run();
- EXPECT_TRUE(task_10_has_run);
- EXPECT_EQ(task_10_delay - step_time_by, pending_task.delay);
-
- pending_task = PopFront(&pending_tasks);
- EXPECT_FALSE(task_11_has_run);
- std::move(pending_task.task).Run();
- EXPECT_TRUE(task_11_has_run);
- EXPECT_EQ(task_11_delay - step_time_by, pending_task.delay);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/test/scoped_path_override.cc b/base/test/scoped_path_override.cc
deleted file mode 100644
index b8cfd4a22a..0000000000
--- a/base/test/scoped_path_override.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/scoped_path_override.h"
-
-#include "base/logging.h"
-#include "base/path_service.h"
-
-namespace base {
-
-ScopedPathOverride::ScopedPathOverride(int key) : key_(key) {
- bool result = temp_dir_.CreateUniqueTempDir();
- CHECK(result);
- result = PathService::Override(key, temp_dir_.GetPath());
- CHECK(result);
-}
-
-ScopedPathOverride::ScopedPathOverride(int key, const base::FilePath& dir)
- : key_(key) {
- bool result = PathService::Override(key, dir);
- CHECK(result);
-}
-
-ScopedPathOverride::ScopedPathOverride(int key,
- const FilePath& path,
- bool is_absolute,
- bool create)
- : key_(key) {
- bool result =
- PathService::OverrideAndCreateIfNeeded(key, path, is_absolute, create);
- CHECK(result);
-}
-
-ScopedPathOverride::~ScopedPathOverride() {
- bool result = PathService::RemoveOverride(key_);
- CHECK(result) << "The override seems to have been removed already!";
-}
-
-} // namespace base
diff --git a/base/test/scoped_path_override.h b/base/test/scoped_path_override.h
deleted file mode 100644
index f5891490b1..0000000000
--- a/base/test/scoped_path_override.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_TEST_SCOPED_PATH_OVERRIDE_H_
-#define BASE_TEST_SCOPED_PATH_OVERRIDE_H_
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-
-namespace base {
-
-class FilePath;
-
-// Sets a path override on construction, and removes it when the object goes out
-// of scope. This class is intended to be used by tests that need to override
-// paths to ensure their overrides are properly handled and reverted when the
-// scope of the test is left.
-class ScopedPathOverride {
- public:
- // Contructor that initializes the override to a scoped temp directory.
- explicit ScopedPathOverride(int key);
-
- // Constructor that would use a path provided by the user.
- ScopedPathOverride(int key, const FilePath& dir);
-
- // See PathService::OverrideAndCreateIfNeeded.
- ScopedPathOverride(int key,
- const FilePath& path,
- bool is_absolute,
- bool create);
- ~ScopedPathOverride();
-
- private:
- int key_;
- ScopedTempDir temp_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedPathOverride);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_SCOPED_PATH_OVERRIDE_H_
diff --git a/base/test/sequenced_task_runner_test_template.cc b/base/test/sequenced_task_runner_test_template.cc
deleted file mode 100644
index de6849230e..0000000000
--- a/base/test/sequenced_task_runner_test_template.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/sequenced_task_runner_test_template.h"
-
-#include <ostream>
-
-#include "base/location.h"
-
-namespace base {
-
-namespace internal {
-
-TaskEvent::TaskEvent(int i, Type type)
- : i(i), type(type) {
-}
-
-SequencedTaskTracker::SequencedTaskTracker()
- : next_post_i_(0),
- task_end_count_(0),
- task_end_cv_(&lock_) {
-}
-
-void SequencedTaskTracker::PostWrappedNonNestableTask(
- SequencedTaskRunner* task_runner,
- const Closure& task) {
- AutoLock event_lock(lock_);
- const int post_i = next_post_i_++;
- Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
- task, post_i);
- task_runner->PostNonNestableTask(FROM_HERE, wrapped_task);
- TaskPosted(post_i);
-}
-
-void SequencedTaskTracker::PostWrappedNestableTask(
- SequencedTaskRunner* task_runner,
- const Closure& task) {
- AutoLock event_lock(lock_);
- const int post_i = next_post_i_++;
- Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
- task, post_i);
- task_runner->PostTask(FROM_HERE, wrapped_task);
- TaskPosted(post_i);
-}
-
-void SequencedTaskTracker::PostWrappedDelayedNonNestableTask(
- SequencedTaskRunner* task_runner,
- const Closure& task,
- TimeDelta delay) {
- AutoLock event_lock(lock_);
- const int post_i = next_post_i_++;
- Closure wrapped_task = Bind(&SequencedTaskTracker::RunTask, this,
- task, post_i);
- task_runner->PostNonNestableDelayedTask(FROM_HERE, wrapped_task, delay);
- TaskPosted(post_i);
-}
-
-void SequencedTaskTracker::PostNonNestableTasks(
- SequencedTaskRunner* task_runner,
- int task_count) {
- for (int i = 0; i < task_count; ++i) {
- PostWrappedNonNestableTask(task_runner, Closure());
- }
-}
-
-void SequencedTaskTracker::RunTask(const Closure& task, int task_i) {
- TaskStarted(task_i);
- if (!task.is_null())
- task.Run();
- TaskEnded(task_i);
-}
-
-void SequencedTaskTracker::TaskPosted(int i) {
- // Caller must own |lock_|.
- events_.push_back(TaskEvent(i, TaskEvent::POST));
-}
-
-void SequencedTaskTracker::TaskStarted(int i) {
- AutoLock lock(lock_);
- events_.push_back(TaskEvent(i, TaskEvent::START));
-}
-
-void SequencedTaskTracker::TaskEnded(int i) {
- AutoLock lock(lock_);
- events_.push_back(TaskEvent(i, TaskEvent::END));
- ++task_end_count_;
- task_end_cv_.Signal();
-}
-
-const std::vector<TaskEvent>&
-SequencedTaskTracker::GetTaskEvents() const {
- return events_;
-}
-
-void SequencedTaskTracker::WaitForCompletedTasks(int count) {
- AutoLock lock(lock_);
- while (task_end_count_ < count)
- task_end_cv_.Wait();
-}
-
-SequencedTaskTracker::~SequencedTaskTracker() = default;
-
-void PrintTo(const TaskEvent& event, std::ostream* os) {
- *os << "(i=" << event.i << ", type=";
- switch (event.type) {
- case TaskEvent::POST: *os << "POST"; break;
- case TaskEvent::START: *os << "START"; break;
- case TaskEvent::END: *os << "END"; break;
- }
- *os << ")";
-}
-
-namespace {
-
-// Returns the task ordinals for the task event type |type| in the order that
-// they were recorded.
-std::vector<int> GetEventTypeOrder(const std::vector<TaskEvent>& events,
- TaskEvent::Type type) {
- std::vector<int> tasks;
- std::vector<TaskEvent>::const_iterator event;
- for (event = events.begin(); event != events.end(); ++event) {
- if (event->type == type)
- tasks.push_back(event->i);
- }
- return tasks;
-}
-
-// Returns all task events for task |task_i|.
-std::vector<TaskEvent::Type> GetEventsForTask(
- const std::vector<TaskEvent>& events,
- int task_i) {
- std::vector<TaskEvent::Type> task_event_orders;
- std::vector<TaskEvent>::const_iterator event;
- for (event = events.begin(); event != events.end(); ++event) {
- if (event->i == task_i)
- task_event_orders.push_back(event->type);
- }
- return task_event_orders;
-}
-
-// Checks that the task events for each task in |events| occur in the order
-// {POST, START, END}, and that there is only one instance of each event type
-// per task.
-::testing::AssertionResult CheckEventOrdersForEachTask(
- const std::vector<TaskEvent>& events,
- int task_count) {
- std::vector<TaskEvent::Type> expected_order;
- expected_order.push_back(TaskEvent::POST);
- expected_order.push_back(TaskEvent::START);
- expected_order.push_back(TaskEvent::END);
-
- // This is O(n^2), but it runs fast enough currently so is not worth
- // optimizing.
- for (int i = 0; i < task_count; ++i) {
- const std::vector<TaskEvent::Type> task_events =
- GetEventsForTask(events, i);
- if (task_events != expected_order) {
- return ::testing::AssertionFailure()
- << "Events for task " << i << " are out of order; expected: "
- << ::testing::PrintToString(expected_order) << "; actual: "
- << ::testing::PrintToString(task_events);
- }
- }
- return ::testing::AssertionSuccess();
-}
-
-// Checks that no two tasks were running at the same time. I.e. the only
-// events allowed between the START and END of a task are the POSTs of other
-// tasks.
-::testing::AssertionResult CheckNoTaskRunsOverlap(
- const std::vector<TaskEvent>& events) {
- // If > -1, we're currently inside a START, END pair.
- int current_task_i = -1;
-
- std::vector<TaskEvent>::const_iterator event;
- for (event = events.begin(); event != events.end(); ++event) {
- bool spurious_event_found = false;
-
- if (current_task_i == -1) { // Not inside a START, END pair.
- switch (event->type) {
- case TaskEvent::POST:
- break;
- case TaskEvent::START:
- current_task_i = event->i;
- break;
- case TaskEvent::END:
- spurious_event_found = true;
- break;
- }
-
- } else { // Inside a START, END pair.
- bool interleaved_task_detected = false;
-
- switch (event->type) {
- case TaskEvent::POST:
- if (event->i == current_task_i)
- spurious_event_found = true;
- break;
- case TaskEvent::START:
- interleaved_task_detected = true;
- break;
- case TaskEvent::END:
- if (event->i != current_task_i)
- interleaved_task_detected = true;
- else
- current_task_i = -1;
- break;
- }
-
- if (interleaved_task_detected) {
- return ::testing::AssertionFailure()
- << "Found event " << ::testing::PrintToString(*event)
- << " between START and END events for task " << current_task_i
- << "; event dump: " << ::testing::PrintToString(events);
- }
- }
-
- if (spurious_event_found) {
- const int event_i = event - events.begin();
- return ::testing::AssertionFailure()
- << "Spurious event " << ::testing::PrintToString(*event)
- << " at position " << event_i << "; event dump: "
- << ::testing::PrintToString(events);
- }
- }
-
- return ::testing::AssertionSuccess();
-}
-
-} // namespace
-
-::testing::AssertionResult CheckNonNestableInvariants(
- const std::vector<TaskEvent>& events,
- int task_count) {
- const std::vector<int> post_order =
- GetEventTypeOrder(events, TaskEvent::POST);
- const std::vector<int> start_order =
- GetEventTypeOrder(events, TaskEvent::START);
- const std::vector<int> end_order =
- GetEventTypeOrder(events, TaskEvent::END);
-
- if (start_order != post_order) {
- return ::testing::AssertionFailure()
- << "Expected START order (which equals actual POST order): \n"
- << ::testing::PrintToString(post_order)
- << "\n Actual START order:\n"
- << ::testing::PrintToString(start_order);
- }
-
- if (end_order != post_order) {
- return ::testing::AssertionFailure()
- << "Expected END order (which equals actual POST order): \n"
- << ::testing::PrintToString(post_order)
- << "\n Actual END order:\n"
- << ::testing::PrintToString(end_order);
- }
-
- const ::testing::AssertionResult result =
- CheckEventOrdersForEachTask(events, task_count);
- if (!result)
- return result;
-
- return CheckNoTaskRunsOverlap(events);
-}
-
-} // namespace internal
-
-} // namespace base
diff --git a/base/test/sequenced_task_runner_test_template.h b/base/test/sequenced_task_runner_test_template.h
deleted file mode 100644
index a510030fb1..0000000000
--- a/base/test/sequenced_task_runner_test_template.h
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright (c) 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.
-
-// SequencedTaskRunnerTest defines tests that implementations of
-// SequencedTaskRunner should pass in order to be conformant.
-// See task_runner_test_template.h for a description of how to use the
-// constructs in this file; these work the same.
-
-#ifndef BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
-#define BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
-
-#include <cstddef>
-#include <iosfwd>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace internal {
-
-struct TaskEvent {
- enum Type { POST, START, END };
- TaskEvent(int i, Type type);
- int i;
- Type type;
-};
-
-// Utility class used in the tests below.
-class SequencedTaskTracker : public RefCountedThreadSafe<SequencedTaskTracker> {
- public:
- SequencedTaskTracker();
-
- // Posts the non-nestable task |task|, and records its post event.
- void PostWrappedNonNestableTask(SequencedTaskRunner* task_runner,
- const Closure& task);
-
- // Posts the nestable task |task|, and records its post event.
- void PostWrappedNestableTask(SequencedTaskRunner* task_runner,
- const Closure& task);
-
- // Posts the delayed non-nestable task |task|, and records its post event.
- void PostWrappedDelayedNonNestableTask(SequencedTaskRunner* task_runner,
- const Closure& task,
- TimeDelta delay);
-
- // Posts |task_count| non-nestable tasks.
- void PostNonNestableTasks(SequencedTaskRunner* task_runner, int task_count);
-
- const std::vector<TaskEvent>& GetTaskEvents() const;
-
- // Returns after the tracker observes a total of |count| task completions.
- void WaitForCompletedTasks(int count);
-
- private:
- friend class RefCountedThreadSafe<SequencedTaskTracker>;
-
- ~SequencedTaskTracker();
-
- // A task which runs |task|, recording the start and end events.
- void RunTask(const Closure& task, int task_i);
-
- // Records a post event for task |i|. The owner is expected to be holding
- // |lock_| (unlike |TaskStarted| and |TaskEnded|).
- void TaskPosted(int i);
-
- // Records a start event for task |i|.
- void TaskStarted(int i);
-
- // Records a end event for task |i|.
- void TaskEnded(int i);
-
- // Protects events_, next_post_i_, task_end_count_ and task_end_cv_.
- Lock lock_;
-
- // The events as they occurred for each task (protected by lock_).
- std::vector<TaskEvent> events_;
-
- // The ordinal to be used for the next task-posting task (protected by
- // lock_).
- int next_post_i_;
-
- // The number of task end events we've received.
- int task_end_count_;
- ConditionVariable task_end_cv_;
-
- DISALLOW_COPY_AND_ASSIGN(SequencedTaskTracker);
-};
-
-void PrintTo(const TaskEvent& event, std::ostream* os);
-
-// Checks the non-nestable task invariants for all tasks in |events|.
-//
-// The invariants are:
-// 1) Events started and ended in the same order that they were posted.
-// 2) Events for an individual tasks occur in the order {POST, START, END},
-// and there is only one instance of each event type for a task.
-// 3) The only events between a task's START and END events are the POSTs of
-// other tasks. I.e. tasks were run sequentially, not interleaved.
-::testing::AssertionResult CheckNonNestableInvariants(
- const std::vector<TaskEvent>& events,
- int task_count);
-
-} // namespace internal
-
-template <typename TaskRunnerTestDelegate>
-class SequencedTaskRunnerTest : public testing::Test {
- protected:
- SequencedTaskRunnerTest()
- : task_tracker_(new internal::SequencedTaskTracker()) {}
-
- const scoped_refptr<internal::SequencedTaskTracker> task_tracker_;
- TaskRunnerTestDelegate delegate_;
-};
-
-TYPED_TEST_CASE_P(SequencedTaskRunnerTest);
-
-// This test posts N non-nestable tasks in sequence, and expects them to run
-// in FIFO order, with no part of any two tasks' execution
-// overlapping. I.e. that each task starts only after the previously-posted
-// one has finished.
-TYPED_TEST_P(SequencedTaskRunnerTest, SequentialNonNestable) {
- const int kTaskCount = 1000;
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- this->task_tracker_->PostWrappedNonNestableTask(
- task_runner.get(),
- Bind(&PlatformThread::Sleep, TimeDelta::FromSeconds(1)));
- for (int i = 1; i < kTaskCount; ++i) {
- this->task_tracker_->PostWrappedNonNestableTask(task_runner.get(),
- Closure());
- }
-
- this->delegate_.StopTaskRunner();
-
- EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(),
- kTaskCount));
-}
-
-// This test posts N nestable tasks in sequence. It has the same expectations
-// as SequentialNonNestable because even though the tasks are nestable, they
-// will not be run nestedly in this case.
-TYPED_TEST_P(SequencedTaskRunnerTest, SequentialNestable) {
- const int kTaskCount = 1000;
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- this->task_tracker_->PostWrappedNestableTask(
- task_runner.get(),
- Bind(&PlatformThread::Sleep, TimeDelta::FromSeconds(1)));
- for (int i = 1; i < kTaskCount; ++i) {
- this->task_tracker_->PostWrappedNestableTask(task_runner.get(), Closure());
- }
-
- this->delegate_.StopTaskRunner();
-
- EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(),
- kTaskCount));
-}
-
-// This test posts non-nestable tasks in order of increasing delay, and checks
-// that that the tasks are run in FIFO order and that there is no execution
-// overlap whatsoever between any two tasks.
-TYPED_TEST_P(SequencedTaskRunnerTest, SequentialDelayedNonNestable) {
- const int kTaskCount = 20;
- const int kDelayIncrementMs = 50;
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- for (int i = 0; i < kTaskCount; ++i) {
- this->task_tracker_->PostWrappedDelayedNonNestableTask(
- task_runner.get(), Closure(),
- TimeDelta::FromMilliseconds(kDelayIncrementMs * i));
- }
-
- this->task_tracker_->WaitForCompletedTasks(kTaskCount);
- this->delegate_.StopTaskRunner();
-
- EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(),
- kTaskCount));
-}
-
-// This test posts a fast, non-nestable task from within each of a number of
-// slow, non-nestable tasks and checks that they all run in the sequence they
-// were posted in and that there is no execution overlap whatsoever.
-TYPED_TEST_P(SequencedTaskRunnerTest, NonNestablePostFromNonNestableTask) {
- const int kParentCount = 10;
- const int kChildrenPerParent = 10;
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- for (int i = 0; i < kParentCount; ++i) {
- Closure task = Bind(
- &internal::SequencedTaskTracker::PostNonNestableTasks,
- this->task_tracker_,
- RetainedRef(task_runner),
- kChildrenPerParent);
- this->task_tracker_->PostWrappedNonNestableTask(task_runner.get(), task);
- }
-
- this->delegate_.StopTaskRunner();
-
- EXPECT_TRUE(CheckNonNestableInvariants(
- this->task_tracker_->GetTaskEvents(),
- kParentCount * (kChildrenPerParent + 1)));
-}
-
-// This test posts two tasks with the same delay, and checks that the tasks are
-// run in the order in which they were posted.
-//
-// NOTE: This is actually an approximate test since the API only takes a
-// "delay" parameter, so we are not exactly simulating two tasks that get
-// posted at the exact same time. It would be nice if the API allowed us to
-// specify the desired run time.
-TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTasksSameDelay) {
- const int kTaskCount = 2;
- const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- this->task_tracker_->PostWrappedDelayedNonNestableTask(task_runner.get(),
- Closure(), kDelay);
- this->task_tracker_->PostWrappedDelayedNonNestableTask(task_runner.get(),
- Closure(), kDelay);
- this->task_tracker_->WaitForCompletedTasks(kTaskCount);
- this->delegate_.StopTaskRunner();
-
- EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(),
- kTaskCount));
-}
-
-// This test posts a normal task and a delayed task, and checks that the
-// delayed task runs after the normal task even if the normal task takes
-// a long time to run.
-TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterLongTask) {
- const int kTaskCount = 2;
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- this->task_tracker_->PostWrappedNonNestableTask(
- task_runner.get(),
- base::Bind(&PlatformThread::Sleep, TimeDelta::FromMilliseconds(50)));
- this->task_tracker_->PostWrappedDelayedNonNestableTask(
- task_runner.get(), Closure(), TimeDelta::FromMilliseconds(10));
- this->task_tracker_->WaitForCompletedTasks(kTaskCount);
- this->delegate_.StopTaskRunner();
-
- EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(),
- kTaskCount));
-}
-
-// Test that a pile of normal tasks and a delayed task run in the
-// time-to-run order.
-TYPED_TEST_P(SequencedTaskRunnerTest, DelayedTaskAfterManyLongTasks) {
- const int kTaskCount = 11;
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- for (int i = 0; i < kTaskCount - 1; i++) {
- this->task_tracker_->PostWrappedNonNestableTask(
- task_runner.get(),
- base::Bind(&PlatformThread::Sleep, TimeDelta::FromMilliseconds(50)));
- }
- this->task_tracker_->PostWrappedDelayedNonNestableTask(
- task_runner.get(), Closure(), TimeDelta::FromMilliseconds(10));
- this->task_tracker_->WaitForCompletedTasks(kTaskCount);
- this->delegate_.StopTaskRunner();
-
- EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(),
- kTaskCount));
-}
-
-
-// TODO(francoisk777@gmail.com) Add a test, similiar to the above, which runs
-// some tasked nestedly (which should be implemented in the test
-// delegate). Also add, to the the test delegate, a predicate which checks
-// whether the implementation supports nested tasks.
-//
-
-// The SequencedTaskRunnerTest test case verifies behaviour that is expected
-// from a sequenced task runner in order to be conformant.
-REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerTest,
- SequentialNonNestable,
- SequentialNestable,
- SequentialDelayedNonNestable,
- NonNestablePostFromNonNestableTask,
- DelayedTasksSameDelay,
- DelayedTaskAfterLongTask,
- DelayedTaskAfterManyLongTasks);
-
-template <typename TaskRunnerTestDelegate>
-class SequencedTaskRunnerDelayedTest
- : public SequencedTaskRunnerTest<TaskRunnerTestDelegate> {};
-
-TYPED_TEST_CASE_P(SequencedTaskRunnerDelayedTest);
-
-// This test posts a delayed task, and checks that the task is run later than
-// the specified time.
-TYPED_TEST_P(SequencedTaskRunnerDelayedTest, DelayedTaskBasic) {
- const int kTaskCount = 1;
- const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
-
- this->delegate_.StartTaskRunner();
- const scoped_refptr<SequencedTaskRunner> task_runner =
- this->delegate_.GetTaskRunner();
-
- Time time_before_run = Time::Now();
- this->task_tracker_->PostWrappedDelayedNonNestableTask(task_runner.get(),
- Closure(), kDelay);
- this->task_tracker_->WaitForCompletedTasks(kTaskCount);
- this->delegate_.StopTaskRunner();
- Time time_after_run = Time::Now();
-
- EXPECT_TRUE(CheckNonNestableInvariants(this->task_tracker_->GetTaskEvents(),
- kTaskCount));
- EXPECT_LE(kDelay, time_after_run - time_before_run);
-}
-
-// SequencedTaskRunnerDelayedTest tests that the |delay| parameter of
-// is used to actually wait for |delay| ms before executing the task.
-// This is not mandatory for a SequencedTaskRunner to be compliant.
-REGISTER_TYPED_TEST_CASE_P(SequencedTaskRunnerDelayedTest, DelayedTaskBasic);
-
-} // namespace base
-
-#endif // BASE_TEST_SEQUENCED_TASK_RUNNER_TEST_TEMPLATE_H_
diff --git a/base/test/task_runner_test_template.cc b/base/test/task_runner_test_template.cc
deleted file mode 100644
index fe702472c7..0000000000
--- a/base/test/task_runner_test_template.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/task_runner_test_template.h"
-
-namespace base {
-
-namespace test {
-
-TaskTracker::TaskTracker() : task_runs_(0), task_runs_cv_(&lock_) {}
-
-TaskTracker::~TaskTracker() = default;
-
-Closure TaskTracker::WrapTask(const Closure& task, int i) {
- return Bind(&TaskTracker::RunTask, this, task, i);
-}
-
-void TaskTracker::RunTask(const Closure& task, int i) {
- AutoLock lock(lock_);
- if (!task.is_null()) {
- task.Run();
- }
- ++task_run_counts_[i];
- ++task_runs_;
- task_runs_cv_.Signal();
-}
-
-std::map<int, int> TaskTracker::GetTaskRunCounts() const {
- AutoLock lock(lock_);
- return task_run_counts_;
-}
-
-void TaskTracker::WaitForCompletedTasks(int count) {
- AutoLock lock(lock_);
- while (task_runs_ < count)
- task_runs_cv_.Wait();
-}
-
-void ExpectRunsTasksInCurrentSequence(bool expected_value,
- TaskRunner* task_runner) {
- EXPECT_EQ(expected_value, task_runner->RunsTasksInCurrentSequence());
-}
-
-} // namespace test
-
-} // namespace base
diff --git a/base/test/task_runner_test_template.h b/base/test/task_runner_test_template.h
deleted file mode 100644
index 4670522e42..0000000000
--- a/base/test/task_runner_test_template.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright (c) 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.
-
-// This file defines tests that implementations of TaskRunner should
-// pass in order to be conformant, as well as test cases for optional behavior.
-// Here's how you use it to test your implementation.
-//
-// Say your class is called MyTaskRunner. Then you need to define a
-// class called MyTaskRunnerTestDelegate in my_task_runner_unittest.cc
-// like this:
-//
-// class MyTaskRunnerTestDelegate {
-// public:
-// // Tasks posted to the task runner after this and before
-// // StopTaskRunner() is called is called should run successfully.
-// void StartTaskRunner() {
-// ...
-// }
-//
-// // Should return the task runner implementation. Only called
-// // after StartTaskRunner and before StopTaskRunner.
-// scoped_refptr<MyTaskRunner> GetTaskRunner() {
-// ...
-// }
-//
-// // Stop the task runner and make sure all tasks posted before
-// // this is called are run. Caveat: delayed tasks are not run,
- // they're simply deleted.
-// void StopTaskRunner() {
-// ...
-// }
-// };
-//
-// The TaskRunnerTest test harness will have a member variable of
-// this delegate type and will call its functions in the various
-// tests.
-//
-// Then you simply #include this file as well as gtest.h and add the
-// following statement to my_task_runner_unittest.cc:
-//
-// INSTANTIATE_TYPED_TEST_CASE_P(
-// MyTaskRunner, TaskRunnerTest, MyTaskRunnerTestDelegate);
-//
-// Easy!
-//
-// The optional test harnesses TaskRunnerAffinityTest can be
-// instanciated in the same way, using the same delegate:
-//
-// INSTANTIATE_TYPED_TEST_CASE_P(
-// MyTaskRunner, TaskRunnerAffinityTest, MyTaskRunnerTestDelegate);
-
-
-#ifndef BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
-#define BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
-
-#include <cstddef>
-#include <map>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/task_runner.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace test {
-
-// Utility class that keeps track of how many times particular tasks
-// are run.
-class TaskTracker : public RefCountedThreadSafe<TaskTracker> {
- public:
- TaskTracker();
-
- // Returns a closure that runs the given task and increments the run
- // count of |i| by one. |task| may be null. It is guaranteed that
- // only one task wrapped by a given tracker will be run at a time.
- Closure WrapTask(const Closure& task, int i);
-
- std::map<int, int> GetTaskRunCounts() const;
-
- // Returns after the tracker observes a total of |count| task completions.
- void WaitForCompletedTasks(int count);
-
- private:
- friend class RefCountedThreadSafe<TaskTracker>;
-
- ~TaskTracker();
-
- void RunTask(const Closure& task, int i);
-
- mutable Lock lock_;
- std::map<int, int> task_run_counts_;
- int task_runs_;
- ConditionVariable task_runs_cv_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskTracker);
-};
-
-} // namespace test
-
-template <typename TaskRunnerTestDelegate>
-class TaskRunnerTest : public testing::Test {
- protected:
- TaskRunnerTest() : task_tracker_(new test::TaskTracker()) {}
-
- const scoped_refptr<test::TaskTracker> task_tracker_;
- TaskRunnerTestDelegate delegate_;
-};
-
-TYPED_TEST_CASE_P(TaskRunnerTest);
-
-// We can't really test much, since TaskRunner provides very few
-// guarantees.
-
-// Post a bunch of tasks to the task runner. They should all
-// complete.
-TYPED_TEST_P(TaskRunnerTest, Basic) {
- std::map<int, int> expected_task_run_counts;
-
- this->delegate_.StartTaskRunner();
- scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
- // Post each ith task i+1 times.
- for (int i = 0; i < 20; ++i) {
- const Closure& ith_task = this->task_tracker_->WrapTask(Closure(), i);
- for (int j = 0; j < i + 1; ++j) {
- task_runner->PostTask(FROM_HERE, ith_task);
- ++expected_task_run_counts[i];
- }
- }
- this->delegate_.StopTaskRunner();
-
- EXPECT_EQ(expected_task_run_counts,
- this->task_tracker_->GetTaskRunCounts());
-}
-
-// Post a bunch of delayed tasks to the task runner. They should all
-// complete.
-TYPED_TEST_P(TaskRunnerTest, Delayed) {
- std::map<int, int> expected_task_run_counts;
- int expected_total_tasks = 0;
-
- this->delegate_.StartTaskRunner();
- scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
- // Post each ith task i+1 times with delays from 0-i.
- for (int i = 0; i < 20; ++i) {
- const Closure& ith_task = this->task_tracker_->WrapTask(Closure(), i);
- for (int j = 0; j < i + 1; ++j) {
- task_runner->PostDelayedTask(
- FROM_HERE, ith_task, base::TimeDelta::FromMilliseconds(j));
- ++expected_task_run_counts[i];
- ++expected_total_tasks;
- }
- }
- this->task_tracker_->WaitForCompletedTasks(expected_total_tasks);
- this->delegate_.StopTaskRunner();
-
- EXPECT_EQ(expected_task_run_counts,
- this->task_tracker_->GetTaskRunCounts());
-}
-
-// The TaskRunnerTest test case verifies behaviour that is expected from a
-// task runner in order to be conformant.
-REGISTER_TYPED_TEST_CASE_P(TaskRunnerTest, Basic, Delayed);
-
-namespace test {
-
-// Calls RunsTasksInCurrentSequence() on |task_runner| and expects it to
-// equal |expected_value|.
-void ExpectRunsTasksInCurrentSequence(bool expected_value,
- TaskRunner* task_runner);
-
-} // namespace test
-
-template <typename TaskRunnerTestDelegate>
-class TaskRunnerAffinityTest : public TaskRunnerTest<TaskRunnerTestDelegate> {};
-
-TYPED_TEST_CASE_P(TaskRunnerAffinityTest);
-
-// Post a bunch of tasks to the task runner as well as to a separate
-// thread, each checking the value of RunsTasksInCurrentSequence(),
-// which should return true for the tasks posted on the task runner
-// and false for the tasks posted on the separate thread.
-TYPED_TEST_P(TaskRunnerAffinityTest, RunsTasksInCurrentSequence) {
- std::map<int, int> expected_task_run_counts;
-
- Thread thread("Non-task-runner thread");
- ASSERT_TRUE(thread.Start());
- this->delegate_.StartTaskRunner();
-
- scoped_refptr<TaskRunner> task_runner = this->delegate_.GetTaskRunner();
- // Post each ith task i+1 times on the task runner and i+1 times on
- // the non-task-runner thread.
- for (int i = 0; i < 20; ++i) {
- const Closure& ith_task_runner_task = this->task_tracker_->WrapTask(
- Bind(&test::ExpectRunsTasksInCurrentSequence, true,
- base::RetainedRef(task_runner)),
- i);
- const Closure& ith_non_task_runner_task = this->task_tracker_->WrapTask(
- Bind(&test::ExpectRunsTasksInCurrentSequence, false,
- base::RetainedRef(task_runner)),
- i);
- for (int j = 0; j < i + 1; ++j) {
- task_runner->PostTask(FROM_HERE, ith_task_runner_task);
- thread.task_runner()->PostTask(FROM_HERE, ith_non_task_runner_task);
- expected_task_run_counts[i] += 2;
- }
- }
-
- this->delegate_.StopTaskRunner();
- thread.Stop();
-
- EXPECT_EQ(expected_task_run_counts,
- this->task_tracker_->GetTaskRunCounts());
-}
-
-// TaskRunnerAffinityTest tests that the TaskRunner implementation
-// can determine if tasks will never be run on a specific thread.
-REGISTER_TYPED_TEST_CASE_P(TaskRunnerAffinityTest, RunsTasksInCurrentSequence);
-
-} // namespace base
-
-#endif // BASE_TEST_TASK_RUNNER_TEST_TEMPLATE_H_
diff --git a/base/test/test_discardable_memory_allocator.cc b/base/test/test_discardable_memory_allocator.cc
deleted file mode 100644
index a9bd097c9d..0000000000
--- a/base/test/test_discardable_memory_allocator.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 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/test_discardable_memory_allocator.h"
-
-#include <cstdint>
-#include <cstring>
-
-#include "base/logging.h"
-#include "base/memory/discardable_memory.h"
-#include "base/memory/ptr_util.h"
-
-namespace base {
-namespace {
-
-class DiscardableMemoryImpl : public DiscardableMemory {
- public:
- explicit DiscardableMemoryImpl(size_t size)
- : data_(new uint8_t[size]), size_(size) {}
-
- // Overridden from DiscardableMemory:
- bool Lock() override {
- DCHECK(!is_locked_);
- is_locked_ = true;
- return false;
- }
-
- void Unlock() override {
- DCHECK(is_locked_);
- is_locked_ = false;
- // Force eviction to catch clients not correctly checking the return value
- // of Lock().
- memset(data_.get(), 0, size_);
- }
-
- void* data() const override {
- DCHECK(is_locked_);
- return data_.get();
- }
-
- trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump(
- const char* name,
- trace_event::ProcessMemoryDump* pmd) const override {
- return nullptr;
- }
-
- private:
- bool is_locked_ = true;
- std::unique_ptr<uint8_t[]> data_;
- size_t size_;
-};
-
-} // namespace
-
-std::unique_ptr<DiscardableMemory>
-TestDiscardableMemoryAllocator::AllocateLockedDiscardableMemory(size_t size) {
- return std::make_unique<DiscardableMemoryImpl>(size);
-}
-
-} // namespace base
diff --git a/base/test/test_discardable_memory_allocator.h b/base/test/test_discardable_memory_allocator.h
deleted file mode 100644
index 87436e3bf4..0000000000
--- a/base/test/test_discardable_memory_allocator.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TEST_TEST_DISCARDABLE_MEMORY_ALLOCATOR_H_
-#define BASE_TEST_TEST_DISCARDABLE_MEMORY_ALLOCATOR_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/memory/discardable_memory_allocator.h"
-
-namespace base {
-
-// TestDiscardableMemoryAllocator is a simple DiscardableMemoryAllocator
-// implementation that can be used for testing. It allocates one-shot
-// DiscardableMemory instances backed by heap memory.
-class TestDiscardableMemoryAllocator : public DiscardableMemoryAllocator {
- public:
- constexpr TestDiscardableMemoryAllocator() = default;
-
- // Overridden from DiscardableMemoryAllocator:
- std::unique_ptr<DiscardableMemory> AllocateLockedDiscardableMemory(
- size_t size) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestDiscardableMemoryAllocator);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_TEST_DISCARDABLE_MEMORY_ALLOCATOR_H_
diff --git a/base/test/test_file_util_android.cc b/base/test/test_file_util_android.cc
deleted file mode 100644
index 6e93e245ba..0000000000
--- a/base/test/test_file_util_android.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 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/test_file_util.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/files/file_path.h"
-#include "jni/ContentUriTestUtils_jni.h"
-
-using base::android::ScopedJavaLocalRef;
-
-namespace base {
-
-FilePath InsertImageIntoMediaStore(const FilePath& path) {
- JNIEnv* env = base::android::AttachCurrentThread();
- ScopedJavaLocalRef<jstring> j_path =
- base::android::ConvertUTF8ToJavaString(env, path.value());
- ScopedJavaLocalRef<jstring> j_uri =
- Java_ContentUriTestUtils_insertImageIntoMediaStore(env, j_path);
- std::string uri = base::android::ConvertJavaStringToUTF8(j_uri);
- return FilePath(uri);
-}
-
-} // namespace base
diff --git a/base/test/test_message_loop.cc b/base/test/test_message_loop.cc
deleted file mode 100644
index bd3610fe65..0000000000
--- a/base/test/test_message_loop.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 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/run_loop.h"
-#include "base/test/test_message_loop.h"
-
-namespace base {
-
-TestMessageLoop::TestMessageLoop() = default;
-
-TestMessageLoop::TestMessageLoop(MessageLoop::Type type) : loop_(type) {}
-
-TestMessageLoop::~TestMessageLoop() {
- RunLoop().RunUntilIdle();
-}
-
-} // namespace base
diff --git a/base/test/test_message_loop.h b/base/test/test_message_loop.h
deleted file mode 100644
index 9c0aed8b8b..0000000000
--- a/base/test/test_message_loop.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TEST_TEST_MESSAGE_LOOP_H_
-#define BASE_TEST_TEST_MESSAGE_LOOP_H_
-
-#include "base/message_loop/message_loop.h"
-
-namespace base {
-
-// TestMessageLoop is a convenience class for unittests that need to create a
-// message loop without a real thread backing it. For most tests,
-// it is sufficient to just instantiate TestMessageLoop as a member variable.
-//
-// TestMessageLoop will attempt to drain the underlying MessageLoop on
-// destruction for clean teardown of tests.
-class TestMessageLoop {
- public:
- TestMessageLoop();
- explicit TestMessageLoop(MessageLoop::Type type);
- ~TestMessageLoop();
-
- const scoped_refptr<SingleThreadTaskRunner>& task_runner() {
- return loop_.task_runner();
- }
-
- private:
- MessageLoop loop_;
-};
-
-} // namespace base
-
-#endif // BASE_TEST_TEST_MESSAGE_LOOP_H_
diff --git a/base/test/test_pending_task_unittest.cc b/base/test/test_pending_task_unittest.cc
deleted file mode 100644
index 6e01c8c66a..0000000000
--- a/base/test/test_pending_task_unittest.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/test_pending_task.h"
-
-#include "base/bind.h"
-#include "base/trace_event/trace_event.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest-spi.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(TestPendingTaskTest, TraceSupport) {
- base::TestPendingTask task;
-
- // Check that TestPendingTask can be sent to the trace subsystem.
- TRACE_EVENT1("test", "TestPendingTask::TraceSupport", "task", task.AsValue());
-
- // Just a basic check that the trace output has *something* in it.
- std::unique_ptr<base::trace_event::ConvertableToTraceFormat> task_value(
- task.AsValue());
- EXPECT_THAT(task_value->ToString(), ::testing::HasSubstr("post_time"));
-}
-
-TEST(TestPendingTaskTest, ToString) {
- base::TestPendingTask task;
-
- // Just a basic check that ToString has *something* in it.
- EXPECT_THAT(task.ToString(), ::testing::StartsWith("TestPendingTask("));
-}
-
-TEST(TestPendingTaskTest, GTestPrettyPrint) {
- base::TestPendingTask task;
-
- // Check that gtest is calling the TestPendingTask's PrintTo method.
- EXPECT_THAT(::testing::PrintToString(task),
- ::testing::StartsWith("TestPendingTask("));
-
- // Check that pretty printing works with the gtest iostreams operator.
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << task, "TestPendingTask(");
-}
-
-TEST(TestPendingTaskTest, ShouldRunBefore) {
- base::TestPendingTask task_first;
- task_first.delay = base::TimeDelta::FromMilliseconds(1);
- base::TestPendingTask task_after;
- task_after.delay = base::TimeDelta::FromMilliseconds(2);
-
- EXPECT_FALSE(task_after.ShouldRunBefore(task_first))
- << task_after << ".ShouldRunBefore(" << task_first << ")\n";
- EXPECT_TRUE(task_first.ShouldRunBefore(task_after))
- << task_first << ".ShouldRunBefore(" << task_after << ")\n";
-}
-
-} // namespace base
diff --git a/base/test/test_shared_library.cc b/base/test/test_shared_library.cc
deleted file mode 100644
index 99c04674ce..0000000000
--- a/base/test/test_shared_library.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2016 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/native_library_test_utils.h"
-
-extern "C" {
-
-int NATIVE_LIBRARY_TEST_ALWAYS_EXPORT GetExportedValue() {
- return g_native_library_exported_value;
-}
-
-void NATIVE_LIBRARY_TEST_ALWAYS_EXPORT SetExportedValue(int value) {
- g_native_library_exported_value = value;
-}
-
-// A test function used only to verify basic dynamic symbol resolution.
-int NATIVE_LIBRARY_TEST_ALWAYS_EXPORT GetSimpleTestValue() {
- return 5;
-}
-
-// When called by |NativeLibraryTest.LoadLibraryPreferOwnSymbols|, this should
-// forward to the local definition of NativeLibraryTestIncrement(), even though
-// the test module also links in the native_library_test_utils source library
-// which exports it.
-int NATIVE_LIBRARY_TEST_ALWAYS_EXPORT GetIncrementValue() {
- return NativeLibraryTestIncrement();
-}
-
-} // extern "C"
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
deleted file mode 100644
index 1862940f04..0000000000
--- a/base/test/test_suite.cc
+++ /dev/null
@@ -1,486 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/test_suite.h"
-
-#include <signal.h>
-
-#include <memory>
-
-#include "base/at_exit.h"
-#include "base/base_paths.h"
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/debug/debugger.h"
-#include "base/debug/profiler.h"
-#include "base/debug/stack_trace.h"
-#include "base/feature_list.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/i18n/icu_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/path_service.h"
-#include "base/process/launch.h"
-#include "base/process/memory.h"
-#include "base/test/gtest_xml_unittest_result_printer.h"
-#include "base/test/gtest_xml_util.h"
-#include "base/test/icu_test_util.h"
-#include "base/test/launcher/unit_test_launcher.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_switches.h"
-#include "base/test/test_timeouts.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
-#if defined(OS_IOS)
-#include "base/test/test_listener_ios.h"
-#endif // OS_IOS
-#endif // OS_MACOSX
-
-#if !defined(OS_WIN)
-#include "base/i18n/rtl.h"
-#if !defined(OS_IOS)
-#include "base/strings/string_util.h"
-#include "third_party/icu/source/common/unicode/uloc.h"
-#endif
-#endif
-
-#if defined(OS_ANDROID)
-#include "base/test/test_support_android.h"
-#endif
-
-#if defined(OS_IOS)
-#include "base/test/test_support_ios.h"
-#endif
-
-#if defined(OS_LINUX)
-#include "base/test/fontconfig_util_linux.h"
-#endif
-
-namespace base {
-
-namespace {
-
-class MaybeTestDisabler : public testing::EmptyTestEventListener {
- public:
- void OnTestStart(const testing::TestInfo& test_info) override {
- ASSERT_FALSE(TestSuite::IsMarkedMaybe(test_info))
- << "Probably the OS #ifdefs don't include all of the necessary "
- "platforms.\nPlease ensure that no tests have the MAYBE_ prefix "
- "after the code is preprocessed.";
- }
-};
-
-class TestClientInitializer : public testing::EmptyTestEventListener {
- public:
- TestClientInitializer()
- : old_command_line_(CommandLine::NO_PROGRAM) {
- }
-
- void OnTestStart(const testing::TestInfo& test_info) override {
- old_command_line_ = *CommandLine::ForCurrentProcess();
- }
-
- void OnTestEnd(const testing::TestInfo& test_info) override {
- *CommandLine::ForCurrentProcess() = old_command_line_;
- }
-
- private:
- CommandLine old_command_line_;
-
- DISALLOW_COPY_AND_ASSIGN(TestClientInitializer);
-};
-
-std::string GetProfileName() {
- static const char kDefaultProfileName[] = "test-profile-{pid}";
- CR_DEFINE_STATIC_LOCAL(std::string, profile_name, ());
- if (profile_name.empty()) {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kProfilingFile))
- profile_name = command_line.GetSwitchValueASCII(switches::kProfilingFile);
- else
- profile_name = std::string(kDefaultProfileName);
- }
- return profile_name;
-}
-
-void InitializeLogging() {
-#if defined(OS_ANDROID)
- InitAndroidTestLogging();
-#else
- FilePath exe;
- PathService::Get(FILE_EXE, &exe);
- FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
- logging::LoggingSettings settings;
- settings.logging_dest = logging::LOG_TO_ALL;
- settings.log_file = log_filename.value().c_str();
- settings.delete_old = logging::DELETE_OLD_LOG_FILE;
- logging::InitLogging(settings);
- // We want process and thread IDs because we may have multiple processes.
- // Note: temporarily enabled timestamps in an effort to catch bug 6361.
- logging::SetLogItems(true, true, true, true);
-#endif // !defined(OS_ANDROID)
-}
-
-} // namespace
-
-int RunUnitTestsUsingBaseTestSuite(int argc, char **argv) {
- TestSuite test_suite(argc, argv);
- return LaunchUnitTests(argc, argv,
- Bind(&TestSuite::Run, Unretained(&test_suite)));
-}
-
-TestSuite::TestSuite(int argc, char** argv) : initialized_command_line_(false) {
- PreInitialize();
- InitializeFromCommandLine(argc, argv);
- // Logging must be initialized before any thread has a chance to call logging
- // functions.
- InitializeLogging();
-}
-
-#if defined(OS_WIN)
-TestSuite::TestSuite(int argc, wchar_t** argv)
- : initialized_command_line_(false) {
- PreInitialize();
- InitializeFromCommandLine(argc, argv);
- // Logging must be initialized before any thread has a chance to call logging
- // functions.
- InitializeLogging();
-}
-#endif // defined(OS_WIN)
-
-TestSuite::~TestSuite() {
- if (initialized_command_line_)
- CommandLine::Reset();
-}
-
-void TestSuite::InitializeFromCommandLine(int argc, char** argv) {
- initialized_command_line_ = CommandLine::Init(argc, argv);
- testing::InitGoogleTest(&argc, argv);
- testing::InitGoogleMock(&argc, argv);
-
-#if defined(OS_IOS)
- InitIOSRunHook(this, argc, argv);
-#endif
-}
-
-#if defined(OS_WIN)
-void TestSuite::InitializeFromCommandLine(int argc, wchar_t** argv) {
- // Windows CommandLine::Init ignores argv anyway.
- initialized_command_line_ = CommandLine::Init(argc, NULL);
- testing::InitGoogleTest(&argc, argv);
- testing::InitGoogleMock(&argc, argv);
-}
-#endif // defined(OS_WIN)
-
-void TestSuite::PreInitialize() {
-#if defined(OS_WIN)
- testing::GTEST_FLAG(catch_exceptions) = false;
-#endif
- EnableTerminationOnHeapCorruption();
-#if defined(OS_LINUX) && defined(USE_AURA)
- // When calling native char conversion functions (e.g wrctomb) we need to
- // have the locale set. In the absence of such a call the "C" locale is the
- // default. In the gtk code (below) gtk_init() implicitly sets a locale.
- setlocale(LC_ALL, "");
-#endif // defined(OS_LINUX) && defined(USE_AURA)
-
- // On Android, AtExitManager is created in
- // testing/android/native_test_wrapper.cc before main() is called.
-#if !defined(OS_ANDROID)
- at_exit_manager_.reset(new AtExitManager);
-#endif
-
- // Don't add additional code to this function. Instead add it to
- // Initialize(). See bug 6436.
-}
-
-
-// static
-bool TestSuite::IsMarkedMaybe(const testing::TestInfo& test) {
- return strncmp(test.name(), "MAYBE_", 6) == 0;
-}
-
-void TestSuite::CatchMaybeTests() {
- testing::TestEventListeners& listeners =
- testing::UnitTest::GetInstance()->listeners();
- listeners.Append(new MaybeTestDisabler);
-}
-
-void TestSuite::ResetCommandLine() {
- testing::TestEventListeners& listeners =
- testing::UnitTest::GetInstance()->listeners();
- listeners.Append(new TestClientInitializer);
-}
-
-void TestSuite::AddTestLauncherResultPrinter() {
- // Only add the custom printer if requested.
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTestLauncherOutput)) {
- return;
- }
-
- FilePath output_path(CommandLine::ForCurrentProcess()->GetSwitchValuePath(
- switches::kTestLauncherOutput));
-
- // Do not add the result printer if output path already exists. It's an
- // indicator there is a process printing to that file, and we're likely
- // its child. Do not clobber the results in that case.
- if (PathExists(output_path)) {
- LOG(WARNING) << "Test launcher output path " << output_path.AsUTF8Unsafe()
- << " exists. Not adding test launcher result printer.";
- return;
- }
-
- printer_ = new XmlUnitTestResultPrinter;
- CHECK(printer_->Initialize(output_path))
- << "Output path is " << output_path.AsUTF8Unsafe()
- << " and PathExists(output_path) is " << PathExists(output_path);
- testing::TestEventListeners& listeners =
- testing::UnitTest::GetInstance()->listeners();
- listeners.Append(printer_);
-}
-
-// Don't add additional code to this method. Instead add it to
-// Initialize(). See bug 6436.
-int TestSuite::Run() {
-#if defined(OS_IOS)
- RunTestsFromIOSApp();
-#endif
-
-#if defined(OS_MACOSX)
- mac::ScopedNSAutoreleasePool scoped_pool;
-#endif
-
- Initialize();
- std::string client_func =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTestChildProcess);
-
- // Check to see if we are being run as a client process.
- if (!client_func.empty())
- return multi_process_function_list::InvokeChildProcessTest(client_func);
-#if defined(OS_IOS)
- test_listener_ios::RegisterTestEndListener();
-#endif
-
- int result = RUN_ALL_TESTS();
-
-#if defined(OS_MACOSX)
- // This MUST happen before Shutdown() since Shutdown() tears down
- // objects (such as NotificationService::current()) that Cocoa
- // objects use to remove themselves as observers.
- scoped_pool.Recycle();
-#endif
-
- Shutdown();
-
- return result;
-}
-
-void TestSuite::UnitTestAssertHandler(const char* file,
- int line,
- const base::StringPiece summary,
- const base::StringPiece stack_trace) {
-#if defined(OS_ANDROID)
- // Correlating test stdio with logcat can be difficult, so we emit this
- // helpful little hint about what was running. Only do this for Android
- // because other platforms don't separate out the relevant logs in the same
- // way.
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- if (test_info) {
- LOG(ERROR) << "Currently running: " << test_info->test_case_name() << "."
- << test_info->name();
- fflush(stderr);
- }
-#endif // defined(OS_ANDROID)
-
- // XmlUnitTestResultPrinter inherits gtest format, where assert has summary
- // and message. In GTest, summary is just a logged text, and message is a
- // logged text, concatenated with stack trace of assert.
- // Concatenate summary and stack_trace here, to pass it as a message.
- if (printer_) {
- const std::string summary_str = summary.as_string();
- const std::string stack_trace_str = summary_str + stack_trace.as_string();
- printer_->OnAssert(file, line, summary_str, stack_trace_str);
- }
-
- // The logging system actually prints the message before calling the assert
- // handler. Just exit now to avoid printing too many stack traces.
- _exit(1);
-}
-
-#if defined(OS_WIN)
-namespace {
-
-// Disable optimizations to prevent function folding or other transformations
-// that will make the call stacks on failures more confusing.
-#pragma optimize("", off)
-// Handlers for invalid parameter, pure call, and abort. They generate a
-// breakpoint to ensure that we get a call stack on these failures.
-void InvalidParameter(const wchar_t* expression,
- const wchar_t* function,
- const wchar_t* file,
- unsigned int line,
- uintptr_t reserved) {
- // CRT printed message is sufficient.
- __debugbreak();
- _exit(1);
-}
-
-void PureCall() {
- fprintf(stderr, "Pure-virtual function call. Terminating.\n");
- __debugbreak();
- _exit(1);
-}
-
-void AbortHandler(int signal) {
- // Print EOL after the CRT abort message.
- fprintf(stderr, "\n");
- __debugbreak();
-}
-#pragma optimize("", on)
-
-} // namespace
-#endif
-
-void TestSuite::SuppressErrorDialogs() {
-#if defined(OS_WIN)
- UINT new_flags = SEM_FAILCRITICALERRORS |
- SEM_NOGPFAULTERRORBOX |
- SEM_NOOPENFILEERRORBOX;
-
- // Preserve existing error mode, as discussed at
- // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
- UINT existing_flags = SetErrorMode(new_flags);
- SetErrorMode(existing_flags | new_flags);
-
-#if defined(_DEBUG)
- // Suppress the "Debug Assertion Failed" dialog.
- // TODO(hbono): remove this code when gtest has it.
- // http://groups.google.com/d/topic/googletestframework/OjuwNlXy5ac/discussion
- _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
-#endif // defined(_DEBUG)
-
- // See crbug.com/783040 for test code to trigger all of these failures.
- _set_invalid_parameter_handler(InvalidParameter);
- _set_purecall_handler(PureCall);
- signal(SIGABRT, AbortHandler);
-#endif // defined(OS_WIN)
-}
-
-void TestSuite::Initialize() {
- const CommandLine* command_line = CommandLine::ForCurrentProcess();
-#if !defined(OS_IOS)
- if (command_line->HasSwitch(switches::kWaitForDebugger)) {
- debug::WaitForDebugger(60, true);
- }
-#endif
- // Set up a FeatureList instance, so that code using that API will not hit a
- // an error that it's not set. It will be cleared automatically.
- // TestFeatureForBrowserTest1 and TestFeatureForBrowserTest2 used in
- // ContentBrowserTestScopedFeatureListTest to ensure ScopedFeatureList keeps
- // features from command line.
- std::string enabled =
- command_line->GetSwitchValueASCII(switches::kEnableFeatures);
- std::string disabled =
- command_line->GetSwitchValueASCII(switches::kDisableFeatures);
- enabled += ",TestFeatureForBrowserTest1";
- disabled += ",TestFeatureForBrowserTest2";
- scoped_feature_list_.InitFromCommandLine(enabled, disabled);
-
- // The enable-features and disable-features flags were just slurped into a
- // FeatureList, so remove them from the command line. Tests should enable and
- // disable features via the ScopedFeatureList API rather than command-line
- // flags.
- CommandLine new_command_line(command_line->GetProgram());
- CommandLine::SwitchMap switches = command_line->GetSwitches();
-
- switches.erase(switches::kEnableFeatures);
- switches.erase(switches::kDisableFeatures);
-
- for (const auto& iter : switches)
- new_command_line.AppendSwitchNative(iter.first, iter.second);
-
- *CommandLine::ForCurrentProcess() = new_command_line;
-
-#if defined(OS_IOS)
- InitIOSTestMessageLoop();
-#endif // OS_IOS
-
-#if defined(OS_ANDROID)
- InitAndroidTestMessageLoop();
-#endif // else defined(OS_ANDROID)
-
- CHECK(debug::EnableInProcessStackDumping());
-#if defined(OS_WIN)
- RouteStdioToConsole(true);
- // Make sure we run with high resolution timer to minimize differences
- // between production code and test code.
- Time::EnableHighResolutionTimer(true);
-#endif // defined(OS_WIN)
-
- // In some cases, we do not want to see standard error dialogs.
- if (!debug::BeingDebugged() &&
- !command_line->HasSwitch("show-error-dialogs")) {
- SuppressErrorDialogs();
- debug::SetSuppressDebugUI(true);
- assert_handler_ = std::make_unique<logging::ScopedLogAssertHandler>(
- base::Bind(&TestSuite::UnitTestAssertHandler, base::Unretained(this)));
- }
-
- base::test::InitializeICUForTesting();
-
- // On the Mac OS X command line, the default locale is *_POSIX. In Chromium,
- // the locale is set via an OS X locale API and is never *_POSIX.
- // Some tests (such as those involving word break iterator) will behave
- // differently and fail if we use *POSIX locale. Setting it to en_US here
- // does not affect tests that explicitly overrides the locale for testing.
- // This can be an issue on all platforms other than Windows.
- // TODO(jshin): Should we set the locale via an OS X locale API here?
-#if !defined(OS_WIN)
-#if defined(OS_IOS)
- i18n::SetICUDefaultLocale("en_US");
-#else
- std::string default_locale(uloc_getDefault());
- if (EndsWith(default_locale, "POSIX", CompareCase::INSENSITIVE_ASCII))
- i18n::SetICUDefaultLocale("en_US");
-#endif
-#endif
-
-#if defined(OS_LINUX)
- // TODO(thomasanderson): Call TearDownFontconfig() in Shutdown(). It would
- // currently crash because of leaked FcFontSet's in font_fallback_linux.cc.
- SetUpFontconfig();
-#endif
-
- CatchMaybeTests();
- ResetCommandLine();
- AddTestLauncherResultPrinter();
-
- TestTimeouts::Initialize();
-
- trace_to_file_.BeginTracingFromCommandLineOptions();
-
- base::debug::StartProfiling(GetProfileName());
-}
-
-void TestSuite::Shutdown() {
- base::debug::StopProfiling();
-}
-
-} // namespace base
diff --git a/base/test/test_suite.h b/base/test/test_suite.h
deleted file mode 100644
index 6d852bafb9..0000000000
--- a/base/test/test_suite.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_TEST_TEST_SUITE_H_
-#define BASE_TEST_TEST_SUITE_H_
-
-// Defines a basic test suite framework for running gtest based tests. You can
-// instantiate this class in your main function and call its Run method to run
-// any gtest based tests that are linked into your executable.
-
-#include <memory>
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/trace_to_file.h"
-#include "build/build_config.h"
-
-namespace testing {
-class TestInfo;
-}
-
-namespace base {
-
-class XmlUnitTestResultPrinter;
-
-// Instantiates TestSuite, runs it and returns exit code.
-int RunUnitTestsUsingBaseTestSuite(int argc, char **argv);
-
-class TestSuite {
- public:
- // Match function used by the GetTestCount method.
- typedef bool (*TestMatch)(const testing::TestInfo&);
-
- TestSuite(int argc, char** argv);
-#if defined(OS_WIN)
- TestSuite(int argc, wchar_t** argv);
-#endif // defined(OS_WIN)
- virtual ~TestSuite();
-
- // Returns true if the test is marked as "MAYBE_".
- // When using different prefixes depending on platform, we use MAYBE_ and
- // preprocessor directives to replace MAYBE_ with the target prefix.
- static bool IsMarkedMaybe(const testing::TestInfo& test);
-
- void CatchMaybeTests();
-
- void ResetCommandLine();
-
- void AddTestLauncherResultPrinter();
-
- int Run();
-
- protected:
- // By default fatal log messages (e.g. from DCHECKs) result in error dialogs
- // which gum up buildbots. Use a minimalistic assert handler which just
- // terminates the process.
- void UnitTestAssertHandler(const char* file,
- int line,
- const base::StringPiece summary,
- const base::StringPiece stack_trace);
-
- // Disable crash dialogs so that it doesn't gum up the buildbot
- virtual void SuppressErrorDialogs();
-
- // Override these for custom initialization and shutdown handling. Use these
- // instead of putting complex code in your constructor/destructor.
-
- virtual void Initialize();
- virtual void Shutdown();
-
- // Make sure that we setup an AtExitManager so Singleton objects will be
- // destroyed.
- std::unique_ptr<base::AtExitManager> at_exit_manager_;
-
- private:
- void InitializeFromCommandLine(int argc, char** argv);
-#if defined(OS_WIN)
- void InitializeFromCommandLine(int argc, wchar_t** argv);
-#endif // defined(OS_WIN)
-
- // Basic initialization for the test suite happens here.
- void PreInitialize();
-
- test::TraceToFile trace_to_file_;
-
- bool initialized_command_line_;
-
- test::ScopedFeatureList scoped_feature_list_;
-
- XmlUnitTestResultPrinter* printer_ = nullptr;
-
- std::unique_ptr<logging::ScopedLogAssertHandler> assert_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(TestSuite);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_TEST_SUITE_H_
diff --git a/base/test/test_support_android.cc b/base/test/test_support_android.cc
deleted file mode 100644
index d5b656a292..0000000000
--- a/base/test/test_support_android.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright (c) 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.
-
-#include <stdarg.h>
-#include <string.h>
-
-#include "base/android/path_utils.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_pump_android.h"
-#include "base/path_service.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/multiprocess_test.h"
-
-namespace {
-
-base::FilePath* g_test_data_dir = nullptr;
-
-struct RunState {
- RunState(base::MessagePump::Delegate* delegate, int run_depth)
- : delegate(delegate),
- run_depth(run_depth),
- should_quit(false) {
- }
-
- base::MessagePump::Delegate* delegate;
-
- // Used to count how many Run() invocations are on the stack.
- int run_depth;
-
- // Used to flag that the current Run() invocation should return ASAP.
- bool should_quit;
-};
-
-RunState* g_state = nullptr;
-
-// A singleton WaitableEvent wrapper so we avoid a busy loop in
-// MessagePumpForUIStub. Other platforms use the native event loop which blocks
-// when there are no pending messages.
-class Waitable {
- public:
- static Waitable* GetInstance() {
- return base::Singleton<Waitable,
- base::LeakySingletonTraits<Waitable>>::get();
- }
-
- // Signals that there are more work to do.
- void Signal() { waitable_event_.Signal(); }
-
- // Blocks until more work is scheduled.
- void Block() { waitable_event_.Wait(); }
-
- void Quit() {
- g_state->should_quit = true;
- Signal();
- }
-
- private:
- friend struct base::DefaultSingletonTraits<Waitable>;
-
- Waitable()
- : waitable_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- base::WaitableEvent waitable_event_;
-
- DISALLOW_COPY_AND_ASSIGN(Waitable);
-};
-
-// The MessagePumpForUI implementation for test purpose.
-class MessagePumpForUIStub : public base::MessagePumpForUI {
- public:
- MessagePumpForUIStub() : base::MessagePumpForUI() { Waitable::GetInstance(); }
- ~MessagePumpForUIStub() override {}
-
- bool IsTestImplementation() const override { return true; }
-
- // In tests, there isn't a native thread, as such RunLoop::Run() should be
- // used to run the loop instead of attaching and delegating to the native
- // loop. As such, this override ignores the Attach() request.
- void Attach(base::MessagePump::Delegate* delegate) override {}
-
- void Run(base::MessagePump::Delegate* delegate) override {
- // The following was based on message_pump_glib.cc, except we're using a
- // WaitableEvent since there are no native message loop to use.
- RunState state(delegate, g_state ? g_state->run_depth + 1 : 1);
-
- RunState* previous_state = g_state;
- g_state = &state;
-
- // When not nested we can use the real implementation, otherwise fall back
- // to the stub implementation.
- if (g_state->run_depth > 1) {
- RunNested(delegate);
- } else {
- MessagePumpForUI::Run(delegate);
- }
-
- g_state = previous_state;
- }
-
- void RunNested(base::MessagePump::Delegate* delegate) {
- bool more_work_is_plausible = true;
-
- for (;;) {
- if (!more_work_is_plausible) {
- Waitable::GetInstance()->Block();
- if (g_state->should_quit)
- break;
- }
-
- more_work_is_plausible = g_state->delegate->DoWork();
- if (g_state->should_quit)
- break;
-
- base::TimeTicks delayed_work_time;
- more_work_is_plausible |=
- g_state->delegate->DoDelayedWork(&delayed_work_time);
- if (g_state->should_quit)
- break;
-
- if (more_work_is_plausible)
- continue;
-
- more_work_is_plausible = g_state->delegate->DoIdleWork();
- if (g_state->should_quit)
- break;
-
- more_work_is_plausible |= !delayed_work_time.is_null();
- }
- }
-
- void Quit() override {
- CHECK(g_state);
- if (g_state->run_depth > 1) {
- Waitable::GetInstance()->Quit();
- } else {
- MessagePumpForUI::Quit();
- }
- }
-
- void ScheduleWork() override {
- if (g_state && g_state->run_depth > 1) {
- Waitable::GetInstance()->Signal();
- } else {
- MessagePumpForUI::ScheduleWork();
- }
- }
-
- void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override {
- if (g_state && g_state->run_depth > 1) {
- Waitable::GetInstance()->Signal();
- } else {
- MessagePumpForUI::ScheduleDelayedWork(delayed_work_time);
- }
- }
-};
-
-std::unique_ptr<base::MessagePump> CreateMessagePumpForUIStub() {
- return std::unique_ptr<base::MessagePump>(new MessagePumpForUIStub());
-};
-
-// Provides the test path for DIR_SOURCE_ROOT and DIR_ANDROID_APP_DATA.
-bool GetTestProviderPath(int key, base::FilePath* result) {
- switch (key) {
- // TODO(agrieve): Stop overriding DIR_ANDROID_APP_DATA.
- // https://crbug.com/617734
- // Instead DIR_ASSETS should be used to discover assets file location in
- // tests.
- case base::DIR_ANDROID_APP_DATA:
- case base::DIR_ASSETS:
- case base::DIR_SOURCE_ROOT:
- CHECK(g_test_data_dir != nullptr);
- *result = *g_test_data_dir;
- return true;
- default:
- return false;
- }
-}
-
-void InitPathProvider(int key) {
- base::FilePath path;
- // If failed to override the key, that means the way has not been registered.
- if (GetTestProviderPath(key, &path) &&
- !base::PathService::Override(key, path)) {
- base::PathService::RegisterProvider(&GetTestProviderPath, key, key + 1);
- }
-}
-
-} // namespace
-
-namespace base {
-
-void InitAndroidTestLogging() {
- logging::LoggingSettings settings;
- settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
- logging::InitLogging(settings);
- // To view log output with IDs and timestamps use "adb logcat -v threadtime".
- logging::SetLogItems(false, // Process ID
- false, // Thread ID
- false, // Timestamp
- false); // Tick count
-}
-
-void InitAndroidTestPaths(const FilePath& test_data_dir) {
- if (g_test_data_dir) {
- CHECK(test_data_dir == *g_test_data_dir);
- return;
- }
- g_test_data_dir = new FilePath(test_data_dir);
- InitPathProvider(DIR_SOURCE_ROOT);
- InitPathProvider(DIR_ANDROID_APP_DATA);
- InitPathProvider(DIR_ASSETS);
-}
-
-void InitAndroidTestMessageLoop() {
- if (!MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub))
- LOG(INFO) << "MessagePumpForUIFactory already set, unable to override.";
-}
-
-} // namespace base
diff --git a/base/test/test_support_android.h b/base/test/test_support_android.h
deleted file mode 100644
index 4942e54611..0000000000
--- a/base/test/test_support_android.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_TEST_TEST_SUPPORT_ANDROID_H_
-#define BASE_TEST_TEST_SUPPORT_ANDROID_H_
-
-#include "base/base_export.h"
-
-namespace base {
-
-class FilePath;
-
-// Init logging for tests on Android. Logs will be output into Android's logcat.
-BASE_EXPORT void InitAndroidTestLogging();
-
-// Init path providers for tests on Android.
-BASE_EXPORT void InitAndroidTestPaths(const FilePath& test_data_dir);
-
-// Init the message loop for tests on Android.
-BASE_EXPORT void InitAndroidTestMessageLoop();
-
-} // namespace base
-
-#endif // BASE_TEST_TEST_SUPPORT_ANDROID_H_
diff --git a/base/test/test_ui_thread_android.cc b/base/test/test_ui_thread_android.cc
deleted file mode 100644
index d19fefaa6b..0000000000
--- a/base/test/test_ui_thread_android.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2015 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/test_ui_thread_android.h"
-
-#include "jni/TestUiThread_jni.h"
-
-namespace base {
-
-void StartTestUiThreadLooper() {
- Java_TestUiThread_loop(base::android::AttachCurrentThread());
-}
-
-} // namespace base
diff --git a/base/test/test_ui_thread_android.h b/base/test/test_ui_thread_android.h
deleted file mode 100644
index 233911aa86..0000000000
--- a/base/test/test_ui_thread_android.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TEST_TEST_UI_THREAD_ANDROID_
-#define BASE_TEST_TEST_UI_THREAD_ANDROID_
-
-#include <jni.h>
-
-namespace base {
-
-// Set up a thread as the Chromium UI Thread, and run its looper. This is is
-// intended for C++ unit tests (e.g. the net unit tests) that don't run with the
-// UI thread as their main looper, but test code that, on Android, uses UI
-// thread events, so need a running UI thread.
-void StartTestUiThreadLooper();
-
-} // namespace base
-
-#endif // BASE_TEST_TEST_UI_THREAD_ANDROID_
diff --git a/base/test/thread_test_helper.cc b/base/test/thread_test_helper.cc
deleted file mode 100644
index f3ca7807f5..0000000000
--- a/base/test/thread_test_helper.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2011 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/thread_test_helper.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/threading/thread_restrictions.h"
-
-namespace base {
-
-ThreadTestHelper::ThreadTestHelper(
- scoped_refptr<SequencedTaskRunner> target_sequence)
- : test_result_(false),
- target_sequence_(std::move(target_sequence)),
- done_event_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
-bool ThreadTestHelper::Run() {
- if (!target_sequence_->PostTask(
- FROM_HERE, base::BindOnce(&ThreadTestHelper::RunOnSequence, this))) {
- return false;
- }
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- done_event_.Wait();
- return test_result_;
-}
-
-void ThreadTestHelper::RunTest() { set_test_result(true); }
-
-ThreadTestHelper::~ThreadTestHelper() = default;
-
-void ThreadTestHelper::RunOnSequence() {
- RunTest();
- done_event_.Signal();
-}
-
-} // namespace base
diff --git a/base/test/thread_test_helper.h b/base/test/thread_test_helper.h
deleted file mode 100644
index 935e7efc6b..0000000000
--- a/base/test/thread_test_helper.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef BASE_TEST_THREAD_TEST_HELPER_H_
-#define BASE_TEST_THREAD_TEST_HELPER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-
-namespace base {
-
-// Helper class that executes code on a given target sequence/thread while
-// blocking on the invoking sequence/thread. To use, derive from this class and
-// overwrite RunTest. An alternative use of this class is to use it directly. It
-// will then block until all pending tasks on a given sequence/thread have been
-// executed.
-class ThreadTestHelper : public RefCountedThreadSafe<ThreadTestHelper> {
- public:
- explicit ThreadTestHelper(scoped_refptr<SequencedTaskRunner> target_sequence);
-
- // True if RunTest() was successfully executed on the target sequence.
- bool Run() WARN_UNUSED_RESULT;
-
- virtual void RunTest();
-
- protected:
- friend class RefCountedThreadSafe<ThreadTestHelper>;
-
- virtual ~ThreadTestHelper();
-
- // Use this method to store the result of RunTest().
- void set_test_result(bool test_result) { test_result_ = test_result; }
-
- private:
- void RunOnSequence();
-
- bool test_result_;
- scoped_refptr<SequencedTaskRunner> target_sequence_;
- WaitableEvent done_event_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadTestHelper);
-};
-
-} // namespace base
-
-#endif // BASE_TEST_THREAD_TEST_HELPER_H_
diff --git a/base/test/trace_event_analyzer.cc b/base/test/trace_event_analyzer.cc
deleted file mode 100644
index cab2899613..0000000000
--- a/base/test/trace_event_analyzer.cc
+++ /dev/null
@@ -1,1069 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/trace_event_analyzer.h"
-
-#include <math.h>
-
-#include <algorithm>
-#include <set>
-
-#include "base/json/json_reader.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/run_loop.h"
-#include "base/strings/pattern.h"
-#include "base/trace_event/trace_buffer.h"
-#include "base/trace_event/trace_config.h"
-#include "base/trace_event/trace_log.h"
-#include "base/values.h"
-
-namespace {
-void OnTraceDataCollected(base::OnceClosure quit_closure,
- base::trace_event::TraceResultBuffer* buffer,
- const scoped_refptr<base::RefCountedString>& json,
- bool has_more_events) {
- buffer->AddFragment(json->data());
- if (!has_more_events)
- std::move(quit_closure).Run();
-}
-} // namespace
-
-namespace trace_analyzer {
-
-// TraceEvent
-
-TraceEvent::TraceEvent()
- : thread(0, 0),
- timestamp(0),
- duration(0),
- phase(TRACE_EVENT_PHASE_BEGIN),
- other_event(nullptr) {}
-
-TraceEvent::TraceEvent(TraceEvent&& other) = default;
-
-TraceEvent::~TraceEvent() = default;
-
-TraceEvent& TraceEvent::operator=(TraceEvent&& rhs) = default;
-
-bool TraceEvent::SetFromJSON(const base::Value* event_value) {
- if (event_value->type() != base::Value::Type::DICTIONARY) {
- LOG(ERROR) << "Value must be Type::DICTIONARY";
- return false;
- }
- const base::DictionaryValue* dictionary =
- static_cast<const base::DictionaryValue*>(event_value);
-
- std::string phase_str;
- const base::DictionaryValue* args = nullptr;
-
- if (!dictionary->GetString("ph", &phase_str)) {
- LOG(ERROR) << "ph is missing from TraceEvent JSON";
- return false;
- }
-
- phase = *phase_str.data();
-
- bool may_have_duration = (phase == TRACE_EVENT_PHASE_COMPLETE);
- bool require_origin = (phase != TRACE_EVENT_PHASE_METADATA);
- bool require_id = (phase == TRACE_EVENT_PHASE_ASYNC_BEGIN ||
- phase == TRACE_EVENT_PHASE_ASYNC_STEP_INTO ||
- phase == TRACE_EVENT_PHASE_ASYNC_STEP_PAST ||
- phase == TRACE_EVENT_PHASE_MEMORY_DUMP ||
- phase == TRACE_EVENT_PHASE_ENTER_CONTEXT ||
- phase == TRACE_EVENT_PHASE_LEAVE_CONTEXT ||
- phase == TRACE_EVENT_PHASE_CREATE_OBJECT ||
- phase == TRACE_EVENT_PHASE_DELETE_OBJECT ||
- phase == TRACE_EVENT_PHASE_SNAPSHOT_OBJECT ||
- phase == TRACE_EVENT_PHASE_ASYNC_END);
-
- if (require_origin && !dictionary->GetInteger("pid", &thread.process_id)) {
- LOG(ERROR) << "pid is missing from TraceEvent JSON";
- return false;
- }
- if (require_origin && !dictionary->GetInteger("tid", &thread.thread_id)) {
- LOG(ERROR) << "tid is missing from TraceEvent JSON";
- return false;
- }
- if (require_origin && !dictionary->GetDouble("ts", &timestamp)) {
- LOG(ERROR) << "ts is missing from TraceEvent JSON";
- return false;
- }
- if (may_have_duration) {
- dictionary->GetDouble("dur", &duration);
- }
- if (!dictionary->GetString("cat", &category)) {
- LOG(ERROR) << "cat is missing from TraceEvent JSON";
- return false;
- }
- if (!dictionary->GetString("name", &name)) {
- LOG(ERROR) << "name is missing from TraceEvent JSON";
- return false;
- }
- if (!dictionary->GetDictionary("args", &args)) {
- LOG(ERROR) << "args is missing from TraceEvent JSON";
- return false;
- }
- if (require_id && !dictionary->GetString("id", &id)) {
- LOG(ERROR) << "id is missing from ASYNC_BEGIN/ASYNC_END TraceEvent JSON";
- return false;
- }
-
- dictionary->GetDouble("tdur", &thread_duration);
- dictionary->GetDouble("tts", &thread_timestamp);
- dictionary->GetString("scope", &scope);
- dictionary->GetString("bind_id", &bind_id);
- dictionary->GetBoolean("flow_out", &flow_out);
- dictionary->GetBoolean("flow_in", &flow_in);
-
- const base::DictionaryValue* id2;
- if (dictionary->GetDictionary("id2", &id2)) {
- id2->GetString("global", &global_id2);
- id2->GetString("local", &local_id2);
- }
-
- // For each argument, copy the type and create a trace_analyzer::TraceValue.
- for (base::DictionaryValue::Iterator it(*args); !it.IsAtEnd();
- it.Advance()) {
- std::string str;
- bool boolean = false;
- int int_num = 0;
- double double_num = 0.0;
- if (it.value().GetAsString(&str)) {
- arg_strings[it.key()] = str;
- } else if (it.value().GetAsInteger(&int_num)) {
- arg_numbers[it.key()] = static_cast<double>(int_num);
- } else if (it.value().GetAsBoolean(&boolean)) {
- arg_numbers[it.key()] = static_cast<double>(boolean ? 1 : 0);
- } else if (it.value().GetAsDouble(&double_num)) {
- arg_numbers[it.key()] = double_num;
- }
- // Record all arguments as values.
- arg_values[it.key()] = it.value().CreateDeepCopy();
- }
-
- return true;
-}
-
-double TraceEvent::GetAbsTimeToOtherEvent() const {
- return fabs(other_event->timestamp - timestamp);
-}
-
-bool TraceEvent::GetArgAsString(const std::string& name,
- std::string* arg) const {
- const auto it = arg_strings.find(name);
- if (it != arg_strings.end()) {
- *arg = it->second;
- return true;
- }
- return false;
-}
-
-bool TraceEvent::GetArgAsNumber(const std::string& name,
- double* arg) const {
- const auto it = arg_numbers.find(name);
- if (it != arg_numbers.end()) {
- *arg = it->second;
- return true;
- }
- return false;
-}
-
-bool TraceEvent::GetArgAsValue(const std::string& name,
- std::unique_ptr<base::Value>* arg) const {
- const auto it = arg_values.find(name);
- if (it != arg_values.end()) {
- *arg = it->second->CreateDeepCopy();
- return true;
- }
- return false;
-}
-
-bool TraceEvent::HasStringArg(const std::string& name) const {
- return (arg_strings.find(name) != arg_strings.end());
-}
-
-bool TraceEvent::HasNumberArg(const std::string& name) const {
- return (arg_numbers.find(name) != arg_numbers.end());
-}
-
-bool TraceEvent::HasArg(const std::string& name) const {
- return (arg_values.find(name) != arg_values.end());
-}
-
-std::string TraceEvent::GetKnownArgAsString(const std::string& name) const {
- std::string arg_string;
- bool result = GetArgAsString(name, &arg_string);
- DCHECK(result);
- return arg_string;
-}
-
-double TraceEvent::GetKnownArgAsDouble(const std::string& name) const {
- double arg_double = 0;
- bool result = GetArgAsNumber(name, &arg_double);
- DCHECK(result);
- return arg_double;
-}
-
-int TraceEvent::GetKnownArgAsInt(const std::string& name) const {
- double arg_double = 0;
- bool result = GetArgAsNumber(name, &arg_double);
- DCHECK(result);
- return static_cast<int>(arg_double);
-}
-
-bool TraceEvent::GetKnownArgAsBool(const std::string& name) const {
- double arg_double = 0;
- bool result = GetArgAsNumber(name, &arg_double);
- DCHECK(result);
- return (arg_double != 0.0);
-}
-
-std::unique_ptr<base::Value> TraceEvent::GetKnownArgAsValue(
- const std::string& name) const {
- std::unique_ptr<base::Value> arg_value;
- bool result = GetArgAsValue(name, &arg_value);
- DCHECK(result);
- return arg_value;
-}
-
-// QueryNode
-
-QueryNode::QueryNode(const Query& query) : query_(query) {
-}
-
-QueryNode::~QueryNode() = default;
-
-// Query
-
-Query::Query(TraceEventMember member)
- : type_(QUERY_EVENT_MEMBER),
- operator_(OP_INVALID),
- member_(member),
- number_(0),
- is_pattern_(false) {
-}
-
-Query::Query(TraceEventMember member, const std::string& arg_name)
- : type_(QUERY_EVENT_MEMBER),
- operator_(OP_INVALID),
- member_(member),
- number_(0),
- string_(arg_name),
- is_pattern_(false) {
-}
-
-Query::Query(const Query& query) = default;
-
-Query::~Query() = default;
-
-Query Query::String(const std::string& str) {
- return Query(str);
-}
-
-Query Query::Double(double num) {
- return Query(num);
-}
-
-Query Query::Int(int32_t num) {
- return Query(static_cast<double>(num));
-}
-
-Query Query::Uint(uint32_t num) {
- return Query(static_cast<double>(num));
-}
-
-Query Query::Bool(bool boolean) {
- return Query(boolean ? 1.0 : 0.0);
-}
-
-Query Query::Phase(char phase) {
- return Query(static_cast<double>(phase));
-}
-
-Query Query::Pattern(const std::string& pattern) {
- Query query(pattern);
- query.is_pattern_ = true;
- return query;
-}
-
-bool Query::Evaluate(const TraceEvent& event) const {
- // First check for values that can convert to bool.
-
- // double is true if != 0:
- double bool_value = 0.0;
- bool is_bool = GetAsDouble(event, &bool_value);
- if (is_bool)
- return (bool_value != 0.0);
-
- // string is true if it is non-empty:
- std::string str_value;
- bool is_str = GetAsString(event, &str_value);
- if (is_str)
- return !str_value.empty();
-
- DCHECK_EQ(QUERY_BOOLEAN_OPERATOR, type_)
- << "Invalid query: missing boolean expression";
- DCHECK(left_.get());
- DCHECK(right_.get() || is_unary_operator());
-
- if (is_comparison_operator()) {
- DCHECK(left().is_value() && right().is_value())
- << "Invalid query: comparison operator used between event member and "
- "value.";
- bool compare_result = false;
- if (CompareAsDouble(event, &compare_result))
- return compare_result;
- if (CompareAsString(event, &compare_result))
- return compare_result;
- return false;
- }
- // It's a logical operator.
- switch (operator_) {
- case OP_AND:
- return left().Evaluate(event) && right().Evaluate(event);
- case OP_OR:
- return left().Evaluate(event) || right().Evaluate(event);
- case OP_NOT:
- return !left().Evaluate(event);
- default:
- NOTREACHED();
- return false;
- }
-}
-
-bool Query::CompareAsDouble(const TraceEvent& event, bool* result) const {
- double lhs, rhs;
- if (!left().GetAsDouble(event, &lhs) || !right().GetAsDouble(event, &rhs))
- return false;
- switch (operator_) {
- case OP_EQ:
- *result = (lhs == rhs);
- return true;
- case OP_NE:
- *result = (lhs != rhs);
- return true;
- case OP_LT:
- *result = (lhs < rhs);
- return true;
- case OP_LE:
- *result = (lhs <= rhs);
- return true;
- case OP_GT:
- *result = (lhs > rhs);
- return true;
- case OP_GE:
- *result = (lhs >= rhs);
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-bool Query::CompareAsString(const TraceEvent& event, bool* result) const {
- std::string lhs, rhs;
- if (!left().GetAsString(event, &lhs) || !right().GetAsString(event, &rhs))
- return false;
- switch (operator_) {
- case OP_EQ:
- if (right().is_pattern_)
- *result = base::MatchPattern(lhs, rhs);
- else if (left().is_pattern_)
- *result = base::MatchPattern(rhs, lhs);
- else
- *result = (lhs == rhs);
- return true;
- case OP_NE:
- if (right().is_pattern_)
- *result = !base::MatchPattern(lhs, rhs);
- else if (left().is_pattern_)
- *result = !base::MatchPattern(rhs, lhs);
- else
- *result = (lhs != rhs);
- return true;
- case OP_LT:
- *result = (lhs < rhs);
- return true;
- case OP_LE:
- *result = (lhs <= rhs);
- return true;
- case OP_GT:
- *result = (lhs > rhs);
- return true;
- case OP_GE:
- *result = (lhs >= rhs);
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-bool Query::EvaluateArithmeticOperator(const TraceEvent& event,
- double* num) const {
- DCHECK_EQ(QUERY_ARITHMETIC_OPERATOR, type_);
- DCHECK(left_.get());
- DCHECK(right_.get() || is_unary_operator());
-
- double lhs = 0, rhs = 0;
- if (!left().GetAsDouble(event, &lhs))
- return false;
- if (!is_unary_operator() && !right().GetAsDouble(event, &rhs))
- return false;
-
- switch (operator_) {
- case OP_ADD:
- *num = lhs + rhs;
- return true;
- case OP_SUB:
- *num = lhs - rhs;
- return true;
- case OP_MUL:
- *num = lhs * rhs;
- return true;
- case OP_DIV:
- *num = lhs / rhs;
- return true;
- case OP_MOD:
- *num = static_cast<double>(static_cast<int64_t>(lhs) %
- static_cast<int64_t>(rhs));
- return true;
- case OP_NEGATE:
- *num = -lhs;
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-bool Query::GetAsDouble(const TraceEvent& event, double* num) const {
- switch (type_) {
- case QUERY_ARITHMETIC_OPERATOR:
- return EvaluateArithmeticOperator(event, num);
- case QUERY_EVENT_MEMBER:
- return GetMemberValueAsDouble(event, num);
- case QUERY_NUMBER:
- *num = number_;
- return true;
- default:
- return false;
- }
-}
-
-bool Query::GetAsString(const TraceEvent& event, std::string* str) const {
- switch (type_) {
- case QUERY_EVENT_MEMBER:
- return GetMemberValueAsString(event, str);
- case QUERY_STRING:
- *str = string_;
- return true;
- default:
- return false;
- }
-}
-
-const TraceEvent* Query::SelectTargetEvent(const TraceEvent* event,
- TraceEventMember member) {
- if (member >= OTHER_FIRST_MEMBER && member <= OTHER_LAST_MEMBER) {
- return event->other_event;
- } else if (member >= PREV_FIRST_MEMBER && member <= PREV_LAST_MEMBER) {
- return event->prev_event;
- } else {
- return event;
- }
-}
-
-bool Query::GetMemberValueAsDouble(const TraceEvent& event,
- double* num) const {
- DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
-
- // This could be a request for a member of |event| or a member of |event|'s
- // associated previous or next event. Store the target event in the_event:
- const TraceEvent* the_event = SelectTargetEvent(&event, member_);
-
- // Request for member of associated event, but there is no associated event.
- if (!the_event)
- return false;
-
- switch (member_) {
- case EVENT_PID:
- case OTHER_PID:
- case PREV_PID:
- *num = static_cast<double>(the_event->thread.process_id);
- return true;
- case EVENT_TID:
- case OTHER_TID:
- case PREV_TID:
- *num = static_cast<double>(the_event->thread.thread_id);
- return true;
- case EVENT_TIME:
- case OTHER_TIME:
- case PREV_TIME:
- *num = the_event->timestamp;
- return true;
- case EVENT_DURATION:
- if (!the_event->has_other_event())
- return false;
- *num = the_event->GetAbsTimeToOtherEvent();
- return true;
- case EVENT_COMPLETE_DURATION:
- if (the_event->phase != TRACE_EVENT_PHASE_COMPLETE)
- return false;
- *num = the_event->duration;
- return true;
- case EVENT_PHASE:
- case OTHER_PHASE:
- case PREV_PHASE:
- *num = static_cast<double>(the_event->phase);
- return true;
- case EVENT_HAS_STRING_ARG:
- case OTHER_HAS_STRING_ARG:
- case PREV_HAS_STRING_ARG:
- *num = (the_event->HasStringArg(string_) ? 1.0 : 0.0);
- return true;
- case EVENT_HAS_NUMBER_ARG:
- case OTHER_HAS_NUMBER_ARG:
- case PREV_HAS_NUMBER_ARG:
- *num = (the_event->HasNumberArg(string_) ? 1.0 : 0.0);
- return true;
- case EVENT_ARG:
- case OTHER_ARG:
- case PREV_ARG: {
- // Search for the argument name and return its value if found.
- std::map<std::string, double>::const_iterator num_i =
- the_event->arg_numbers.find(string_);
- if (num_i == the_event->arg_numbers.end())
- return false;
- *num = num_i->second;
- return true;
- }
- case EVENT_HAS_OTHER:
- // return 1.0 (true) if the other event exists
- *num = event.other_event ? 1.0 : 0.0;
- return true;
- case EVENT_HAS_PREV:
- *num = event.prev_event ? 1.0 : 0.0;
- return true;
- default:
- return false;
- }
-}
-
-bool Query::GetMemberValueAsString(const TraceEvent& event,
- std::string* str) const {
- DCHECK_EQ(QUERY_EVENT_MEMBER, type_);
-
- // This could be a request for a member of |event| or a member of |event|'s
- // associated previous or next event. Store the target event in the_event:
- const TraceEvent* the_event = SelectTargetEvent(&event, member_);
-
- // Request for member of associated event, but there is no associated event.
- if (!the_event)
- return false;
-
- switch (member_) {
- case EVENT_CATEGORY:
- case OTHER_CATEGORY:
- case PREV_CATEGORY:
- *str = the_event->category;
- return true;
- case EVENT_NAME:
- case OTHER_NAME:
- case PREV_NAME:
- *str = the_event->name;
- return true;
- case EVENT_ID:
- case OTHER_ID:
- case PREV_ID:
- *str = the_event->id;
- return true;
- case EVENT_ARG:
- case OTHER_ARG:
- case PREV_ARG: {
- // Search for the argument name and return its value if found.
- std::map<std::string, std::string>::const_iterator str_i =
- the_event->arg_strings.find(string_);
- if (str_i == the_event->arg_strings.end())
- return false;
- *str = str_i->second;
- return true;
- }
- default:
- return false;
- }
-}
-
-Query::Query(const std::string& str)
- : type_(QUERY_STRING),
- operator_(OP_INVALID),
- member_(EVENT_INVALID),
- number_(0),
- string_(str),
- is_pattern_(false) {
-}
-
-Query::Query(double num)
- : type_(QUERY_NUMBER),
- operator_(OP_INVALID),
- member_(EVENT_INVALID),
- number_(num),
- is_pattern_(false) {
-}
-const Query& Query::left() const {
- return left_->query();
-}
-
-const Query& Query::right() const {
- return right_->query();
-}
-
-Query Query::operator==(const Query& rhs) const {
- return Query(*this, rhs, OP_EQ);
-}
-
-Query Query::operator!=(const Query& rhs) const {
- return Query(*this, rhs, OP_NE);
-}
-
-Query Query::operator<(const Query& rhs) const {
- return Query(*this, rhs, OP_LT);
-}
-
-Query Query::operator<=(const Query& rhs) const {
- return Query(*this, rhs, OP_LE);
-}
-
-Query Query::operator>(const Query& rhs) const {
- return Query(*this, rhs, OP_GT);
-}
-
-Query Query::operator>=(const Query& rhs) const {
- return Query(*this, rhs, OP_GE);
-}
-
-Query Query::operator&&(const Query& rhs) const {
- return Query(*this, rhs, OP_AND);
-}
-
-Query Query::operator||(const Query& rhs) const {
- return Query(*this, rhs, OP_OR);
-}
-
-Query Query::operator!() const {
- return Query(*this, OP_NOT);
-}
-
-Query Query::operator+(const Query& rhs) const {
- return Query(*this, rhs, OP_ADD);
-}
-
-Query Query::operator-(const Query& rhs) const {
- return Query(*this, rhs, OP_SUB);
-}
-
-Query Query::operator*(const Query& rhs) const {
- return Query(*this, rhs, OP_MUL);
-}
-
-Query Query::operator/(const Query& rhs) const {
- return Query(*this, rhs, OP_DIV);
-}
-
-Query Query::operator%(const Query& rhs) const {
- return Query(*this, rhs, OP_MOD);
-}
-
-Query Query::operator-() const {
- return Query(*this, OP_NEGATE);
-}
-
-
-Query::Query(const Query& left, const Query& right, Operator binary_op)
- : operator_(binary_op),
- left_(new QueryNode(left)),
- right_(new QueryNode(right)),
- member_(EVENT_INVALID),
- number_(0) {
- type_ = (binary_op < OP_ADD ?
- QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
-}
-
-Query::Query(const Query& left, Operator unary_op)
- : operator_(unary_op),
- left_(new QueryNode(left)),
- member_(EVENT_INVALID),
- number_(0) {
- type_ = (unary_op < OP_ADD ?
- QUERY_BOOLEAN_OPERATOR : QUERY_ARITHMETIC_OPERATOR);
-}
-
-namespace {
-
-// Search |events| for |query| and add matches to |output|.
-size_t FindMatchingEvents(const std::vector<TraceEvent>& events,
- const Query& query,
- TraceEventVector* output,
- bool ignore_metadata_events) {
- for (size_t i = 0; i < events.size(); ++i) {
- if (ignore_metadata_events && events[i].phase == TRACE_EVENT_PHASE_METADATA)
- continue;
- if (query.Evaluate(events[i]))
- output->push_back(&events[i]);
- }
- return output->size();
-}
-
-bool ParseEventsFromJson(const std::string& json,
- std::vector<TraceEvent>* output) {
- std::unique_ptr<base::Value> root = base::JSONReader::Read(json);
-
- base::ListValue* root_list = nullptr;
- if (!root.get() || !root->GetAsList(&root_list))
- return false;
-
- for (size_t i = 0; i < root_list->GetSize(); ++i) {
- base::Value* item = nullptr;
- if (root_list->Get(i, &item)) {
- TraceEvent event;
- if (event.SetFromJSON(item))
- output->push_back(std::move(event));
- else
- return false;
- }
- }
-
- return true;
-}
-
-} // namespace
-
-// TraceAnalyzer
-
-TraceAnalyzer::TraceAnalyzer()
- : ignore_metadata_events_(false), allow_association_changes_(true) {}
-
-TraceAnalyzer::~TraceAnalyzer() = default;
-
-// static
-TraceAnalyzer* TraceAnalyzer::Create(const std::string& json_events) {
- std::unique_ptr<TraceAnalyzer> analyzer(new TraceAnalyzer());
- if (analyzer->SetEvents(json_events))
- return analyzer.release();
- return nullptr;
-}
-
-bool TraceAnalyzer::SetEvents(const std::string& json_events) {
- raw_events_.clear();
- if (!ParseEventsFromJson(json_events, &raw_events_))
- return false;
- std::stable_sort(raw_events_.begin(), raw_events_.end());
- ParseMetadata();
- return true;
-}
-
-void TraceAnalyzer::AssociateBeginEndEvents() {
- using trace_analyzer::Query;
-
- Query begin(Query::EventPhaseIs(TRACE_EVENT_PHASE_BEGIN));
- Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_END));
- Query match(Query::EventName() == Query::OtherName() &&
- Query::EventCategory() == Query::OtherCategory() &&
- Query::EventTid() == Query::OtherTid() &&
- Query::EventPid() == Query::OtherPid());
-
- AssociateEvents(begin, end, match);
-}
-
-void TraceAnalyzer::AssociateAsyncBeginEndEvents(bool match_pid) {
- using trace_analyzer::Query;
-
- Query begin(
- Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_BEGIN) ||
- Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
- Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
- Query end(Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_END) ||
- Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_INTO) ||
- Query::EventPhaseIs(TRACE_EVENT_PHASE_ASYNC_STEP_PAST));
- Query match(Query::EventCategory() == Query::OtherCategory() &&
- Query::EventId() == Query::OtherId());
-
- if (match_pid) {
- match = match && Query::EventPid() == Query::OtherPid();
- }
-
- AssociateEvents(begin, end, match);
-}
-
-void TraceAnalyzer::AssociateEvents(const Query& first,
- const Query& second,
- const Query& match) {
- DCHECK(allow_association_changes_)
- << "AssociateEvents not allowed after FindEvents";
-
- // Search for matching begin/end event pairs. When a matching end is found,
- // it is associated with the begin event.
- std::vector<TraceEvent*> begin_stack;
- for (size_t event_index = 0; event_index < raw_events_.size();
- ++event_index) {
-
- TraceEvent& this_event = raw_events_[event_index];
-
- if (second.Evaluate(this_event)) {
- // Search stack for matching begin, starting from end.
- for (int stack_index = static_cast<int>(begin_stack.size()) - 1;
- stack_index >= 0; --stack_index) {
- TraceEvent& begin_event = *begin_stack[stack_index];
-
- // Temporarily set other to test against the match query.
- const TraceEvent* other_backup = begin_event.other_event;
- begin_event.other_event = &this_event;
- if (match.Evaluate(begin_event)) {
- // Found a matching begin/end pair.
- // Set the associated previous event
- this_event.prev_event = &begin_event;
- // Erase the matching begin event index from the stack.
- begin_stack.erase(begin_stack.begin() + stack_index);
- break;
- }
-
- // Not a match, restore original other and continue.
- begin_event.other_event = other_backup;
- }
- }
- // Even if this_event is a |second| event that has matched an earlier
- // |first| event, it can still also be a |first| event and be associated
- // with a later |second| event.
- if (first.Evaluate(this_event)) {
- begin_stack.push_back(&this_event);
- }
- }
-}
-
-void TraceAnalyzer::MergeAssociatedEventArgs() {
- for (size_t i = 0; i < raw_events_.size(); ++i) {
- // Merge all associated events with the first event.
- const TraceEvent* other = raw_events_[i].other_event;
- // Avoid looping by keeping set of encountered TraceEvents.
- std::set<const TraceEvent*> encounters;
- encounters.insert(&raw_events_[i]);
- while (other && encounters.find(other) == encounters.end()) {
- encounters.insert(other);
- raw_events_[i].arg_numbers.insert(
- other->arg_numbers.begin(),
- other->arg_numbers.end());
- raw_events_[i].arg_strings.insert(
- other->arg_strings.begin(),
- other->arg_strings.end());
- other = other->other_event;
- }
- }
-}
-
-size_t TraceAnalyzer::FindEvents(const Query& query, TraceEventVector* output) {
- allow_association_changes_ = false;
- output->clear();
- return FindMatchingEvents(
- raw_events_, query, output, ignore_metadata_events_);
-}
-
-const TraceEvent* TraceAnalyzer::FindFirstOf(const Query& query) {
- TraceEventVector output;
- if (FindEvents(query, &output) > 0)
- return output.front();
- return nullptr;
-}
-
-const TraceEvent* TraceAnalyzer::FindLastOf(const Query& query) {
- TraceEventVector output;
- if (FindEvents(query, &output) > 0)
- return output.back();
- return nullptr;
-}
-
-const std::string& TraceAnalyzer::GetThreadName(
- const TraceEvent::ProcessThreadID& thread) {
- // If thread is not found, just add and return empty string.
- return thread_names_[thread];
-}
-
-void TraceAnalyzer::ParseMetadata() {
- for (size_t i = 0; i < raw_events_.size(); ++i) {
- TraceEvent& this_event = raw_events_[i];
- // Check for thread name metadata.
- if (this_event.phase != TRACE_EVENT_PHASE_METADATA ||
- this_event.name != "thread_name")
- continue;
- std::map<std::string, std::string>::const_iterator string_it =
- this_event.arg_strings.find("name");
- if (string_it != this_event.arg_strings.end())
- thread_names_[this_event.thread] = string_it->second;
- }
-}
-
-// Utility functions for collecting process-local traces and creating a
-// |TraceAnalyzer| from the result.
-
-void Start(const std::string& category_filter_string) {
- DCHECK(!base::trace_event::TraceLog::GetInstance()->IsEnabled());
- base::trace_event::TraceLog::GetInstance()->SetEnabled(
- base::trace_event::TraceConfig(category_filter_string, ""),
- base::trace_event::TraceLog::RECORDING_MODE);
-}
-
-std::unique_ptr<TraceAnalyzer> Stop() {
- DCHECK(base::trace_event::TraceLog::GetInstance()->IsEnabled());
- base::trace_event::TraceLog::GetInstance()->SetDisabled();
-
- base::trace_event::TraceResultBuffer buffer;
- base::trace_event::TraceResultBuffer::SimpleOutput trace_output;
- buffer.SetOutputCallback(trace_output.GetCallback());
- base::RunLoop run_loop;
- buffer.Start();
- base::trace_event::TraceLog::GetInstance()->Flush(
- base::BindRepeating(&OnTraceDataCollected, run_loop.QuitClosure(),
- base::Unretained(&buffer)));
- run_loop.Run();
- buffer.Finish();
-
- return base::WrapUnique(TraceAnalyzer::Create(trace_output.json_output));
-}
-
-// TraceEventVector utility functions.
-
-bool GetRateStats(const TraceEventVector& events,
- RateStats* stats,
- const RateStatsOptions* options) {
- DCHECK(stats);
- // Need at least 3 events to calculate rate stats.
- const size_t kMinEvents = 3;
- if (events.size() < kMinEvents) {
- LOG(ERROR) << "Not enough events: " << events.size();
- return false;
- }
-
- std::vector<double> deltas;
- size_t num_deltas = events.size() - 1;
- for (size_t i = 0; i < num_deltas; ++i) {
- double delta = events.at(i + 1)->timestamp - events.at(i)->timestamp;
- if (delta < 0.0) {
- LOG(ERROR) << "Events are out of order";
- return false;
- }
- deltas.push_back(delta);
- }
-
- std::sort(deltas.begin(), deltas.end());
-
- if (options) {
- if (options->trim_min + options->trim_max > events.size() - kMinEvents) {
- LOG(ERROR) << "Attempt to trim too many events";
- return false;
- }
- deltas.erase(deltas.begin(), deltas.begin() + options->trim_min);
- deltas.erase(deltas.end() - options->trim_max, deltas.end());
- }
-
- num_deltas = deltas.size();
- double delta_sum = 0.0;
- for (size_t i = 0; i < num_deltas; ++i)
- delta_sum += deltas[i];
-
- stats->min_us = *std::min_element(deltas.begin(), deltas.end());
- stats->max_us = *std::max_element(deltas.begin(), deltas.end());
- stats->mean_us = delta_sum / static_cast<double>(num_deltas);
-
- double sum_mean_offsets_squared = 0.0;
- for (size_t i = 0; i < num_deltas; ++i) {
- double offset = fabs(deltas[i] - stats->mean_us);
- sum_mean_offsets_squared += offset * offset;
- }
- stats->standard_deviation_us =
- sqrt(sum_mean_offsets_squared / static_cast<double>(num_deltas - 1));
-
- return true;
-}
-
-bool FindFirstOf(const TraceEventVector& events,
- const Query& query,
- size_t position,
- size_t* return_index) {
- DCHECK(return_index);
- for (size_t i = position; i < events.size(); ++i) {
- if (query.Evaluate(*events[i])) {
- *return_index = i;
- return true;
- }
- }
- return false;
-}
-
-bool FindLastOf(const TraceEventVector& events,
- const Query& query,
- size_t position,
- size_t* return_index) {
- DCHECK(return_index);
- for (size_t i = std::min(position + 1, events.size()); i != 0; --i) {
- if (query.Evaluate(*events[i - 1])) {
- *return_index = i - 1;
- return true;
- }
- }
- return false;
-}
-
-bool FindClosest(const TraceEventVector& events,
- const Query& query,
- size_t position,
- size_t* return_closest,
- size_t* return_second_closest) {
- DCHECK(return_closest);
- if (events.empty() || position >= events.size())
- return false;
- size_t closest = events.size();
- size_t second_closest = events.size();
- for (size_t i = 0; i < events.size(); ++i) {
- if (!query.Evaluate(*events.at(i)))
- continue;
- if (closest == events.size()) {
- closest = i;
- continue;
- }
- if (fabs(events.at(i)->timestamp - events.at(position)->timestamp) <
- fabs(events.at(closest)->timestamp - events.at(position)->timestamp)) {
- second_closest = closest;
- closest = i;
- } else if (second_closest == events.size()) {
- second_closest = i;
- }
- }
-
- if (closest < events.size() &&
- (!return_second_closest || second_closest < events.size())) {
- *return_closest = closest;
- if (return_second_closest)
- *return_second_closest = second_closest;
- return true;
- }
-
- return false;
-}
-
-size_t CountMatches(const TraceEventVector& events,
- const Query& query,
- size_t begin_position,
- size_t end_position) {
- if (begin_position >= events.size())
- return 0u;
- end_position = (end_position < events.size()) ? end_position : events.size();
- size_t count = 0u;
- for (size_t i = begin_position; i < end_position; ++i) {
- if (query.Evaluate(*events.at(i)))
- ++count;
- }
- return count;
-}
-
-} // namespace trace_analyzer
diff --git a/base/test/trace_event_analyzer.h b/base/test/trace_event_analyzer.h
deleted file mode 100644
index dcdd2e4b5e..0000000000
--- a/base/test/trace_event_analyzer.h
+++ /dev/null
@@ -1,842 +0,0 @@
-// Copyright (c) 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.
-
-// Use trace_analyzer::Query and trace_analyzer::TraceAnalyzer to search for
-// specific trace events that were generated by the trace_event.h API.
-//
-// Basic procedure:
-// - Get trace events JSON string from base::trace_event::TraceLog.
-// - Create TraceAnalyzer with JSON string.
-// - Call TraceAnalyzer::AssociateBeginEndEvents (optional).
-// - Call TraceAnalyzer::AssociateEvents (zero or more times).
-// - Call TraceAnalyzer::FindEvents with queries to find specific events.
-//
-// A Query is a boolean expression tree that evaluates to true or false for a
-// given trace event. Queries can be combined into a tree using boolean,
-// arithmetic and comparison operators that refer to data of an individual trace
-// event.
-//
-// The events are returned as trace_analyzer::TraceEvent objects.
-// TraceEvent contains a single trace event's data, as well as a pointer to
-// a related trace event. The related trace event is typically the matching end
-// of a begin event or the matching begin of an end event.
-//
-// The following examples use this basic setup code to construct TraceAnalyzer
-// with the json trace string retrieved from TraceLog and construct an event
-// vector for retrieving events:
-//
-// TraceAnalyzer analyzer(json_events);
-// TraceEventVector events;
-//
-// EXAMPLE 1: Find events named "my_event".
-//
-// analyzer.FindEvents(Query(EVENT_NAME) == "my_event", &events);
-//
-// EXAMPLE 2: Find begin events named "my_event" with duration > 1 second.
-//
-// Query q = (Query(EVENT_NAME) == Query::String("my_event") &&
-// Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_BEGIN) &&
-// Query(EVENT_DURATION) > Query::Double(1000000.0));
-// analyzer.FindEvents(q, &events);
-//
-// EXAMPLE 3: Associating event pairs across threads.
-//
-// If the test needs to analyze something that starts and ends on different
-// threads, the test needs to use INSTANT events. The typical procedure is to
-// specify the same unique ID as a TRACE_EVENT argument on both the start and
-// finish INSTANT events. Then use the following procedure to associate those
-// events.
-//
-// Step 1: instrument code with custom begin/end trace events.
-// [Thread 1 tracing code]
-// TRACE_EVENT_INSTANT1("test_latency", "timing1_begin", "id", 3);
-// [Thread 2 tracing code]
-// TRACE_EVENT_INSTANT1("test_latency", "timing1_end", "id", 3);
-//
-// Step 2: associate these custom begin/end pairs.
-// Query begin(Query(EVENT_NAME) == Query::String("timing1_begin"));
-// Query end(Query(EVENT_NAME) == Query::String("timing1_end"));
-// Query match(Query(EVENT_ARG, "id") == Query(OTHER_ARG, "id"));
-// analyzer.AssociateEvents(begin, end, match);
-//
-// Step 3: search for "timing1_begin" events with existing other event.
-// Query q = (Query(EVENT_NAME) == Query::String("timing1_begin") &&
-// Query(EVENT_HAS_OTHER));
-// analyzer.FindEvents(q, &events);
-//
-// Step 4: analyze events, such as checking durations.
-// for (size_t i = 0; i < events.size(); ++i) {
-// double duration;
-// EXPECT_TRUE(events[i].GetAbsTimeToOtherEvent(&duration));
-// EXPECT_LT(duration, 1000000.0/60.0); // expect less than 1/60 second.
-// }
-//
-// There are two helper functions, Start(category_filter_string) and Stop(), for
-// facilitating the collection of process-local traces and building a
-// TraceAnalyzer from them. A typical test, that uses the helper functions,
-// looks like the following:
-//
-// TEST_F(...) {
-// Start("*");
-// [Invoke the functions you want to test their traces]
-// auto analyzer = Stop();
-//
-// [Use the analyzer to verify produced traces, as explained above]
-// }
-//
-// Note: The Stop() function needs a SingleThreadTaskRunner.
-
-#ifndef BASE_TEST_TRACE_EVENT_ANALYZER_H_
-#define BASE_TEST_TRACE_EVENT_ANALYZER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-class Value;
-}
-
-namespace trace_analyzer {
-class QueryNode;
-
-// trace_analyzer::TraceEvent is a more convenient form of the
-// base::trace_event::TraceEvent class to make tracing-based tests easier to
-// write.
-struct TraceEvent {
- // ProcessThreadID contains a Process ID and Thread ID.
- struct ProcessThreadID {
- ProcessThreadID() : process_id(0), thread_id(0) {}
- ProcessThreadID(int process_id, int thread_id)
- : process_id(process_id), thread_id(thread_id) {}
- bool operator< (const ProcessThreadID& rhs) const {
- if (process_id != rhs.process_id)
- return process_id < rhs.process_id;
- return thread_id < rhs.thread_id;
- }
- int process_id;
- int thread_id;
- };
-
- TraceEvent();
- TraceEvent(TraceEvent&& other);
- ~TraceEvent();
-
- bool SetFromJSON(const base::Value* event_value) WARN_UNUSED_RESULT;
-
- bool operator< (const TraceEvent& rhs) const {
- return timestamp < rhs.timestamp;
- }
-
- TraceEvent& operator=(TraceEvent&& rhs);
-
- bool has_other_event() const { return other_event; }
-
- // Returns absolute duration in microseconds between this event and other
- // event. Must have already verified that other_event exists by
- // Query(EVENT_HAS_OTHER) or by calling has_other_event().
- double GetAbsTimeToOtherEvent() const;
-
- // Return the argument value if it exists and it is a string.
- bool GetArgAsString(const std::string& name, std::string* arg) const;
- // Return the argument value if it exists and it is a number.
- bool GetArgAsNumber(const std::string& name, double* arg) const;
- // Return the argument value if it exists.
- bool GetArgAsValue(const std::string& name,
- std::unique_ptr<base::Value>* arg) const;
-
- // Check if argument exists and is string.
- bool HasStringArg(const std::string& name) const;
- // Check if argument exists and is number (double, int or bool).
- bool HasNumberArg(const std::string& name) const;
- // Check if argument exists.
- bool HasArg(const std::string& name) const;
-
- // Get known existing arguments as specific types.
- // Useful when you have already queried the argument with
- // Query(HAS_NUMBER_ARG) or Query(HAS_STRING_ARG).
- std::string GetKnownArgAsString(const std::string& name) const;
- double GetKnownArgAsDouble(const std::string& name) const;
- int GetKnownArgAsInt(const std::string& name) const;
- bool GetKnownArgAsBool(const std::string& name) const;
- std::unique_ptr<base::Value> GetKnownArgAsValue(
- const std::string& name) const;
-
- // Process ID and Thread ID.
- ProcessThreadID thread;
-
- // Time since epoch in microseconds.
- // Stored as double to match its JSON representation.
- double timestamp;
- double duration;
- char phase;
- std::string category;
- std::string name;
- std::string id;
- double thread_duration = 0.0;
- double thread_timestamp = 0.0;
- std::string scope;
- std::string bind_id;
- bool flow_out = false;
- bool flow_in = false;
- std::string global_id2;
- std::string local_id2;
-
- // All numbers and bool values from TraceEvent args are cast to double.
- // bool becomes 1.0 (true) or 0.0 (false).
- std::map<std::string, double> arg_numbers;
- std::map<std::string, std::string> arg_strings;
- std::map<std::string, std::unique_ptr<base::Value>> arg_values;
-
- // The other event associated with this event (or NULL).
- const TraceEvent* other_event;
-
- // A back-link for |other_event|. That is, if other_event is not null, then
- // |event->other_event->prev_event == event| is always true.
- const TraceEvent* prev_event;
-};
-
-typedef std::vector<const TraceEvent*> TraceEventVector;
-
-class Query {
- public:
- Query(const Query& query);
-
- ~Query();
-
- ////////////////////////////////////////////////////////////////
- // Query literal values
-
- // Compare with the given string.
- static Query String(const std::string& str);
-
- // Compare with the given number.
- static Query Double(double num);
- static Query Int(int32_t num);
- static Query Uint(uint32_t num);
-
- // Compare with the given bool.
- static Query Bool(bool boolean);
-
- // Compare with the given phase.
- static Query Phase(char phase);
-
- // Compare with the given string pattern. Only works with == and != operators.
- // Example: Query(EVENT_NAME) == Query::Pattern("MyEvent*")
- static Query Pattern(const std::string& pattern);
-
- ////////////////////////////////////////////////////////////////
- // Query event members
-
- static Query EventPid() { return Query(EVENT_PID); }
-
- static Query EventTid() { return Query(EVENT_TID); }
-
- // Return the timestamp of the event in microseconds since epoch.
- static Query EventTime() { return Query(EVENT_TIME); }
-
- // Return the absolute time between event and other event in microseconds.
- // Only works if Query::EventHasOther() == true.
- static Query EventDuration() { return Query(EVENT_DURATION); }
-
- // Return the duration of a COMPLETE event.
- static Query EventCompleteDuration() {
- return Query(EVENT_COMPLETE_DURATION);
- }
-
- static Query EventPhase() { return Query(EVENT_PHASE); }
-
- static Query EventCategory() { return Query(EVENT_CATEGORY); }
-
- static Query EventName() { return Query(EVENT_NAME); }
-
- static Query EventId() { return Query(EVENT_ID); }
-
- static Query EventPidIs(int process_id) {
- return Query(EVENT_PID) == Query::Int(process_id);
- }
-
- static Query EventTidIs(int thread_id) {
- return Query(EVENT_TID) == Query::Int(thread_id);
- }
-
- static Query EventThreadIs(const TraceEvent::ProcessThreadID& thread) {
- return EventPidIs(thread.process_id) && EventTidIs(thread.thread_id);
- }
-
- static Query EventTimeIs(double timestamp) {
- return Query(EVENT_TIME) == Query::Double(timestamp);
- }
-
- static Query EventDurationIs(double duration) {
- return Query(EVENT_DURATION) == Query::Double(duration);
- }
-
- static Query EventPhaseIs(char phase) {
- return Query(EVENT_PHASE) == Query::Phase(phase);
- }
-
- static Query EventCategoryIs(const std::string& category) {
- return Query(EVENT_CATEGORY) == Query::String(category);
- }
-
- static Query EventNameIs(const std::string& name) {
- return Query(EVENT_NAME) == Query::String(name);
- }
-
- static Query EventIdIs(const std::string& id) {
- return Query(EVENT_ID) == Query::String(id);
- }
-
- // Evaluates to true if arg exists and is a string.
- static Query EventHasStringArg(const std::string& arg_name) {
- return Query(EVENT_HAS_STRING_ARG, arg_name);
- }
-
- // Evaluates to true if arg exists and is a number.
- // Number arguments include types double, int and bool.
- static Query EventHasNumberArg(const std::string& arg_name) {
- return Query(EVENT_HAS_NUMBER_ARG, arg_name);
- }
-
- // Evaluates to arg value (string or number).
- static Query EventArg(const std::string& arg_name) {
- return Query(EVENT_ARG, arg_name);
- }
-
- // Return true if associated event exists.
- static Query EventHasOther() { return Query(EVENT_HAS_OTHER); }
-
- // Access the associated other_event's members:
-
- static Query OtherPid() { return Query(OTHER_PID); }
-
- static Query OtherTid() { return Query(OTHER_TID); }
-
- static Query OtherTime() { return Query(OTHER_TIME); }
-
- static Query OtherPhase() { return Query(OTHER_PHASE); }
-
- static Query OtherCategory() { return Query(OTHER_CATEGORY); }
-
- static Query OtherName() { return Query(OTHER_NAME); }
-
- static Query OtherId() { return Query(OTHER_ID); }
-
- static Query OtherPidIs(int process_id) {
- return Query(OTHER_PID) == Query::Int(process_id);
- }
-
- static Query OtherTidIs(int thread_id) {
- return Query(OTHER_TID) == Query::Int(thread_id);
- }
-
- static Query OtherThreadIs(const TraceEvent::ProcessThreadID& thread) {
- return OtherPidIs(thread.process_id) && OtherTidIs(thread.thread_id);
- }
-
- static Query OtherTimeIs(double timestamp) {
- return Query(OTHER_TIME) == Query::Double(timestamp);
- }
-
- static Query OtherPhaseIs(char phase) {
- return Query(OTHER_PHASE) == Query::Phase(phase);
- }
-
- static Query OtherCategoryIs(const std::string& category) {
- return Query(OTHER_CATEGORY) == Query::String(category);
- }
-
- static Query OtherNameIs(const std::string& name) {
- return Query(OTHER_NAME) == Query::String(name);
- }
-
- static Query OtherIdIs(const std::string& id) {
- return Query(OTHER_ID) == Query::String(id);
- }
-
- // Evaluates to true if arg exists and is a string.
- static Query OtherHasStringArg(const std::string& arg_name) {
- return Query(OTHER_HAS_STRING_ARG, arg_name);
- }
-
- // Evaluates to true if arg exists and is a number.
- // Number arguments include types double, int and bool.
- static Query OtherHasNumberArg(const std::string& arg_name) {
- return Query(OTHER_HAS_NUMBER_ARG, arg_name);
- }
-
- // Evaluates to arg value (string or number).
- static Query OtherArg(const std::string& arg_name) {
- return Query(OTHER_ARG, arg_name);
- }
-
- // Access the associated prev_event's members:
-
- static Query PrevPid() { return Query(PREV_PID); }
-
- static Query PrevTid() { return Query(PREV_TID); }
-
- static Query PrevTime() { return Query(PREV_TIME); }
-
- static Query PrevPhase() { return Query(PREV_PHASE); }
-
- static Query PrevCategory() { return Query(PREV_CATEGORY); }
-
- static Query PrevName() { return Query(PREV_NAME); }
-
- static Query PrevId() { return Query(PREV_ID); }
-
- static Query PrevPidIs(int process_id) {
- return Query(PREV_PID) == Query::Int(process_id);
- }
-
- static Query PrevTidIs(int thread_id) {
- return Query(PREV_TID) == Query::Int(thread_id);
- }
-
- static Query PrevThreadIs(const TraceEvent::ProcessThreadID& thread) {
- return PrevPidIs(thread.process_id) && PrevTidIs(thread.thread_id);
- }
-
- static Query PrevTimeIs(double timestamp) {
- return Query(PREV_TIME) == Query::Double(timestamp);
- }
-
- static Query PrevPhaseIs(char phase) {
- return Query(PREV_PHASE) == Query::Phase(phase);
- }
-
- static Query PrevCategoryIs(const std::string& category) {
- return Query(PREV_CATEGORY) == Query::String(category);
- }
-
- static Query PrevNameIs(const std::string& name) {
- return Query(PREV_NAME) == Query::String(name);
- }
-
- static Query PrevIdIs(const std::string& id) {
- return Query(PREV_ID) == Query::String(id);
- }
-
- // Evaluates to true if arg exists and is a string.
- static Query PrevHasStringArg(const std::string& arg_name) {
- return Query(PREV_HAS_STRING_ARG, arg_name);
- }
-
- // Evaluates to true if arg exists and is a number.
- // Number arguments include types double, int and bool.
- static Query PrevHasNumberArg(const std::string& arg_name) {
- return Query(PREV_HAS_NUMBER_ARG, arg_name);
- }
-
- // Evaluates to arg value (string or number).
- static Query PrevArg(const std::string& arg_name) {
- return Query(PREV_ARG, arg_name);
- }
-
- ////////////////////////////////////////////////////////////////
- // Common queries:
-
- // Find BEGIN events that have a corresponding END event.
- static Query MatchBeginWithEnd() {
- return (Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_BEGIN)) &&
- Query(EVENT_HAS_OTHER);
- }
-
- // Find COMPLETE events.
- static Query MatchComplete() {
- return (Query(EVENT_PHASE) == Query::Phase(TRACE_EVENT_PHASE_COMPLETE));
- }
-
- // Find ASYNC_BEGIN events that have a corresponding ASYNC_END event.
- static Query MatchAsyncBeginWithNext() {
- return (Query(EVENT_PHASE) ==
- Query::Phase(TRACE_EVENT_PHASE_ASYNC_BEGIN)) &&
- Query(EVENT_HAS_OTHER);
- }
-
- // Find BEGIN events of given |name| which also have associated END events.
- static Query MatchBeginName(const std::string& name) {
- return (Query(EVENT_NAME) == Query(name)) && MatchBeginWithEnd();
- }
-
- // Find COMPLETE events of given |name|.
- static Query MatchCompleteName(const std::string& name) {
- return (Query(EVENT_NAME) == Query(name)) && MatchComplete();
- }
-
- // Match given Process ID and Thread ID.
- static Query MatchThread(const TraceEvent::ProcessThreadID& thread) {
- return (Query(EVENT_PID) == Query::Int(thread.process_id)) &&
- (Query(EVENT_TID) == Query::Int(thread.thread_id));
- }
-
- // Match event pair that spans multiple threads.
- static Query MatchCrossThread() {
- return (Query(EVENT_PID) != Query(OTHER_PID)) ||
- (Query(EVENT_TID) != Query(OTHER_TID));
- }
-
- ////////////////////////////////////////////////////////////////
- // Operators:
-
- // Boolean operators:
- Query operator==(const Query& rhs) const;
- Query operator!=(const Query& rhs) const;
- Query operator< (const Query& rhs) const;
- Query operator<=(const Query& rhs) const;
- Query operator> (const Query& rhs) const;
- Query operator>=(const Query& rhs) const;
- Query operator&&(const Query& rhs) const;
- Query operator||(const Query& rhs) const;
- Query operator!() const;
-
- // Arithmetic operators:
- // Following operators are applied to double arguments:
- Query operator+(const Query& rhs) const;
- Query operator-(const Query& rhs) const;
- Query operator*(const Query& rhs) const;
- Query operator/(const Query& rhs) const;
- Query operator-() const;
- // Mod operates on int64_t args (doubles are casted to int64_t beforehand):
- Query operator%(const Query& rhs) const;
-
- // Return true if the given event matches this query tree.
- // This is a recursive method that walks the query tree.
- bool Evaluate(const TraceEvent& event) const;
-
- enum TraceEventMember {
- EVENT_INVALID,
- EVENT_PID,
- EVENT_TID,
- EVENT_TIME,
- EVENT_DURATION,
- EVENT_COMPLETE_DURATION,
- EVENT_PHASE,
- EVENT_CATEGORY,
- EVENT_NAME,
- EVENT_ID,
- EVENT_HAS_STRING_ARG,
- EVENT_HAS_NUMBER_ARG,
- EVENT_ARG,
- EVENT_HAS_OTHER,
- EVENT_HAS_PREV,
-
- OTHER_PID,
- OTHER_TID,
- OTHER_TIME,
- OTHER_PHASE,
- OTHER_CATEGORY,
- OTHER_NAME,
- OTHER_ID,
- OTHER_HAS_STRING_ARG,
- OTHER_HAS_NUMBER_ARG,
- OTHER_ARG,
-
- PREV_PID,
- PREV_TID,
- PREV_TIME,
- PREV_PHASE,
- PREV_CATEGORY,
- PREV_NAME,
- PREV_ID,
- PREV_HAS_STRING_ARG,
- PREV_HAS_NUMBER_ARG,
- PREV_ARG,
-
- OTHER_FIRST_MEMBER = OTHER_PID,
- OTHER_LAST_MEMBER = OTHER_ARG,
-
- PREV_FIRST_MEMBER = PREV_PID,
- PREV_LAST_MEMBER = PREV_ARG,
- };
-
- enum Operator {
- OP_INVALID,
- // Boolean operators:
- OP_EQ,
- OP_NE,
- OP_LT,
- OP_LE,
- OP_GT,
- OP_GE,
- OP_AND,
- OP_OR,
- OP_NOT,
- // Arithmetic operators:
- OP_ADD,
- OP_SUB,
- OP_MUL,
- OP_DIV,
- OP_MOD,
- OP_NEGATE
- };
-
- enum QueryType {
- QUERY_BOOLEAN_OPERATOR,
- QUERY_ARITHMETIC_OPERATOR,
- QUERY_EVENT_MEMBER,
- QUERY_NUMBER,
- QUERY_STRING
- };
-
- // Compare with the given member.
- explicit Query(TraceEventMember member);
-
- // Compare with the given member argument value.
- Query(TraceEventMember member, const std::string& arg_name);
-
- // Compare with the given string.
- explicit Query(const std::string& str);
-
- // Compare with the given number.
- explicit Query(double num);
-
- // Construct a boolean Query that returns (left <binary_op> right).
- Query(const Query& left, const Query& right, Operator binary_op);
-
- // Construct a boolean Query that returns (<binary_op> left).
- Query(const Query& left, Operator unary_op);
-
- // Try to compare left_ against right_ based on operator_.
- // If either left or right does not convert to double, false is returned.
- // Otherwise, true is returned and |result| is set to the comparison result.
- bool CompareAsDouble(const TraceEvent& event, bool* result) const;
-
- // Try to compare left_ against right_ based on operator_.
- // If either left or right does not convert to string, false is returned.
- // Otherwise, true is returned and |result| is set to the comparison result.
- bool CompareAsString(const TraceEvent& event, bool* result) const;
-
- // Attempt to convert this Query to a double. On success, true is returned
- // and the double value is stored in |num|.
- bool GetAsDouble(const TraceEvent& event, double* num) const;
-
- // Attempt to convert this Query to a string. On success, true is returned
- // and the string value is stored in |str|.
- bool GetAsString(const TraceEvent& event, std::string* str) const;
-
- // Evaluate this Query as an arithmetic operator on left_ and right_.
- bool EvaluateArithmeticOperator(const TraceEvent& event,
- double* num) const;
-
- // For QUERY_EVENT_MEMBER Query: attempt to get the double value of the Query.
- bool GetMemberValueAsDouble(const TraceEvent& event, double* num) const;
-
- // For QUERY_EVENT_MEMBER Query: attempt to get the string value of the Query.
- bool GetMemberValueAsString(const TraceEvent& event, std::string* num) const;
-
- // Does this Query represent a value?
- bool is_value() const { return type_ != QUERY_BOOLEAN_OPERATOR; }
-
- bool is_unary_operator() const {
- return operator_ == OP_NOT || operator_ == OP_NEGATE;
- }
-
- bool is_comparison_operator() const {
- return operator_ != OP_INVALID && operator_ < OP_AND;
- }
-
- static const TraceEvent* SelectTargetEvent(const TraceEvent* ev,
- TraceEventMember member);
-
- const Query& left() const;
- const Query& right() const;
-
- private:
- QueryType type_;
- Operator operator_;
- scoped_refptr<QueryNode> left_;
- scoped_refptr<QueryNode> right_;
- TraceEventMember member_;
- double number_;
- std::string string_;
- bool is_pattern_;
-};
-
-// Implementation detail:
-// QueryNode allows Query to store a ref-counted query tree.
-class QueryNode : public base::RefCounted<QueryNode> {
- public:
- explicit QueryNode(const Query& query);
- const Query& query() const { return query_; }
-
- private:
- friend class base::RefCounted<QueryNode>;
- ~QueryNode();
-
- Query query_;
-};
-
-// TraceAnalyzer helps tests search for trace events.
-class TraceAnalyzer {
- public:
- ~TraceAnalyzer();
-
- // Use trace events from JSON string generated by tracing API.
- // Returns non-NULL if the JSON is successfully parsed.
- static TraceAnalyzer* Create(const std::string& json_events)
- WARN_UNUSED_RESULT;
-
- void SetIgnoreMetadataEvents(bool ignore) {
- ignore_metadata_events_ = ignore;
- }
-
- // Associate BEGIN and END events with each other. This allows Query(OTHER_*)
- // to access the associated event and enables Query(EVENT_DURATION).
- // An end event will match the most recent begin event with the same name,
- // category, process ID and thread ID. This matches what is shown in
- // about:tracing. After association, the BEGIN event will point to the
- // matching END event, but the END event will not point to the BEGIN event.
- void AssociateBeginEndEvents();
-
- // Associate ASYNC_BEGIN, ASYNC_STEP and ASYNC_END events with each other.
- // An ASYNC_END event will match the most recent ASYNC_BEGIN or ASYNC_STEP
- // event with the same name, category, and ID. This creates a singly linked
- // list of ASYNC_BEGIN->ASYNC_STEP...->ASYNC_END.
- // |match_pid| - If true, will only match async events which are running
- // under the same process ID, otherwise will allow linking
- // async events from different processes.
- void AssociateAsyncBeginEndEvents(bool match_pid = true);
-
- // AssociateEvents can be used to customize event associations by setting the
- // other_event member of TraceEvent. This should be used to associate two
- // INSTANT events.
- //
- // The assumptions are:
- // - |first| events occur before |second| events.
- // - the closest matching |second| event is the correct match.
- //
- // |first| - Eligible |first| events match this query.
- // |second| - Eligible |second| events match this query.
- // |match| - This query is run on the |first| event. The OTHER_* EventMember
- // queries will point to an eligible |second| event. The query
- // should evaluate to true if the |first|/|second| pair is a match.
- //
- // When a match is found, the pair will be associated by having the first
- // event's other_event member point to the other. AssociateEvents does not
- // clear previous associations, so it is possible to associate multiple pairs
- // of events by calling AssociateEvents more than once with different queries.
- //
- // NOTE: AssociateEvents will overwrite existing other_event associations if
- // the queries pass for events that already had a previous association.
- //
- // After calling any Find* method, it is not allowed to call AssociateEvents
- // again.
- void AssociateEvents(const Query& first,
- const Query& second,
- const Query& match);
-
- // For each event, copy its arguments to the other_event argument map. If
- // argument name already exists, it will not be overwritten.
- void MergeAssociatedEventArgs();
-
- // Find all events that match query and replace output vector.
- size_t FindEvents(const Query& query, TraceEventVector* output);
-
- // Find first event that matches query or NULL if not found.
- const TraceEvent* FindFirstOf(const Query& query);
-
- // Find last event that matches query or NULL if not found.
- const TraceEvent* FindLastOf(const Query& query);
-
- const std::string& GetThreadName(const TraceEvent::ProcessThreadID& thread);
-
- private:
- TraceAnalyzer();
-
- bool SetEvents(const std::string& json_events) WARN_UNUSED_RESULT;
-
- // Read metadata (thread names, etc) from events.
- void ParseMetadata();
-
- std::map<TraceEvent::ProcessThreadID, std::string> thread_names_;
- std::vector<TraceEvent> raw_events_;
- bool ignore_metadata_events_;
- bool allow_association_changes_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceAnalyzer);
-};
-
-// Utility functions for collecting process-local traces and creating a
-// |TraceAnalyzer| from the result. Please see comments in trace_config.h to
-// understand how the |category_filter_string| works. Use "*" to enable all
-// default categories.
-void Start(const std::string& category_filter_string);
-std::unique_ptr<TraceAnalyzer> Stop();
-
-// Utility functions for TraceEventVector.
-
-struct RateStats {
- double min_us;
- double max_us;
- double mean_us;
- double standard_deviation_us;
-};
-
-struct RateStatsOptions {
- RateStatsOptions() : trim_min(0u), trim_max(0u) {}
- // After the times between events are sorted, the number of specified elements
- // will be trimmed before calculating the RateStats. This is useful in cases
- // where extreme outliers are tolerable and should not skew the overall
- // average.
- size_t trim_min; // Trim this many minimum times.
- size_t trim_max; // Trim this many maximum times.
-};
-
-// Calculate min/max/mean and standard deviation from the times between
-// adjacent events.
-bool GetRateStats(const TraceEventVector& events,
- RateStats* stats,
- const RateStatsOptions* options);
-
-// Starting from |position|, find the first event that matches |query|.
-// Returns true if found, false otherwise.
-bool FindFirstOf(const TraceEventVector& events,
- const Query& query,
- size_t position,
- size_t* return_index);
-
-// Starting from |position|, find the last event that matches |query|.
-// Returns true if found, false otherwise.
-bool FindLastOf(const TraceEventVector& events,
- const Query& query,
- size_t position,
- size_t* return_index);
-
-// Find the closest events to |position| in time that match |query|.
-// return_second_closest may be NULL. Closeness is determined by comparing
-// with the event timestamp.
-// Returns true if found, false otherwise. If both return parameters are
-// requested, both must be found for a successful result.
-bool FindClosest(const TraceEventVector& events,
- const Query& query,
- size_t position,
- size_t* return_closest,
- size_t* return_second_closest);
-
-// Count matches, inclusive of |begin_position|, exclusive of |end_position|.
-size_t CountMatches(const TraceEventVector& events,
- const Query& query,
- size_t begin_position,
- size_t end_position);
-
-// Count all matches.
-static inline size_t CountMatches(const TraceEventVector& events,
- const Query& query) {
- return CountMatches(events, query, 0u, events.size());
-}
-
-} // namespace trace_analyzer
-
-#endif // BASE_TEST_TRACE_EVENT_ANALYZER_H_
diff --git a/base/test/trace_event_analyzer_unittest.cc b/base/test/trace_event_analyzer_unittest.cc
deleted file mode 100644
index 6461b0fe14..0000000000
--- a/base/test/trace_event_analyzer_unittest.cc
+++ /dev/null
@@ -1,961 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/trace_event_analyzer.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/trace_event/trace_buffer.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace trace_analyzer {
-
-namespace {
-
-class TraceEventAnalyzerTest : public testing::Test {
- public:
- void ManualSetUp();
- void OnTraceDataCollected(
- base::WaitableEvent* flush_complete_event,
- const scoped_refptr<base::RefCountedString>& json_events_str,
- bool has_more_events);
- void BeginTracing();
- void EndTracing();
-
- base::trace_event::TraceResultBuffer::SimpleOutput output_;
- base::trace_event::TraceResultBuffer buffer_;
-};
-
-void TraceEventAnalyzerTest::ManualSetUp() {
- ASSERT_TRUE(base::trace_event::TraceLog::GetInstance());
- buffer_.SetOutputCallback(output_.GetCallback());
- output_.json_output.clear();
-}
-
-void TraceEventAnalyzerTest::OnTraceDataCollected(
- base::WaitableEvent* flush_complete_event,
- const scoped_refptr<base::RefCountedString>& json_events_str,
- bool has_more_events) {
- buffer_.AddFragment(json_events_str->data());
- if (!has_more_events)
- flush_complete_event->Signal();
-}
-
-void TraceEventAnalyzerTest::BeginTracing() {
- output_.json_output.clear();
- buffer_.Start();
- base::trace_event::TraceLog::GetInstance()->SetEnabled(
- base::trace_event::TraceConfig("*", ""),
- base::trace_event::TraceLog::RECORDING_MODE);
-}
-
-void TraceEventAnalyzerTest::EndTracing() {
- base::trace_event::TraceLog::GetInstance()->SetDisabled();
- base::WaitableEvent flush_complete_event(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::trace_event::TraceLog::GetInstance()->Flush(
- base::Bind(&TraceEventAnalyzerTest::OnTraceDataCollected,
- base::Unretained(this),
- base::Unretained(&flush_complete_event)));
- flush_complete_event.Wait();
- buffer_.Finish();
-}
-
-} // namespace
-
-TEST_F(TraceEventAnalyzerTest, NoEvents) {
- ManualSetUp();
-
- // Create an empty JSON event string:
- buffer_.Start();
- buffer_.Finish();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
-
- // Search for all events and verify that nothing is returned.
- TraceEventVector found;
- analyzer->FindEvents(Query::Bool(true), &found);
- EXPECT_EQ(0u, found.size());
-}
-
-TEST_F(TraceEventAnalyzerTest, TraceEvent) {
- ManualSetUp();
-
- int int_num = 2;
- double double_num = 3.5;
- const char str[] = "the string";
-
- TraceEvent event;
- event.arg_numbers["false"] = 0.0;
- event.arg_numbers["true"] = 1.0;
- event.arg_numbers["int"] = static_cast<double>(int_num);
- event.arg_numbers["double"] = double_num;
- event.arg_strings["string"] = str;
- event.arg_values["dict"] = WrapUnique(new base::DictionaryValue());
-
- ASSERT_TRUE(event.HasNumberArg("false"));
- ASSERT_TRUE(event.HasNumberArg("true"));
- ASSERT_TRUE(event.HasNumberArg("int"));
- ASSERT_TRUE(event.HasNumberArg("double"));
- ASSERT_TRUE(event.HasStringArg("string"));
- ASSERT_FALSE(event.HasNumberArg("notfound"));
- ASSERT_FALSE(event.HasStringArg("notfound"));
- ASSERT_TRUE(event.HasArg("dict"));
- ASSERT_FALSE(event.HasArg("notfound"));
-
- EXPECT_FALSE(event.GetKnownArgAsBool("false"));
- EXPECT_TRUE(event.GetKnownArgAsBool("true"));
- EXPECT_EQ(int_num, event.GetKnownArgAsInt("int"));
- EXPECT_EQ(double_num, event.GetKnownArgAsDouble("double"));
- EXPECT_STREQ(str, event.GetKnownArgAsString("string").c_str());
-
- std::unique_ptr<base::Value> arg;
- EXPECT_TRUE(event.GetArgAsValue("dict", &arg));
- EXPECT_EQ(base::Value::Type::DICTIONARY, arg->type());
-}
-
-TEST_F(TraceEventAnalyzerTest, QueryEventMember) {
- ManualSetUp();
-
- TraceEvent event;
- event.thread.process_id = 3;
- event.thread.thread_id = 4;
- event.timestamp = 1.5;
- event.phase = TRACE_EVENT_PHASE_BEGIN;
- event.category = "category";
- event.name = "name";
- event.id = "1";
- event.arg_numbers["num"] = 7.0;
- event.arg_strings["str"] = "the string";
-
- // Other event with all different members:
- TraceEvent other;
- other.thread.process_id = 5;
- other.thread.thread_id = 6;
- other.timestamp = 2.5;
- other.phase = TRACE_EVENT_PHASE_END;
- other.category = "category2";
- other.name = "name2";
- other.id = "2";
- other.arg_numbers["num2"] = 8.0;
- other.arg_strings["str2"] = "the string 2";
-
- event.other_event = &other;
- ASSERT_TRUE(event.has_other_event());
- double duration = event.GetAbsTimeToOtherEvent();
-
- Query event_pid = Query::EventPidIs(event.thread.process_id);
- Query event_tid = Query::EventTidIs(event.thread.thread_id);
- Query event_time = Query::EventTimeIs(event.timestamp);
- Query event_duration = Query::EventDurationIs(duration);
- Query event_phase = Query::EventPhaseIs(event.phase);
- Query event_category = Query::EventCategoryIs(event.category);
- Query event_name = Query::EventNameIs(event.name);
- Query event_id = Query::EventIdIs(event.id);
- Query event_has_arg1 = Query::EventHasNumberArg("num");
- Query event_has_arg2 = Query::EventHasStringArg("str");
- Query event_arg1 =
- (Query::EventArg("num") == Query::Double(event.arg_numbers["num"]));
- Query event_arg2 =
- (Query::EventArg("str") == Query::String(event.arg_strings["str"]));
- Query event_has_other = Query::EventHasOther();
- Query other_pid = Query::OtherPidIs(other.thread.process_id);
- Query other_tid = Query::OtherTidIs(other.thread.thread_id);
- Query other_time = Query::OtherTimeIs(other.timestamp);
- Query other_phase = Query::OtherPhaseIs(other.phase);
- Query other_category = Query::OtherCategoryIs(other.category);
- Query other_name = Query::OtherNameIs(other.name);
- Query other_id = Query::OtherIdIs(other.id);
- Query other_has_arg1 = Query::OtherHasNumberArg("num2");
- Query other_has_arg2 = Query::OtherHasStringArg("str2");
- Query other_arg1 =
- (Query::OtherArg("num2") == Query::Double(other.arg_numbers["num2"]));
- Query other_arg2 =
- (Query::OtherArg("str2") == Query::String(other.arg_strings["str2"]));
-
- EXPECT_TRUE(event_pid.Evaluate(event));
- EXPECT_TRUE(event_tid.Evaluate(event));
- EXPECT_TRUE(event_time.Evaluate(event));
- EXPECT_TRUE(event_duration.Evaluate(event));
- EXPECT_TRUE(event_phase.Evaluate(event));
- EXPECT_TRUE(event_category.Evaluate(event));
- EXPECT_TRUE(event_name.Evaluate(event));
- EXPECT_TRUE(event_id.Evaluate(event));
- EXPECT_TRUE(event_has_arg1.Evaluate(event));
- EXPECT_TRUE(event_has_arg2.Evaluate(event));
- EXPECT_TRUE(event_arg1.Evaluate(event));
- EXPECT_TRUE(event_arg2.Evaluate(event));
- EXPECT_TRUE(event_has_other.Evaluate(event));
- EXPECT_TRUE(other_pid.Evaluate(event));
- EXPECT_TRUE(other_tid.Evaluate(event));
- EXPECT_TRUE(other_time.Evaluate(event));
- EXPECT_TRUE(other_phase.Evaluate(event));
- EXPECT_TRUE(other_category.Evaluate(event));
- EXPECT_TRUE(other_name.Evaluate(event));
- EXPECT_TRUE(other_id.Evaluate(event));
- EXPECT_TRUE(other_has_arg1.Evaluate(event));
- EXPECT_TRUE(other_has_arg2.Evaluate(event));
- EXPECT_TRUE(other_arg1.Evaluate(event));
- EXPECT_TRUE(other_arg2.Evaluate(event));
-
- // Evaluate event queries against other to verify the queries fail when the
- // event members are wrong.
- EXPECT_FALSE(event_pid.Evaluate(other));
- EXPECT_FALSE(event_tid.Evaluate(other));
- EXPECT_FALSE(event_time.Evaluate(other));
- EXPECT_FALSE(event_duration.Evaluate(other));
- EXPECT_FALSE(event_phase.Evaluate(other));
- EXPECT_FALSE(event_category.Evaluate(other));
- EXPECT_FALSE(event_name.Evaluate(other));
- EXPECT_FALSE(event_id.Evaluate(other));
- EXPECT_FALSE(event_has_arg1.Evaluate(other));
- EXPECT_FALSE(event_has_arg2.Evaluate(other));
- EXPECT_FALSE(event_arg1.Evaluate(other));
- EXPECT_FALSE(event_arg2.Evaluate(other));
- EXPECT_FALSE(event_has_other.Evaluate(other));
-}
-
-TEST_F(TraceEventAnalyzerTest, BooleanOperators) {
- ManualSetUp();
-
- BeginTracing();
- {
- TRACE_EVENT_INSTANT1("cat1", "name1", TRACE_EVENT_SCOPE_THREAD, "num", 1);
- TRACE_EVENT_INSTANT1("cat1", "name2", TRACE_EVENT_SCOPE_THREAD, "num", 2);
- TRACE_EVENT_INSTANT1("cat2", "name3", TRACE_EVENT_SCOPE_THREAD, "num", 3);
- TRACE_EVENT_INSTANT1("cat2", "name4", TRACE_EVENT_SCOPE_THREAD, "num", 4);
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer);
- analyzer->SetIgnoreMetadataEvents(true);
-
- TraceEventVector found;
-
- // ==
-
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat1"), &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name2", found[1]->name.c_str());
-
- analyzer->FindEvents(Query::EventArg("num") == Query::Int(2), &found);
- ASSERT_EQ(1u, found.size());
- EXPECT_STREQ("name2", found[0]->name.c_str());
-
- // !=
-
- analyzer->FindEvents(Query::EventCategory() != Query::String("cat1"), &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name3", found[0]->name.c_str());
- EXPECT_STREQ("name4", found[1]->name.c_str());
-
- analyzer->FindEvents(Query::EventArg("num") != Query::Int(2), &found);
- ASSERT_EQ(3u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name3", found[1]->name.c_str());
- EXPECT_STREQ("name4", found[2]->name.c_str());
-
- // <
- analyzer->FindEvents(Query::EventArg("num") < Query::Int(2), &found);
- ASSERT_EQ(1u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
-
- // <=
- analyzer->FindEvents(Query::EventArg("num") <= Query::Int(2), &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name2", found[1]->name.c_str());
-
- // >
- analyzer->FindEvents(Query::EventArg("num") > Query::Int(3), &found);
- ASSERT_EQ(1u, found.size());
- EXPECT_STREQ("name4", found[0]->name.c_str());
-
- // >=
- analyzer->FindEvents(Query::EventArg("num") >= Query::Int(4), &found);
- ASSERT_EQ(1u, found.size());
- EXPECT_STREQ("name4", found[0]->name.c_str());
-
- // &&
- analyzer->FindEvents(Query::EventName() != Query::String("name1") &&
- Query::EventArg("num") < Query::Int(3), &found);
- ASSERT_EQ(1u, found.size());
- EXPECT_STREQ("name2", found[0]->name.c_str());
-
- // ||
- analyzer->FindEvents(Query::EventName() == Query::String("name1") ||
- Query::EventArg("num") == Query::Int(3), &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name3", found[1]->name.c_str());
-
- // !
- analyzer->FindEvents(!(Query::EventName() == Query::String("name1") ||
- Query::EventArg("num") == Query::Int(3)), &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name2", found[0]->name.c_str());
- EXPECT_STREQ("name4", found[1]->name.c_str());
-}
-
-TEST_F(TraceEventAnalyzerTest, ArithmeticOperators) {
- ManualSetUp();
-
- BeginTracing();
- {
- // These events are searched for:
- TRACE_EVENT_INSTANT2("cat1", "math1", TRACE_EVENT_SCOPE_THREAD,
- "a", 10, "b", 5);
- TRACE_EVENT_INSTANT2("cat1", "math2", TRACE_EVENT_SCOPE_THREAD,
- "a", 10, "b", 10);
- // Extra events that never match, for noise:
- TRACE_EVENT_INSTANT2("noise", "math3", TRACE_EVENT_SCOPE_THREAD,
- "a", 1, "b", 3);
- TRACE_EVENT_INSTANT2("noise", "math4", TRACE_EVENT_SCOPE_THREAD,
- "c", 10, "d", 5);
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
-
- TraceEventVector found;
-
- // Verify that arithmetic operators function:
-
- // +
- analyzer->FindEvents(Query::EventArg("a") + Query::EventArg("b") ==
- Query::Int(20), &found);
- EXPECT_EQ(1u, found.size());
- EXPECT_STREQ("math2", found.front()->name.c_str());
-
- // -
- analyzer->FindEvents(Query::EventArg("a") - Query::EventArg("b") ==
- Query::Int(5), &found);
- EXPECT_EQ(1u, found.size());
- EXPECT_STREQ("math1", found.front()->name.c_str());
-
- // *
- analyzer->FindEvents(Query::EventArg("a") * Query::EventArg("b") ==
- Query::Int(50), &found);
- EXPECT_EQ(1u, found.size());
- EXPECT_STREQ("math1", found.front()->name.c_str());
-
- // /
- analyzer->FindEvents(Query::EventArg("a") / Query::EventArg("b") ==
- Query::Int(2), &found);
- EXPECT_EQ(1u, found.size());
- EXPECT_STREQ("math1", found.front()->name.c_str());
-
- // %
- analyzer->FindEvents(Query::EventArg("a") % Query::EventArg("b") ==
- Query::Int(0), &found);
- EXPECT_EQ(2u, found.size());
-
- // - (negate)
- analyzer->FindEvents(-Query::EventArg("b") == Query::Int(-10), &found);
- EXPECT_EQ(1u, found.size());
- EXPECT_STREQ("math2", found.front()->name.c_str());
-}
-
-TEST_F(TraceEventAnalyzerTest, StringPattern) {
- ManualSetUp();
-
- BeginTracing();
- {
- TRACE_EVENT_INSTANT0("cat1", "name1", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat1", "name2", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat1", "no match", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat1", "name3x", TRACE_EVENT_SCOPE_THREAD);
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
- analyzer->SetIgnoreMetadataEvents(true);
-
- TraceEventVector found;
-
- analyzer->FindEvents(Query::EventName() == Query::Pattern("name?"), &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name2", found[1]->name.c_str());
-
- analyzer->FindEvents(Query::EventName() == Query::Pattern("name*"), &found);
- ASSERT_EQ(3u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name2", found[1]->name.c_str());
- EXPECT_STREQ("name3x", found[2]->name.c_str());
-
- analyzer->FindEvents(Query::EventName() != Query::Pattern("name*"), &found);
- ASSERT_EQ(1u, found.size());
- EXPECT_STREQ("no match", found[0]->name.c_str());
-}
-
-// Test that duration queries work.
-TEST_F(TraceEventAnalyzerTest, BeginEndDuration) {
- ManualSetUp();
-
- const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(200);
- // We will search for events that have a duration of greater than 90% of the
- // sleep time, so that there is no flakiness.
- int64_t duration_cutoff_us = (kSleepTime.InMicroseconds() * 9) / 10;
-
- BeginTracing();
- {
- TRACE_EVENT_BEGIN0("cat1", "name1"); // found by duration query
- TRACE_EVENT_BEGIN0("noise", "name2"); // not searched for, just noise
- {
- TRACE_EVENT_BEGIN0("cat2", "name3"); // found by duration query
- // next event not searched for, just noise
- TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD);
- base::PlatformThread::Sleep(kSleepTime);
- TRACE_EVENT_BEGIN0("cat2", "name5"); // not found (duration too short)
- TRACE_EVENT_END0("cat2", "name5"); // not found (duration too short)
- TRACE_EVENT_END0("cat2", "name3"); // found by duration query
- }
- TRACE_EVENT_END0("noise", "name2"); // not searched for, just noise
- TRACE_EVENT_END0("cat1", "name1"); // found by duration query
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
- analyzer->AssociateBeginEndEvents();
-
- TraceEventVector found;
- analyzer->FindEvents(
- Query::MatchBeginWithEnd() &&
- Query::EventDuration() >
- Query::Int(static_cast<int>(duration_cutoff_us)) &&
- (Query::EventCategory() == Query::String("cat1") ||
- Query::EventCategory() == Query::String("cat2") ||
- Query::EventCategory() == Query::String("cat3")),
- &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name3", found[1]->name.c_str());
-}
-
-// Test that duration queries work.
-TEST_F(TraceEventAnalyzerTest, CompleteDuration) {
- ManualSetUp();
-
- const base::TimeDelta kSleepTime = base::TimeDelta::FromMilliseconds(200);
- // We will search for events that have a duration of greater than 90% of the
- // sleep time, so that there is no flakiness.
- int64_t duration_cutoff_us = (kSleepTime.InMicroseconds() * 9) / 10;
-
- BeginTracing();
- {
- TRACE_EVENT0("cat1", "name1"); // found by duration query
- TRACE_EVENT0("noise", "name2"); // not searched for, just noise
- {
- TRACE_EVENT0("cat2", "name3"); // found by duration query
- // next event not searched for, just noise
- TRACE_EVENT_INSTANT0("noise", "name4", TRACE_EVENT_SCOPE_THREAD);
- base::PlatformThread::Sleep(kSleepTime);
- TRACE_EVENT0("cat2", "name5"); // not found (duration too short)
- }
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
- analyzer->AssociateBeginEndEvents();
-
- TraceEventVector found;
- analyzer->FindEvents(
- Query::EventCompleteDuration() >
- Query::Int(static_cast<int>(duration_cutoff_us)) &&
- (Query::EventCategory() == Query::String("cat1") ||
- Query::EventCategory() == Query::String("cat2") ||
- Query::EventCategory() == Query::String("cat3")),
- &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STREQ("name1", found[0]->name.c_str());
- EXPECT_STREQ("name3", found[1]->name.c_str());
-}
-
-// Test AssociateBeginEndEvents
-TEST_F(TraceEventAnalyzerTest, BeginEndAssocations) {
- ManualSetUp();
-
- BeginTracing();
- {
- TRACE_EVENT_END0("cat1", "name1"); // does not match out of order begin
- TRACE_EVENT_BEGIN0("cat1", "name2");
- TRACE_EVENT_INSTANT0("cat1", "name3", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_BEGIN0("cat1", "name1");
- TRACE_EVENT_END0("cat1", "name2");
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
- analyzer->AssociateBeginEndEvents();
-
- TraceEventVector found;
- analyzer->FindEvents(Query::MatchBeginWithEnd(), &found);
- ASSERT_EQ(1u, found.size());
- EXPECT_STREQ("name2", found[0]->name.c_str());
-}
-
-// Test MergeAssociatedEventArgs
-TEST_F(TraceEventAnalyzerTest, MergeAssociatedEventArgs) {
- ManualSetUp();
-
- const char arg_string[] = "arg_string";
- BeginTracing();
- {
- TRACE_EVENT_BEGIN0("cat1", "name1");
- TRACE_EVENT_END1("cat1", "name1", "arg", arg_string);
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
- analyzer->AssociateBeginEndEvents();
-
- TraceEventVector found;
- analyzer->FindEvents(Query::MatchBeginName("name1"), &found);
- ASSERT_EQ(1u, found.size());
- std::string arg_actual;
- EXPECT_FALSE(found[0]->GetArgAsString("arg", &arg_actual));
-
- analyzer->MergeAssociatedEventArgs();
- EXPECT_TRUE(found[0]->GetArgAsString("arg", &arg_actual));
- EXPECT_STREQ(arg_string, arg_actual.c_str());
-}
-
-// Test AssociateAsyncBeginEndEvents
-TEST_F(TraceEventAnalyzerTest, AsyncBeginEndAssocations) {
- ManualSetUp();
-
- BeginTracing();
- {
- TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xA); // no match / out of order
- TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xB);
- TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xC);
- TRACE_EVENT_INSTANT0("cat1", "name1", TRACE_EVENT_SCOPE_THREAD); // noise
- TRACE_EVENT0("cat1", "name1"); // noise
- TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xB);
- TRACE_EVENT_ASYNC_END0("cat1", "name1", 0xC);
- TRACE_EVENT_ASYNC_BEGIN0("cat1", "name1", 0xA); // no match / out of order
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
- analyzer->AssociateAsyncBeginEndEvents();
-
- TraceEventVector found;
- analyzer->FindEvents(Query::MatchAsyncBeginWithNext(), &found);
- ASSERT_EQ(2u, found.size());
- EXPECT_STRCASEEQ("0xb", found[0]->id.c_str());
- EXPECT_STRCASEEQ("0xc", found[1]->id.c_str());
-}
-
-// Test AssociateAsyncBeginEndEvents
-TEST_F(TraceEventAnalyzerTest, AsyncBeginEndAssocationsWithSteps) {
- ManualSetUp();
-
- BeginTracing();
- {
- TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xA, "s1");
- TRACE_EVENT_ASYNC_END0("c", "n", 0xA);
- TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xB);
- TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xC);
- TRACE_EVENT_ASYNC_STEP_PAST0("c", "n", 0xB, "s1");
- TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xC, "s1");
- TRACE_EVENT_ASYNC_STEP_INTO1("c", "n", 0xC, "s2", "a", 1);
- TRACE_EVENT_ASYNC_END0("c", "n", 0xB);
- TRACE_EVENT_ASYNC_END0("c", "n", 0xC);
- TRACE_EVENT_ASYNC_BEGIN0("c", "n", 0xA);
- TRACE_EVENT_ASYNC_STEP_INTO0("c", "n", 0xA, "s2");
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
- analyzer->AssociateAsyncBeginEndEvents();
-
- TraceEventVector found;
- analyzer->FindEvents(Query::MatchAsyncBeginWithNext(), &found);
- ASSERT_EQ(3u, found.size());
-
- EXPECT_STRCASEEQ("0xb", found[0]->id.c_str());
- EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, found[0]->other_event->phase);
- EXPECT_EQ(found[0], found[0]->other_event->prev_event);
- EXPECT_TRUE(found[0]->other_event->other_event);
- EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_END,
- found[0]->other_event->other_event->phase);
- EXPECT_EQ(found[0]->other_event,
- found[0]->other_event->other_event->prev_event);
-
- EXPECT_STRCASEEQ("0xc", found[1]->id.c_str());
- EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, found[1]->other_event->phase);
- EXPECT_EQ(found[1], found[1]->other_event->prev_event);
- EXPECT_TRUE(found[1]->other_event->other_event);
- EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO,
- found[1]->other_event->other_event->phase);
- EXPECT_EQ(found[1]->other_event,
- found[1]->other_event->other_event->prev_event);
- double arg_actual = 0;
- EXPECT_TRUE(found[1]->other_event->other_event->GetArgAsNumber(
- "a", &arg_actual));
- EXPECT_EQ(1.0, arg_actual);
- EXPECT_TRUE(found[1]->other_event->other_event->other_event);
- EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_END,
- found[1]->other_event->other_event->other_event->phase);
-
- EXPECT_STRCASEEQ("0xa", found[2]->id.c_str());
- EXPECT_EQ(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, found[2]->other_event->phase);
-}
-
-// Test that the TraceAnalyzer custom associations work.
-TEST_F(TraceEventAnalyzerTest, CustomAssociations) {
- ManualSetUp();
-
- // Add events that begin/end in pipelined ordering with unique ID parameter
- // to match up the begin/end pairs.
- BeginTracing();
- {
- // no begin match
- TRACE_EVENT_INSTANT1("cat1", "end", TRACE_EVENT_SCOPE_THREAD, "id", 1);
- // end is cat4
- TRACE_EVENT_INSTANT1("cat2", "begin", TRACE_EVENT_SCOPE_THREAD, "id", 2);
- // end is cat5
- TRACE_EVENT_INSTANT1("cat3", "begin", TRACE_EVENT_SCOPE_THREAD, "id", 3);
- TRACE_EVENT_INSTANT1("cat4", "end", TRACE_EVENT_SCOPE_THREAD, "id", 2);
- TRACE_EVENT_INSTANT1("cat5", "end", TRACE_EVENT_SCOPE_THREAD, "id", 3);
- // no end match
- TRACE_EVENT_INSTANT1("cat6", "begin", TRACE_EVENT_SCOPE_THREAD, "id", 1);
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
-
- // begin, end, and match queries to find proper begin/end pairs.
- Query begin(Query::EventName() == Query::String("begin"));
- Query end(Query::EventName() == Query::String("end"));
- Query match(Query::EventArg("id") == Query::OtherArg("id"));
- analyzer->AssociateEvents(begin, end, match);
-
- TraceEventVector found;
-
- // cat1 has no other_event.
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat1") &&
- Query::EventHasOther(), &found);
- EXPECT_EQ(0u, found.size());
-
- // cat1 has no other_event.
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat1") &&
- !Query::EventHasOther(), &found);
- EXPECT_EQ(1u, found.size());
-
- // cat6 has no other_event.
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat6") &&
- !Query::EventHasOther(), &found);
- EXPECT_EQ(1u, found.size());
-
- // cat2 and cat4 are associated.
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat2") &&
- Query::OtherCategory() == Query::String("cat4"), &found);
- EXPECT_EQ(1u, found.size());
-
- // cat4 and cat2 are not associated.
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat4") &&
- Query::OtherCategory() == Query::String("cat2"), &found);
- EXPECT_EQ(0u, found.size());
-
- // cat3 and cat5 are associated.
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat3") &&
- Query::OtherCategory() == Query::String("cat5"), &found);
- EXPECT_EQ(1u, found.size());
-
- // cat5 and cat3 are not associated.
- analyzer->FindEvents(Query::EventCategory() == Query::String("cat5") &&
- Query::OtherCategory() == Query::String("cat3"), &found);
- EXPECT_EQ(0u, found.size());
-}
-
-// Verify that Query literals and types are properly casted.
-TEST_F(TraceEventAnalyzerTest, Literals) {
- ManualSetUp();
-
- // Since these queries don't refer to the event data, the dummy event below
- // will never be accessed.
- TraceEvent dummy;
- char char_num = 5;
- short short_num = -5;
- EXPECT_TRUE((Query::Double(5.0) == Query::Int(char_num)).Evaluate(dummy));
- EXPECT_TRUE((Query::Double(-5.0) == Query::Int(short_num)).Evaluate(dummy));
- EXPECT_TRUE((Query::Double(1.0) == Query::Uint(1u)).Evaluate(dummy));
- EXPECT_TRUE((Query::Double(1.0) == Query::Int(1)).Evaluate(dummy));
- EXPECT_TRUE((Query::Double(-1.0) == Query::Int(-1)).Evaluate(dummy));
- EXPECT_TRUE((Query::Double(1.0) == Query::Double(1.0f)).Evaluate(dummy));
- EXPECT_TRUE((Query::Bool(true) == Query::Int(1)).Evaluate(dummy));
- EXPECT_TRUE((Query::Bool(false) == Query::Int(0)).Evaluate(dummy));
- EXPECT_TRUE((Query::Bool(true) == Query::Double(1.0f)).Evaluate(dummy));
- EXPECT_TRUE((Query::Bool(false) == Query::Double(0.0f)).Evaluate(dummy));
-}
-
-// Test GetRateStats.
-TEST_F(TraceEventAnalyzerTest, RateStats) {
- std::vector<TraceEvent> events;
- events.reserve(100);
- TraceEventVector event_ptrs;
- double timestamp = 0.0;
- double little_delta = 1.0;
- double big_delta = 10.0;
- double tiny_delta = 0.1;
- RateStats stats;
- RateStatsOptions options;
-
- // Insert 10 events, each apart by little_delta.
- for (int i = 0; i < 10; ++i) {
- timestamp += little_delta;
- TraceEvent event;
- event.timestamp = timestamp;
- events.push_back(std::move(event));
- event_ptrs.push_back(&events.back());
- }
-
- ASSERT_TRUE(GetRateStats(event_ptrs, &stats, nullptr));
- EXPECT_EQ(little_delta, stats.mean_us);
- EXPECT_EQ(little_delta, stats.min_us);
- EXPECT_EQ(little_delta, stats.max_us);
- EXPECT_EQ(0.0, stats.standard_deviation_us);
-
- // Add an event apart by big_delta.
- {
- timestamp += big_delta;
- TraceEvent event;
- event.timestamp = timestamp;
- events.push_back(std::move(event));
- event_ptrs.push_back(&events.back());
- }
-
- ASSERT_TRUE(GetRateStats(event_ptrs, &stats, nullptr));
- EXPECT_LT(little_delta, stats.mean_us);
- EXPECT_EQ(little_delta, stats.min_us);
- EXPECT_EQ(big_delta, stats.max_us);
- EXPECT_LT(0.0, stats.standard_deviation_us);
-
- // Trim off the biggest delta and verify stats.
- options.trim_min = 0;
- options.trim_max = 1;
- ASSERT_TRUE(GetRateStats(event_ptrs, &stats, &options));
- EXPECT_EQ(little_delta, stats.mean_us);
- EXPECT_EQ(little_delta, stats.min_us);
- EXPECT_EQ(little_delta, stats.max_us);
- EXPECT_EQ(0.0, stats.standard_deviation_us);
-
- // Add an event apart by tiny_delta.
- {
- timestamp += tiny_delta;
- TraceEvent event;
- event.timestamp = timestamp;
- events.push_back(std::move(event));
- event_ptrs.push_back(&events.back());
- }
-
- // Trim off both the biggest and tiniest delta and verify stats.
- options.trim_min = 1;
- options.trim_max = 1;
- ASSERT_TRUE(GetRateStats(event_ptrs, &stats, &options));
- EXPECT_EQ(little_delta, stats.mean_us);
- EXPECT_EQ(little_delta, stats.min_us);
- EXPECT_EQ(little_delta, stats.max_us);
- EXPECT_EQ(0.0, stats.standard_deviation_us);
-
- // Verify smallest allowed number of events.
- {
- TraceEvent event;
- TraceEventVector few_event_ptrs;
- few_event_ptrs.push_back(&event);
- few_event_ptrs.push_back(&event);
- ASSERT_FALSE(GetRateStats(few_event_ptrs, &stats, nullptr));
- few_event_ptrs.push_back(&event);
- ASSERT_TRUE(GetRateStats(few_event_ptrs, &stats, nullptr));
-
- // Trim off more than allowed and verify failure.
- options.trim_min = 0;
- options.trim_max = 1;
- ASSERT_FALSE(GetRateStats(few_event_ptrs, &stats, &options));
- }
-}
-
-// Test FindFirstOf and FindLastOf.
-TEST_F(TraceEventAnalyzerTest, FindOf) {
- size_t num_events = 100;
- size_t index = 0;
- TraceEventVector event_ptrs;
- EXPECT_FALSE(FindFirstOf(event_ptrs, Query::Bool(true), 0, &index));
- EXPECT_FALSE(FindFirstOf(event_ptrs, Query::Bool(true), 10, &index));
- EXPECT_FALSE(FindLastOf(event_ptrs, Query::Bool(true), 0, &index));
- EXPECT_FALSE(FindLastOf(event_ptrs, Query::Bool(true), 10, &index));
-
- std::vector<TraceEvent> events;
- events.resize(num_events);
- for (size_t i = 0; i < events.size(); ++i)
- event_ptrs.push_back(&events[i]);
- size_t bam_index = num_events/2;
- events[bam_index].name = "bam";
- Query query_bam = Query::EventName() == Query::String(events[bam_index].name);
-
- // FindFirstOf
- EXPECT_FALSE(FindFirstOf(event_ptrs, Query::Bool(false), 0, &index));
- EXPECT_TRUE(FindFirstOf(event_ptrs, Query::Bool(true), 0, &index));
- EXPECT_EQ(0u, index);
- EXPECT_TRUE(FindFirstOf(event_ptrs, Query::Bool(true), 5, &index));
- EXPECT_EQ(5u, index);
-
- EXPECT_FALSE(FindFirstOf(event_ptrs, query_bam, bam_index + 1, &index));
- EXPECT_TRUE(FindFirstOf(event_ptrs, query_bam, 0, &index));
- EXPECT_EQ(bam_index, index);
- EXPECT_TRUE(FindFirstOf(event_ptrs, query_bam, bam_index, &index));
- EXPECT_EQ(bam_index, index);
-
- // FindLastOf
- EXPECT_FALSE(FindLastOf(event_ptrs, Query::Bool(false), 1000, &index));
- EXPECT_TRUE(FindLastOf(event_ptrs, Query::Bool(true), 1000, &index));
- EXPECT_EQ(num_events - 1, index);
- EXPECT_TRUE(FindLastOf(event_ptrs, Query::Bool(true), num_events - 5,
- &index));
- EXPECT_EQ(num_events - 5, index);
-
- EXPECT_FALSE(FindLastOf(event_ptrs, query_bam, bam_index - 1, &index));
- EXPECT_TRUE(FindLastOf(event_ptrs, query_bam, num_events, &index));
- EXPECT_EQ(bam_index, index);
- EXPECT_TRUE(FindLastOf(event_ptrs, query_bam, bam_index, &index));
- EXPECT_EQ(bam_index, index);
-}
-
-// Test FindClosest.
-TEST_F(TraceEventAnalyzerTest, FindClosest) {
- size_t index_1 = 0;
- size_t index_2 = 0;
- TraceEventVector event_ptrs;
- EXPECT_FALSE(FindClosest(event_ptrs, Query::Bool(true), 0,
- &index_1, &index_2));
-
- size_t num_events = 5;
- std::vector<TraceEvent> events;
- events.resize(num_events);
- for (size_t i = 0; i < events.size(); ++i) {
- // timestamps go up exponentially so the lower index is always closer in
- // time than the higher index.
- events[i].timestamp = static_cast<double>(i) * static_cast<double>(i);
- event_ptrs.push_back(&events[i]);
- }
- events[0].name = "one";
- events[2].name = "two";
- events[4].name = "three";
- Query query_named = Query::EventName() != Query::String(std::string());
- Query query_one = Query::EventName() == Query::String("one");
-
- // Only one event matches query_one, so two closest can't be found.
- EXPECT_FALSE(FindClosest(event_ptrs, query_one, 0, &index_1, &index_2));
-
- EXPECT_TRUE(FindClosest(event_ptrs, query_one, 3, &index_1, nullptr));
- EXPECT_EQ(0u, index_1);
-
- EXPECT_TRUE(FindClosest(event_ptrs, query_named, 1, &index_1, &index_2));
- EXPECT_EQ(0u, index_1);
- EXPECT_EQ(2u, index_2);
-
- EXPECT_TRUE(FindClosest(event_ptrs, query_named, 4, &index_1, &index_2));
- EXPECT_EQ(4u, index_1);
- EXPECT_EQ(2u, index_2);
-
- EXPECT_TRUE(FindClosest(event_ptrs, query_named, 3, &index_1, &index_2));
- EXPECT_EQ(2u, index_1);
- EXPECT_EQ(0u, index_2);
-}
-
-// Test CountMatches.
-TEST_F(TraceEventAnalyzerTest, CountMatches) {
- TraceEventVector event_ptrs;
- EXPECT_EQ(0u, CountMatches(event_ptrs, Query::Bool(true), 0, 10));
-
- size_t num_events = 5;
- size_t num_named = 3;
- std::vector<TraceEvent> events;
- events.resize(num_events);
- for (size_t i = 0; i < events.size(); ++i)
- event_ptrs.push_back(&events[i]);
- events[0].name = "one";
- events[2].name = "two";
- events[4].name = "three";
- Query query_named = Query::EventName() != Query::String(std::string());
- Query query_one = Query::EventName() == Query::String("one");
-
- EXPECT_EQ(0u, CountMatches(event_ptrs, Query::Bool(false)));
- EXPECT_EQ(num_events, CountMatches(event_ptrs, Query::Bool(true)));
- EXPECT_EQ(num_events - 1, CountMatches(event_ptrs, Query::Bool(true),
- 1, num_events));
- EXPECT_EQ(1u, CountMatches(event_ptrs, query_one));
- EXPECT_EQ(num_events - 1, CountMatches(event_ptrs, !query_one));
- EXPECT_EQ(num_named, CountMatches(event_ptrs, query_named));
-}
-
-TEST_F(TraceEventAnalyzerTest, ComplexArgument) {
- ManualSetUp();
-
- BeginTracing();
- {
- std::unique_ptr<base::trace_event::TracedValue> value(
- new base::trace_event::TracedValue);
- value->SetString("property", "value");
- TRACE_EVENT1("cat", "name", "arg", std::move(value));
- }
- EndTracing();
-
- std::unique_ptr<TraceAnalyzer> analyzer(
- TraceAnalyzer::Create(output_.json_output));
- ASSERT_TRUE(analyzer.get());
-
- TraceEventVector events;
- analyzer->FindEvents(Query::EventName() == Query::String("name"), &events);
-
- EXPECT_EQ(1u, events.size());
- EXPECT_EQ("cat", events[0]->category);
- EXPECT_EQ("name", events[0]->name);
- EXPECT_TRUE(events[0]->HasArg("arg"));
-
- std::unique_ptr<base::Value> arg;
- events[0]->GetArgAsValue("arg", &arg);
- base::DictionaryValue* arg_dict;
- EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
- std::string property;
- EXPECT_TRUE(arg_dict->GetString("property", &property));
- EXPECT_EQ("value", property);
-}
-
-} // namespace trace_analyzer
diff --git a/base/test/trace_to_file.cc b/base/test/trace_to_file.cc
deleted file mode 100644
index 17aa80b39b..0000000000
--- a/base/test/trace_to_file.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 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/trace_to_file.h"
-
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/run_loop.h"
-#include "base/trace_event/trace_buffer.h"
-#include "base/trace_event/trace_log.h"
-
-namespace base {
-namespace test {
-
-TraceToFile::TraceToFile() : started_(false) {
-}
-
-TraceToFile::~TraceToFile() {
- EndTracingIfNeeded();
-}
-
-void TraceToFile::BeginTracingFromCommandLineOptions() {
- DCHECK(CommandLine::InitializedForCurrentProcess());
- DCHECK(!started_);
-
- if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFile))
- return;
-
- // Empty filter (i.e. just --trace-to-file) turns into default categories in
- // TraceEventImpl
- std::string filter = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTraceToFile);
-
- FilePath path;
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToFileName)) {
- path = FilePath(CommandLine::ForCurrentProcess()
- ->GetSwitchValuePath(switches::kTraceToFileName));
- } else {
- path = FilePath(FILE_PATH_LITERAL("trace.json"));
- }
-
- BeginTracing(path, filter);
-}
-
-void TraceToFile::BeginTracing(const FilePath& path,
- const std::string& categories) {
- DCHECK(!started_);
- started_ = true;
- path_ = path;
- WriteFileHeader();
-
- trace_event::TraceLog::GetInstance()->SetEnabled(
- trace_event::TraceConfig(categories, trace_event::RECORD_UNTIL_FULL),
- trace_event::TraceLog::RECORDING_MODE);
-}
-
-void TraceToFile::WriteFileHeader() {
- const char str[] = "{\"traceEvents\": [";
- WriteFile(path_, str, static_cast<int>(strlen(str)));
-}
-
-void TraceToFile::AppendFileFooter() {
- const char str[] = "]}";
- AppendToFile(path_, str, static_cast<int>(strlen(str)));
-}
-
-void TraceToFile::TraceOutputCallback(const std::string& data) {
- bool ret = AppendToFile(path_, data.c_str(), static_cast<int>(data.size()));
- DCHECK(ret);
-}
-
-static void OnTraceDataCollected(
- Closure quit_closure,
- trace_event::TraceResultBuffer* buffer,
- const scoped_refptr<RefCountedString>& json_events_str,
- bool has_more_events) {
- buffer->AddFragment(json_events_str->data());
- if (!has_more_events)
- quit_closure.Run();
-}
-
-void TraceToFile::EndTracingIfNeeded() {
- if (!started_)
- return;
- started_ = false;
-
- trace_event::TraceLog::GetInstance()->SetDisabled();
-
- trace_event::TraceResultBuffer buffer;
- buffer.SetOutputCallback(
- Bind(&TraceToFile::TraceOutputCallback, Unretained(this)));
-
- RunLoop run_loop;
- trace_event::TraceLog::GetInstance()->Flush(
- Bind(&OnTraceDataCollected, run_loop.QuitClosure(), Unretained(&buffer)));
- run_loop.Run();
-
- AppendFileFooter();
-}
-
-} // namespace test
-} // namespace base
diff --git a/base/test/trace_to_file.h b/base/test/trace_to_file.h
deleted file mode 100644
index 43087367c3..0000000000
--- a/base/test/trace_to_file.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_TEST_TRACE_TO_FILE_H_
-#define BASE_TEST_TRACE_TO_FILE_H_
-
-#include "base/files/file_path.h"
-
-namespace base {
-namespace test {
-
-class TraceToFile {
- public:
- TraceToFile();
- ~TraceToFile();
-
- void BeginTracingFromCommandLineOptions();
- void BeginTracing(const base::FilePath& path, const std::string& categories);
- void EndTracingIfNeeded();
-
- private:
- void WriteFileHeader();
- void AppendFileFooter();
-
- void TraceOutputCallback(const std::string& data);
-
- base::FilePath path_;
- bool started_;
-};
-
-} // namespace test
-} // namespace base
-
-#endif // BASE_TEST_TRACE_TO_FILE_H_
diff --git a/base/test/values_test_util.cc b/base/test/values_test_util.cc
deleted file mode 100644
index a65c2c0674..0000000000
--- a/base/test/values_test_util.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/test/values_test_util.h"
-
-#include <memory>
-
-#include "base/json/json_reader.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-void ExpectDictBooleanValue(bool expected_value,
- const DictionaryValue& value,
- const std::string& key) {
- bool boolean_value = false;
- EXPECT_TRUE(value.GetBoolean(key, &boolean_value)) << key;
- EXPECT_EQ(expected_value, boolean_value) << key;
-}
-
-void ExpectDictDictionaryValue(const DictionaryValue& expected_value,
- const DictionaryValue& value,
- const std::string& key) {
- const DictionaryValue* dict_value = nullptr;
- EXPECT_TRUE(value.GetDictionary(key, &dict_value)) << key;
- EXPECT_EQ(expected_value, *dict_value) << key;
-}
-
-void ExpectDictIntegerValue(int expected_value,
- const DictionaryValue& value,
- const std::string& key) {
- int integer_value = 0;
- EXPECT_TRUE(value.GetInteger(key, &integer_value)) << key;
- EXPECT_EQ(expected_value, integer_value) << key;
-}
-
-void ExpectDictListValue(const ListValue& expected_value,
- const DictionaryValue& value,
- const std::string& key) {
- const ListValue* list_value = nullptr;
- EXPECT_TRUE(value.GetList(key, &list_value)) << key;
- EXPECT_EQ(expected_value, *list_value) << key;
-}
-
-void ExpectDictStringValue(const std::string& expected_value,
- const DictionaryValue& value,
- const std::string& key) {
- std::string string_value;
- EXPECT_TRUE(value.GetString(key, &string_value)) << key;
- EXPECT_EQ(expected_value, string_value) << key;
-}
-
-void ExpectStringValue(const std::string& expected_str, const Value& actual) {
- EXPECT_EQ(Value::Type::STRING, actual.type());
- EXPECT_EQ(expected_str, actual.GetString());
-}
-
-namespace test {
-
-std::unique_ptr<Value> ParseJson(base::StringPiece json) {
- std::string error_msg;
- std::unique_ptr<Value> result = base::JSONReader::ReadAndReturnError(
- json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, &error_msg);
- if (!result) {
- ADD_FAILURE() << "Failed to parse \"" << json << "\": " << error_msg;
- result = std::make_unique<Value>();
- }
- return result;
-}
-
-} // namespace test
-} // namespace base
diff --git a/base/test/values_test_util.h b/base/test/values_test_util.h
deleted file mode 100644
index 02ebca104d..0000000000
--- a/base/test/values_test_util.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_TEST_VALUES_TEST_UTIL_H_
-#define BASE_TEST_VALUES_TEST_UTIL_H_
-
-#include <memory>
-#include <string>
-
-#include "base/strings/string_piece.h"
-
-namespace base {
-class DictionaryValue;
-class ListValue;
-class Value;
-
-// All the functions below expect that the value for the given key in
-// the given dictionary equals the given expected value.
-
-void ExpectDictBooleanValue(bool expected_value,
- const DictionaryValue& value,
- const std::string& key);
-
-void ExpectDictDictionaryValue(const DictionaryValue& expected_value,
- const DictionaryValue& value,
- const std::string& key);
-
-void ExpectDictIntegerValue(int expected_value,
- const DictionaryValue& value,
- const std::string& key);
-
-void ExpectDictListValue(const ListValue& expected_value,
- const DictionaryValue& value,
- const std::string& key);
-
-void ExpectDictStringValue(const std::string& expected_value,
- const DictionaryValue& value,
- const std::string& key);
-
-void ExpectStringValue(const std::string& expected_str, const Value& actual);
-
-namespace test {
-
-// Parses |json| as JSON, allowing trailing commas, and returns the
-// resulting value. If the json fails to parse, causes an EXPECT
-// failure and returns the Null Value (but never a NULL pointer).
-std::unique_ptr<Value> ParseJson(base::StringPiece json);
-
-} // namespace test
-} // namespace base
-
-#endif // BASE_TEST_VALUES_TEST_UTIL_H_
diff --git a/base/third_party/dynamic_annotations/LICENSE b/base/third_party/dynamic_annotations/LICENSE
deleted file mode 100644
index 5c581a9391..0000000000
--- a/base/third_party/dynamic_annotations/LICENSE
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright (c) 2008-2009, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ---
- * Author: Kostya Serebryany
- */
diff --git a/base/third_party/dynamic_annotations/README.chromium b/base/third_party/dynamic_annotations/README.chromium
deleted file mode 100644
index c029f8eda7..0000000000
--- a/base/third_party/dynamic_annotations/README.chromium
+++ /dev/null
@@ -1,23 +0,0 @@
-Name: dynamic annotations
-URL: http://code.google.com/p/data-race-test/wiki/DynamicAnnotations
-Version: 4384
-License: BSD
-
-ATTENTION: please avoid using these annotations in Chromium code.
-They were mainly intended to instruct the Valgrind-based version of
-ThreadSanitizer to handle atomic operations. The new version of ThreadSanitizer
-based on compiler instrumentation understands atomic operations out of the box,
-so normally you don't need the annotations.
-If you still think you do, please consider writing a comment at http://crbug.com/349861
-
-One header and one source file (dynamic_annotations.h and dynamic_annotations.c)
-in this directory define runtime macros useful for annotating synchronization
-utilities and benign data races so data race detectors can handle Chromium code
-with better precision.
-
-These files were taken from
-http://code.google.com/p/data-race-test/source/browse/?#svn/trunk/dynamic_annotations
-The files are covered under BSD license as described within the files.
-
-Local modifications:
-* made lineno an unsigned short (for -Wconstant-conversion warning fixes)
diff --git a/base/third_party/valgrind/LICENSE b/base/third_party/valgrind/LICENSE
deleted file mode 100644
index 41f677bd17..0000000000
--- a/base/third_party/valgrind/LICENSE
+++ /dev/null
@@ -1,39 +0,0 @@
- Notice that the following BSD-style license applies to the Valgrind header
- files used by Chromium (valgrind.h and memcheck.h). However, the rest of
- Valgrind is licensed under the terms of the GNU General Public License,
- version 2, unless otherwise indicated.
-
- ----------------------------------------------------------------
-
- Copyright (C) 2000-2008 Julian Seward. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/base/third_party/valgrind/README.chromium b/base/third_party/valgrind/README.chromium
deleted file mode 100644
index 56a1cbb492..0000000000
--- a/base/third_party/valgrind/README.chromium
+++ /dev/null
@@ -1,11 +0,0 @@
-Name: valgrind
-URL: http://valgrind.org
-License: BSD
-
-Header files in this directory define runtime macros that determine whether the
-current process is running under Valgrind and tell Memcheck tool about custom
-memory allocators.
-
-These header files were taken from Valgrind source code
-(svn://svn.valgrind.org/valgrind/trunk@11504, dated 21 Jan 2011). The files are
-covered under BSD license as described within.
diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc
deleted file mode 100644
index fd90d35102..0000000000
--- a/base/threading/platform_thread_android.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/threading/platform_thread.h"
-
-#include <errno.h>
-#include <stddef.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/android/jni_android.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/threading/platform_thread_internal_posix.h"
-#include "base/threading/thread_id_name_manager.h"
-#include "jni/ThreadUtils_jni.h"
-
-namespace base {
-
-namespace internal {
-
-// - BACKGROUND corresponds to Android's PRIORITY_BACKGROUND = 10 value and can
-// result in heavy throttling and force the thread onto a little core on
-// big.LITTLE devices.
-// - DISPLAY corresponds to Android's PRIORITY_DISPLAY = -4 value.
-// - REALTIME_AUDIO corresponds to Android's PRIORITY_AUDIO = -16 value.
-const ThreadPriorityToNiceValuePair kThreadPriorityToNiceValueMap[4] = {
- {ThreadPriority::BACKGROUND, 10},
- {ThreadPriority::NORMAL, 0},
- {ThreadPriority::DISPLAY, -4},
- {ThreadPriority::REALTIME_AUDIO, -16},
-};
-
-bool SetCurrentThreadPriorityForPlatform(ThreadPriority priority) {
- // On Android, we set the Audio priority through JNI as Audio priority
- // will also allow the process to run while it is backgrounded.
- if (priority == ThreadPriority::REALTIME_AUDIO) {
- JNIEnv* env = base::android::AttachCurrentThread();
- Java_ThreadUtils_setThreadPriorityAudio(env, PlatformThread::CurrentId());
- return true;
- }
- return false;
-}
-
-bool GetCurrentThreadPriorityForPlatform(ThreadPriority* priority) {
- DCHECK(priority);
- *priority = ThreadPriority::NORMAL;
- JNIEnv* env = base::android::AttachCurrentThread();
- if (Java_ThreadUtils_isThreadPriorityAudio(
- env, PlatformThread::CurrentId())) {
- *priority = ThreadPriority::REALTIME_AUDIO;
- return true;
- }
- return false;
-}
-
-} // namespace internal
-
-void PlatformThread::SetName(const std::string& name) {
- ThreadIdNameManager::GetInstance()->SetName(name);
-
- // Like linux, on android we can get the thread names to show up in the
- // debugger by setting the process name for the LWP.
- // We don't want to do this for the main thread because that would rename
- // the process, causing tools like killall to stop working.
- if (PlatformThread::CurrentId() == getpid())
- return;
-
- // Set the name for the LWP (which gets truncated to 15 characters).
- int err = prctl(PR_SET_NAME, name.c_str());
- if (err < 0 && errno != EPERM)
- DPLOG(ERROR) << "prctl(PR_SET_NAME)";
-}
-
-
-void InitThreading() {
-}
-
-void TerminateOnThread() {
- base::android::DetachFromVM();
-}
-
-size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
-#if !defined(ADDRESS_SANITIZER)
- return 0;
-#else
- // AddressSanitizer bloats the stack approximately 2x. Default stack size of
- // 1Mb is not enough for some tests (see http://crbug.com/263749 for example).
- return 2 * (1 << 20); // 2Mb
-#endif
-}
-
-} // namespace base
diff --git a/base/threading/post_task_and_reply_impl_unittest.cc b/base/threading/post_task_and_reply_impl_unittest.cc
deleted file mode 100644
index 319327dfea..0000000000
--- a/base/threading/post_task_and_reply_impl_unittest.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2016 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/threading/post_task_and_reply_impl.h"
-
-#include <utility>
-
-#include "base/auto_reset.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-
-namespace base {
-namespace internal {
-
-namespace {
-
-class PostTaskAndReplyTaskRunner : public internal::PostTaskAndReplyImpl {
- public:
- explicit PostTaskAndReplyTaskRunner(TaskRunner* destination)
- : destination_(destination) {}
-
- private:
- bool PostTask(const Location& from_here, OnceClosure task) override {
- return destination_->PostTask(from_here, std::move(task));
- }
-
- // Non-owning.
- TaskRunner* const destination_;
-};
-
-class ObjectToDelete : public RefCounted<ObjectToDelete> {
- public:
- // |delete_flag| is set to true when this object is deleted
- ObjectToDelete(bool* delete_flag) : delete_flag_(delete_flag) {
- EXPECT_FALSE(*delete_flag_);
- }
-
- private:
- friend class RefCounted<ObjectToDelete>;
- ~ObjectToDelete() { *delete_flag_ = true; }
-
- bool* const delete_flag_;
-
- DISALLOW_COPY_AND_ASSIGN(ObjectToDelete);
-};
-
-class MockObject {
- public:
- MockObject() = default;
-
- MOCK_METHOD1(Task, void(scoped_refptr<ObjectToDelete>));
- MOCK_METHOD1(Reply, void(scoped_refptr<ObjectToDelete>));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockObject);
-};
-
-class MockRunsTasksInCurrentSequenceTaskRunner : public TestMockTimeTaskRunner {
- public:
- MockRunsTasksInCurrentSequenceTaskRunner(
- TestMockTimeTaskRunner::Type type =
- TestMockTimeTaskRunner::Type::kStandalone)
- : TestMockTimeTaskRunner(type) {}
-
- void RunUntilIdleWithRunsTasksInCurrentSequence() {
- AutoReset<bool> reset(&runs_tasks_in_current_sequence_, true);
- RunUntilIdle();
- }
-
- void ClearPendingTasksWithRunsTasksInCurrentSequence() {
- AutoReset<bool> reset(&runs_tasks_in_current_sequence_, true);
- ClearPendingTasks();
- }
-
- // TestMockTimeTaskRunner:
- bool RunsTasksInCurrentSequence() const override {
- return runs_tasks_in_current_sequence_;
- }
-
- private:
- ~MockRunsTasksInCurrentSequenceTaskRunner() override = default;
-
- bool runs_tasks_in_current_sequence_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(MockRunsTasksInCurrentSequenceTaskRunner);
-};
-
-class PostTaskAndReplyImplTest : public testing::Test {
- protected:
- PostTaskAndReplyImplTest() = default;
-
- void PostTaskAndReplyToMockObject() {
- // Expect the post to succeed.
- EXPECT_TRUE(
- PostTaskAndReplyTaskRunner(post_runner_.get())
- .PostTaskAndReply(
- FROM_HERE,
- BindOnce(&MockObject::Task, Unretained(&mock_object_),
- MakeRefCounted<ObjectToDelete>(&delete_task_flag_)),
- BindOnce(&MockObject::Reply, Unretained(&mock_object_),
- MakeRefCounted<ObjectToDelete>(&delete_reply_flag_))));
-
- // Expect the first task to be posted to |post_runner_|.
- EXPECT_TRUE(post_runner_->HasPendingTask());
- EXPECT_FALSE(reply_runner_->HasPendingTask());
- EXPECT_FALSE(delete_task_flag_);
- EXPECT_FALSE(delete_reply_flag_);
- }
-
- scoped_refptr<MockRunsTasksInCurrentSequenceTaskRunner> post_runner_ =
- MakeRefCounted<MockRunsTasksInCurrentSequenceTaskRunner>();
- scoped_refptr<MockRunsTasksInCurrentSequenceTaskRunner> reply_runner_ =
- MakeRefCounted<MockRunsTasksInCurrentSequenceTaskRunner>(
- TestMockTimeTaskRunner::Type::kBoundToThread);
- testing::StrictMock<MockObject> mock_object_;
- bool delete_task_flag_ = false;
- bool delete_reply_flag_ = false;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PostTaskAndReplyImplTest);
-};
-
-} // namespace
-
-TEST_F(PostTaskAndReplyImplTest, PostTaskAndReply) {
- PostTaskAndReplyToMockObject();
-
- EXPECT_CALL(mock_object_, Task(_));
- post_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
- testing::Mock::VerifyAndClear(&mock_object_);
- // The task should have been deleted right after being run.
- EXPECT_TRUE(delete_task_flag_);
- EXPECT_FALSE(delete_reply_flag_);
-
- // Expect the reply to be posted to |reply_runner_|.
- EXPECT_FALSE(post_runner_->HasPendingTask());
- EXPECT_TRUE(reply_runner_->HasPendingTask());
-
- EXPECT_CALL(mock_object_, Reply(_));
- reply_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
- testing::Mock::VerifyAndClear(&mock_object_);
- EXPECT_TRUE(delete_task_flag_);
- // The reply should have been deleted right after being run.
- EXPECT_TRUE(delete_reply_flag_);
-
- // Expect no pending task in |post_runner_| and |reply_runner_|.
- EXPECT_FALSE(post_runner_->HasPendingTask());
- EXPECT_FALSE(reply_runner_->HasPendingTask());
-}
-
-TEST_F(PostTaskAndReplyImplTest, TaskDoesNotRun) {
- PostTaskAndReplyToMockObject();
-
- // Clear the |post_runner_|. Both callbacks should be scheduled for deletion
- // on the |reply_runner_|.
- post_runner_->ClearPendingTasksWithRunsTasksInCurrentSequence();
- EXPECT_FALSE(post_runner_->HasPendingTask());
- EXPECT_TRUE(reply_runner_->HasPendingTask());
- EXPECT_FALSE(delete_task_flag_);
- EXPECT_FALSE(delete_reply_flag_);
-
- // Run the |reply_runner_|. Both callbacks should be deleted.
- reply_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
- EXPECT_TRUE(delete_task_flag_);
- EXPECT_TRUE(delete_reply_flag_);
-}
-
-TEST_F(PostTaskAndReplyImplTest, ReplyDoesNotRun) {
- PostTaskAndReplyToMockObject();
-
- EXPECT_CALL(mock_object_, Task(_));
- post_runner_->RunUntilIdleWithRunsTasksInCurrentSequence();
- testing::Mock::VerifyAndClear(&mock_object_);
- // The task should have been deleted right after being run.
- EXPECT_TRUE(delete_task_flag_);
- EXPECT_FALSE(delete_reply_flag_);
-
- // Expect the reply to be posted to |reply_runner_|.
- EXPECT_FALSE(post_runner_->HasPendingTask());
- EXPECT_TRUE(reply_runner_->HasPendingTask());
-
- // Clear the |reply_runner_| queue without running tasks. The reply callback
- // should be deleted.
- reply_runner_->ClearPendingTasksWithRunsTasksInCurrentSequence();
- EXPECT_TRUE(delete_task_flag_);
- EXPECT_TRUE(delete_reply_flag_);
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/threading/sequenced_task_runner_handle_unittest.cc b/base/threading/sequenced_task_runner_handle_unittest.cc
deleted file mode 100644
index 48394da6c2..0000000000
--- a/base/threading/sequenced_task_runner_handle_unittest.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2015 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/threading/sequenced_task_runner_handle.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/sequence_checker_impl.h"
-#include "base/sequenced_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class SequencedTaskRunnerHandleTest : public ::testing::Test {
- protected:
- // Verifies that the context it runs on has a SequencedTaskRunnerHandle
- // and that posting to it results in the posted task running in that same
- // context (sequence).
- static void VerifyCurrentSequencedTaskRunner() {
- ASSERT_TRUE(SequencedTaskRunnerHandle::IsSet());
- scoped_refptr<SequencedTaskRunner> task_runner =
- SequencedTaskRunnerHandle::Get();
- ASSERT_TRUE(task_runner);
-
- // Use SequenceCheckerImpl to make sure it's not a no-op in Release builds.
- std::unique_ptr<SequenceCheckerImpl> sequence_checker(
- new SequenceCheckerImpl);
- task_runner->PostTask(
- FROM_HERE,
- base::BindOnce(&SequencedTaskRunnerHandleTest::CheckValidSequence,
- std::move(sequence_checker)));
- }
-
- static void CheckValidSequence(
- std::unique_ptr<SequenceCheckerImpl> sequence_checker) {
- EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
- }
-
- base::test::ScopedTaskEnvironment scoped_task_environment_;
-};
-
-TEST_F(SequencedTaskRunnerHandleTest, FromMessageLoop) {
- VerifyCurrentSequencedTaskRunner();
- RunLoop().RunUntilIdle();
-}
-
-TEST_F(SequencedTaskRunnerHandleTest, FromTaskSchedulerSequencedTask) {
- base::CreateSequencedTaskRunnerWithTraits({})->PostTask(
- FROM_HERE,
- base::BindOnce(
- &SequencedTaskRunnerHandleTest::VerifyCurrentSequencedTaskRunner));
- scoped_task_environment_.RunUntilIdle();
-}
-
-TEST_F(SequencedTaskRunnerHandleTest, NoHandleFromUnsequencedTask) {
- base::PostTask(FROM_HERE, base::BindOnce([]() {
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
- }));
- scoped_task_environment_.RunUntilIdle();
-}
-
-TEST(SequencedTaskRunnerHandleTestWithoutMessageLoop, FromHandleInScope) {
- scoped_refptr<SequencedTaskRunner> test_task_runner(new TestSimpleTaskRunner);
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- {
- SequencedTaskRunnerHandle handle(test_task_runner);
- EXPECT_TRUE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(test_task_runner, SequencedTaskRunnerHandle::Get());
- }
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
-}
-
-} // namespace
-} // namespace base
diff --git a/base/threading/thread_perftest.cc b/base/threading/thread_perftest.cc
deleted file mode 100644
index d3fad972f8..0000000000
--- a/base/threading/thread_perftest.cc
+++ /dev/null
@@ -1,321 +0,0 @@
-// 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 <stddef.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-
-#if defined(OS_POSIX)
-#include <pthread.h>
-#endif
-
-namespace base {
-
-namespace {
-
-const int kNumRuns = 100000;
-
-// Base class for a threading perf-test. This sets up some threads for the
-// test and measures the clock-time in addition to time spent on each thread.
-class ThreadPerfTest : public testing::Test {
- public:
- ThreadPerfTest()
- : done_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- // To be implemented by each test. Subclass must uses threads_ such that
- // their cpu-time can be measured. Test must return from PingPong() _and_
- // call FinishMeasurement from any thread to complete the test.
- virtual void Init() {
- if (ThreadTicks::IsSupported())
- ThreadTicks::WaitUntilInitialized();
- }
- virtual void PingPong(int hops) = 0;
- virtual void Reset() {}
-
- void TimeOnThread(base::ThreadTicks* ticks, base::WaitableEvent* done) {
- *ticks = base::ThreadTicks::Now();
- done->Signal();
- }
-
- base::ThreadTicks ThreadNow(const base::Thread& thread) {
- base::WaitableEvent done(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- base::ThreadTicks ticks;
- thread.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ThreadPerfTest::TimeOnThread,
- base::Unretained(this), &ticks, &done));
- done.Wait();
- return ticks;
- }
-
- void RunPingPongTest(const std::string& name, unsigned num_threads) {
- // Create threads and collect starting cpu-time for each thread.
- std::vector<base::ThreadTicks> thread_starts;
- while (threads_.size() < num_threads) {
- threads_.push_back(std::make_unique<base::Thread>("PingPonger"));
- threads_.back()->Start();
- if (base::ThreadTicks::IsSupported())
- thread_starts.push_back(ThreadNow(*threads_.back()));
- }
-
- Init();
-
- base::TimeTicks start = base::TimeTicks::Now();
- PingPong(kNumRuns);
- done_.Wait();
- base::TimeTicks end = base::TimeTicks::Now();
-
- // Gather the cpu-time spent on each thread. This does one extra tasks,
- // but that should be in the noise given enough runs.
- base::TimeDelta thread_time;
- while (threads_.size()) {
- if (base::ThreadTicks::IsSupported()) {
- thread_time += ThreadNow(*threads_.back()) - thread_starts.back();
- thread_starts.pop_back();
- }
- threads_.pop_back();
- }
-
- Reset();
-
- double num_runs = static_cast<double>(kNumRuns);
- double us_per_task_clock = (end - start).InMicroseconds() / num_runs;
- double us_per_task_cpu = thread_time.InMicroseconds() / num_runs;
-
- // Clock time per task.
- perf_test::PrintResult(
- "task", "", name + "_time ", us_per_task_clock, "us/hop", true);
-
- // Total utilization across threads if available (likely higher).
- if (base::ThreadTicks::IsSupported()) {
- perf_test::PrintResult(
- "task", "", name + "_cpu ", us_per_task_cpu, "us/hop", true);
- }
- }
-
- protected:
- void FinishMeasurement() { done_.Signal(); }
- std::vector<std::unique_ptr<base::Thread>> threads_;
-
- private:
- base::WaitableEvent done_;
-};
-
-// Class to test task performance by posting empty tasks back and forth.
-class TaskPerfTest : public ThreadPerfTest {
- base::Thread* NextThread(int count) {
- return threads_[count % threads_.size()].get();
- }
-
- void PingPong(int hops) override {
- if (!hops) {
- FinishMeasurement();
- return;
- }
- NextThread(hops)->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ThreadPerfTest::PingPong,
- base::Unretained(this), hops - 1));
- }
-};
-
-// This tries to test the 'best-case' as well as the 'worst-case' task posting
-// performance. The best-case keeps one thread alive such that it never yeilds,
-// while the worse-case forces a context switch for every task. Four threads are
-// used to ensure the threads do yeild (with just two it might be possible for
-// both threads to stay awake if they can signal each other fast enough).
-TEST_F(TaskPerfTest, TaskPingPong) {
- RunPingPongTest("1_Task_Threads", 1);
- RunPingPongTest("4_Task_Threads", 4);
-}
-
-
-// Same as above, but add observers to test their perf impact.
-class MessageLoopObserver : public base::MessageLoop::TaskObserver {
- public:
- void WillProcessTask(const base::PendingTask& pending_task) override {}
- void DidProcessTask(const base::PendingTask& pending_task) override {}
-};
-MessageLoopObserver message_loop_observer;
-
-class TaskObserverPerfTest : public TaskPerfTest {
- public:
- void Init() override {
- TaskPerfTest::Init();
- for (size_t i = 0; i < threads_.size(); i++) {
- threads_[i]->message_loop()->task_runner()->PostTask(
- FROM_HERE, BindOnce(&MessageLoop::AddTaskObserver,
- Unretained(threads_[i]->message_loop()),
- Unretained(&message_loop_observer)));
- }
- }
-};
-
-TEST_F(TaskObserverPerfTest, TaskPingPong) {
- RunPingPongTest("1_Task_Threads_With_Observer", 1);
- RunPingPongTest("4_Task_Threads_With_Observer", 4);
-}
-
-// Class to test our WaitableEvent performance by signaling back and fort.
-// WaitableEvent is templated so we can also compare with other versions.
-template <typename WaitableEventType>
-class EventPerfTest : public ThreadPerfTest {
- public:
- void Init() override {
- for (size_t i = 0; i < threads_.size(); i++) {
- events_.push_back(std::make_unique<WaitableEventType>(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED));
- }
- }
-
- void Reset() override { events_.clear(); }
-
- void WaitAndSignalOnThread(size_t event) {
- size_t next_event = (event + 1) % events_.size();
- int my_hops = 0;
- do {
- events_[event]->Wait();
- my_hops = --remaining_hops_; // We own 'hops' between Wait and Signal.
- events_[next_event]->Signal();
- } while (my_hops > 0);
- // Once we are done, all threads will signal as hops passes zero.
- // We only signal completion once, on the thread that reaches zero.
- if (!my_hops)
- FinishMeasurement();
- }
-
- void PingPong(int hops) override {
- remaining_hops_ = hops;
- for (size_t i = 0; i < threads_.size(); i++) {
- threads_[i]->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&EventPerfTest::WaitAndSignalOnThread,
- base::Unretained(this), i));
- }
-
- // Kick off the Signal ping-ponging.
- events_.front()->Signal();
- }
-
- int remaining_hops_;
- std::vector<std::unique_ptr<WaitableEventType>> events_;
-};
-
-// Similar to the task posting test, this just tests similar functionality
-// using WaitableEvents. We only test four threads (worst-case), but we
-// might want to craft a way to test the best-case (where the thread doesn't
-// end up blocking because the event is already signalled).
-typedef EventPerfTest<base::WaitableEvent> WaitableEventThreadPerfTest;
-TEST_F(WaitableEventThreadPerfTest, EventPingPong) {
- RunPingPongTest("4_WaitableEvent_Threads", 4);
-}
-
-// Build a minimal event using ConditionVariable.
-class ConditionVariableEvent {
- public:
- ConditionVariableEvent(WaitableEvent::ResetPolicy reset_policy,
- WaitableEvent::InitialState initial_state)
- : cond_(&lock_), signaled_(false) {
- DCHECK_EQ(WaitableEvent::ResetPolicy::AUTOMATIC, reset_policy);
- DCHECK_EQ(WaitableEvent::InitialState::NOT_SIGNALED, initial_state);
- }
-
- void Signal() {
- {
- base::AutoLock scoped_lock(lock_);
- signaled_ = true;
- }
- cond_.Signal();
- }
-
- void Wait() {
- base::AutoLock scoped_lock(lock_);
- while (!signaled_)
- cond_.Wait();
- signaled_ = false;
- }
-
- private:
- base::Lock lock_;
- base::ConditionVariable cond_;
- bool signaled_;
-};
-
-// This is meant to test the absolute minimal context switching time
-// using our own base synchronization code.
-typedef EventPerfTest<ConditionVariableEvent> ConditionVariablePerfTest;
-TEST_F(ConditionVariablePerfTest, EventPingPong) {
- RunPingPongTest("4_ConditionVariable_Threads", 4);
-}
-#if defined(OS_POSIX)
-
-// Absolutely 100% minimal posix waitable event. If there is a better/faster
-// way to force a context switch, we should use that instead.
-class PthreadEvent {
- public:
- PthreadEvent(WaitableEvent::ResetPolicy reset_policy,
- WaitableEvent::InitialState initial_state) {
- DCHECK_EQ(WaitableEvent::ResetPolicy::AUTOMATIC, reset_policy);
- DCHECK_EQ(WaitableEvent::InitialState::NOT_SIGNALED, initial_state);
- pthread_mutex_init(&mutex_, nullptr);
- pthread_cond_init(&cond_, nullptr);
- signaled_ = false;
- }
-
- ~PthreadEvent() {
- pthread_cond_destroy(&cond_);
- pthread_mutex_destroy(&mutex_);
- }
-
- void Signal() {
- pthread_mutex_lock(&mutex_);
- signaled_ = true;
- pthread_mutex_unlock(&mutex_);
- pthread_cond_signal(&cond_);
- }
-
- void Wait() {
- pthread_mutex_lock(&mutex_);
- while (!signaled_)
- pthread_cond_wait(&cond_, &mutex_);
- signaled_ = false;
- pthread_mutex_unlock(&mutex_);
- }
-
- private:
- bool signaled_;
- pthread_mutex_t mutex_;
- pthread_cond_t cond_;
-};
-
-// This is meant to test the absolute minimal context switching time.
-// If there is any faster way to do this we should substitute it in.
-typedef EventPerfTest<PthreadEvent> PthreadEventPerfTest;
-TEST_F(PthreadEventPerfTest, EventPingPong) {
- RunPingPongTest("4_PthreadCondVar_Threads", 4);
-}
-
-#endif
-
-} // namespace
-
-} // namespace base
diff --git a/base/threading/thread_task_runner_handle_unittest.cc b/base/threading/thread_task_runner_handle_unittest.cc
deleted file mode 100644
index 1aa02d151d..0000000000
--- a/base/threading/thread_task_runner_handle_unittest.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2017 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/threading/thread_task_runner_handle.h"
-
-#include "base/memory/ref_counted.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_simple_task_runner.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(ThreadTaskRunnerHandleTest, Basic) {
- scoped_refptr<SingleThreadTaskRunner> task_runner(new TestSimpleTaskRunner);
-
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- {
- ThreadTaskRunnerHandle ttrh1(task_runner);
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner, ThreadTaskRunnerHandle::Get());
- }
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
-}
-
-TEST(ThreadTaskRunnerHandleTest, DeathOnImplicitOverride) {
- scoped_refptr<SingleThreadTaskRunner> task_runner(new TestSimpleTaskRunner);
- scoped_refptr<SingleThreadTaskRunner> overidding_task_runner(
- new TestSimpleTaskRunner);
-
- ThreadTaskRunnerHandle ttrh(task_runner);
- EXPECT_DCHECK_DEATH(
- { ThreadTaskRunnerHandle overriding_ttrh(overidding_task_runner); });
-}
-
-TEST(ThreadTaskRunnerHandleTest, OverrideForTestingExistingTTRH) {
- scoped_refptr<SingleThreadTaskRunner> task_runner_1(new TestSimpleTaskRunner);
- scoped_refptr<SingleThreadTaskRunner> task_runner_2(new TestSimpleTaskRunner);
- scoped_refptr<SingleThreadTaskRunner> task_runner_3(new TestSimpleTaskRunner);
- scoped_refptr<SingleThreadTaskRunner> task_runner_4(new TestSimpleTaskRunner);
-
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- {
- // TTRH in place prior to override.
- ThreadTaskRunnerHandle ttrh1(task_runner_1);
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
-
- {
- // Override.
- ScopedClosureRunner undo_override_2 =
- ThreadTaskRunnerHandle::OverrideForTesting(task_runner_2);
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_2, ThreadTaskRunnerHandle::Get());
-
- {
- // Nested override.
- ScopedClosureRunner undo_override_3 =
- ThreadTaskRunnerHandle::OverrideForTesting(task_runner_3);
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_3, ThreadTaskRunnerHandle::Get());
- }
-
- // Back to single override.
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_2, ThreadTaskRunnerHandle::Get());
-
- {
- // Backup to double override with another TTRH.
- ScopedClosureRunner undo_override_4 =
- ThreadTaskRunnerHandle::OverrideForTesting(task_runner_4);
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_4, ThreadTaskRunnerHandle::Get());
- }
- }
-
- // Back to simple TTRH.
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
- }
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
-}
-
-TEST(ThreadTaskRunnerHandleTest, OverrideForTestingNoExistingTTRH) {
- scoped_refptr<SingleThreadTaskRunner> task_runner_1(new TestSimpleTaskRunner);
- scoped_refptr<SingleThreadTaskRunner> task_runner_2(new TestSimpleTaskRunner);
-
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- {
- // Override with no TTRH in place.
- ScopedClosureRunner undo_override_1 =
- ThreadTaskRunnerHandle::OverrideForTesting(task_runner_1);
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
-
- {
- // Nested override works the same.
- ScopedClosureRunner undo_override_2 =
- ThreadTaskRunnerHandle::OverrideForTesting(task_runner_2);
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_2, ThreadTaskRunnerHandle::Get());
- }
-
- // Back to single override.
- EXPECT_TRUE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_EQ(task_runner_1, ThreadTaskRunnerHandle::Get());
- }
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
-}
-
-TEST(ThreadTaskRunnerHandleTest, DeathOnTTRHOverOverride) {
- scoped_refptr<SingleThreadTaskRunner> task_runner(new TestSimpleTaskRunner);
- scoped_refptr<SingleThreadTaskRunner> overidding_task_runner(
- new TestSimpleTaskRunner);
-
- ScopedClosureRunner undo_override =
- ThreadTaskRunnerHandle::OverrideForTesting(task_runner);
- EXPECT_DCHECK_DEATH(
- { ThreadTaskRunnerHandle overriding_ttrh(overidding_task_runner); });
-}
-
-} // namespace base
diff --git a/base/threading/watchdog.cc b/base/threading/watchdog.cc
deleted file mode 100644
index 0e48c8e452..0000000000
--- a/base/threading/watchdog.cc
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/threading/watchdog.h"
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/no_destructor.h"
-#include "base/threading/platform_thread.h"
-
-namespace base {
-
-namespace {
-
-// When the debugger breaks (when we alarm), all the other alarms that are
-// armed will expire (also alarm). To diminish this effect, we track any
-// delay due to debugger breaks, and we *try* to adjust the effective start
-// time of other alarms to step past the debugging break.
-// Without this safety net, any alarm will typically trigger a host of follow
-// on alarms from callers that specify old times.
-
-struct StaticData {
- // Lock for access of static data...
- Lock lock;
-
- // When did we last alarm and get stuck (for a while) in a debugger?
- TimeTicks last_debugged_alarm_time;
-
- // How long did we sit on a break in the debugger?
- TimeDelta last_debugged_alarm_delay;
-};
-
-StaticData* GetStaticData() {
- static base::NoDestructor<StaticData> static_data;
- return static_data.get();
-}
-
-} // namespace
-
-// Start thread running in a Disarmed state.
-Watchdog::Watchdog(const TimeDelta& duration,
- const std::string& thread_watched_name,
- bool enabled)
- : enabled_(enabled),
- lock_(),
- condition_variable_(&lock_),
- state_(DISARMED),
- duration_(duration),
- thread_watched_name_(thread_watched_name),
- delegate_(this) {
- if (!enabled_)
- return; // Don't start thread, or doing anything really.
- enabled_ = PlatformThread::Create(0, // Default stack size.
- &delegate_,
- &handle_);
- DCHECK(enabled_);
-}
-
-// Notify watchdog thread, and wait for it to finish up.
-Watchdog::~Watchdog() {
- if (!enabled_)
- return;
- if (!IsJoinable())
- Cleanup();
- PlatformThread::Join(handle_);
-}
-
-void Watchdog::Cleanup() {
- if (!enabled_)
- return;
- AutoLock lock(lock_);
- state_ = SHUTDOWN;
- condition_variable_.Signal();
-}
-
-bool Watchdog::IsJoinable() {
- if (!enabled_)
- return true;
- AutoLock lock(lock_);
- return (state_ == JOINABLE);
-}
-
-void Watchdog::Arm() {
- ArmAtStartTime(TimeTicks::Now());
-}
-
-void Watchdog::ArmSomeTimeDeltaAgo(const TimeDelta& time_delta) {
- ArmAtStartTime(TimeTicks::Now() - time_delta);
-}
-
-// Start clock for watchdog.
-void Watchdog::ArmAtStartTime(const TimeTicks start_time) {
- AutoLock lock(lock_);
- start_time_ = start_time;
- state_ = ARMED;
- // Force watchdog to wake up, and go to sleep with the timer ticking with the
- // proper duration.
- condition_variable_.Signal();
-}
-
-// Disable watchdog so that it won't do anything when time expires.
-void Watchdog::Disarm() {
- AutoLock lock(lock_);
- state_ = DISARMED;
- // We don't need to signal, as the watchdog will eventually wake up, and it
- // will check its state and time, and act accordingly.
-}
-
-void Watchdog::Alarm() {
- DVLOG(1) << "Watchdog alarmed for " << thread_watched_name_;
-}
-
-//------------------------------------------------------------------------------
-// Internal private methods that the watchdog thread uses.
-
-void Watchdog::ThreadDelegate::ThreadMain() {
- SetThreadName();
- TimeDelta remaining_duration;
- StaticData* static_data = GetStaticData();
- while (1) {
- AutoLock lock(watchdog_->lock_);
- while (DISARMED == watchdog_->state_)
- watchdog_->condition_variable_.Wait();
- if (SHUTDOWN == watchdog_->state_) {
- watchdog_->state_ = JOINABLE;
- return;
- }
- DCHECK(ARMED == watchdog_->state_);
- remaining_duration = watchdog_->duration_ -
- (TimeTicks::Now() - watchdog_->start_time_);
- if (remaining_duration.InMilliseconds() > 0) {
- // Spurios wake? Timer drifts? Go back to sleep for remaining time.
- watchdog_->condition_variable_.TimedWait(remaining_duration);
- continue;
- }
- // We overslept, so this seems like a real alarm.
- // Watch out for a user that stopped the debugger on a different alarm!
- {
- AutoLock static_lock(static_data->lock);
- if (static_data->last_debugged_alarm_time > watchdog_->start_time_) {
- // False alarm: we started our clock before the debugger break (last
- // alarm time).
- watchdog_->start_time_ += static_data->last_debugged_alarm_delay;
- if (static_data->last_debugged_alarm_time > watchdog_->start_time_)
- // Too many alarms must have taken place.
- watchdog_->state_ = DISARMED;
- continue;
- }
- }
- watchdog_->state_ = DISARMED; // Only alarm at most once.
- TimeTicks last_alarm_time = TimeTicks::Now();
- {
- AutoUnlock unlock(watchdog_->lock_);
- watchdog_->Alarm(); // Set a break point here to debug on alarms.
- }
- TimeDelta last_alarm_delay = TimeTicks::Now() - last_alarm_time;
- if (last_alarm_delay <= TimeDelta::FromMilliseconds(2))
- continue;
- // Ignore race of two alarms/breaks going off at roughly the same time.
- AutoLock static_lock(static_data->lock);
- // This was a real debugger break.
- static_data->last_debugged_alarm_time = last_alarm_time;
- static_data->last_debugged_alarm_delay = last_alarm_delay;
- }
-}
-
-void Watchdog::ThreadDelegate::SetThreadName() const {
- std::string name = watchdog_->thread_watched_name_ + " Watchdog";
- PlatformThread::SetName(name);
- DVLOG(1) << "Watchdog active: " << name;
-}
-
-// static
-void Watchdog::ResetStaticData() {
- StaticData* static_data = GetStaticData();
- AutoLock lock(static_data->lock);
- // See https://crbug.com/734232 for why this cannot be zero-initialized.
- static_data->last_debugged_alarm_time = TimeTicks::Min();
- static_data->last_debugged_alarm_delay = TimeDelta();
-}
-
-} // namespace base
diff --git a/base/threading/watchdog.h b/base/threading/watchdog.h
deleted file mode 100644
index f8069846e4..0000000000
--- a/base/threading/watchdog.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 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.
-
-// The Watchdog class creates a second thread that can Alarm if a specific
-// duration of time passes without proper attention. The duration of time is
-// specified at construction time. The Watchdog may be used many times by
-// simply calling Arm() (to start timing) and Disarm() (to reset the timer).
-// The Watchdog is typically used under a debugger, where the stack traces on
-// other threads can be examined if/when the Watchdog alarms.
-
-// Some watchdogs will be enabled or disabled via command line switches. To
-// facilitate such code, an "enabled" argument for the constuctor can be used
-// to permanently disable the watchdog. Disabled watchdogs don't even spawn
-// a second thread, and their methods call (Arm() and Disarm()) return very
-// quickly.
-
-#ifndef BASE_THREADING_WATCHDOG_H_
-#define BASE_THREADING_WATCHDOG_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-
-namespace base {
-
-class BASE_EXPORT Watchdog {
- public:
- // Constructor specifies how long the Watchdog will wait before alarming.
- Watchdog(const TimeDelta& duration,
- const std::string& thread_watched_name,
- bool enabled);
- virtual ~Watchdog();
-
- // Notify watchdog thread to finish up. Sets the state_ to SHUTDOWN.
- void Cleanup();
-
- // Returns true if we state_ is JOINABLE (which indicates that Watchdog has
- // exited).
- bool IsJoinable();
-
- // Start timing, and alarm when time expires (unless we're disarm()ed.)
- void Arm(); // Arm starting now.
- void ArmSomeTimeDeltaAgo(const TimeDelta& time_delta);
- void ArmAtStartTime(const TimeTicks start_time);
-
- // Reset time, and do not set off the alarm.
- void Disarm();
-
- // Alarm is called if the time expires after an Arm() without someone calling
- // Disarm(). This method can be overridden to create testable classes.
- virtual void Alarm();
-
- // Reset static data to initial state. Useful for tests, to ensure
- // they are independent.
- static void ResetStaticData();
-
- private:
- class ThreadDelegate : public PlatformThread::Delegate {
- public:
- explicit ThreadDelegate(Watchdog* watchdog) : watchdog_(watchdog) {
- }
- void ThreadMain() override;
-
- private:
- void SetThreadName() const;
-
- Watchdog* watchdog_;
- };
-
- enum State {ARMED, DISARMED, SHUTDOWN, JOINABLE };
-
- bool enabled_;
-
- Lock lock_; // Mutex for state_.
- ConditionVariable condition_variable_;
- State state_;
- const TimeDelta duration_; // How long after start_time_ do we alarm?
- const std::string thread_watched_name_;
- PlatformThreadHandle handle_;
- ThreadDelegate delegate_; // Store it, because it must outlive the thread.
-
- TimeTicks start_time_; // Start of epoch, and alarm after duration_.
-
- DISALLOW_COPY_AND_ASSIGN(Watchdog);
-};
-
-} // namespace base
-
-#endif // BASE_THREADING_WATCHDOG_H_
diff --git a/base/threading/watchdog_unittest.cc b/base/threading/watchdog_unittest.cc
deleted file mode 100644
index f534a863d4..0000000000
--- a/base/threading/watchdog_unittest.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/threading/watchdog.h"
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/synchronization/spin_wait.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-//------------------------------------------------------------------------------
-// Provide a derived class to facilitate testing.
-
-class WatchdogCounter : public Watchdog {
- public:
- WatchdogCounter(const TimeDelta& duration,
- const std::string& thread_watched_name,
- bool enabled)
- : Watchdog(duration, thread_watched_name, enabled),
- alarm_counter_(0) {
- }
-
- ~WatchdogCounter() override = default;
-
- void Alarm() override {
- alarm_counter_++;
- Watchdog::Alarm();
- }
-
- int alarm_counter() { return alarm_counter_; }
-
- private:
- int alarm_counter_;
-
- DISALLOW_COPY_AND_ASSIGN(WatchdogCounter);
-};
-
-class WatchdogTest : public testing::Test {
- public:
- void SetUp() override { Watchdog::ResetStaticData(); }
-};
-
-} // namespace
-
-//------------------------------------------------------------------------------
-// Actual tests
-
-// Minimal constructor/destructor test.
-TEST_F(WatchdogTest, StartupShutdownTest) {
- Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
- Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
-}
-
-// Test ability to call Arm and Disarm repeatedly.
-TEST_F(WatchdogTest, ArmDisarmTest) {
- Watchdog watchdog1(TimeDelta::FromMilliseconds(300), "Disabled", false);
- watchdog1.Arm();
- watchdog1.Disarm();
- watchdog1.Arm();
- watchdog1.Disarm();
-
- Watchdog watchdog2(TimeDelta::FromMilliseconds(300), "Enabled", true);
- watchdog2.Arm();
- watchdog2.Disarm();
- watchdog2.Arm();
- watchdog2.Disarm();
-}
-
-// Make sure a basic alarm fires when the time has expired.
-TEST_F(WatchdogTest, AlarmTest) {
- WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Enabled", true);
- watchdog.Arm();
- SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
- watchdog.alarm_counter() > 0);
- EXPECT_EQ(1, watchdog.alarm_counter());
-}
-
-// Make sure a basic alarm fires when the time has expired.
-TEST_F(WatchdogTest, AlarmPriorTimeTest) {
- WatchdogCounter watchdog(TimeDelta(), "Enabled2", true);
- // Set a time in the past.
- watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(2));
- // It should instantly go off, but certainly in less than 5 minutes.
- SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
- watchdog.alarm_counter() > 0);
-
- EXPECT_EQ(1, watchdog.alarm_counter());
-}
-
-// Make sure a disable alarm does nothing, even if we arm it.
-TEST_F(WatchdogTest, ConstructorDisabledTest) {
- WatchdogCounter watchdog(TimeDelta::FromMilliseconds(10), "Disabled", false);
- watchdog.Arm();
- // Alarm should not fire, as it was disabled.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(500));
- EXPECT_EQ(0, watchdog.alarm_counter());
-}
-
-// Make sure Disarming will prevent firing, even after Arming.
-TEST_F(WatchdogTest, DisarmTest) {
- WatchdogCounter watchdog(TimeDelta::FromSeconds(1), "Enabled3", true);
-
- TimeTicks start = TimeTicks::Now();
- watchdog.Arm();
- // Sleep a bit, but not past the alarm point.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
- watchdog.Disarm();
- TimeTicks end = TimeTicks::Now();
-
- if (end - start > TimeDelta::FromMilliseconds(500)) {
- LOG(WARNING) << "100ms sleep took over 500ms, making the results of this "
- << "timing-sensitive test suspicious. Aborting now.";
- return;
- }
-
- // Alarm should not have fired before it was disarmed.
- EXPECT_EQ(0, watchdog.alarm_counter());
-
- // Sleep past the point where it would have fired if it wasn't disarmed,
- // and verify that it didn't fire.
- PlatformThread::Sleep(TimeDelta::FromSeconds(1));
- EXPECT_EQ(0, watchdog.alarm_counter());
-
- // ...but even after disarming, we can still use the alarm...
- // Set a time greater than the timeout into the past.
- watchdog.ArmSomeTimeDeltaAgo(TimeDelta::FromSeconds(10));
- // It should almost instantly go off, but certainly in less than 5 minutes.
- SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(5),
- watchdog.alarm_counter() > 0);
-
- EXPECT_EQ(1, watchdog.alarm_counter());
-}
-
-} // namespace base
diff --git a/base/time/time.h b/base/time/time.h
index ba7be4b8c4..b3c77e7289 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -199,8 +199,10 @@ class BASE_EXPORT TimeDelta {
double InMicrosecondsF() const;
int64_t InNanoseconds() const;
- constexpr TimeDelta& operator=(const TimeDelta&) = default;
- constexpr TimeDelta(const TimeDelta&) = default;
+ constexpr TimeDelta& operator=(TimeDelta other) {
+ delta_ = other.delta_;
+ return *this;
+ }
// Computations with other deltas. Can easily be made constexpr with C++17 but
// hard to do until then per limitations around
diff --git a/base/tools_sanity_unittest.cc b/base/tools_sanity_unittest.cc
deleted file mode 100644
index 98c30df47d..0000000000
--- a/base/tools_sanity_unittest.cc
+++ /dev/null
@@ -1,423 +0,0 @@
-// Copyright (c) 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.
-//
-// This file contains intentional memory errors, some of which may lead to
-// crashes if the test is ran without special memory testing tools. We use these
-// errors to verify the sanity of the tools.
-
-#include <stddef.h>
-
-#include "base/atomicops.h"
-#include "base/cfi_buildflags.h"
-#include "base/debug/asan_invalid_access.h"
-#include "base/debug/profiler.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/threading/thread.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-const base::subtle::Atomic32 kMagicValue = 42;
-
-// Helper for memory accesses that can potentially corrupt memory or cause a
-// crash during a native run.
-#if defined(ADDRESS_SANITIZER)
-#if defined(OS_IOS)
-// EXPECT_DEATH is not supported on IOS.
-#define HARMFUL_ACCESS(action,error_regexp) do { action; } while (0)
-#else
-#define HARMFUL_ACCESS(action,error_regexp) EXPECT_DEATH(action,error_regexp)
-#endif // !OS_IOS
-#else
-#define HARMFUL_ACCESS(action, error_regexp)
-#define HARMFUL_ACCESS_IS_NOOP
-#endif
-
-void DoReadUninitializedValue(char *ptr) {
- // Comparison with 64 is to prevent clang from optimizing away the
- // jump -- valgrind only catches jumps and conditional moves, but clang uses
- // the borrow flag if the condition is just `*ptr == '\0'`. We no longer
- // support valgrind, but this constant should be fine to keep as-is.
- if (*ptr == 64) {
- VLOG(1) << "Uninit condition is true";
- } else {
- VLOG(1) << "Uninit condition is false";
- }
-}
-
-void ReadUninitializedValue(char *ptr) {
-#if defined(MEMORY_SANITIZER)
- EXPECT_DEATH(DoReadUninitializedValue(ptr),
- "use-of-uninitialized-value");
-#else
- DoReadUninitializedValue(ptr);
-#endif
-}
-
-#ifndef HARMFUL_ACCESS_IS_NOOP
-void ReadValueOutOfArrayBoundsLeft(char *ptr) {
- char c = ptr[-2];
- VLOG(1) << "Reading a byte out of bounds: " << c;
-}
-
-void ReadValueOutOfArrayBoundsRight(char *ptr, size_t size) {
- char c = ptr[size + 1];
- VLOG(1) << "Reading a byte out of bounds: " << c;
-}
-
-void WriteValueOutOfArrayBoundsLeft(char *ptr) {
- ptr[-1] = kMagicValue;
-}
-
-void WriteValueOutOfArrayBoundsRight(char *ptr, size_t size) {
- ptr[size] = kMagicValue;
-}
-#endif // HARMFUL_ACCESS_IS_NOOP
-
-void MakeSomeErrors(char *ptr, size_t size) {
- ReadUninitializedValue(ptr);
-
- HARMFUL_ACCESS(ReadValueOutOfArrayBoundsLeft(ptr),
- "2 bytes to the left");
- HARMFUL_ACCESS(ReadValueOutOfArrayBoundsRight(ptr, size),
- "1 bytes to the right");
- HARMFUL_ACCESS(WriteValueOutOfArrayBoundsLeft(ptr),
- "1 bytes to the left");
- HARMFUL_ACCESS(WriteValueOutOfArrayBoundsRight(ptr, size),
- "0 bytes to the right");
-}
-
-} // namespace
-
-// A memory leak detector should report an error in this test.
-TEST(ToolsSanityTest, MemoryLeak) {
- // Without the |volatile|, clang optimizes away the next two lines.
- int* volatile leak = new int[256]; // Leak some memory intentionally.
- leak[4] = 1; // Make sure the allocated memory is used.
-}
-
-#if (defined(ADDRESS_SANITIZER) && defined(OS_IOS))
-// Because iOS doesn't support death tests, each of the following tests will
-// crash the whole program under Asan.
-#define MAYBE_AccessesToNewMemory DISABLED_AccessesToNewMemory
-#define MAYBE_AccessesToMallocMemory DISABLED_AccessesToMallocMemory
-#else
-#define MAYBE_AccessesToNewMemory AccessesToNewMemory
-#define MAYBE_AccessesToMallocMemory AccessesToMallocMemory
-#endif // (defined(ADDRESS_SANITIZER) && defined(OS_IOS))
-
-// The following tests pass with Clang r170392, but not r172454, which
-// makes AddressSanitizer detect errors in them. We disable these tests under
-// AddressSanitizer until we fully switch to Clang r172454. After that the
-// tests should be put back under the (defined(OS_IOS) || defined(OS_WIN))
-// clause above.
-// See also http://crbug.com/172614.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_SingleElementDeletedWithBraces \
- DISABLED_SingleElementDeletedWithBraces
-#define MAYBE_ArrayDeletedWithoutBraces DISABLED_ArrayDeletedWithoutBraces
-#else
-#define MAYBE_ArrayDeletedWithoutBraces ArrayDeletedWithoutBraces
-#define MAYBE_SingleElementDeletedWithBraces SingleElementDeletedWithBraces
-#endif // defined(ADDRESS_SANITIZER)
-
-TEST(ToolsSanityTest, MAYBE_AccessesToNewMemory) {
- char *foo = new char[10];
- MakeSomeErrors(foo, 10);
- delete [] foo;
- // Use after delete.
- HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free");
-}
-
-TEST(ToolsSanityTest, MAYBE_AccessesToMallocMemory) {
- char *foo = reinterpret_cast<char*>(malloc(10));
- MakeSomeErrors(foo, 10);
- free(foo);
- // Use after free.
- HARMFUL_ACCESS(foo[5] = 0, "heap-use-after-free");
-}
-
-#if defined(ADDRESS_SANITIZER)
-
-static int* allocateArray() {
- // Clang warns about the mismatched new[]/delete if they occur in the same
- // function.
- return new int[10];
-}
-
-// This test may corrupt memory if not compiled with AddressSanitizer.
-TEST(ToolsSanityTest, MAYBE_ArrayDeletedWithoutBraces) {
- // Without the |volatile|, clang optimizes away the next two lines.
- int* volatile foo = allocateArray();
- delete foo;
-}
-#endif
-
-#if defined(ADDRESS_SANITIZER)
-static int* allocateScalar() {
- // Clang warns about the mismatched new/delete[] if they occur in the same
- // function.
- return new int;
-}
-
-// This test may corrupt memory if not compiled with AddressSanitizer.
-TEST(ToolsSanityTest, MAYBE_SingleElementDeletedWithBraces) {
- // Without the |volatile|, clang optimizes away the next two lines.
- int* volatile foo = allocateScalar();
- (void) foo;
- delete [] foo;
-}
-#endif
-
-#if defined(ADDRESS_SANITIZER)
-
-TEST(ToolsSanityTest, DISABLED_AddressSanitizerNullDerefCrashTest) {
- // Intentionally crash to make sure AddressSanitizer is running.
- // This test should not be ran on bots.
- int* volatile zero = NULL;
- *zero = 0;
-}
-
-TEST(ToolsSanityTest, DISABLED_AddressSanitizerLocalOOBCrashTest) {
- // Intentionally crash to make sure AddressSanitizer is instrumenting
- // the local variables.
- // This test should not be ran on bots.
- int array[5];
- // Work around the OOB warning reported by Clang.
- int* volatile access = &array[5];
- *access = 43;
-}
-
-namespace {
-int g_asan_test_global_array[10];
-} // namespace
-
-TEST(ToolsSanityTest, DISABLED_AddressSanitizerGlobalOOBCrashTest) {
- // Intentionally crash to make sure AddressSanitizer is instrumenting
- // the global variables.
- // This test should not be ran on bots.
-
- // Work around the OOB warning reported by Clang.
- int* volatile access = g_asan_test_global_array - 1;
- *access = 43;
-}
-
-#ifndef HARMFUL_ACCESS_IS_NOOP
-TEST(ToolsSanityTest, AsanHeapOverflow) {
- HARMFUL_ACCESS(debug::AsanHeapOverflow() ,"to the right");
-}
-
-TEST(ToolsSanityTest, AsanHeapUnderflow) {
- HARMFUL_ACCESS(debug::AsanHeapUnderflow(), "to the left");
-}
-
-TEST(ToolsSanityTest, AsanHeapUseAfterFree) {
- HARMFUL_ACCESS(debug::AsanHeapUseAfterFree(), "heap-use-after-free");
-}
-
-#if defined(OS_WIN)
-// The ASAN runtime doesn't detect heap corruption, this needs fixing before
-// ASAN builds can ship to the wild. See https://crbug.com/818747.
-TEST(ToolsSanityTest, DISABLED_AsanCorruptHeapBlock) {
- HARMFUL_ACCESS(debug::AsanCorruptHeapBlock(), "");
-}
-
-TEST(ToolsSanityTest, DISABLED_AsanCorruptHeap) {
- // This test will kill the process by raising an exception, there's no
- // particular string to look for in the stack trace.
- EXPECT_DEATH(debug::AsanCorruptHeap(), "");
-}
-#endif // OS_WIN
-#endif // !HARMFUL_ACCESS_IS_NOOP
-
-#endif // ADDRESS_SANITIZER
-
-namespace {
-
-// We use caps here just to ensure that the method name doesn't interfere with
-// the wildcarded suppressions.
-class TOOLS_SANITY_TEST_CONCURRENT_THREAD : public PlatformThread::Delegate {
- public:
- explicit TOOLS_SANITY_TEST_CONCURRENT_THREAD(bool *value) : value_(value) {}
- ~TOOLS_SANITY_TEST_CONCURRENT_THREAD() override = default;
- void ThreadMain() override {
- *value_ = true;
-
- // Sleep for a few milliseconds so the two threads are more likely to live
- // simultaneously. Otherwise we may miss the report due to mutex
- // lock/unlock's inside thread creation code in pure-happens-before mode...
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
- }
- private:
- bool *value_;
-};
-
-class ReleaseStoreThread : public PlatformThread::Delegate {
- public:
- explicit ReleaseStoreThread(base::subtle::Atomic32 *value) : value_(value) {}
- ~ReleaseStoreThread() override = default;
- void ThreadMain() override {
- base::subtle::Release_Store(value_, kMagicValue);
-
- // Sleep for a few milliseconds so the two threads are more likely to live
- // simultaneously. Otherwise we may miss the report due to mutex
- // lock/unlock's inside thread creation code in pure-happens-before mode...
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
- }
- private:
- base::subtle::Atomic32 *value_;
-};
-
-class AcquireLoadThread : public PlatformThread::Delegate {
- public:
- explicit AcquireLoadThread(base::subtle::Atomic32 *value) : value_(value) {}
- ~AcquireLoadThread() override = default;
- void ThreadMain() override {
- // Wait for the other thread to make Release_Store
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
- base::subtle::Acquire_Load(value_);
- }
- private:
- base::subtle::Atomic32 *value_;
-};
-
-void RunInParallel(PlatformThread::Delegate *d1, PlatformThread::Delegate *d2) {
- PlatformThreadHandle a;
- PlatformThreadHandle b;
- PlatformThread::Create(0, d1, &a);
- PlatformThread::Create(0, d2, &b);
- PlatformThread::Join(a);
- PlatformThread::Join(b);
-}
-
-#if defined(THREAD_SANITIZER)
-void DataRace() {
- bool *shared = new bool(false);
- TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(shared), thread2(shared);
- RunInParallel(&thread1, &thread2);
- EXPECT_TRUE(*shared);
- delete shared;
- // We're in a death test - crash.
- CHECK(0);
-}
-#endif
-
-} // namespace
-
-#if defined(THREAD_SANITIZER)
-// A data race detector should report an error in this test.
-TEST(ToolsSanityTest, DataRace) {
- // The suppression regexp must match that in base/debug/tsan_suppressions.cc.
- EXPECT_DEATH(DataRace(), "1 race:base/tools_sanity_unittest.cc");
-}
-#endif
-
-TEST(ToolsSanityTest, AnnotateBenignRace) {
- bool shared = false;
- ANNOTATE_BENIGN_RACE(&shared, "Intentional race - make sure doesn't show up");
- TOOLS_SANITY_TEST_CONCURRENT_THREAD thread1(&shared), thread2(&shared);
- RunInParallel(&thread1, &thread2);
- EXPECT_TRUE(shared);
-}
-
-TEST(ToolsSanityTest, AtomicsAreIgnored) {
- base::subtle::Atomic32 shared = 0;
- ReleaseStoreThread thread1(&shared);
- AcquireLoadThread thread2(&shared);
- RunInParallel(&thread1, &thread2);
- EXPECT_EQ(kMagicValue, shared);
-}
-
-#if BUILDFLAG(CFI_ENFORCEMENT_TRAP)
-#if defined(OS_WIN)
-#define CFI_ERROR_MSG "EXCEPTION_ILLEGAL_INSTRUCTION"
-#elif defined(OS_ANDROID)
-// TODO(pcc): Produce proper stack dumps on Android and test for the correct
-// si_code here.
-#define CFI_ERROR_MSG "^$"
-#else
-#define CFI_ERROR_MSG "ILL_ILLOPN"
-#endif
-#elif BUILDFLAG(CFI_ENFORCEMENT_DIAGNOSTIC)
-#define CFI_ERROR_MSG "runtime error: control flow integrity check"
-#endif // BUILDFLAG(CFI_ENFORCEMENT_TRAP || CFI_ENFORCEMENT_DIAGNOSTIC)
-
-#if defined(CFI_ERROR_MSG)
-class A {
- public:
- A(): n_(0) {}
- virtual void f() { n_++; }
- protected:
- int n_;
-};
-
-class B: public A {
- public:
- void f() override { n_--; }
-};
-
-class C: public B {
- public:
- void f() override { n_ += 2; }
-};
-
-NOINLINE void KillVptrAndCall(A *obj) {
- *reinterpret_cast<void **>(obj) = 0;
- obj->f();
-}
-
-TEST(ToolsSanityTest, BadVirtualCallNull) {
- A a;
- B b;
- EXPECT_DEATH({ KillVptrAndCall(&a); KillVptrAndCall(&b); }, CFI_ERROR_MSG);
-}
-
-NOINLINE void OverwriteVptrAndCall(B *obj, A *vptr) {
- *reinterpret_cast<void **>(obj) = *reinterpret_cast<void **>(vptr);
- obj->f();
-}
-
-TEST(ToolsSanityTest, BadVirtualCallWrongType) {
- A a;
- B b;
- C c;
- EXPECT_DEATH({ OverwriteVptrAndCall(&b, &a); OverwriteVptrAndCall(&b, &c); },
- CFI_ERROR_MSG);
-}
-
-// TODO(pcc): remove CFI_CAST_CHECK, see https://crbug.com/626794.
-#if BUILDFLAG(CFI_CAST_CHECK)
-TEST(ToolsSanityTest, BadDerivedCast) {
- A a;
- EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG);
-}
-
-TEST(ToolsSanityTest, BadUnrelatedCast) {
- class A {
- virtual void f() {}
- };
-
- class B {
- virtual void f() {}
- };
-
- A a;
- EXPECT_DEATH((void)(B*)&a, CFI_ERROR_MSG);
-}
-#endif // BUILDFLAG(CFI_CAST_CHECK)
-
-#endif // CFI_ERROR_MSG
-
-#undef CFI_ERROR_MSG
-#undef MAYBE_AccessesToNewMemory
-#undef MAYBE_AccessesToMallocMemory
-#undef MAYBE_ArrayDeletedWithoutBraces
-#undef MAYBE_SingleElementDeletedWithBraces
-#undef HARMFUL_ACCESS
-#undef HARMFUL_ACCESS_IS_NOOP
-
-} // namespace base
diff --git a/base/trace_event/auto_open_close_event.cc b/base/trace_event/auto_open_close_event.cc
deleted file mode 100644
index 1879700b39..0000000000
--- a/base/trace_event/auto_open_close_event.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2016 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/trace_event/auto_open_close_event.h"
-
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace trace_event {
-
-AutoOpenCloseEvent::AutoOpenCloseEvent(AutoOpenCloseEvent::Type type,
- const char* category, const char* event_name):
- category_(category),
- event_name_(event_name),
- weak_factory_(this) {
- base::trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver(
- weak_factory_.GetWeakPtr());
-}
-
-AutoOpenCloseEvent::~AutoOpenCloseEvent() {
- DCHECK(thread_checker_.CalledOnValidThread());
- base::trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(
- this);
-}
-
-void AutoOpenCloseEvent::Begin() {
- DCHECK(thread_checker_.CalledOnValidThread());
- start_time_ = TRACE_TIME_TICKS_NOW();
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(
- category_, event_name_, static_cast<void*>(this), start_time_);
-}
-
-void AutoOpenCloseEvent::End() {
- DCHECK(thread_checker_.CalledOnValidThread());
- TRACE_EVENT_ASYNC_END0(category_, event_name_, static_cast<void*>(this));
- start_time_ = base::TimeTicks();
-}
-
-void AutoOpenCloseEvent::OnTraceLogEnabled() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (start_time_.ToInternalValue() != 0)
- TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(
- category_, event_name_, static_cast<void*>(this), start_time_);
-}
-
-void AutoOpenCloseEvent::OnTraceLogDisabled() {}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/auto_open_close_event.h b/base/trace_event/auto_open_close_event.h
deleted file mode 100644
index 795a4948ac..0000000000
--- a/base/trace_event/auto_open_close_event.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_AUTO_OPEN_CLOSE_EVENT_H_
-#define BASE_AUTO_OPEN_CLOSE_EVENT_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace trace_event {
-
-// Class for tracing events that support "auto-opening" and "auto-closing".
-// "auto-opening" = if the trace event is started (call Begin() before
-// tracing is started,the trace event will be opened, with the start time
-// being the time that the trace event was actually started.
-// "auto-closing" = if the trace event is started but not ended by the time
-// tracing ends, then the trace event will be automatically closed at the
-// end of tracing.
-class BASE_EXPORT AutoOpenCloseEvent
- : public TraceLog::AsyncEnabledStateObserver {
- public:
- enum Type {
- ASYNC
- };
-
- // As in the rest of the tracing macros, the const char* arguments here
- // must be pointers to indefinitely lived strings (e.g. hard-coded string
- // literals are okay, but not strings created by c_str())
- AutoOpenCloseEvent(Type type, const char* category, const char* event_name);
- ~AutoOpenCloseEvent() override;
-
- void Begin();
- void End();
-
- // AsyncEnabledStateObserver implementation
- void OnTraceLogEnabled() override;
- void OnTraceLogDisabled() override;
-
- private:
- const char* const category_;
- const char* const event_name_;
- base::TimeTicks start_time_;
- base::ThreadChecker thread_checker_;
- WeakPtrFactory<AutoOpenCloseEvent> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AutoOpenCloseEvent);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_AUTO_OPEN_CLOSE_EVENT_H_ \ No newline at end of file
diff --git a/base/trace_event/blame_context.cc b/base/trace_event/blame_context.cc
deleted file mode 100644
index ae0b718201..0000000000
--- a/base/trace_event/blame_context.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2016 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/trace_event/blame_context.h"
-
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-
-namespace base {
-namespace trace_event {
-
-BlameContext::BlameContext(const char* category,
- const char* name,
- const char* type,
- const char* scope,
- int64_t id,
- const BlameContext* parent_context)
- : category_(category),
- name_(name),
- type_(type),
- scope_(scope),
- id_(id),
- parent_scope_(parent_context ? parent_context->scope() : nullptr),
- parent_id_(parent_context ? parent_context->id() : 0),
- category_group_enabled_(nullptr),
- weak_factory_(this) {
- DCHECK(!parent_context || !std::strcmp(name_, parent_context->name()))
- << "Parent blame context must have the same name";
-}
-
-BlameContext::~BlameContext() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(WasInitialized());
- TRACE_EVENT_API_ADD_TRACE_EVENT(
- TRACE_EVENT_PHASE_DELETE_OBJECT, category_group_enabled_, type_, scope_,
- id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID);
- trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(this);
-}
-
-void BlameContext::Enter() {
- DCHECK(WasInitialized());
- TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_ENTER_CONTEXT,
- category_group_enabled_, name_, scope_, id_,
- 0 /* num_args */, nullptr, nullptr, nullptr,
- nullptr, TRACE_EVENT_FLAG_HAS_ID);
-}
-
-void BlameContext::Leave() {
- DCHECK(WasInitialized());
- TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_LEAVE_CONTEXT,
- category_group_enabled_, name_, scope_, id_,
- 0 /* num_args */, nullptr, nullptr, nullptr,
- nullptr, TRACE_EVENT_FLAG_HAS_ID);
-}
-
-void BlameContext::TakeSnapshot() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(WasInitialized());
- if (!*category_group_enabled_)
- return;
- std::unique_ptr<trace_event::TracedValue> snapshot(
- new trace_event::TracedValue);
- AsValueInto(snapshot.get());
- static const char* const kArgName = "snapshot";
- const int kNumArgs = 1;
- unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE};
- std::unique_ptr<trace_event::ConvertableToTraceFormat> arg_values[1] = {
- std::move(snapshot)};
- TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT,
- category_group_enabled_, type_, scope_, id_,
- kNumArgs, &kArgName, arg_types, nullptr,
- arg_values, TRACE_EVENT_FLAG_HAS_ID);
-}
-
-void BlameContext::OnTraceLogEnabled() {
- DCHECK(WasInitialized());
- TakeSnapshot();
-}
-
-void BlameContext::OnTraceLogDisabled() {}
-
-void BlameContext::AsValueInto(trace_event::TracedValue* state) {
- DCHECK(WasInitialized());
- if (!parent_id_)
- return;
- state->BeginDictionary("parent");
- state->SetString("id_ref", StringPrintf("0x%" PRIx64, parent_id_));
- state->SetString("scope", parent_scope_);
- state->EndDictionary();
-}
-
-void BlameContext::Initialize() {
- DCHECK(thread_checker_.CalledOnValidThread());
- category_group_enabled_ =
- TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_);
- TRACE_EVENT_API_ADD_TRACE_EVENT(
- TRACE_EVENT_PHASE_CREATE_OBJECT, category_group_enabled_, type_, scope_,
- id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID);
- trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver(
- weak_factory_.GetWeakPtr());
- TakeSnapshot();
-}
-
-bool BlameContext::WasInitialized() const {
- return category_group_enabled_ != nullptr;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/blame_context.h b/base/trace_event/blame_context.h
deleted file mode 100644
index a973a28fd2..0000000000
--- a/base/trace_event/blame_context.h
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_BLAME_CONTEXT_H_
-#define BASE_TRACE_EVENT_BLAME_CONTEXT_H_
-
-#include <inttypes.h>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "base/trace_event/trace_log.h"
-
-namespace base {
-namespace trace_event {
-class TracedValue;
-}
-
-namespace trace_event {
-
-// A blame context represents a logical unit to which we want to attribute
-// different costs (e.g., CPU, network, or memory usage). An example of a blame
-// context is an <iframe> element on a web page. Different subsystems can
-// "enter" and "leave" blame contexts to indicate that they are doing work which
-// should be accounted against this blame context.
-//
-// A blame context can optionally have a parent context, forming a blame context
-// tree. When work is attributed to a particular blame context, it is considered
-// to count against all of that context's children too. This is useful when work
-// cannot be exactly attributed into a more specific context. For example,
-// Javascript garbage collection generally needs to inspect all objects on a
-// page instead looking at each <iframe> individually. In this case the work
-// should be attributed to a blame context which is the parent of all <iframe>
-// blame contexts.
-class BASE_EXPORT BlameContext
- : public trace_event::TraceLog::AsyncEnabledStateObserver {
- public:
- // Construct a blame context belonging to the blame context tree |name|, using
- // the tracing category |category|, identified by |id| from the |scope|
- // namespace. |type| identifies the type of this object snapshot in the blame
- // context tree. |parent_context| is the parent of this blame context or
- // null. Note that all strings must have application lifetime.
- //
- // For example, a blame context which represents a specific <iframe> in a
- // browser frame tree could be specified with:
- //
- // category="blink",
- // name="FrameTree",
- // type="IFrame",
- // scope="IFrameIdentifier",
- // id=1234.
- //
- // Each <iframe> blame context could have another <iframe> context as a
- // parent, or a top-level context which represents the entire browser:
- //
- // category="blink",
- // name="FrameTree",
- // type="Browser",
- // scope="BrowserIdentifier",
- // id=1.
- //
- // Note that the |name| property is identical, signifying that both context
- // types are part of the same tree.
- //
- BlameContext(const char* category,
- const char* name,
- const char* type,
- const char* scope,
- int64_t id,
- const BlameContext* parent_context);
- ~BlameContext() override;
-
- // Initialize the blame context, automatically taking a snapshot if tracing is
- // enabled. Must be called before any other methods on this class.
- void Initialize();
-
- // Indicate that the current thread is now doing work which should count
- // against this blame context. This function is allowed to be called in a
- // thread different from where the blame context was created; However, any
- // client doing that must be fully responsible for ensuring thready safety.
- void Enter();
-
- // Leave and stop doing work for a previously entered blame context. If
- // another blame context belonging to the same tree was entered prior to this
- // one, it becomes the active blame context for this thread again. Similar
- // to Enter(), this function can be called in a thread different from where
- // the blame context was created, and the same requirement on thread safety
- // must be satisfied.
- void Leave();
-
- // Record a snapshot of the blame context. This is normally only needed if a
- // blame context subclass defines custom properties (see AsValueInto) and one
- // or more of those properties have changed.
- void TakeSnapshot();
-
- const char* category() const { return category_; }
- const char* name() const { return name_; }
- const char* type() const { return type_; }
- const char* scope() const { return scope_; }
- int64_t id() const { return id_; }
-
- // trace_event::TraceLog::EnabledStateObserver implementation:
- void OnTraceLogEnabled() override;
- void OnTraceLogDisabled() override;
-
- protected:
- // Serialize the properties of this blame context into |state|. Subclasses can
- // override this method to record additional properties (e.g, the URL for an
- // <iframe> blame context). Note that an overridden implementation must still
- // call this base method.
- virtual void AsValueInto(trace_event::TracedValue* state);
-
- private:
- bool WasInitialized() const;
-
- // The following string pointers have application lifetime.
- const char* category_;
- const char* name_;
- const char* type_;
- const char* scope_;
- const int64_t id_;
-
- const char* parent_scope_;
- const int64_t parent_id_;
-
- const unsigned char* category_group_enabled_;
-
- ThreadChecker thread_checker_;
- WeakPtrFactory<BlameContext> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(BlameContext);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_BLAME_CONTEXT_H_
diff --git a/base/trace_event/blame_context_unittest.cc b/base/trace_event/blame_context_unittest.cc
deleted file mode 100644
index 12e7857bdf..0000000000
--- a/base/trace_event/blame_context_unittest.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2016 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/trace_event/blame_context.h"
-
-#include "base/json/json_writer.h"
-#include "base/message_loop/message_loop.h"
-#include "base/test/trace_event_analyzer.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-namespace {
-
-const char kTestBlameContextCategory[] = "test";
-const char kDisabledTestBlameContextCategory[] = "disabled-by-default-test";
-const char kTestBlameContextName[] = "TestBlameContext";
-const char kTestBlameContextType[] = "TestBlameContextType";
-const char kTestBlameContextScope[] = "TestBlameContextScope";
-
-class TestBlameContext : public BlameContext {
- public:
- explicit TestBlameContext(int id)
- : BlameContext(kTestBlameContextCategory,
- kTestBlameContextName,
- kTestBlameContextType,
- kTestBlameContextScope,
- id,
- nullptr) {}
-
- TestBlameContext(int id, const TestBlameContext& parent)
- : BlameContext(kTestBlameContextCategory,
- kTestBlameContextName,
- kTestBlameContextType,
- kTestBlameContextScope,
- id,
- &parent) {}
-
- protected:
- void AsValueInto(trace_event::TracedValue* state) override {
- BlameContext::AsValueInto(state);
- state->SetBoolean("crossStreams", false);
- }
-};
-
-class DisabledTestBlameContext : public BlameContext {
- public:
- explicit DisabledTestBlameContext(int id)
- : BlameContext(kDisabledTestBlameContextCategory,
- kTestBlameContextName,
- kTestBlameContextType,
- kTestBlameContextScope,
- id,
- nullptr) {}
-};
-
-class BlameContextTest : public testing::Test {
- protected:
- MessageLoop loop_;
-};
-
-TEST_F(BlameContextTest, EnterAndLeave) {
- using trace_analyzer::Query;
- trace_analyzer::Start("*");
- {
- TestBlameContext blame_context(0x1234);
- blame_context.Initialize();
- blame_context.Enter();
- blame_context.Leave();
- }
- auto analyzer = trace_analyzer::Stop();
-
- trace_analyzer::TraceEventVector events;
- Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) ||
- Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT);
- analyzer->FindEvents(q, &events);
-
- EXPECT_EQ(2u, events.size());
- EXPECT_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, events[0]->phase);
- EXPECT_EQ(kTestBlameContextCategory, events[0]->category);
- EXPECT_EQ(kTestBlameContextName, events[0]->name);
- EXPECT_EQ("0x1234", events[0]->id);
- EXPECT_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, events[1]->phase);
- EXPECT_EQ(kTestBlameContextCategory, events[1]->category);
- EXPECT_EQ(kTestBlameContextName, events[1]->name);
- EXPECT_EQ("0x1234", events[1]->id);
-}
-
-TEST_F(BlameContextTest, DifferentCategories) {
- // Ensure there is no cross talk between blame contexts from different
- // categories.
- using trace_analyzer::Query;
- trace_analyzer::Start("*");
- {
- TestBlameContext blame_context(0x1234);
- DisabledTestBlameContext disabled_blame_context(0x5678);
- blame_context.Initialize();
- blame_context.Enter();
- blame_context.Leave();
- disabled_blame_context.Initialize();
- disabled_blame_context.Enter();
- disabled_blame_context.Leave();
- }
- auto analyzer = trace_analyzer::Stop();
-
- trace_analyzer::TraceEventVector events;
- Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) ||
- Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT);
- analyzer->FindEvents(q, &events);
-
- // None of the events from the disabled-by-default category should show up.
- EXPECT_EQ(2u, events.size());
- EXPECT_EQ(TRACE_EVENT_PHASE_ENTER_CONTEXT, events[0]->phase);
- EXPECT_EQ(kTestBlameContextCategory, events[0]->category);
- EXPECT_EQ(kTestBlameContextName, events[0]->name);
- EXPECT_EQ("0x1234", events[0]->id);
- EXPECT_EQ(TRACE_EVENT_PHASE_LEAVE_CONTEXT, events[1]->phase);
- EXPECT_EQ(kTestBlameContextCategory, events[1]->category);
- EXPECT_EQ(kTestBlameContextName, events[1]->name);
- EXPECT_EQ("0x1234", events[1]->id);
-}
-
-TEST_F(BlameContextTest, TakeSnapshot) {
- using trace_analyzer::Query;
- trace_analyzer::Start("*");
- {
- TestBlameContext parent_blame_context(0x5678);
- TestBlameContext blame_context(0x1234, parent_blame_context);
- parent_blame_context.Initialize();
- blame_context.Initialize();
- blame_context.TakeSnapshot();
- }
- auto analyzer = trace_analyzer::Stop();
-
- trace_analyzer::TraceEventVector events;
- Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT);
- analyzer->FindEvents(q, &events);
-
- // We should have 3 snapshots: one for both calls to Initialize() and one from
- // the explicit call to TakeSnapshot().
- EXPECT_EQ(3u, events.size());
- EXPECT_EQ(kTestBlameContextCategory, events[0]->category);
- EXPECT_EQ(kTestBlameContextType, events[0]->name);
- EXPECT_EQ("0x5678", events[0]->id);
- EXPECT_TRUE(events[0]->HasArg("snapshot"));
-
- EXPECT_EQ(kTestBlameContextCategory, events[1]->category);
- EXPECT_EQ(kTestBlameContextType, events[1]->name);
- EXPECT_EQ("0x1234", events[1]->id);
- EXPECT_TRUE(events[0]->HasArg("snapshot"));
-
- EXPECT_EQ(kTestBlameContextCategory, events[2]->category);
- EXPECT_EQ(kTestBlameContextType, events[2]->name);
- EXPECT_EQ("0x1234", events[2]->id);
- EXPECT_TRUE(events[0]->HasArg("snapshot"));
-
- const char kExpectedSnapshotJson[] =
- "{"
- "\"crossStreams\":false,"
- "\"parent\":{"
- "\"id_ref\":\"0x5678\","
- "\"scope\":\"TestBlameContextScope\""
- "}"
- "}";
-
- std::string snapshot_json;
- JSONWriter::Write(*events[2]->GetKnownArgAsValue("snapshot"), &snapshot_json);
- EXPECT_EQ(kExpectedSnapshotJson, snapshot_json);
-}
-
-} // namepace
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/category_registry.cc b/base/trace_event/category_registry.cc
deleted file mode 100644
index e7c14606d6..0000000000
--- a/base/trace_event/category_registry.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2016 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/trace_event/category_registry.h"
-
-#include <string.h>
-
-#include <type_traits>
-
-#include "base/atomicops.h"
-#include "base/debug/leak_annotations.h"
-#include "base/logging.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/trace_event/trace_category.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-constexpr size_t kMaxCategories = 200;
-const int kNumBuiltinCategories = 4;
-
-// |g_categories| might end up causing creating dynamic initializers if not POD.
-static_assert(std::is_pod<TraceCategory>::value, "TraceCategory must be POD");
-
-// These entries must be kept consistent with the kCategory* consts below.
-TraceCategory g_categories[kMaxCategories] = {
- {0, 0, "tracing categories exhausted; must increase kMaxCategories"},
- {0, 0, "tracing already shutdown"}, // See kCategoryAlreadyShutdown below.
- {0, 0, "__metadata"}, // See kCategoryMetadata below.
- {0, 0, "toplevel"}, // Warmup the toplevel category.
-};
-
-base::subtle::AtomicWord g_category_index = kNumBuiltinCategories;
-
-bool IsValidCategoryPtr(const TraceCategory* category) {
- // If any of these are hit, something has cached a corrupt category pointer.
- uintptr_t ptr = reinterpret_cast<uintptr_t>(category);
- return ptr % sizeof(void*) == 0 &&
- ptr >= reinterpret_cast<uintptr_t>(&g_categories[0]) &&
- ptr <= reinterpret_cast<uintptr_t>(&g_categories[kMaxCategories - 1]);
-}
-
-} // namespace
-
-// static
-TraceCategory* const CategoryRegistry::kCategoryExhausted = &g_categories[0];
-TraceCategory* const CategoryRegistry::kCategoryAlreadyShutdown =
- &g_categories[1];
-TraceCategory* const CategoryRegistry::kCategoryMetadata = &g_categories[2];
-
-// static
-void CategoryRegistry::Initialize() {
- // Trace is enabled or disabled on one thread while other threads are
- // accessing the enabled flag. We don't care whether edge-case events are
- // traced or not, so we allow races on the enabled flag to keep the trace
- // macros fast.
- for (size_t i = 0; i < kMaxCategories; ++i) {
- ANNOTATE_BENIGN_RACE(g_categories[i].state_ptr(),
- "trace_event category enabled");
- // If this DCHECK is hit in a test it means that ResetForTesting() is not
- // called and the categories state leaks between test fixtures.
- DCHECK(!g_categories[i].is_enabled());
- }
-}
-
-// static
-void CategoryRegistry::ResetForTesting() {
- // reset_for_testing clears up only the enabled state and filters. The
- // categories themselves cannot be cleared up because the static pointers
- // injected by the macros still point to them and cannot be reset.
- for (size_t i = 0; i < kMaxCategories; ++i)
- g_categories[i].reset_for_testing();
-}
-
-// static
-TraceCategory* CategoryRegistry::GetCategoryByName(const char* category_name) {
- DCHECK(!strchr(category_name, '"'))
- << "Category names may not contain double quote";
-
- // The g_categories is append only, avoid using a lock for the fast path.
- size_t category_index = base::subtle::Acquire_Load(&g_category_index);
-
- // Search for pre-existing category group.
- for (size_t i = 0; i < category_index; ++i) {
- if (strcmp(g_categories[i].name(), category_name) == 0) {
- return &g_categories[i];
- }
- }
- return nullptr;
-}
-
-bool CategoryRegistry::GetOrCreateCategoryLocked(
- const char* category_name,
- CategoryInitializerFn category_initializer_fn,
- TraceCategory** category) {
- // This is the slow path: the lock is not held in the fastpath
- // (GetCategoryByName), so more than one thread could have reached here trying
- // to add the same category.
- *category = GetCategoryByName(category_name);
- if (*category)
- return false;
-
- // Create a new category.
- size_t category_index = base::subtle::Acquire_Load(&g_category_index);
- if (category_index >= kMaxCategories) {
- NOTREACHED() << "must increase kMaxCategories";
- *category = kCategoryExhausted;
- return false;
- }
-
- // TODO(primiano): this strdup should be removed. The only documented reason
- // for it was TraceWatchEvent, which is gone. However, something might have
- // ended up relying on this. Needs some auditing before removal.
- const char* category_name_copy = strdup(category_name);
- ANNOTATE_LEAKING_OBJECT_PTR(category_name_copy);
-
- *category = &g_categories[category_index];
- DCHECK(!(*category)->is_valid());
- DCHECK(!(*category)->is_enabled());
- (*category)->set_name(category_name_copy);
- category_initializer_fn(*category);
-
- // Update the max index now.
- base::subtle::Release_Store(&g_category_index, category_index + 1);
- return true;
-}
-
-// static
-const TraceCategory* CategoryRegistry::GetCategoryByStatePtr(
- const uint8_t* category_state) {
- const TraceCategory* category = TraceCategory::FromStatePtr(category_state);
- DCHECK(IsValidCategoryPtr(category));
- return category;
-}
-
-// static
-bool CategoryRegistry::IsBuiltinCategory(const TraceCategory* category) {
- DCHECK(IsValidCategoryPtr(category));
- return category < &g_categories[kNumBuiltinCategories];
-}
-
-// static
-CategoryRegistry::Range CategoryRegistry::GetAllCategories() {
- // The |g_categories| array is append only. We have to only guarantee to
- // not return an index to a category which is being initialized by
- // GetOrCreateCategoryByName().
- size_t category_index = base::subtle::Acquire_Load(&g_category_index);
- return CategoryRegistry::Range(&g_categories[0],
- &g_categories[category_index]);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/category_registry.h b/base/trace_event/category_registry.h
deleted file mode 100644
index 9c08efa3e1..0000000000
--- a/base/trace_event/category_registry.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
-#define BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/base_export.h"
-#include "base/logging.h"
-
-namespace base {
-namespace trace_event {
-
-struct TraceCategory;
-class TraceCategoryTest;
-class TraceLog;
-
-// Allows fast and thread-safe acces to the state of all tracing categories.
-// All the methods in this class can be concurrently called on multiple threads,
-// unless otherwise noted (e.g., GetOrCreateCategoryLocked).
-// The reason why this is a fully static class with global state is to allow to
-// statically define known categories as global linker-initialized structs,
-// without requiring static initializers.
-class BASE_EXPORT CategoryRegistry {
- public:
- // Allows for-each iterations over a slice of the categories array.
- class Range {
- public:
- Range(TraceCategory* begin, TraceCategory* end) : begin_(begin), end_(end) {
- DCHECK_LE(begin, end);
- }
- TraceCategory* begin() const { return begin_; }
- TraceCategory* end() const { return end_; }
-
- private:
- TraceCategory* const begin_;
- TraceCategory* const end_;
- };
-
- // Known categories.
- static TraceCategory* const kCategoryExhausted;
- static TraceCategory* const kCategoryMetadata;
- static TraceCategory* const kCategoryAlreadyShutdown;
-
- // Returns a category entry from the Category.state_ptr() pointer.
- // TODO(primiano): trace macros should just keep a pointer to the entire
- // TraceCategory, not just the enabled state pointer. That would remove the
- // need for this function and make everything cleaner at no extra cost (as
- // long as the |state_| is the first field of the struct, which can be
- // guaranteed via static_assert, see TraceCategory ctor).
- static const TraceCategory* GetCategoryByStatePtr(
- const uint8_t* category_state);
-
- // Returns a category from its name or nullptr if not found.
- // The output |category| argument is an undefinitely lived pointer to the
- // TraceCategory owned by the registry. TRACE_EVENTx macros will cache this
- // pointer and use it for checks in their fast-paths.
- static TraceCategory* GetCategoryByName(const char* category_name);
-
- static bool IsBuiltinCategory(const TraceCategory*);
-
- private:
- friend class TraceCategoryTest;
- friend class TraceLog;
- using CategoryInitializerFn = void (*)(TraceCategory*);
-
- // Only for debugging/testing purposes, is a no-op on release builds.
- static void Initialize();
-
- // Resets the state of all categories, to clear up the state between tests.
- static void ResetForTesting();
-
- // Used to get/create a category in the slow-path. If the category exists
- // already, this has the same effect of GetCategoryByName and returns false.
- // If not, a new category is created and the CategoryInitializerFn is invoked
- // before retuning true. The caller must guarantee serialization: either call
- // this method from a single thread or hold a lock when calling this.
- static bool GetOrCreateCategoryLocked(const char* category_name,
- CategoryInitializerFn,
- TraceCategory**);
-
- // Allows to iterate over the valid categories in a for-each loop.
- // This includes builtin categories such as __metadata.
- static Range GetAllCategories();
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_CATEGORY_REGISTRY_H_
diff --git a/base/trace_event/cfi_backtrace_android.cc b/base/trace_event/cfi_backtrace_android.cc
deleted file mode 100644
index 8fd8b955dc..0000000000
--- a/base/trace_event/cfi_backtrace_android.cc
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright 2018 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/trace_event/cfi_backtrace_android.h"
-
-#include <sys/mman.h>
-#include <sys/types.h>
-
-#include "base/android/apk_assets.h"
-
-#if !defined(ARCH_CPU_ARMEL)
-#error This file should not be built for this architecture.
-#endif
-
-/*
-Basics of unwinding:
-For each instruction in a function we need to know what is the offset of SP
-(Stack Pointer) to reach the previous function's stack frame. To know which
-function is being invoked, we need the return address of the next function. The
-CFI information for an instruction is made up of 2 offsets, CFA (Call Frame
-Address) offset and RA (Return Address) offset. The CFA offset is the change in
-SP made by the function till the current instruction. This depends on amount of
-memory allocated on stack by the function plus some registers that the function
-stores that needs to be restored at the end of function. So, at each instruction
-the CFA offset tells the offset from original SP before the function call. The
-RA offset tells us the offset from the previous SP into the current function
-where the return address is stored.
-
-The unwind table file has 2 tables UNW_INDEX and UNW_DATA, inspired from ARM
-EHABI format. The first table contains function addresses and an index into the
-UNW_DATA table. The second table contains one or more rows for the function
-unwind information.
-
-UNW_INDEX contains two columns of N rows each, where N is the number of
-functions.
- 1. First column 4 byte rows of all the function start address as offset from
- start of the binary, in sorted order.
- 2. For each function addr, the second column contains 2 byte indices in order.
- The indices are offsets (in count of 2 bytes) of the CFI data from start of
- UNW_DATA.
-The last entry in the table always contains CANT_UNWIND index to specify the
-end address of the last function.
-
-UNW_DATA contains data of all the functions. Each function data contains N rows.
-The data found at the address pointed from UNW_INDEX will be:
- 2 bytes: N - number of rows that belong to current function.
- N * 4 bytes: N rows of data. 16 bits : Address offset from function start.
- 14 bits : CFA offset / 4.
- 2 bits : RA offset / 4.
-If the RA offset of a row is 0, then use the offset of the previous rows in the
-same function.
-TODO(ssid): Make sure RA offset is always present.
-
-See extract_unwind_tables.py for details about how this data is extracted from
-breakpad symbol files.
-*/
-
-extern "C" {
-extern char __executable_start;
-extern char _etext;
-}
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// The value of index when the function does not have unwind information.
-constexpr uint32_t kCantUnwind = 0xFFFF;
-
-// The mask on the CFI row data that is used to get the high 14 bits and
-// multiply it by 4 to get CFA offset. Since the last 2 bits are masked out, a
-// shift is not necessary.
-constexpr uint16_t kCFAMask = 0xfffc;
-
-// The mask on the CFI row data that is used to get the low 2 bits and multiply
-// it by 4 to get the RA offset.
-constexpr uint16_t kRAMask = 0x3;
-constexpr uint16_t kRAShift = 2;
-
-// The code in this file assumes we are running in 32-bit builds since all the
-// addresses in the unwind table are specified in 32 bits.
-static_assert(sizeof(uintptr_t) == 4,
- "The unwind table format is only valid for 32 bit builds.");
-
-// The CFI data in UNW_DATA table starts with number of rows (N) and then
-// followed by N rows of 4 bytes long. The CFIUnwindDataRow represents a single
-// row of CFI data of a function in the table. Since we cast the memory at the
-// address after the address of number of rows, into an array of
-// CFIUnwindDataRow, the size of the struct should be 4 bytes and the order of
-// the members is fixed according to the given format. The first 2 bytes tell
-// the address of function and last 2 bytes give the CFI data for the offset.
-struct CFIUnwindDataRow {
- // The address of the instruction in terms of offset from the start of the
- // function.
- uint16_t addr_offset;
- // Represents the CFA and RA offsets to get information about next stack
- // frame. This is the CFI data at the point before executing the instruction
- // at |addr_offset| from the start of the function.
- uint16_t cfi_data;
-
- // Return the RA offset for the current unwind row.
- size_t ra_offset() const { return (cfi_data & kRAMask) << kRAShift; }
-
- // Returns the CFA offset for the current unwind row.
- size_t cfa_offset() const { return cfi_data & kCFAMask; }
-};
-
-static_assert(
- sizeof(CFIUnwindDataRow) == 4,
- "The CFIUnwindDataRow struct must be exactly 4 bytes for searching.");
-
-} // namespace
-
-// static
-CFIBacktraceAndroid* CFIBacktraceAndroid::GetInitializedInstance() {
- static CFIBacktraceAndroid* instance = new CFIBacktraceAndroid();
- return instance;
-}
-
-CFIBacktraceAndroid::CFIBacktraceAndroid()
- : thread_local_cfi_cache_(
- [](void* ptr) { delete static_cast<CFICache*>(ptr); }) {
- Initialize();
-}
-
-CFIBacktraceAndroid::~CFIBacktraceAndroid() {}
-
-void CFIBacktraceAndroid::Initialize() {
- // The address |_etext| gives the end of the .text section in the binary. This
- // value is more accurate than parsing the memory map since the mapped
- // regions are usualy larger than the .text section.
- executable_end_addr_ = reinterpret_cast<uintptr_t>(&_etext);
- // The address of |__executable_start| gives the start address of the
- // executable. This value is used to find the offset address of the
- // instruction in binary from PC.
- executable_start_addr_ = reinterpret_cast<uintptr_t>(&__executable_start);
-
- // This file name is defined by extract_unwind_tables.gni.
- static constexpr char kCfiFileName[] = "assets/unwind_cfi_32";
- MemoryMappedFile::Region cfi_region;
- int fd = base::android::OpenApkAsset(kCfiFileName, &cfi_region);
- if (fd < 0)
- return;
- cfi_mmap_ = std::make_unique<MemoryMappedFile>();
- // The CFI region starts at |cfi_region.offset|.
- if (!cfi_mmap_->Initialize(base::File(fd), cfi_region))
- return;
-
- ParseCFITables();
- can_unwind_stack_frames_ = true;
-}
-
-void CFIBacktraceAndroid::ParseCFITables() {
- // The first 4 bytes in the file is the size of UNW_INDEX table.
- static constexpr size_t kUnwIndexRowSize =
- sizeof(*unw_index_function_col_) + sizeof(*unw_index_indices_col_);
- size_t unw_index_size = 0;
- memcpy(&unw_index_size, cfi_mmap_->data(), sizeof(unw_index_size));
- DCHECK_EQ(0u, unw_index_size % kUnwIndexRowSize);
- // UNW_INDEX table starts after 4 bytes.
- unw_index_function_col_ =
- reinterpret_cast<const uintptr_t*>(cfi_mmap_->data()) + 1;
- unw_index_row_count_ = unw_index_size / kUnwIndexRowSize;
- unw_index_indices_col_ = reinterpret_cast<const uint16_t*>(
- unw_index_function_col_ + unw_index_row_count_);
-
- // The UNW_DATA table data is right after the end of UNW_INDEX table.
- // Interpret the UNW_DATA table as an array of 2 byte numbers since the
- // indexes we have from the UNW_INDEX table are in terms of 2 bytes.
- unw_data_start_addr_ = unw_index_indices_col_ + unw_index_row_count_;
-}
-
-size_t CFIBacktraceAndroid::Unwind(const void** out_trace, size_t max_depth) {
- // This function walks the stack using the call frame information to find the
- // return addresses of all the functions that belong to current binary in call
- // stack. For each function the CFI table defines the offset of the previous
- // call frame and offset where the return address is stored.
- if (!can_unwind_stack_frames())
- return 0;
-
- // Get the current register state. This register state can be taken at any
- // point in the function and the unwind information would be for this point.
- // Define local variables before trying to get the current PC and SP to make
- // sure the register state obtained is consistent with each other.
- uintptr_t pc = 0, sp = 0;
- asm volatile("mov %0, pc" : "=r"(pc));
- asm volatile("mov %0, sp" : "=r"(sp));
-
- // We can only unwind as long as the pc is within the chrome.so.
- size_t depth = 0;
- while (pc > executable_start_addr_ && pc <= executable_end_addr_ &&
- depth < max_depth) {
- out_trace[depth++] = reinterpret_cast<void*>(pc);
- // The offset of function from the start of the chrome.so binary:
- uintptr_t func_addr = pc - executable_start_addr_;
- CFIRow cfi{};
- if (!FindCFIRowForPC(func_addr, &cfi))
- break;
-
- // The rules for unwinding using the CFI information are:
- // SP_prev = SP_cur + cfa_offset and
- // PC_prev = * (SP_prev - ra_offset).
- sp = sp + cfi.cfa_offset;
- memcpy(&pc, reinterpret_cast<uintptr_t*>(sp - cfi.ra_offset),
- sizeof(uintptr_t));
- }
- return depth;
-}
-
-bool CFIBacktraceAndroid::FindCFIRowForPC(uintptr_t func_addr,
- CFIBacktraceAndroid::CFIRow* cfi) {
- auto* cache = GetThreadLocalCFICache();
- *cfi = {0};
- if (cache->Find(func_addr, cfi))
- return true;
-
- // Consider each column of UNW_INDEX table as arrays of uintptr_t (function
- // addresses) and uint16_t (indices). Define start and end iterator on the
- // first column array (addresses) and use std::lower_bound() to binary search
- // on this array to find the required function address.
- static const uintptr_t* const unw_index_fn_end =
- unw_index_function_col_ + unw_index_row_count_;
- const uintptr_t* found =
- std::lower_bound(unw_index_function_col_, unw_index_fn_end, func_addr);
-
- // If found is start, then the given function is not in the table. If the
- // given pc is start of a function then we cannot unwind.
- if (found == unw_index_function_col_ || *found == func_addr)
- return false;
-
- // std::lower_bound() returns the iter that corresponds to the first address
- // that is greater than the given address. So, the required iter is always one
- // less than the value returned by std::lower_bound().
- --found;
- uintptr_t func_start_addr = *found;
- size_t row_num = found - unw_index_function_col_;
- uint16_t index = unw_index_indices_col_[row_num];
- DCHECK_LE(func_start_addr, func_addr);
- // If the index is CANT_UNWIND then we do not have unwind infomation for the
- // function.
- if (index == kCantUnwind)
- return false;
-
- // The unwind data for the current function is at an offsset of the index
- // found in UNW_INDEX table.
- const uint16_t* unwind_data = unw_data_start_addr_ + index;
- // The value of first 2 bytes is the CFI data row count for the function.
- uint16_t row_count = 0;
- memcpy(&row_count, unwind_data, sizeof(row_count));
- // And the actual CFI rows start after 2 bytes from the |unwind_data|. Cast
- // the data into an array of CFIUnwindDataRow since the struct is designed to
- // represent each row. We should be careful to read only |row_count| number of
- // elements in the array.
- const CFIUnwindDataRow* function_data =
- reinterpret_cast<const CFIUnwindDataRow*>(unwind_data + 1);
-
- // Iterate through the CFI rows of the function to find the row that gives
- // offset for the given instruction address.
- CFIUnwindDataRow cfi_row = {0, 0};
- uint16_t ra_offset = 0;
- for (uint16_t i = 0; i < row_count; ++i) {
- CFIUnwindDataRow row;
- memcpy(&row, function_data + i, sizeof(CFIUnwindDataRow));
- // The return address of the function is the instruction that is not yet
- // been executed. The cfi row specifies the unwind info before executing the
- // given instruction. If the given address is equal to the instruction
- // offset, then use the current row. Or use the row with highest address
- // less than the given address.
- if (row.addr_offset + func_start_addr > func_addr)
- break;
-
- cfi_row = row;
- // The ra offset of the last specified row should be used, if unspecified.
- // So, keep updating the RA offset till we reach the correct CFI row.
- // TODO(ssid): This should be fixed in the format and we should always
- // output ra offset.
- if (cfi_row.ra_offset())
- ra_offset = cfi_row.ra_offset();
- }
- DCHECK_NE(0u, cfi_row.addr_offset);
- *cfi = {cfi_row.cfa_offset(), ra_offset};
- DCHECK(cfi->cfa_offset);
- DCHECK(cfi->ra_offset);
-
- // safe to update since the cache is thread local.
- cache->Add(func_addr, *cfi);
- return true;
-}
-
-CFIBacktraceAndroid::CFICache* CFIBacktraceAndroid::GetThreadLocalCFICache() {
- auto* cache = static_cast<CFICache*>(thread_local_cfi_cache_.Get());
- if (!cache) {
- cache = new CFICache();
- thread_local_cfi_cache_.Set(cache);
- }
- return cache;
-}
-
-void CFIBacktraceAndroid::CFICache::Add(uintptr_t address, CFIRow cfi) {
- cache_[address % kLimit] = {address, cfi};
-}
-
-bool CFIBacktraceAndroid::CFICache::Find(uintptr_t address, CFIRow* cfi) {
- if (cache_[address % kLimit].address == address) {
- *cfi = cache_[address % kLimit].cfi;
- return true;
- }
- return false;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/cfi_backtrace_android.h b/base/trace_event/cfi_backtrace_android.h
deleted file mode 100644
index 0c513321c8..0000000000
--- a/base/trace_event/cfi_backtrace_android.h
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2018 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.
-
-#ifndef BASE_TRACE_EVENT_CFI_BACKTRACE_ANDROID_H_
-#define BASE_TRACE_EVENT_CFI_BACKTRACE_ANDROID_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/base_export.h"
-#include "base/debug/debugging_buildflags.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/gtest_prod_util.h"
-#include "base/threading/thread_local_storage.h"
-
-namespace base {
-namespace trace_event {
-
-// This class is used to unwind stack frames in the current thread. The unwind
-// information (dwarf debug info) is stripped from the chrome binary and we do
-// not build with exception tables (ARM EHABI) in release builds. So, we use a
-// custom unwind table which is generated and added to specific android builds,
-// when add_unwind_tables_in_apk build option is specified. This unwind table
-// contains information for unwinding stack frames when the functions calls are
-// from lib[mono]chrome.so. The file is added as an asset to the apk and the
-// table is used to unwind stack frames for profiling. This class implements
-// methods to read and parse the unwind table and unwind stack frames using this
-// data.
-class BASE_EXPORT CFIBacktraceAndroid {
- public:
- // Creates and initializes by memory mapping the unwind tables from apk assets
- // on first call.
- static CFIBacktraceAndroid* GetInitializedInstance();
-
- // Returns true if stack unwinding is possible using CFI unwind tables in apk.
- // There is no need to check this before each unwind call. Will always return
- // the same value based on CFI tables being present in the binary.
- bool can_unwind_stack_frames() const { return can_unwind_stack_frames_; }
-
- // Returns the program counters by unwinding stack in the current thread in
- // order of latest call frame first. Unwinding works only if
- // can_unwind_stack_frames() returns true. This function allocates memory from
- // heap for caches. For each stack frame, this method searches through the
- // unwind table mapped in memory to find the unwind information for function
- // and walks the stack to find all the return address. This only works until
- // the last function call from the chrome.so. We do not have unwind
- // information to unwind beyond any frame outside of chrome.so. Calls to
- // Unwind() are thread safe and lock free, once Initialize() returns success.
- size_t Unwind(const void** out_trace, size_t max_depth);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(CFIBacktraceAndroidTest, TestCFICache);
- FRIEND_TEST_ALL_PREFIXES(CFIBacktraceAndroidTest, TestFindCFIRow);
- FRIEND_TEST_ALL_PREFIXES(CFIBacktraceAndroidTest, TestUnwinding);
-
- // The CFI information that correspond to an instruction.
- struct CFIRow {
- bool operator==(const CFIBacktraceAndroid::CFIRow& o) const {
- return cfa_offset == o.cfa_offset && ra_offset == o.ra_offset;
- }
-
- // The offset of the call frame address of previous function from the
- // current stack pointer. Rule for unwinding SP: SP_prev = SP_cur +
- // cfa_offset.
- uint16_t cfa_offset = 0;
- // The offset of location of return address from the previous call frame
- // address. Rule for unwinding PC: PC_prev = * (SP_prev - ra_offset).
- uint16_t ra_offset = 0;
- };
-
- // A simple cache that stores entries in table using prime modulo hashing.
- // This cache with 500 entries already gives us 95% hit rate, and fits in a
- // single system page (usually 4KiB). Using a thread local cache for each
- // thread gives us 30% improvements on performance of heap profiling.
- class CFICache {
- public:
- // Add new item to the cache. It replaces an existing item with same hash.
- // Constant time operation.
- void Add(uintptr_t address, CFIRow cfi);
-
- // Finds the given address and fills |cfi| with the info for the address.
- // returns true if found, otherwise false. Assumes |address| is never 0.
- bool Find(uintptr_t address, CFIRow* cfi);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(CFIBacktraceAndroidTest, TestCFICache);
-
- // Size is the highest prime which fits the cache in a single system page,
- // usually 4KiB. A prime is chosen to make sure addresses are hashed evenly.
- static const int kLimit = 509;
-
- struct AddrAndCFI {
- uintptr_t address;
- CFIRow cfi;
- };
- AddrAndCFI cache_[kLimit] = {};
- };
-
- static_assert(sizeof(CFIBacktraceAndroid::CFICache) < 4096,
- "The cache does not fit in a single page.");
-
- CFIBacktraceAndroid();
- ~CFIBacktraceAndroid();
-
- // Initializes unwind tables using the CFI asset file in the apk if present.
- // Also stores the limits of mapped region of the lib[mono]chrome.so binary,
- // since the unwind is only feasible for addresses within the .so file. Once
- // initialized, the memory map of the unwind table is never cleared since we
- // cannot guarantee that all the threads are done using the memory map when
- // heap profiling is turned off. But since we keep the memory map is clean,
- // the system can choose to evict the unused pages when needed. This would
- // still reduce the total amount of address space available in process.
- void Initialize();
-
- // Finds the UNW_INDEX and UNW_DATA tables in from the CFI file memory map.
- void ParseCFITables();
-
- // Finds the CFI row for the given |func_addr| in terms of offset from
- // the start of the current binary.
- bool FindCFIRowForPC(uintptr_t func_addr, CFIRow* out);
-
- CFICache* GetThreadLocalCFICache();
-
- // Details about the memory mapped region which contains the libchrome.so
- // library file.
- uintptr_t executable_start_addr_ = 0;
- uintptr_t executable_end_addr_ = 0;
-
- // The start address of the memory mapped unwind table asset file. Unique ptr
- // because it is replaced in tests.
- std::unique_ptr<MemoryMappedFile> cfi_mmap_;
-
- // The UNW_INDEX table: Start address of the function address column. The
- // memory segment corresponding to this column is treated as an array of
- // uintptr_t.
- const uintptr_t* unw_index_function_col_ = nullptr;
- // The UNW_INDEX table: Start address of the index column. The memory segment
- // corresponding to this column is treated as an array of uint16_t.
- const uint16_t* unw_index_indices_col_ = nullptr;
- // The number of rows in UNW_INDEX table.
- size_t unw_index_row_count_ = 0;
-
- // The start address of UNW_DATA table.
- const uint16_t* unw_data_start_addr_ = nullptr;
-
- bool can_unwind_stack_frames_ = false;
-
- ThreadLocalStorage::Slot thread_local_cfi_cache_;
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_CFI_BACKTRACE_ANDROID_H_
diff --git a/base/trace_event/cfi_backtrace_android_unittest.cc b/base/trace_event/cfi_backtrace_android_unittest.cc
deleted file mode 100644
index 3ad3d33042..0000000000
--- a/base/trace_event/cfi_backtrace_android_unittest.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2018 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/trace_event/cfi_backtrace_android.h"
-
-#include "base/files/file_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-void* GetPC() {
- return __builtin_return_address(0);
-}
-
-} // namespace
-
-TEST(CFIBacktraceAndroidTest, TestUnwinding) {
- auto* unwinder = CFIBacktraceAndroid::GetInitializedInstance();
- EXPECT_TRUE(unwinder->can_unwind_stack_frames());
- EXPECT_GT(unwinder->executable_start_addr_, 0u);
- EXPECT_GT(unwinder->executable_end_addr_, unwinder->executable_start_addr_);
- EXPECT_GT(unwinder->cfi_mmap_->length(), 0u);
-
- const size_t kMaxFrames = 100;
- const void* frames[kMaxFrames];
- size_t unwind_count = unwinder->Unwind(frames, kMaxFrames);
- // Expect at least 2 frames in the result.
- ASSERT_GT(unwind_count, 2u);
- EXPECT_LE(unwind_count, kMaxFrames);
-
- const size_t kMaxCurrentFuncCodeSize = 50;
- const uintptr_t current_pc = reinterpret_cast<uintptr_t>(GetPC());
- const uintptr_t actual_frame = reinterpret_cast<uintptr_t>(frames[2]);
- EXPECT_NEAR(current_pc, actual_frame, kMaxCurrentFuncCodeSize);
-
- for (size_t i = 0; i < unwind_count; ++i) {
- EXPECT_GT(reinterpret_cast<uintptr_t>(frames[i]),
- unwinder->executable_start_addr_);
- EXPECT_LT(reinterpret_cast<uintptr_t>(frames[i]),
- unwinder->executable_end_addr_);
- }
-}
-
-// Flaky: https://bugs.chromium.org/p/chromium/issues/detail?id=829555
-TEST(CFIBacktraceAndroidTest, DISABLED_TestFindCFIRow) {
- auto* unwinder = CFIBacktraceAndroid::GetInitializedInstance();
- /* Input is generated from the CFI file:
- STACK CFI INIT 1000 500
- STACK CFI 1002 .cfa: sp 272 + .ra: .cfa -4 + ^ r4: .cfa -16 +
- STACK CFI 1008 .cfa: sp 544 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
- STACK CFI 1040 .cfa: sp 816 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
- STACK CFI 1050 .cfa: sp 816 + .ra: .cfa -8 + ^ r4: .cfa -16 + ^
- STACK CFI 1080 .cfa: sp 544 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
-
- STACK CFI INIT 2000 22
- STACK CFI 2004 .cfa: sp 16 + .ra: .cfa -12 + ^ r4: .cfa -16 + ^
- STACK CFI 2008 .cfa: sp 16 + .ra: .cfa -12 + ^ r4: .cfa -16 + ^
-
- STACK CFI INIT 2024 100
- STACK CFI 2030 .cfa: sp 48 + .ra: .cfa -12 + ^ r4: .cfa -16 + ^
- STACK CFI 2100 .cfa: sp 64 + .r1: .cfa -0 + ^ r4: .cfa -16 + ^
-
- STACK CFI INIT 2200 10
- STACK CFI 2204 .cfa: sp 44 + .ra: .cfa -8 + ^ r4: .cfa -16 + ^
- */
- uint16_t input[] = {// UNW_INDEX size
- 0x2A,
-
- // UNW_INDEX address column (4 byte rows).
- 0x0, 0x1000, 0x0, 0x1502, 0x0, 0x2000, 0x0, 0x2024, 0x0,
- 0x2126, 0x0, 0x2200, 0x0, 0x2212, 0x0,
-
- // UNW_INDEX index column (2 byte rows).
- 0x0, 0xffff, 0xb, 0x10, 0xffff, 0x15, 0xffff,
-
- // UNW_DATA table.
- 0x5, 0x2, 0x111, 0x8, 0x220, 0x40, 0x330, 0x50, 0x332,
- 0x80, 0x220, 0x2, 0x4, 0x13, 0x8, 0x13, 0x2, 0xc, 0x33,
- 0xdc, 0x40, 0x1, 0x4, 0x2e};
- FilePath temp_path;
- CreateTemporaryFile(&temp_path);
- EXPECT_EQ(
- static_cast<int>(sizeof(input)),
- WriteFile(temp_path, reinterpret_cast<char*>(input), sizeof(input)));
-
- unwinder->cfi_mmap_.reset(new MemoryMappedFile());
- unwinder->cfi_mmap_->Initialize(temp_path);
- unwinder->ParseCFITables();
-
- CFIBacktraceAndroid::CFIRow cfi_row = {0};
- EXPECT_FALSE(unwinder->FindCFIRowForPC(0x01, &cfi_row));
- EXPECT_FALSE(unwinder->FindCFIRowForPC(0x100, &cfi_row));
- EXPECT_FALSE(unwinder->FindCFIRowForPC(0x1502, &cfi_row));
- EXPECT_FALSE(unwinder->FindCFIRowForPC(0x3000, &cfi_row));
- EXPECT_FALSE(unwinder->FindCFIRowForPC(0x2024, &cfi_row));
- EXPECT_FALSE(unwinder->FindCFIRowForPC(0x2212, &cfi_row));
-
- const CFIBacktraceAndroid::CFIRow kRow1 = {0x110, 0x4};
- const CFIBacktraceAndroid::CFIRow kRow2 = {0x220, 0x4};
- const CFIBacktraceAndroid::CFIRow kRow3 = {0x220, 0x8};
- const CFIBacktraceAndroid::CFIRow kRow4 = {0x30, 0xc};
- const CFIBacktraceAndroid::CFIRow kRow5 = {0x2c, 0x8};
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1002, &cfi_row));
- EXPECT_EQ(kRow1, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1003, &cfi_row));
- EXPECT_EQ(kRow1, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1008, &cfi_row));
- EXPECT_EQ(kRow2, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1009, &cfi_row));
- EXPECT_EQ(kRow2, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1039, &cfi_row));
- EXPECT_EQ(kRow2, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1080, &cfi_row));
- EXPECT_EQ(kRow3, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1100, &cfi_row));
- EXPECT_EQ(kRow3, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2050, &cfi_row));
- EXPECT_EQ(kRow4, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2208, &cfi_row));
- EXPECT_EQ(kRow5, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2210, &cfi_row));
- EXPECT_EQ(kRow5, cfi_row);
-
- // Test if cache is used on the future calls to Find, all addresses should
- // have different hash. Resetting the memory map to make sure it is never
- // accessed in Find().
- unwinder->cfi_mmap_.reset(new MemoryMappedFile());
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1002, &cfi_row));
- EXPECT_EQ(kRow1, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1003, &cfi_row));
- EXPECT_EQ(kRow1, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1008, &cfi_row));
- EXPECT_EQ(kRow2, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1009, &cfi_row));
- EXPECT_EQ(kRow2, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1039, &cfi_row));
- EXPECT_EQ(kRow2, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1080, &cfi_row));
- EXPECT_EQ(kRow3, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x1100, &cfi_row));
- EXPECT_EQ(kRow3, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2050, &cfi_row));
- EXPECT_EQ(kRow4, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2208, &cfi_row));
- EXPECT_EQ(kRow5, cfi_row);
- EXPECT_TRUE(unwinder->FindCFIRowForPC(0x2210, &cfi_row));
- EXPECT_EQ(kRow5, cfi_row);
-}
-
-TEST(CFIBacktraceAndroidTest, TestCFICache) {
- // Use ASSERT macros in this function since they are in loop and using EXPECT
- // prints too many failures.
- CFIBacktraceAndroid::CFICache cache;
- CFIBacktraceAndroid::CFIRow cfi;
-
- // Empty cache should not find anything.
- EXPECT_FALSE(cache.Find(1, &cfi));
-
- // Insert 1 - 2*kLimit
- for (size_t i = 1; i <= 2 * cache.kLimit; ++i) {
- CFIBacktraceAndroid::CFIRow val = {4 * i, 2 * i};
- cache.Add(i, val);
- ASSERT_TRUE(cache.Find(i, &cfi));
- ASSERT_EQ(cfi, val);
-
- // Inserting more than kLimit items evicts |i - cache.kLimit| from cache.
- if (i >= cache.kLimit)
- ASSERT_FALSE(cache.Find(i - cache.kLimit, &cfi));
- }
- // Cache contains kLimit+1 - 2*kLimit.
-
- // Check that 1 - kLimit cannot be found.
- for (size_t i = 1; i <= cache.kLimit; ++i) {
- ASSERT_FALSE(cache.Find(i, &cfi));
- }
-
- // Check if kLimit+1 - 2*kLimit still exists in cache.
- for (size_t i = cache.kLimit + 1; i <= 2 * cache.kLimit; ++i) {
- CFIBacktraceAndroid::CFIRow val = {4 * i, 2 * i};
- ASSERT_TRUE(cache.Find(i, &cfi));
- ASSERT_EQ(cfi, val);
- }
-
- // Insert 2*kLimit+1, will evict kLimit.
- cfi = {1, 1};
- cache.Add(2 * cache.kLimit + 1, cfi);
- EXPECT_TRUE(cache.Find(2 * cache.kLimit + 1, &cfi));
- EXPECT_FALSE(cache.Find(cache.kLimit + 1, &cfi));
- // Cache contains kLimit+1 - 2*kLimit.
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/event_name_filter.cc b/base/trace_event/event_name_filter.cc
deleted file mode 100644
index 7bf932e040..0000000000
--- a/base/trace_event/event_name_filter.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 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/trace_event/event_name_filter.h"
-
-#include "base/trace_event/trace_event_impl.h"
-
-namespace base {
-namespace trace_event {
-
-// static
-const char EventNameFilter::kName[] = "event_whitelist_predicate";
-
-EventNameFilter::EventNameFilter(
- std::unique_ptr<EventNamesWhitelist> event_names_whitelist)
- : event_names_whitelist_(std::move(event_names_whitelist)) {}
-
-EventNameFilter::~EventNameFilter() = default;
-
-bool EventNameFilter::FilterTraceEvent(const TraceEvent& trace_event) const {
- return event_names_whitelist_->count(trace_event.name()) != 0;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/event_name_filter.h b/base/trace_event/event_name_filter.h
deleted file mode 100644
index 19333b3e03..0000000000
--- a/base/trace_event/event_name_filter.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_EVENT_NAME_FILTER_H_
-#define BASE_TRACE_EVENT_EVENT_NAME_FILTER_H_
-
-#include <memory>
-#include <string>
-#include <unordered_set>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/trace_event/trace_event_filter.h"
-
-namespace base {
-namespace trace_event {
-
-class TraceEvent;
-
-// Filters trace events by checking the full name against a whitelist.
-// The current implementation is quite simple and dumb and just uses a
-// hashtable which requires char* to std::string conversion. It could be smarter
-// and use a bloom filter trie. However, today this is used too rarely to
-// justify that cost.
-class BASE_EXPORT EventNameFilter : public TraceEventFilter {
- public:
- using EventNamesWhitelist = std::unordered_set<std::string>;
- static const char kName[];
-
- EventNameFilter(std::unique_ptr<EventNamesWhitelist>);
- ~EventNameFilter() override;
-
- // TraceEventFilter implementation.
- bool FilterTraceEvent(const TraceEvent&) const override;
-
- private:
- std::unique_ptr<const EventNamesWhitelist> event_names_whitelist_;
-
- DISALLOW_COPY_AND_ASSIGN(EventNameFilter);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_EVENT_NAME_FILTER_H_
diff --git a/base/trace_event/event_name_filter_unittest.cc b/base/trace_event/event_name_filter_unittest.cc
deleted file mode 100644
index 134be0df33..0000000000
--- a/base/trace_event/event_name_filter_unittest.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 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/trace_event/event_name_filter.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-const TraceEvent& MakeTraceEvent(const char* name) {
- static TraceEvent event;
- event.Reset();
- event.Initialize(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name, "", 0, 0,
- 0, nullptr, nullptr, nullptr, nullptr, 0);
- return event;
-}
-
-TEST(TraceEventNameFilterTest, Whitelist) {
- auto empty_whitelist =
- std::make_unique<EventNameFilter::EventNamesWhitelist>();
- auto filter = std::make_unique<EventNameFilter>(std::move(empty_whitelist));
-
- // No events should be filtered if the whitelist is empty.
- EXPECT_FALSE(filter->FilterTraceEvent(MakeTraceEvent("foo")));
-
- auto whitelist = std::make_unique<EventNameFilter::EventNamesWhitelist>();
- whitelist->insert("foo");
- whitelist->insert("bar");
- filter = std::make_unique<EventNameFilter>(std::move(whitelist));
- EXPECT_TRUE(filter->FilterTraceEvent(MakeTraceEvent("foo")));
- EXPECT_FALSE(filter->FilterTraceEvent(MakeTraceEvent("fooz")));
- EXPECT_FALSE(filter->FilterTraceEvent(MakeTraceEvent("afoo")));
- EXPECT_TRUE(filter->FilterTraceEvent(MakeTraceEvent("bar")));
- EXPECT_FALSE(filter->FilterTraceEvent(MakeTraceEvent("foobar")));
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/heap_profiler_allocation_context.cc b/base/trace_event/heap_profiler_allocation_context.cc
deleted file mode 100644
index bdc3c58bd4..0000000000
--- a/base/trace_event/heap_profiler_allocation_context.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2015 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/trace_event/heap_profiler_allocation_context.h"
-
-#include <cstring>
-
-#include "base/hash.h"
-#include "base/macros.h"
-
-namespace base {
-namespace trace_event {
-
-bool operator < (const StackFrame& lhs, const StackFrame& rhs) {
- return lhs.value < rhs.value;
-}
-
-bool operator == (const StackFrame& lhs, const StackFrame& rhs) {
- return lhs.value == rhs.value;
-}
-
-bool operator != (const StackFrame& lhs, const StackFrame& rhs) {
- return !(lhs.value == rhs.value);
-}
-
-Backtrace::Backtrace() = default;
-
-bool operator==(const Backtrace& lhs, const Backtrace& rhs) {
- if (lhs.frame_count != rhs.frame_count) return false;
- return std::equal(lhs.frames, lhs.frames + lhs.frame_count, rhs.frames);
-}
-
-bool operator!=(const Backtrace& lhs, const Backtrace& rhs) {
- return !(lhs == rhs);
-}
-
-AllocationContext::AllocationContext(): type_name(nullptr) {}
-
-AllocationContext::AllocationContext(const Backtrace& backtrace,
- const char* type_name)
- : backtrace(backtrace), type_name(type_name) {}
-
-bool operator==(const AllocationContext& lhs, const AllocationContext& rhs) {
- return (lhs.backtrace == rhs.backtrace) && (lhs.type_name == rhs.type_name);
-}
-
-bool operator!=(const AllocationContext& lhs, const AllocationContext& rhs) {
- return !(lhs == rhs);
-}
-
-} // namespace trace_event
-} // namespace base
-
-namespace std {
-
-using base::trace_event::AllocationContext;
-using base::trace_event::Backtrace;
-using base::trace_event::StackFrame;
-
-size_t hash<StackFrame>::operator()(const StackFrame& frame) const {
- return hash<const void*>()(frame.value);
-}
-
-size_t hash<Backtrace>::operator()(const Backtrace& backtrace) const {
- const void* values[Backtrace::kMaxFrameCount];
- for (size_t i = 0; i != backtrace.frame_count; ++i) {
- values[i] = backtrace.frames[i].value;
- }
- return base::PersistentHash(values, backtrace.frame_count * sizeof(*values));
-}
-
-size_t hash<AllocationContext>::operator()(const AllocationContext& ctx) const {
- size_t backtrace_hash = hash<Backtrace>()(ctx.backtrace);
-
- // Multiplicative hash from [Knuth 1998]. Works best if |size_t| is 32 bits,
- // because the magic number is a prime very close to 2^32 / golden ratio, but
- // will still redistribute keys bijectively on 64-bit architectures because
- // the magic number is coprime to 2^64.
- size_t type_hash = reinterpret_cast<size_t>(ctx.type_name) * 2654435761;
-
- // Multiply one side to break the commutativity of +. Multiplication with a
- // number coprime to |numeric_limits<size_t>::max() + 1| is bijective so
- // randomness is preserved.
- return (backtrace_hash * 3) + type_hash;
-}
-
-} // namespace std
diff --git a/base/trace_event/heap_profiler_allocation_context.h b/base/trace_event/heap_profiler_allocation_context.h
deleted file mode 100644
index c35663fb10..0000000000
--- a/base/trace_event/heap_profiler_allocation_context.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_
-#define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <functional>
-
-#include "base/base_export.h"
-
-namespace base {
-namespace trace_event {
-
-// When heap profiling is enabled, tracing keeps track of the allocation
-// context for each allocation intercepted. It is generated by the
-// |AllocationContextTracker| which keeps stacks of context in TLS.
-// The tracker is initialized lazily.
-
-// The backtrace in the allocation context is a snapshot of the stack. For now,
-// this is the pseudo stack where frames are created by trace event macros. In
-// the future, we might add the option to use the native call stack. In that
-// case, |Backtrace| and |AllocationContextTracker::GetContextSnapshot| might
-// have different implementations that can be selected by a compile time flag.
-
-// The number of stack frames stored in the backtrace is a trade off between
-// memory used for tracing and accuracy. Measurements done on a prototype
-// revealed that:
-//
-// - In 60 percent of the cases, pseudo stack depth <= 7.
-// - In 87 percent of the cases, pseudo stack depth <= 9.
-// - In 95 percent of the cases, pseudo stack depth <= 11.
-//
-// See the design doc (https://goo.gl/4s7v7b) for more details.
-
-// Represents (pseudo) stack frame. Used in Backtrace class below.
-//
-// Conceptually stack frame is identified by its value, and type is used
-// mostly to properly format the value. Value is expected to be a valid
-// pointer from process' address space.
-struct BASE_EXPORT StackFrame {
- enum class Type {
- TRACE_EVENT_NAME, // const char* string
- THREAD_NAME, // const char* thread name
- PROGRAM_COUNTER, // as returned by stack tracing (e.g. by StackTrace)
- };
-
- static StackFrame FromTraceEventName(const char* name) {
- return {Type::TRACE_EVENT_NAME, name};
- }
- static StackFrame FromThreadName(const char* name) {
- return {Type::THREAD_NAME, name};
- }
- static StackFrame FromProgramCounter(const void* pc) {
- return {Type::PROGRAM_COUNTER, pc};
- }
-
- Type type;
- const void* value;
-};
-
-bool BASE_EXPORT operator < (const StackFrame& lhs, const StackFrame& rhs);
-bool BASE_EXPORT operator == (const StackFrame& lhs, const StackFrame& rhs);
-bool BASE_EXPORT operator != (const StackFrame& lhs, const StackFrame& rhs);
-
-struct BASE_EXPORT Backtrace {
- Backtrace();
-
- // If the stack is higher than what can be stored here, the top frames
- // (the ones further from main()) are stored. Depth of 12 is enough for most
- // pseudo traces (see above), but not for native traces, where we need more.
- enum { kMaxFrameCount = 48 };
- StackFrame frames[kMaxFrameCount];
- size_t frame_count = 0;
-};
-
-bool BASE_EXPORT operator==(const Backtrace& lhs, const Backtrace& rhs);
-bool BASE_EXPORT operator!=(const Backtrace& lhs, const Backtrace& rhs);
-
-// The |AllocationContext| is context metadata that is kept for every allocation
-// when heap profiling is enabled. To simplify memory management for book-
-// keeping, this struct has a fixed size.
-struct BASE_EXPORT AllocationContext {
- AllocationContext();
- AllocationContext(const Backtrace& backtrace, const char* type_name);
-
- Backtrace backtrace;
-
- // Type name of the type stored in the allocated memory. A null pointer
- // indicates "unknown type". Grouping is done by comparing pointers, not by
- // deep string comparison. In a component build, where a type name can have a
- // string literal in several dynamic libraries, this may distort grouping.
- const char* type_name;
-};
-
-bool BASE_EXPORT operator==(const AllocationContext& lhs,
- const AllocationContext& rhs);
-bool BASE_EXPORT operator!=(const AllocationContext& lhs,
- const AllocationContext& rhs);
-
-// Struct to store the size and count of the allocations.
-struct AllocationMetrics {
- size_t size;
- size_t count;
-};
-
-} // namespace trace_event
-} // namespace base
-
-namespace std {
-
-template <>
-struct BASE_EXPORT hash<base::trace_event::StackFrame> {
- size_t operator()(const base::trace_event::StackFrame& frame) const;
-};
-
-template <>
-struct BASE_EXPORT hash<base::trace_event::Backtrace> {
- size_t operator()(const base::trace_event::Backtrace& backtrace) const;
-};
-
-template <>
-struct BASE_EXPORT hash<base::trace_event::AllocationContext> {
- size_t operator()(const base::trace_event::AllocationContext& context) const;
-};
-
-} // namespace std
-
-#endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_H_
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc
deleted file mode 100644
index 556719e9ae..0000000000
--- a/base/trace_event/heap_profiler_allocation_context_tracker.cc
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright 2015 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/trace_event/heap_profiler_allocation_context_tracker.h"
-
-#include <algorithm>
-#include <iterator>
-
-#include "base/atomicops.h"
-#include "base/debug/debugging_buildflags.h"
-#include "base/debug/leak_annotations.h"
-#include "base/debug/stack_trace.h"
-#include "base/no_destructor.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local_storage.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#include "build/build_config.h"
-
-#if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE)
-#include "base/trace_event/cfi_backtrace_android.h"
-#endif
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#include <sys/prctl.h>
-#endif
-
-namespace base {
-namespace trace_event {
-
-subtle::Atomic32 AllocationContextTracker::capture_mode_ =
- static_cast<int32_t>(AllocationContextTracker::CaptureMode::DISABLED);
-
-namespace {
-
-const size_t kMaxStackDepth = 128u;
-const size_t kMaxTaskDepth = 16u;
-AllocationContextTracker* const kInitializingSentinel =
- reinterpret_cast<AllocationContextTracker*>(-1);
-
-// This function is added to the TLS slot to clean up the instance when the
-// thread exits.
-void DestructAllocationContextTracker(void* alloc_ctx_tracker) {
- delete static_cast<AllocationContextTracker*>(alloc_ctx_tracker);
-}
-
-ThreadLocalStorage::Slot& AllocationContextTrackerTLS() {
- static NoDestructor<ThreadLocalStorage::Slot> tls_alloc_ctx_tracker(
- &DestructAllocationContextTracker);
- return *tls_alloc_ctx_tracker;
-}
-
-// Cannot call ThreadIdNameManager::GetName because it holds a lock and causes
-// deadlock when lock is already held by ThreadIdNameManager before the current
-// allocation. Gets the thread name from kernel if available or returns a string
-// with id. This function intentionally leaks the allocated strings since they
-// are used to tag allocations even after the thread dies.
-const char* GetAndLeakThreadName() {
- char name[16];
-#if defined(OS_LINUX) || defined(OS_ANDROID)
- // If the thread name is not set, try to get it from prctl. Thread name might
- // not be set in cases where the thread started before heap profiling was
- // enabled.
- int err = prctl(PR_GET_NAME, name);
- if (!err) {
- return strdup(name);
- }
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
- // Use tid if we don't have a thread name.
- snprintf(name, sizeof(name), "%lu",
- static_cast<unsigned long>(PlatformThread::CurrentId()));
- return strdup(name);
-}
-
-} // namespace
-
-// static
-AllocationContextTracker*
-AllocationContextTracker::GetInstanceForCurrentThread() {
- AllocationContextTracker* tracker = static_cast<AllocationContextTracker*>(
- AllocationContextTrackerTLS().Get());
- if (tracker == kInitializingSentinel)
- return nullptr; // Re-entrancy case.
-
- if (!tracker) {
- AllocationContextTrackerTLS().Set(kInitializingSentinel);
- tracker = new AllocationContextTracker();
- AllocationContextTrackerTLS().Set(tracker);
- }
-
- return tracker;
-}
-
-AllocationContextTracker::AllocationContextTracker()
- : thread_name_(nullptr), ignore_scope_depth_(0) {
- tracked_stack_.reserve(kMaxStackDepth);
- task_contexts_.reserve(kMaxTaskDepth);
-}
-AllocationContextTracker::~AllocationContextTracker() = default;
-
-// static
-void AllocationContextTracker::SetCurrentThreadName(const char* name) {
- if (name && capture_mode() != CaptureMode::DISABLED) {
- GetInstanceForCurrentThread()->thread_name_ = name;
- }
-}
-
-// static
-void AllocationContextTracker::SetCaptureMode(CaptureMode mode) {
- // Release ordering ensures that when a thread observes |capture_mode_| to
- // be true through an acquire load, the TLS slot has been initialized.
- subtle::Release_Store(&capture_mode_, static_cast<int32_t>(mode));
-}
-
-void AllocationContextTracker::PushPseudoStackFrame(
- AllocationContextTracker::PseudoStackFrame stack_frame) {
- // Impose a limit on the height to verify that every push is popped, because
- // in practice the pseudo stack never grows higher than ~20 frames.
- if (tracked_stack_.size() < kMaxStackDepth) {
- tracked_stack_.push_back(
- StackFrame::FromTraceEventName(stack_frame.trace_event_name));
- } else {
- NOTREACHED();
- }
-}
-
-void AllocationContextTracker::PopPseudoStackFrame(
- AllocationContextTracker::PseudoStackFrame stack_frame) {
- // Guard for stack underflow. If tracing was started with a TRACE_EVENT in
- // scope, the frame was never pushed, so it is possible that pop is called
- // on an empty stack.
- if (tracked_stack_.empty())
- return;
-
- tracked_stack_.pop_back();
-}
-
-void AllocationContextTracker::PushNativeStackFrame(const void* pc) {
- if (tracked_stack_.size() < kMaxStackDepth)
- tracked_stack_.push_back(StackFrame::FromProgramCounter(pc));
- else
- NOTREACHED();
-}
-
-void AllocationContextTracker::PopNativeStackFrame(const void* pc) {
- if (tracked_stack_.empty())
- return;
-
- DCHECK_EQ(pc, tracked_stack_.back().value);
- tracked_stack_.pop_back();
-}
-
-void AllocationContextTracker::PushCurrentTaskContext(const char* context) {
- DCHECK(context);
- if (task_contexts_.size() < kMaxTaskDepth)
- task_contexts_.push_back(context);
- else
- NOTREACHED();
-}
-
-void AllocationContextTracker::PopCurrentTaskContext(const char* context) {
- // Guard for stack underflow. If tracing was started with a TRACE_EVENT in
- // scope, the context was never pushed, so it is possible that pop is called
- // on an empty stack.
- if (task_contexts_.empty())
- return;
-
- DCHECK_EQ(context, task_contexts_.back())
- << "Encountered an unmatched context end";
- task_contexts_.pop_back();
-}
-
-bool AllocationContextTracker::GetContextSnapshot(AllocationContext* ctx) {
- if (ignore_scope_depth_)
- return false;
-
- CaptureMode mode = static_cast<CaptureMode>(
- subtle::NoBarrier_Load(&capture_mode_));
-
- auto* backtrace = std::begin(ctx->backtrace.frames);
- auto* backtrace_end = std::end(ctx->backtrace.frames);
-
- if (!thread_name_) {
- // Ignore the string allocation made by GetAndLeakThreadName to avoid
- // reentrancy.
- ignore_scope_depth_++;
- thread_name_ = GetAndLeakThreadName();
- ANNOTATE_LEAKING_OBJECT_PTR(thread_name_);
- DCHECK(thread_name_);
- ignore_scope_depth_--;
- }
-
- // Add the thread name as the first entry in pseudo stack.
- if (thread_name_) {
- *backtrace++ = StackFrame::FromThreadName(thread_name_);
- }
-
- switch (mode) {
- case CaptureMode::DISABLED:
- {
- break;
- }
- case CaptureMode::PSEUDO_STACK:
- case CaptureMode::MIXED_STACK:
- {
- for (const StackFrame& stack_frame : tracked_stack_) {
- if (backtrace == backtrace_end)
- break;
- *backtrace++ = stack_frame;
- }
- break;
- }
- case CaptureMode::NATIVE_STACK:
- {
-// Backtrace contract requires us to return bottom frames, i.e.
-// from main() and up. Stack unwinding produces top frames, i.e.
-// from this point and up until main(). We intentionally request
-// kMaxFrameCount + 1 frames, so that we know if there are more frames
-// than our backtrace capacity.
-#if !defined(OS_NACL) // We don't build base/debug/stack_trace.cc for NaCl.
-#if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE)
- const void* frames[Backtrace::kMaxFrameCount + 1];
- static_assert(arraysize(frames) >= Backtrace::kMaxFrameCount,
- "not requesting enough frames to fill Backtrace");
- size_t frame_count =
- CFIBacktraceAndroid::GetInitializedInstance()->Unwind(
- frames, arraysize(frames));
-#elif BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
- const void* frames[Backtrace::kMaxFrameCount + 1];
- static_assert(arraysize(frames) >= Backtrace::kMaxFrameCount,
- "not requesting enough frames to fill Backtrace");
- size_t frame_count = debug::TraceStackFramePointers(
- frames, arraysize(frames),
- 1 /* exclude this function from the trace */);
-#else
- // Fall-back to capturing the stack with base::debug::StackTrace,
- // which is likely slower, but more reliable.
- base::debug::StackTrace stack_trace(Backtrace::kMaxFrameCount + 1);
- size_t frame_count = 0u;
- const void* const* frames = stack_trace.Addresses(&frame_count);
-#endif
-
- // If there are too many frames, keep the ones furthest from main().
- size_t backtrace_capacity = backtrace_end - backtrace;
- int32_t starting_frame_index = frame_count;
- if (frame_count > backtrace_capacity) {
- starting_frame_index = backtrace_capacity - 1;
- *backtrace++ = StackFrame::FromTraceEventName("<truncated>");
- }
- for (int32_t i = starting_frame_index - 1; i >= 0; --i) {
- const void* frame = frames[i];
- *backtrace++ = StackFrame::FromProgramCounter(frame);
- }
-#endif // !defined(OS_NACL)
- break;
- }
- }
-
- ctx->backtrace.frame_count = backtrace - std::begin(ctx->backtrace.frames);
-
- // TODO(ssid): Fix crbug.com/594803 to add file name as 3rd dimension
- // (component name) in the heap profiler and not piggy back on the type name.
- if (!task_contexts_.empty()) {
- ctx->type_name = task_contexts_.back();
- } else {
- ctx->type_name = nullptr;
- }
-
- return true;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.h b/base/trace_event/heap_profiler_allocation_context_tracker.h
deleted file mode 100644
index da03b7f6d6..0000000000
--- a/base/trace_event/heap_profiler_allocation_context_tracker.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_
-#define BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_
-
-#include <vector>
-
-#include "base/atomicops.h"
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-
-namespace base {
-namespace trace_event {
-
-// AllocationContextTracker is a thread-local object. Its main purpose is to
-// keep track of a pseudo stack of trace events. Chrome has been instrumented
-// with lots of `TRACE_EVENT` macros. These trace events push their name to a
-// thread-local stack when they go into scope, and pop when they go out of
-// scope, if all of the following conditions have been met:
-//
-// * A trace is being recorded.
-// * The category of the event is enabled in the trace config.
-// * Heap profiling is enabled (with the `--enable-heap-profiling` flag).
-//
-// This means that allocations that occur before tracing is started will not
-// have backtrace information in their context.
-//
-// AllocationContextTracker also keeps track of some thread state not related to
-// trace events. See |AllocationContext|.
-//
-// A thread-local instance of the context tracker is initialized lazily when it
-// is first accessed. This might be because a trace event pushed or popped, or
-// because `GetContextSnapshot()` was called when an allocation occurred
-class BASE_EXPORT AllocationContextTracker {
- public:
- enum class CaptureMode : int32_t {
- DISABLED, // Don't capture anything
- PSEUDO_STACK, // Backtrace has trace events
- MIXED_STACK, // Backtrace has trace events + from
- // HeapProfilerScopedStackFrame
- NATIVE_STACK, // Backtrace has full native backtraces from stack unwinding
- };
-
- // Stack frame constructed from trace events in codebase.
- struct BASE_EXPORT PseudoStackFrame {
- const char* trace_event_category;
- const char* trace_event_name;
-
- bool operator==(const PseudoStackFrame& other) const {
- return trace_event_category == other.trace_event_category &&
- trace_event_name == other.trace_event_name;
- }
- };
-
- // Globally sets capturing mode.
- // TODO(primiano): How to guard against *_STACK -> DISABLED -> *_STACK?
- static void SetCaptureMode(CaptureMode mode);
-
- // Returns global capturing mode.
- inline static CaptureMode capture_mode() {
- // A little lag after heap profiling is enabled or disabled is fine, it is
- // more important that the check is as cheap as possible when capturing is
- // not enabled, so do not issue a memory barrier in the fast path.
- if (subtle::NoBarrier_Load(&capture_mode_) ==
- static_cast<int32_t>(CaptureMode::DISABLED))
- return CaptureMode::DISABLED;
-
- // In the slow path, an acquire load is required to pair with the release
- // store in |SetCaptureMode|. This is to ensure that the TLS slot for
- // the thread-local allocation context tracker has been initialized if
- // |capture_mode| returns something other than DISABLED.
- return static_cast<CaptureMode>(subtle::Acquire_Load(&capture_mode_));
- }
-
- // Returns the thread-local instance, creating one if necessary. Returns
- // always a valid instance, unless it is called re-entrantly, in which case
- // returns nullptr in the nested calls.
- static AllocationContextTracker* GetInstanceForCurrentThread();
-
- // Set the thread name in the AllocationContextTracker of the current thread
- // if capture is enabled.
- static void SetCurrentThreadName(const char* name);
-
- // Starts and ends a new ignore scope between which the allocations are
- // ignored by the heap profiler. GetContextSnapshot() returns false when
- // allocations are ignored.
- void begin_ignore_scope() { ignore_scope_depth_++; }
- void end_ignore_scope() {
- if (ignore_scope_depth_)
- ignore_scope_depth_--;
- }
-
- // Pushes and pops a frame onto the thread-local pseudo stack.
- // TODO(ssid): Change PseudoStackFrame to const char*. Only event name is
- // used.
- void PushPseudoStackFrame(PseudoStackFrame stack_frame);
- void PopPseudoStackFrame(PseudoStackFrame stack_frame);
-
- // Pushes and pops a native stack frame onto thread local tracked stack.
- void PushNativeStackFrame(const void* pc);
- void PopNativeStackFrame(const void* pc);
-
- // Push and pop current task's context. A stack is used to support nested
- // tasks and the top of the stack will be used in allocation context.
- void PushCurrentTaskContext(const char* context);
- void PopCurrentTaskContext(const char* context);
-
- // Fills a snapshot of the current thread-local context. Doesn't fill and
- // returns false if allocations are being ignored.
- bool GetContextSnapshot(AllocationContext* snapshot);
-
- ~AllocationContextTracker();
-
- private:
- AllocationContextTracker();
-
- static subtle::Atomic32 capture_mode_;
-
- // The pseudo stack where frames are |TRACE_EVENT| names or inserted PCs.
- std::vector<StackFrame> tracked_stack_;
-
- // The thread name is used as the first entry in the pseudo stack.
- const char* thread_name_;
-
- // Stack of tasks' contexts. Context serves as a different dimension than
- // pseudo stack to cluster allocations.
- std::vector<const char*> task_contexts_;
-
- uint32_t ignore_scope_depth_;
-
- DISALLOW_COPY_AND_ASSIGN(AllocationContextTracker);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_HEAP_PROFILER_ALLOCATION_CONTEXT_TRACKER_H_
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc b/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc
deleted file mode 100644
index c26149efaa..0000000000
--- a/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2015 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 <stddef.h>
-
-#include <iterator>
-
-#include "base/memory/ref_counted.h"
-#include "base/pending_task.h"
-#include "base/trace_event/heap_profiler.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/trace_event.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-// Define all strings once, because the pseudo stack requires pointer equality,
-// and string interning is unreliable.
-const char kThreadName[] = "TestThread";
-const char kCupcake[] = "Cupcake";
-const char kDonut[] = "Donut";
-const char kEclair[] = "Eclair";
-const char kFroyo[] = "Froyo";
-const char kGingerbread[] = "Gingerbread";
-
-const char kFilteringTraceConfig[] =
- "{"
- " \"event_filters\": ["
- " {"
- " \"excluded_categories\": [],"
- " \"filter_args\": {},"
- " \"filter_predicate\": \"heap_profiler_predicate\","
- " \"included_categories\": ["
- " \"*\","
- " \"" TRACE_DISABLED_BY_DEFAULT("Testing") "\"]"
- " }"
- " ]"
- "}";
-
-// Asserts that the fixed-size array |expected_backtrace| matches the backtrace
-// in |AllocationContextTracker::GetContextSnapshot|.
-template <size_t N>
-void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) {
- AllocationContext ctx;
- ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx));
-
- auto* actual = std::begin(ctx.backtrace.frames);
- auto* actual_bottom = actual + ctx.backtrace.frame_count;
- auto expected = std::begin(expected_backtrace);
- auto expected_bottom = std::end(expected_backtrace);
-
- // Note that this requires the pointers to be equal, this is not doing a deep
- // string comparison.
- for (; actual != actual_bottom && expected != expected_bottom;
- actual++, expected++)
- ASSERT_EQ(*expected, *actual);
-
- // Ensure that the height of the stacks is the same.
- ASSERT_EQ(actual, actual_bottom);
- ASSERT_EQ(expected, expected_bottom);
-}
-
-void AssertBacktraceContainsOnlyThreadName() {
- StackFrame t = StackFrame::FromThreadName(kThreadName);
- AllocationContext ctx;
- ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx));
-
- ASSERT_EQ(1u, ctx.backtrace.frame_count);
- ASSERT_EQ(t, ctx.backtrace.frames[0]);
-}
-
-class AllocationContextTrackerTest : public testing::Test {
- public:
- void SetUp() override {
- AllocationContextTracker::SetCaptureMode(
- AllocationContextTracker::CaptureMode::PSEUDO_STACK);
- // Enabling memory-infra category sets default memory dump config which
- // includes filters for capturing pseudo stack.
- TraceConfig config(kFilteringTraceConfig);
- TraceLog::GetInstance()->SetEnabled(config, TraceLog::FILTERING_MODE);
- AllocationContextTracker::SetCurrentThreadName(kThreadName);
- }
-
- void TearDown() override {
- AllocationContextTracker::SetCaptureMode(
- AllocationContextTracker::CaptureMode::DISABLED);
- TraceLog::GetInstance()->SetDisabled(TraceLog::FILTERING_MODE);
- }
-};
-
-// Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly.
-TEST_F(AllocationContextTrackerTest, PseudoStackScopedTrace) {
- StackFrame t = StackFrame::FromThreadName(kThreadName);
- StackFrame c = StackFrame::FromTraceEventName(kCupcake);
- StackFrame d = StackFrame::FromTraceEventName(kDonut);
- StackFrame e = StackFrame::FromTraceEventName(kEclair);
- StackFrame f = StackFrame::FromTraceEventName(kFroyo);
-
- AssertBacktraceContainsOnlyThreadName();
-
- {
- TRACE_EVENT0("Testing", kCupcake);
- StackFrame frame_c[] = {t, c};
- AssertBacktraceEquals(frame_c);
-
- {
- TRACE_EVENT0("Testing", kDonut);
- StackFrame frame_cd[] = {t, c, d};
- AssertBacktraceEquals(frame_cd);
- }
-
- AssertBacktraceEquals(frame_c);
-
- {
- TRACE_EVENT0("Testing", kEclair);
- StackFrame frame_ce[] = {t, c, e};
- AssertBacktraceEquals(frame_ce);
- }
-
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("NotTesting"), kDonut);
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("Testing"), kCupcake);
- StackFrame frame_cc[] = {t, c, c};
- AssertBacktraceEquals(frame_cc);
- }
-
- AssertBacktraceEquals(frame_c);
- }
-
- AssertBacktraceContainsOnlyThreadName();
-
- {
- TRACE_EVENT0("Testing", kFroyo);
- StackFrame frame_f[] = {t, f};
- AssertBacktraceEquals(frame_f);
- }
-
- AssertBacktraceContainsOnlyThreadName();
-}
-
-// Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and
-// |TRACE_EVENT_END| macros.
-TEST_F(AllocationContextTrackerTest, PseudoStackBeginEndTrace) {
- StackFrame t = StackFrame::FromThreadName(kThreadName);
- StackFrame c = StackFrame::FromTraceEventName(kCupcake);
- StackFrame d = StackFrame::FromTraceEventName(kDonut);
- StackFrame e = StackFrame::FromTraceEventName(kEclair);
- StackFrame f = StackFrame::FromTraceEventName(kFroyo);
-
- StackFrame frame_c[] = {t, c};
- StackFrame frame_cd[] = {t, c, d};
- StackFrame frame_ce[] = {t, c, e};
- StackFrame frame_f[] = {t, f};
-
- AssertBacktraceContainsOnlyThreadName();
-
- TRACE_EVENT_BEGIN0("Testing", kCupcake);
- AssertBacktraceEquals(frame_c);
-
- TRACE_EVENT_BEGIN0("Testing", kDonut);
- AssertBacktraceEquals(frame_cd);
- TRACE_EVENT_END0("Testing", kDonut);
-
- AssertBacktraceEquals(frame_c);
-
- TRACE_EVENT_BEGIN0("Testing", kEclair);
- AssertBacktraceEquals(frame_ce);
- TRACE_EVENT_END0("Testing", kEclair);
-
- AssertBacktraceEquals(frame_c);
- TRACE_EVENT_END0("Testing", kCupcake);
-
- AssertBacktraceContainsOnlyThreadName();
-
- TRACE_EVENT_BEGIN0("Testing", kFroyo);
- AssertBacktraceEquals(frame_f);
- TRACE_EVENT_END0("Testing", kFroyo);
-
- AssertBacktraceContainsOnlyThreadName();
-}
-
-TEST_F(AllocationContextTrackerTest, PseudoStackMixedTrace) {
- StackFrame t = StackFrame::FromThreadName(kThreadName);
- StackFrame c = StackFrame::FromTraceEventName(kCupcake);
- StackFrame d = StackFrame::FromTraceEventName(kDonut);
- StackFrame e = StackFrame::FromTraceEventName(kEclair);
- StackFrame f = StackFrame::FromTraceEventName(kFroyo);
-
- StackFrame frame_c[] = {t, c};
- StackFrame frame_cd[] = {t, c, d};
- StackFrame frame_e[] = {t, e};
- StackFrame frame_ef[] = {t, e, f};
-
- AssertBacktraceContainsOnlyThreadName();
-
- TRACE_EVENT_BEGIN0("Testing", kCupcake);
- AssertBacktraceEquals(frame_c);
-
- {
- TRACE_EVENT0("Testing", kDonut);
- AssertBacktraceEquals(frame_cd);
- }
-
- AssertBacktraceEquals(frame_c);
- TRACE_EVENT_END0("Testing", kCupcake);
- AssertBacktraceContainsOnlyThreadName();
-
- {
- TRACE_EVENT0("Testing", kEclair);
- AssertBacktraceEquals(frame_e);
-
- TRACE_EVENT_BEGIN0("Testing", kFroyo);
- AssertBacktraceEquals(frame_ef);
- TRACE_EVENT_END0("Testing", kFroyo);
- AssertBacktraceEquals(frame_e);
- }
-
- AssertBacktraceContainsOnlyThreadName();
-}
-
-TEST_F(AllocationContextTrackerTest, MixedStackWithProgramCounter) {
- StackFrame t = StackFrame::FromThreadName(kThreadName);
- StackFrame c = StackFrame::FromTraceEventName(kCupcake);
- StackFrame f = StackFrame::FromTraceEventName(kFroyo);
- const void* pc1 = reinterpret_cast<void*>(0x1000);
- const void* pc2 = reinterpret_cast<void*>(0x2000);
- StackFrame n1 = StackFrame::FromProgramCounter(pc1);
- StackFrame n2 = StackFrame::FromProgramCounter(pc2);
-
- StackFrame frame_c[] = {t, c};
- StackFrame frame_cd[] = {t, c, n1};
- StackFrame frame_e[] = {t, n2, n1};
- StackFrame frame_ef[] = {t, n2, n1, f};
-
- AssertBacktraceContainsOnlyThreadName();
-
- AllocationContextTracker::SetCaptureMode(
- AllocationContextTracker::CaptureMode::MIXED_STACK);
-
- TRACE_EVENT_BEGIN0("Testing", kCupcake);
- AssertBacktraceEquals(frame_c);
-
- {
- TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER e1(pc1);
- AssertBacktraceEquals(frame_cd);
- }
-
- AssertBacktraceEquals(frame_c);
- TRACE_EVENT_END0("Testing", kCupcake);
- AssertBacktraceContainsOnlyThreadName();
-
- {
- TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER e1(pc2);
- TRACE_HEAP_PROFILER_API_SCOPED_WITH_PROGRAM_COUNTER e2(pc1);
- AssertBacktraceEquals(frame_e);
-
- TRACE_EVENT0("Testing", kFroyo);
- AssertBacktraceEquals(frame_ef);
- }
-
- AssertBacktraceContainsOnlyThreadName();
- AllocationContextTracker::SetCaptureMode(
- AllocationContextTracker::CaptureMode::DISABLED);
-}
-
-TEST_F(AllocationContextTrackerTest, BacktraceTakesTop) {
- StackFrame t = StackFrame::FromThreadName(kThreadName);
- StackFrame c = StackFrame::FromTraceEventName(kCupcake);
- StackFrame f = StackFrame::FromTraceEventName(kFroyo);
-
- // Push 11 events onto the pseudo stack.
- TRACE_EVENT0("Testing", kCupcake);
- TRACE_EVENT0("Testing", kCupcake);
- TRACE_EVENT0("Testing", kCupcake);
-
- TRACE_EVENT0("Testing", kCupcake);
- TRACE_EVENT0("Testing", kCupcake);
- TRACE_EVENT0("Testing", kCupcake);
- TRACE_EVENT0("Testing", kCupcake);
-
- TRACE_EVENT0("Testing", kCupcake);
- TRACE_EVENT0("Testing", kDonut);
- TRACE_EVENT0("Testing", kEclair);
- TRACE_EVENT0("Testing", kFroyo);
-
- {
- TRACE_EVENT0("Testing", kGingerbread);
- AllocationContext ctx;
- ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx));
-
- // The pseudo stack relies on pointer equality, not deep string comparisons.
- ASSERT_EQ(t, ctx.backtrace.frames[0]);
- ASSERT_EQ(c, ctx.backtrace.frames[1]);
- ASSERT_EQ(f, ctx.backtrace.frames[11]);
- }
-
- {
- AllocationContext ctx;
- ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx));
- ASSERT_EQ(t, ctx.backtrace.frames[0]);
- ASSERT_EQ(c, ctx.backtrace.frames[1]);
- ASSERT_EQ(f, ctx.backtrace.frames[11]);
- }
-}
-
-TEST_F(AllocationContextTrackerTest, TrackCategoryName) {
- const char kContext1[] = "context1";
- const char kContext2[] = "context2";
- {
- // The context from the scoped task event should be used as type name.
- TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event1(kContext1);
- AllocationContext ctx1;
- ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx1));
- ASSERT_EQ(kContext1, ctx1.type_name);
-
- // In case of nested events, the last event's context should be used.
- TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event2(kContext2);
- AllocationContext ctx2;
- ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx2));
- ASSERT_EQ(kContext2, ctx2.type_name);
- }
-
- // Type should be nullptr without task event.
- AllocationContext ctx;
- ASSERT_TRUE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx));
- ASSERT_FALSE(ctx.type_name);
-}
-
-TEST_F(AllocationContextTrackerTest, IgnoreAllocationTest) {
- TRACE_EVENT0("Testing", kCupcake);
- TRACE_EVENT0("Testing", kDonut);
- HEAP_PROFILER_SCOPED_IGNORE;
- AllocationContext ctx;
- ASSERT_FALSE(AllocationContextTracker::GetInstanceForCurrentThread()
- ->GetContextSnapshot(&ctx));
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/heap_profiler_event_filter.cc b/base/trace_event/heap_profiler_event_filter.cc
deleted file mode 100644
index 937072ca7b..0000000000
--- a/base/trace_event/heap_profiler_event_filter.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 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/trace_event/heap_profiler_event_filter.h"
-
-#include "base/trace_event/category_registry.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "base/trace_event/trace_category.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_impl.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-inline bool IsPseudoStackEnabled() {
- // Only PSEUDO_STACK and MIXED_STACK modes require trace events.
- return AllocationContextTracker::capture_mode() ==
- AllocationContextTracker::CaptureMode::PSEUDO_STACK ||
- AllocationContextTracker::capture_mode() ==
- AllocationContextTracker::CaptureMode::MIXED_STACK;
-}
-
-inline AllocationContextTracker* GetThreadLocalTracker() {
- return AllocationContextTracker::GetInstanceForCurrentThread();
-}
-
-} // namespace
-
-// static
-const char HeapProfilerEventFilter::kName[] = "heap_profiler_predicate";
-
-HeapProfilerEventFilter::HeapProfilerEventFilter() = default;
-HeapProfilerEventFilter::~HeapProfilerEventFilter() = default;
-
-bool HeapProfilerEventFilter::FilterTraceEvent(
- const TraceEvent& trace_event) const {
- if (!IsPseudoStackEnabled())
- return true;
-
- // TODO(primiano): Add support for events with copied name crbug.com/581079.
- if (trace_event.flags() & TRACE_EVENT_FLAG_COPY)
- return true;
-
- const auto* category = CategoryRegistry::GetCategoryByStatePtr(
- trace_event.category_group_enabled());
- AllocationContextTracker::PseudoStackFrame frame = {category->name(),
- trace_event.name()};
- if (trace_event.phase() == TRACE_EVENT_PHASE_BEGIN ||
- trace_event.phase() == TRACE_EVENT_PHASE_COMPLETE) {
- GetThreadLocalTracker()->PushPseudoStackFrame(frame);
- } else if (trace_event.phase() == TRACE_EVENT_PHASE_END) {
- // The pop for |TRACE_EVENT_PHASE_COMPLETE| events is in |EndEvent|.
- GetThreadLocalTracker()->PopPseudoStackFrame(frame);
- }
- // Do not filter-out any events and always return true. TraceLog adds the
- // event only if it is enabled for recording.
- return true;
-}
-
-void HeapProfilerEventFilter::EndEvent(const char* category_name,
- const char* event_name) const {
- if (IsPseudoStackEnabled())
- GetThreadLocalTracker()->PopPseudoStackFrame({category_name, event_name});
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/heap_profiler_event_filter.h b/base/trace_event/heap_profiler_event_filter.h
deleted file mode 100644
index 47368a1b07..0000000000
--- a/base/trace_event/heap_profiler_event_filter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_HEAP_PROFILER_EVENT_FILTER_H_
-#define BASE_TRACE_EVENT_HEAP_PROFILER_EVENT_FILTER_H_
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/trace_event/trace_event_filter.h"
-
-namespace base {
-namespace trace_event {
-
-class TraceEvent;
-
-// This filter unconditionally accepts all events and pushes/pops them from the
-// thread-local AllocationContextTracker instance as they are seen.
-// This is used to cheaply construct the heap profiler pseudo stack without
-// having to actually record all events.
-class BASE_EXPORT HeapProfilerEventFilter : public TraceEventFilter {
- public:
- static const char kName[];
-
- HeapProfilerEventFilter();
- ~HeapProfilerEventFilter() override;
-
- // TraceEventFilter implementation.
- bool FilterTraceEvent(const TraceEvent& trace_event) const override;
- void EndEvent(const char* category_name,
- const char* event_name) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HeapProfilerEventFilter);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_HEAP_PROFILER_EVENT_FILTER_H_
diff --git a/base/trace_event/java_heap_dump_provider_android.cc b/base/trace_event/java_heap_dump_provider_android.cc
deleted file mode 100644
index 684f7301cf..0000000000
--- a/base/trace_event/java_heap_dump_provider_android.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2015 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/trace_event/java_heap_dump_provider_android.h"
-
-#include "base/android/java_runtime.h"
-#include "base/trace_event/process_memory_dump.h"
-
-namespace base {
-namespace trace_event {
-
-// static
-JavaHeapDumpProvider* JavaHeapDumpProvider::GetInstance() {
- return Singleton<JavaHeapDumpProvider,
- LeakySingletonTraits<JavaHeapDumpProvider>>::get();
-}
-
-JavaHeapDumpProvider::JavaHeapDumpProvider() {
-}
-
-JavaHeapDumpProvider::~JavaHeapDumpProvider() {
-}
-
-// Called at trace dump point time. Creates a snapshot with the memory counters
-// for the current process.
-bool JavaHeapDumpProvider::OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) {
- // These numbers come from java.lang.Runtime stats.
- long total_heap_size = 0;
- long free_heap_size = 0;
- android::JavaRuntime::GetMemoryUsage(&total_heap_size, &free_heap_size);
-
- MemoryAllocatorDump* outer_dump = pmd->CreateAllocatorDump("java_heap");
- outer_dump->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes, total_heap_size);
-
- MemoryAllocatorDump* inner_dump =
- pmd->CreateAllocatorDump("java_heap/allocated_objects");
- inner_dump->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes,
- total_heap_size - free_heap_size);
- return true;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/java_heap_dump_provider_android.h b/base/trace_event/java_heap_dump_provider_android.h
deleted file mode 100644
index b9f2333089..0000000000
--- a/base/trace_event/java_heap_dump_provider_android.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
-#define BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/trace_event/memory_dump_provider.h"
-
-namespace base {
-namespace trace_event {
-
-// Dump provider which collects process-wide memory stats.
-class BASE_EXPORT JavaHeapDumpProvider : public MemoryDumpProvider {
- public:
- static JavaHeapDumpProvider* GetInstance();
-
- // MemoryDumpProvider implementation.
- bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) override;
-
- private:
- friend struct DefaultSingletonTraits<JavaHeapDumpProvider>;
-
- JavaHeapDumpProvider();
- ~JavaHeapDumpProvider() override;
-
- DISALLOW_COPY_AND_ASSIGN(JavaHeapDumpProvider);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
diff --git a/base/trace_event/java_heap_dump_provider_android_unittest.cc b/base/trace_event/java_heap_dump_provider_android_unittest.cc
deleted file mode 100644
index 4deaf839ec..0000000000
--- a/base/trace_event/java_heap_dump_provider_android_unittest.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 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/trace_event/java_heap_dump_provider_android.h"
-
-#include "base/trace_event/process_memory_dump.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-TEST(JavaHeapDumpProviderTest, JavaHeapDump) {
- auto* jhdp = JavaHeapDumpProvider::GetInstance();
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
- std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(dump_args));
-
- jhdp->OnMemoryDump(dump_args, pmd.get());
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/malloc_dump_provider.cc b/base/trace_event/malloc_dump_provider.cc
deleted file mode 100644
index 46fdb3e214..0000000000
--- a/base/trace_event/malloc_dump_provider.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2015 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/trace_event/malloc_dump_provider.h"
-
-#include <stddef.h>
-
-#include <unordered_map>
-
-#include "base/allocator/allocator_extension.h"
-#include "base/allocator/buildflags.h"
-#include "base/debug/profiler.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "build/build_config.h"
-
-#if defined(OS_MACOSX)
-#include <malloc/malloc.h>
-#else
-#include <malloc.h>
-#endif
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace base {
-namespace trace_event {
-
-namespace {
-#if defined(OS_WIN)
-// A structure containing some information about a given heap.
-struct WinHeapInfo {
- size_t committed_size;
- size_t uncommitted_size;
- size_t allocated_size;
- size_t block_count;
-};
-
-// NOTE: crbug.com/665516
-// Unfortunately, there is no safe way to collect information from secondary
-// heaps due to limitations and racy nature of this piece of WinAPI.
-void WinHeapMemoryDumpImpl(WinHeapInfo* crt_heap_info) {
- // Iterate through whichever heap our CRT is using.
- HANDLE crt_heap = reinterpret_cast<HANDLE>(_get_heap_handle());
- ::HeapLock(crt_heap);
- PROCESS_HEAP_ENTRY heap_entry;
- heap_entry.lpData = nullptr;
- // Walk over all the entries in the main heap.
- while (::HeapWalk(crt_heap, &heap_entry) != FALSE) {
- if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) {
- crt_heap_info->allocated_size += heap_entry.cbData;
- crt_heap_info->block_count++;
- } else if ((heap_entry.wFlags & PROCESS_HEAP_REGION) != 0) {
- crt_heap_info->committed_size += heap_entry.Region.dwCommittedSize;
- crt_heap_info->uncommitted_size += heap_entry.Region.dwUnCommittedSize;
- }
- }
- CHECK(::HeapUnlock(crt_heap) == TRUE);
-}
-#endif // defined(OS_WIN)
-} // namespace
-
-// static
-const char MallocDumpProvider::kAllocatedObjects[] = "malloc/allocated_objects";
-
-// static
-MallocDumpProvider* MallocDumpProvider::GetInstance() {
- return Singleton<MallocDumpProvider,
- LeakySingletonTraits<MallocDumpProvider>>::get();
-}
-
-MallocDumpProvider::MallocDumpProvider() = default;
-MallocDumpProvider::~MallocDumpProvider() = default;
-
-// Called at trace dump point time. Creates a snapshot the memory counters for
-// the current process.
-bool MallocDumpProvider::OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) {
- {
- base::AutoLock auto_lock(emit_metrics_on_memory_dump_lock_);
- if (!emit_metrics_on_memory_dump_)
- return true;
- }
-
- size_t total_virtual_size = 0;
- size_t resident_size = 0;
- size_t allocated_objects_size = 0;
- size_t allocated_objects_count = 0;
-#if defined(USE_TCMALLOC)
- bool res =
- allocator::GetNumericProperty("generic.heap_size", &total_virtual_size);
- DCHECK(res);
- res = allocator::GetNumericProperty("generic.total_physical_bytes",
- &resident_size);
- DCHECK(res);
- res = allocator::GetNumericProperty("generic.current_allocated_bytes",
- &allocated_objects_size);
- DCHECK(res);
-#elif defined(OS_MACOSX) || defined(OS_IOS)
- malloc_statistics_t stats = {0};
- malloc_zone_statistics(nullptr, &stats);
- total_virtual_size = stats.size_allocated;
- allocated_objects_size = stats.size_in_use;
-
- // Resident size is approximated pretty well by stats.max_size_in_use.
- // However, on macOS, freed blocks are both resident and reusable, which is
- // semantically equivalent to deallocated. The implementation of libmalloc
- // will also only hold a fixed number of freed regions before actually
- // starting to deallocate them, so stats.max_size_in_use is also not
- // representative of the peak size. As a result, stats.max_size_in_use is
- // typically somewhere between actually resident [non-reusable] pages, and
- // peak size. This is not very useful, so we just use stats.size_in_use for
- // resident_size, even though it's an underestimate and fails to account for
- // fragmentation. See
- // https://bugs.chromium.org/p/chromium/issues/detail?id=695263#c1.
- resident_size = stats.size_in_use;
-#elif defined(OS_WIN)
- // This is too expensive on Windows, crbug.com/780735.
- if (args.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) {
- WinHeapInfo main_heap_info = {};
- WinHeapMemoryDumpImpl(&main_heap_info);
- total_virtual_size =
- main_heap_info.committed_size + main_heap_info.uncommitted_size;
- // Resident size is approximated with committed heap size. Note that it is
- // possible to do this with better accuracy on windows by intersecting the
- // working set with the virtual memory ranges occuipied by the heap. It's
- // not clear that this is worth it, as it's fairly expensive to do.
- resident_size = main_heap_info.committed_size;
- allocated_objects_size = main_heap_info.allocated_size;
- allocated_objects_count = main_heap_info.block_count;
- }
-#elif defined(OS_FUCHSIA)
-// TODO(fuchsia): Port, see https://crbug.com/706592.
-#else
- struct mallinfo info = mallinfo();
- DCHECK_GE(info.arena + info.hblkhd, info.uordblks);
-
- // In case of Android's jemalloc |arena| is 0 and the outer pages size is
- // reported by |hblkhd|. In case of dlmalloc the total is given by
- // |arena| + |hblkhd|. For more details see link: http://goo.gl/fMR8lF.
- total_virtual_size = info.arena + info.hblkhd;
- resident_size = info.uordblks;
-
- // Total allocated space is given by |uordblks|.
- allocated_objects_size = info.uordblks;
-#endif
-
- MemoryAllocatorDump* outer_dump = pmd->CreateAllocatorDump("malloc");
- outer_dump->AddScalar("virtual_size", MemoryAllocatorDump::kUnitsBytes,
- total_virtual_size);
- outer_dump->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes, resident_size);
-
- MemoryAllocatorDump* inner_dump = pmd->CreateAllocatorDump(kAllocatedObjects);
- inner_dump->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes,
- allocated_objects_size);
- if (allocated_objects_count != 0) {
- inner_dump->AddScalar(MemoryAllocatorDump::kNameObjectCount,
- MemoryAllocatorDump::kUnitsObjects,
- allocated_objects_count);
- }
-
- if (resident_size > allocated_objects_size) {
- // Explicitly specify why is extra memory resident. In tcmalloc it accounts
- // for free lists and caches. In mac and ios it accounts for the
- // fragmentation and metadata.
- MemoryAllocatorDump* other_dump =
- pmd->CreateAllocatorDump("malloc/metadata_fragmentation_caches");
- other_dump->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes,
- resident_size - allocated_objects_size);
- }
- return true;
-}
-
-void MallocDumpProvider::EnableMetrics() {
- base::AutoLock auto_lock(emit_metrics_on_memory_dump_lock_);
- emit_metrics_on_memory_dump_ = true;
-}
-
-void MallocDumpProvider::DisableMetrics() {
- base::AutoLock auto_lock(emit_metrics_on_memory_dump_lock_);
- emit_metrics_on_memory_dump_ = false;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/malloc_dump_provider.h b/base/trace_event/malloc_dump_provider.h
deleted file mode 100644
index e02eb9d1a9..0000000000
--- a/base/trace_event/malloc_dump_provider.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
-#define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/synchronization/lock.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "build/build_config.h"
-
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_WIN) || \
- (defined(OS_MACOSX) && !defined(OS_IOS))
-#define MALLOC_MEMORY_TRACING_SUPPORTED
-#endif
-
-namespace base {
-namespace trace_event {
-
-// Dump provider which collects process-wide memory stats.
-class BASE_EXPORT MallocDumpProvider : public MemoryDumpProvider {
- public:
- // Name of the allocated_objects dump. Use this to declare suballocator dumps
- // from other dump providers.
- static const char kAllocatedObjects[];
-
- static MallocDumpProvider* GetInstance();
-
- // MemoryDumpProvider implementation.
- bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) override;
-
- // Used by out-of-process heap-profiling. When malloc is profiled by an
- // external process, that process will be responsible for emitting metrics on
- // behalf of this one. Thus, MallocDumpProvider should not do anything.
- void EnableMetrics();
- void DisableMetrics();
-
- private:
- friend struct DefaultSingletonTraits<MallocDumpProvider>;
-
- MallocDumpProvider();
- ~MallocDumpProvider() override;
-
- bool emit_metrics_on_memory_dump_ = true;
- base::Lock emit_metrics_on_memory_dump_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(MallocDumpProvider);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_
diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc
deleted file mode 100644
index 5260a734db..0000000000
--- a/base/trace_event/memory_allocator_dump.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2015 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/trace_event/memory_allocator_dump.h"
-
-#include <string.h>
-
-#include "base/format_macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/values.h"
-
-namespace base {
-namespace trace_event {
-
-const char MemoryAllocatorDump::kNameSize[] = "size";
-const char MemoryAllocatorDump::kNameObjectCount[] = "object_count";
-const char MemoryAllocatorDump::kTypeScalar[] = "scalar";
-const char MemoryAllocatorDump::kTypeString[] = "string";
-const char MemoryAllocatorDump::kUnitsBytes[] = "bytes";
-const char MemoryAllocatorDump::kUnitsObjects[] = "objects";
-
-MemoryAllocatorDump::MemoryAllocatorDump(
- const std::string& absolute_name,
- MemoryDumpLevelOfDetail level_of_detail,
- const MemoryAllocatorDumpGuid& guid)
- : absolute_name_(absolute_name),
- guid_(guid),
- level_of_detail_(level_of_detail),
- flags_(Flags::DEFAULT) {
- // The |absolute_name| cannot be empty.
- DCHECK(!absolute_name.empty());
-
- // The |absolute_name| can contain slash separator, but not leading or
- // trailing ones.
- DCHECK(absolute_name[0] != '/' && *absolute_name.rbegin() != '/');
-}
-
-MemoryAllocatorDump::~MemoryAllocatorDump() = default;
-
-void MemoryAllocatorDump::AddScalar(const char* name,
- const char* units,
- uint64_t value) {
- entries_.emplace_back(name, units, value);
-}
-
-void MemoryAllocatorDump::AddString(const char* name,
- const char* units,
- const std::string& value) {
- // String attributes are disabled in background mode.
- if (level_of_detail_ == MemoryDumpLevelOfDetail::BACKGROUND) {
- NOTREACHED();
- return;
- }
- entries_.emplace_back(name, units, value);
-}
-
-void MemoryAllocatorDump::AsValueInto(TracedValue* value) const {
- std::string string_conversion_buffer;
- value->BeginDictionaryWithCopiedName(absolute_name_);
- value->SetString("guid", guid_.ToString());
- value->BeginDictionary("attrs");
-
- for (const Entry& entry : entries_) {
- value->BeginDictionaryWithCopiedName(entry.name);
- switch (entry.entry_type) {
- case Entry::kUint64:
- SStringPrintf(&string_conversion_buffer, "%" PRIx64,
- entry.value_uint64);
- value->SetString("type", kTypeScalar);
- value->SetString("units", entry.units);
- value->SetString("value", string_conversion_buffer);
- break;
- case Entry::kString:
- value->SetString("type", kTypeString);
- value->SetString("units", entry.units);
- value->SetString("value", entry.value_string);
- break;
- }
- value->EndDictionary();
- }
- value->EndDictionary(); // "attrs": { ... }
- if (flags_)
- value->SetInteger("flags", flags_);
- value->EndDictionary(); // "allocator_name/heap_subheap": { ... }
-}
-
-uint64_t MemoryAllocatorDump::GetSizeInternal() const {
- if (cached_size_.has_value())
- return *cached_size_;
- for (const auto& entry : entries_) {
- if (entry.entry_type == Entry::kUint64 && entry.units == kUnitsBytes &&
- strcmp(entry.name.c_str(), kNameSize) == 0) {
- cached_size_ = entry.value_uint64;
- return entry.value_uint64;
- }
- }
- return 0;
-};
-
-MemoryAllocatorDump::Entry::Entry() : entry_type(kString), value_uint64() {}
-MemoryAllocatorDump::Entry::Entry(MemoryAllocatorDump::Entry&&) noexcept =
- default;
-MemoryAllocatorDump::Entry& MemoryAllocatorDump::Entry::operator=(
- MemoryAllocatorDump::Entry&&) = default;
-MemoryAllocatorDump::Entry::Entry(std::string name,
- std::string units,
- uint64_t value)
- : name(name), units(units), entry_type(kUint64), value_uint64(value) {}
-MemoryAllocatorDump::Entry::Entry(std::string name,
- std::string units,
- std::string value)
- : name(name), units(units), entry_type(kString), value_string(value) {}
-
-bool MemoryAllocatorDump::Entry::operator==(const Entry& rhs) const {
- if (!(name == rhs.name && units == rhs.units && entry_type == rhs.entry_type))
- return false;
- switch (entry_type) {
- case EntryType::kUint64:
- return value_uint64 == rhs.value_uint64;
- case EntryType::kString:
- return value_string == rhs.value_string;
- }
- NOTREACHED();
- return false;
-}
-
-void PrintTo(const MemoryAllocatorDump::Entry& entry, std::ostream* out) {
- switch (entry.entry_type) {
- case MemoryAllocatorDump::Entry::EntryType::kUint64:
- *out << "<Entry(\"" << entry.name << "\", \"" << entry.units << "\", "
- << entry.value_uint64 << ")>";
- return;
- case MemoryAllocatorDump::Entry::EntryType::kString:
- *out << "<Entry(\"" << entry.name << "\", \"" << entry.units << "\", \""
- << entry.value_string << "\")>";
- return;
- }
- NOTREACHED();
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_allocator_dump.h b/base/trace_event/memory_allocator_dump.h
deleted file mode 100644
index de38afd9e7..0000000000
--- a/base/trace_event/memory_allocator_dump.h
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
-#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <ostream>
-#include <string>
-
-#include "base/base_export.h"
-#include "base/gtest_prod_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "base/trace_event/memory_allocator_dump_guid.h"
-#include "base/trace_event/memory_dump_request_args.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/unguessable_token.h"
-#include "base/values.h"
-
-namespace base {
-namespace trace_event {
-
-class ProcessMemoryDump;
-class TracedValue;
-
-// Data model for user-land memory allocator dumps.
-class BASE_EXPORT MemoryAllocatorDump {
- public:
- enum Flags {
- DEFAULT = 0,
-
- // A dump marked weak will be discarded by TraceViewer.
- WEAK = 1 << 0,
- };
-
- // In the TraceViewer UI table each MemoryAllocatorDump becomes
- // a row and each Entry generates a column (if it doesn't already
- // exist).
- struct BASE_EXPORT Entry {
- enum EntryType {
- kUint64,
- kString,
- };
-
- // By design name, units and value_string are always coming from
- // indefinitely lived const char* strings, the only reason we copy
- // them into a std::string is to handle Mojo (de)serialization.
- // TODO(hjd): Investigate optimization (e.g. using StringPiece).
- Entry(); // Only for deserialization.
- Entry(std::string name, std::string units, uint64_t value);
- Entry(std::string name, std::string units, std::string value);
- Entry(Entry&& other) noexcept;
- Entry& operator=(Entry&& other);
- bool operator==(const Entry& rhs) const;
-
- std::string name;
- std::string units;
-
- EntryType entry_type;
-
- uint64_t value_uint64;
- std::string value_string;
-
- DISALLOW_COPY_AND_ASSIGN(Entry);
- };
-
- MemoryAllocatorDump(const std::string& absolute_name,
- MemoryDumpLevelOfDetail,
- const MemoryAllocatorDumpGuid&);
- ~MemoryAllocatorDump();
-
- // Standard attribute |name|s for the AddScalar and AddString() methods.
- static const char kNameSize[]; // To represent allocated space.
- static const char kNameObjectCount[]; // To represent number of objects.
-
- // Standard attribute |unit|s for the AddScalar and AddString() methods.
- static const char kUnitsBytes[]; // Unit name to represent bytes.
- static const char kUnitsObjects[]; // Unit name to represent #objects.
-
- // Constants used only internally and by tests.
- static const char kTypeScalar[]; // Type name for scalar attributes.
- static const char kTypeString[]; // Type name for string attributes.
-
- // Setters for scalar attributes. Some examples:
- // - "size" column (all dumps are expected to have at least this one):
- // AddScalar(kNameSize, kUnitsBytes, 1234);
- // - Some extra-column reporting internal details of the subsystem:
- // AddScalar("number_of_freelist_entries", kUnitsObjects, 42)
- // - Other informational column:
- // AddString("kitten", "name", "shadow");
- void AddScalar(const char* name, const char* units, uint64_t value);
- void AddString(const char* name, const char* units, const std::string& value);
-
- // Absolute name, unique within the scope of an entire ProcessMemoryDump.
- const std::string& absolute_name() const { return absolute_name_; }
-
- // Called at trace generation time to populate the TracedValue.
- void AsValueInto(TracedValue* value) const;
-
- // Get the size for this dump.
- // The size is the value set with AddScalar(kNameSize, kUnitsBytes, size);
- // TODO(hjd): this should return an Optional<uint64_t>.
- uint64_t GetSizeInternal() const;
-
- MemoryDumpLevelOfDetail level_of_detail() const { return level_of_detail_; }
-
- // Use enum Flags to set values.
- void set_flags(int flags) { flags_ |= flags; }
- void clear_flags(int flags) { flags_ &= ~flags; }
- int flags() const { return flags_; }
-
- // |guid| is an optional global dump identifier, unique across all processes
- // within the scope of a global dump. It is only required when using the
- // graph APIs (see TODO_method_name) to express retention / suballocation or
- // cross process sharing. See crbug.com/492102 for design docs.
- // Subsequent MemoryAllocatorDump(s) with the same |absolute_name| are
- // expected to have the same guid.
- const MemoryAllocatorDumpGuid& guid() const { return guid_; }
-
- const std::vector<Entry>& entries() const { return entries_; }
-
- // Only for mojo serialization, which can mutate the collection.
- std::vector<Entry>* mutable_entries_for_serialization() const {
- cached_size_.reset(); // The caller can mutate the collection.
-
- // Mojo takes a const input argument even for move-only types that can be
- // mutate while serializing (like this one). Hence the const_cast.
- return const_cast<std::vector<Entry>*>(&entries_);
- }
-
- private:
- const std::string absolute_name_;
- MemoryAllocatorDumpGuid guid_;
- MemoryDumpLevelOfDetail level_of_detail_;
- int flags_; // See enum Flags.
- mutable Optional<uint64_t> cached_size_; // Lazy, for GetSizeInternal().
- std::vector<Entry> entries_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorDump);
-};
-
-// This is required by gtest to print a readable output on test failures.
-void BASE_EXPORT PrintTo(const MemoryAllocatorDump::Entry&, std::ostream*);
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_
diff --git a/base/trace_event/memory_allocator_dump_guid.cc b/base/trace_event/memory_allocator_dump_guid.cc
deleted file mode 100644
index 08ac677cfe..0000000000
--- a/base/trace_event/memory_allocator_dump_guid.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 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/trace_event/memory_allocator_dump_guid.h"
-
-#include "base/format_macros.h"
-#include "base/sha1.h"
-#include "base/strings/stringprintf.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-uint64_t HashString(const std::string& str) {
- uint64_t hash[(kSHA1Length + sizeof(uint64_t) - 1) / sizeof(uint64_t)] = {0};
- SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.data()), str.size(),
- reinterpret_cast<unsigned char*>(hash));
- return hash[0];
-}
-
-} // namespace
-
-MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid(uint64_t guid) : guid_(guid) {}
-
-MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid()
- : MemoryAllocatorDumpGuid(0u) {
-}
-
-MemoryAllocatorDumpGuid::MemoryAllocatorDumpGuid(const std::string& guid_str)
- : MemoryAllocatorDumpGuid(HashString(guid_str)) {
-}
-
-std::string MemoryAllocatorDumpGuid::ToString() const {
- return StringPrintf("%" PRIx64, guid_);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_allocator_dump_guid.h b/base/trace_event/memory_allocator_dump_guid.h
deleted file mode 100644
index 2a420a2af7..0000000000
--- a/base/trace_event/memory_allocator_dump_guid.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_GUID_H_
-#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_GUID_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/base_export.h"
-
-namespace base {
-namespace trace_event {
-
-class BASE_EXPORT MemoryAllocatorDumpGuid {
- public:
- MemoryAllocatorDumpGuid();
- explicit MemoryAllocatorDumpGuid(uint64_t guid);
-
- // Utility ctor to hash a GUID if the caller prefers a string. The caller
- // still has to ensure that |guid_str| is unique, per snapshot, within the
- // global scope of all the traced processes.
- explicit MemoryAllocatorDumpGuid(const std::string& guid_str);
-
- uint64_t ToUint64() const { return guid_; }
-
- // Returns a (hex-encoded) string representation of the guid.
- std::string ToString() const;
-
- bool empty() const { return guid_ == 0u; }
-
- bool operator==(const MemoryAllocatorDumpGuid& other) const {
- return guid_ == other.guid_;
- }
-
- bool operator!=(const MemoryAllocatorDumpGuid& other) const {
- return !(*this == other);
- }
-
- bool operator<(const MemoryAllocatorDumpGuid& other) const {
- return guid_ < other.guid_;
- }
-
- private:
- uint64_t guid_;
-
- // Deliberately copy-able.
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_GUID_H_
diff --git a/base/trace_event/memory_allocator_dump_unittest.cc b/base/trace_event/memory_allocator_dump_unittest.cc
deleted file mode 100644
index 78a545ff84..0000000000
--- a/base/trace_event/memory_allocator_dump_unittest.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2015 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/trace_event/memory_allocator_dump.h"
-
-#include <stdint.h>
-
-#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/memory_allocator_dump_guid.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::ElementsAre;
-using testing::Eq;
-using testing::ByRef;
-using testing::IsEmpty;
-using testing::Contains;
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-class FakeMemoryAllocatorDumpProvider : public MemoryDumpProvider {
- public:
- bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) override {
- MemoryAllocatorDump* root_heap =
- pmd->CreateAllocatorDump("foobar_allocator");
-
- root_heap->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes, 4096);
- root_heap->AddScalar(MemoryAllocatorDump::kNameObjectCount,
- MemoryAllocatorDump::kUnitsObjects, 42);
- root_heap->AddScalar("attr1", "units1", 1234);
- root_heap->AddString("attr2", "units2", "string_value");
-
- MemoryAllocatorDump* sub_heap =
- pmd->CreateAllocatorDump("foobar_allocator/sub_heap");
- sub_heap->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes, 1);
- sub_heap->AddScalar(MemoryAllocatorDump::kNameObjectCount,
- MemoryAllocatorDump::kUnitsObjects, 3);
-
- pmd->CreateAllocatorDump("foobar_allocator/sub_heap/empty");
- // Leave the rest of sub heap deliberately uninitialized, to check that
- // CreateAllocatorDump returns a properly zero-initialized object.
-
- return true;
- }
-};
-
-void CheckString(const MemoryAllocatorDump* dump,
- const std::string& name,
- const char* expected_units,
- const std::string& expected_value) {
- MemoryAllocatorDump::Entry expected(name, expected_units, expected_value);
- EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(expected))));
-}
-
-void CheckScalar(const MemoryAllocatorDump* dump,
- const std::string& name,
- const char* expected_units,
- uint64_t expected_value) {
- MemoryAllocatorDump::Entry expected(name, expected_units, expected_value);
- EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(expected))));
-}
-
-} // namespace
-
-TEST(MemoryAllocatorDumpTest, GuidGeneration) {
- std::unique_ptr<MemoryAllocatorDump> mad(new MemoryAllocatorDump(
- "foo", MemoryDumpLevelOfDetail::FIRST, MemoryAllocatorDumpGuid(0x42u)));
- ASSERT_EQ("42", mad->guid().ToString());
-}
-
-TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) {
- FakeMemoryAllocatorDumpProvider fmadp;
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
- ProcessMemoryDump pmd(dump_args);
-
- fmadp.OnMemoryDump(dump_args, &pmd);
-
- ASSERT_EQ(3u, pmd.allocator_dumps().size());
-
- const MemoryAllocatorDump* root_heap =
- pmd.GetAllocatorDump("foobar_allocator");
- ASSERT_NE(nullptr, root_heap);
- EXPECT_EQ("foobar_allocator", root_heap->absolute_name());
- CheckScalar(root_heap, MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes, 4096);
- CheckScalar(root_heap, MemoryAllocatorDump::kNameObjectCount,
- MemoryAllocatorDump::kUnitsObjects, 42);
- CheckScalar(root_heap, "attr1", "units1", 1234);
- CheckString(root_heap, "attr2", "units2", "string_value");
-
- const MemoryAllocatorDump* sub_heap =
- pmd.GetAllocatorDump("foobar_allocator/sub_heap");
- ASSERT_NE(nullptr, sub_heap);
- EXPECT_EQ("foobar_allocator/sub_heap", sub_heap->absolute_name());
- CheckScalar(sub_heap, MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes, 1);
- CheckScalar(sub_heap, MemoryAllocatorDump::kNameObjectCount,
- MemoryAllocatorDump::kUnitsObjects, 3);
- const MemoryAllocatorDump* empty_sub_heap =
- pmd.GetAllocatorDump("foobar_allocator/sub_heap/empty");
- ASSERT_NE(nullptr, empty_sub_heap);
- EXPECT_EQ("foobar_allocator/sub_heap/empty", empty_sub_heap->absolute_name());
-
- EXPECT_THAT(empty_sub_heap->entries(), IsEmpty());
-
- // Check that calling serialization routines doesn't cause a crash.
- std::unique_ptr<TracedValue> traced_value(new TracedValue);
- pmd.SerializeAllocatorDumpsInto(traced_value.get());
-}
-
-TEST(MemoryAllocatorDumpTest, GetSize) {
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
- ProcessMemoryDump pmd(dump_args);
- MemoryAllocatorDump* dump = pmd.CreateAllocatorDump("allocator_for_size");
- dump->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes, 1);
- dump->AddScalar("foo", MemoryAllocatorDump::kUnitsBytes, 2);
- EXPECT_EQ(1u, dump->GetSizeInternal());
-}
-
-TEST(MemoryAllocatorDumpTest, ReadValues) {
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
- ProcessMemoryDump pmd(dump_args);
- MemoryAllocatorDump* dump = pmd.CreateAllocatorDump("allocator_for_size");
- dump->AddScalar("one", "byte", 1);
- dump->AddString("one", "object", "one");
-
- MemoryAllocatorDump::Entry expected_scalar("one", "byte", 1);
- MemoryAllocatorDump::Entry expected_string("one", "object", "one");
- EXPECT_THAT(dump->entries(), ElementsAre(Eq(ByRef(expected_scalar)),
- Eq(ByRef(expected_string))));
-}
-
-TEST(MemoryAllocatorDumpTest, MovingAnEntry) {
- MemoryAllocatorDump::Entry expected_entry("one", "byte", 1);
- MemoryAllocatorDump::Entry from_entry("one", "byte", 1);
- MemoryAllocatorDump::Entry to_entry = std::move(from_entry);
- EXPECT_EQ(expected_entry, to_entry);
-}
-
-// DEATH tests are not supported in Android/iOS/Fuchsia.
-#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS) && \
- !defined(OS_FUCHSIA)
-TEST(MemoryAllocatorDumpTest, ForbidDuplicatesDeathTest) {
- FakeMemoryAllocatorDumpProvider fmadp;
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
- ProcessMemoryDump pmd(dump_args);
- pmd.CreateAllocatorDump("foo_allocator");
- pmd.CreateAllocatorDump("bar_allocator/heap");
- ASSERT_DEATH(pmd.CreateAllocatorDump("foo_allocator"), "");
- ASSERT_DEATH(pmd.CreateAllocatorDump("bar_allocator/heap"), "");
- ASSERT_DEATH(pmd.CreateAllocatorDump(""), "");
-}
-
-TEST(MemoryAllocatorDumpTest, ForbidStringsInBackgroundModeDeathTest) {
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::BACKGROUND};
- ProcessMemoryDump pmd(dump_args);
- MemoryAllocatorDump* dump = pmd.CreateAllocatorDump("malloc");
- ASSERT_DEATH(dump->AddString("foo", "bar", "baz"), "");
-}
-#endif
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
deleted file mode 100644
index d61528af8e..0000000000
--- a/base/trace_event/memory_dump_manager.cc
+++ /dev/null
@@ -1,545 +0,0 @@
-// Copyright 2015 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/trace_event/memory_dump_manager.h"
-
-#include <inttypes.h>
-#include <stdio.h>
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "base/allocator/buildflags.h"
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/debug/alias.h"
-#include "base/debug/stack_trace.h"
-#include "base/debug/thread_heap_usage_tracker.h"
-#include "base/memory/ptr_util.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/heap_profiler.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "base/trace_event/heap_profiler_event_filter.h"
-#include "base/trace_event/malloc_dump_provider.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "base/trace_event/memory_dump_scheduler.h"
-#include "base/trace_event/memory_infra_background_whitelist.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "build/build_config.h"
-
-#if defined(OS_ANDROID)
-#include "base/trace_event/java_heap_dump_provider_android.h"
-
-#if BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE)
-#include "base/trace_event/cfi_backtrace_android.h"
-#endif
-
-#endif // defined(OS_ANDROID)
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-MemoryDumpManager* g_memory_dump_manager_for_testing = nullptr;
-
-// Temporary (until scheduler is moved outside of here)
-// trampoline function to match the |request_dump_function| passed to Initialize
-// to the callback expected by MemoryDumpScheduler.
-// TODO(primiano): remove this.
-void DoGlobalDumpWithoutCallback(
- MemoryDumpManager::RequestGlobalDumpFunction global_dump_fn,
- MemoryDumpType dump_type,
- MemoryDumpLevelOfDetail level_of_detail) {
- global_dump_fn.Run(dump_type, level_of_detail);
-}
-
-} // namespace
-
-// static
-const char* const MemoryDumpManager::kTraceCategory =
- TRACE_DISABLED_BY_DEFAULT("memory-infra");
-
-// static
-const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3;
-
-// static
-const uint64_t MemoryDumpManager::kInvalidTracingProcessId = 0;
-
-// static
-const char* const MemoryDumpManager::kSystemAllocatorPoolName =
-#if defined(MALLOC_MEMORY_TRACING_SUPPORTED)
- MallocDumpProvider::kAllocatedObjects;
-#else
- nullptr;
-#endif
-
-// static
-MemoryDumpManager* MemoryDumpManager::GetInstance() {
- if (g_memory_dump_manager_for_testing)
- return g_memory_dump_manager_for_testing;
-
- return Singleton<MemoryDumpManager,
- LeakySingletonTraits<MemoryDumpManager>>::get();
-}
-
-// static
-std::unique_ptr<MemoryDumpManager>
-MemoryDumpManager::CreateInstanceForTesting() {
- DCHECK(!g_memory_dump_manager_for_testing);
- std::unique_ptr<MemoryDumpManager> instance(new MemoryDumpManager());
- g_memory_dump_manager_for_testing = instance.get();
- return instance;
-}
-
-MemoryDumpManager::MemoryDumpManager()
- : is_coordinator_(false),
- tracing_process_id_(kInvalidTracingProcessId),
- dumper_registrations_ignored_for_testing_(false) {}
-
-MemoryDumpManager::~MemoryDumpManager() {
- Thread* dump_thread = nullptr;
- {
- AutoLock lock(lock_);
- if (dump_thread_) {
- dump_thread = dump_thread_.get();
- }
- }
- if (dump_thread) {
- dump_thread->Stop();
- }
- AutoLock lock(lock_);
- dump_thread_.reset();
- g_memory_dump_manager_for_testing = nullptr;
-}
-
-void MemoryDumpManager::Initialize(
- RequestGlobalDumpFunction request_dump_function,
- bool is_coordinator) {
- {
- AutoLock lock(lock_);
- DCHECK(!request_dump_function.is_null());
- DCHECK(!can_request_global_dumps());
- request_dump_function_ = request_dump_function;
- is_coordinator_ = is_coordinator;
- }
-
-// Enable the core dump providers.
-#if defined(MALLOC_MEMORY_TRACING_SUPPORTED)
- RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr);
-#endif
-
-#if defined(OS_ANDROID)
- RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap",
- nullptr);
-#endif
-
- TRACE_EVENT_WARMUP_CATEGORY(kTraceCategory);
-}
-
-void MemoryDumpManager::RegisterDumpProvider(
- MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- MemoryDumpProvider::Options options) {
- options.dumps_on_single_thread_task_runner = true;
- RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
-}
-
-void MemoryDumpManager::RegisterDumpProvider(
- MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SingleThreadTaskRunner> task_runner) {
- // Set |dumps_on_single_thread_task_runner| to true because all providers
- // without task runner are run on dump thread.
- MemoryDumpProvider::Options options;
- options.dumps_on_single_thread_task_runner = true;
- RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
-}
-
-void MemoryDumpManager::RegisterDumpProviderWithSequencedTaskRunner(
- MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SequencedTaskRunner> task_runner,
- MemoryDumpProvider::Options options) {
- DCHECK(task_runner);
- options.dumps_on_single_thread_task_runner = false;
- RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options);
-}
-
-void MemoryDumpManager::RegisterDumpProviderInternal(
- MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SequencedTaskRunner> task_runner,
- const MemoryDumpProvider::Options& options) {
- if (dumper_registrations_ignored_for_testing_)
- return;
-
- // Only a handful of MDPs are required to compute the memory metrics. These
- // have small enough performance overhead that it is resonable to run them
- // in the background while the user is doing other things. Those MDPs are
- // 'whitelisted for background mode'.
- bool whitelisted_for_background_mode = IsMemoryDumpProviderWhitelisted(name);
-
- scoped_refptr<MemoryDumpProviderInfo> mdpinfo =
- new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options,
- whitelisted_for_background_mode);
-
- {
- AutoLock lock(lock_);
- bool already_registered = !dump_providers_.insert(mdpinfo).second;
- // This actually happens in some tests which don't have a clean tear-down
- // path for RenderThreadImpl::Init().
- if (already_registered)
- return;
- }
-}
-
-void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
- UnregisterDumpProviderInternal(mdp, false /* delete_async */);
-}
-
-void MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon(
- std::unique_ptr<MemoryDumpProvider> mdp) {
- UnregisterDumpProviderInternal(mdp.release(), true /* delete_async */);
-}
-
-void MemoryDumpManager::UnregisterDumpProviderInternal(
- MemoryDumpProvider* mdp,
- bool take_mdp_ownership_and_delete_async) {
- std::unique_ptr<MemoryDumpProvider> owned_mdp;
- if (take_mdp_ownership_and_delete_async)
- owned_mdp.reset(mdp);
-
- AutoLock lock(lock_);
-
- auto mdp_iter = dump_providers_.begin();
- for (; mdp_iter != dump_providers_.end(); ++mdp_iter) {
- if ((*mdp_iter)->dump_provider == mdp)
- break;
- }
-
- if (mdp_iter == dump_providers_.end())
- return; // Not registered / already unregistered.
-
- if (take_mdp_ownership_and_delete_async) {
- // The MDP will be deleted whenever the MDPInfo struct will, that is either:
- // - At the end of this function, if no dump is in progress.
- // - In ContinueAsyncProcessDump() when MDPInfo is removed from
- // |pending_dump_providers|.
- DCHECK(!(*mdp_iter)->owned_dump_provider);
- (*mdp_iter)->owned_dump_provider = std::move(owned_mdp);
- } else {
- // If you hit this DCHECK, your dump provider has a bug.
- // Unregistration of a MemoryDumpProvider is safe only if:
- // - The MDP has specified a sequenced task runner affinity AND the
- // unregistration happens on the same task runner. So that the MDP cannot
- // unregister and be in the middle of a OnMemoryDump() at the same time.
- // - The MDP has NOT specified a task runner affinity and its ownership is
- // transferred via UnregisterAndDeleteDumpProviderSoon().
- // In all the other cases, it is not possible to guarantee that the
- // unregistration will not race with OnMemoryDump() calls.
- DCHECK((*mdp_iter)->task_runner &&
- (*mdp_iter)->task_runner->RunsTasksInCurrentSequence())
- << "MemoryDumpProvider \"" << (*mdp_iter)->name << "\" attempted to "
- << "unregister itself in a racy way. Please file a crbug.";
- }
-
- // The MDPInfo instance can still be referenced by the
- // |ProcessMemoryDumpAsyncState.pending_dump_providers|. For this reason
- // the MDPInfo is flagged as disabled. It will cause InvokeOnMemoryDump()
- // to just skip it, without actually invoking the |mdp|, which might be
- // destroyed by the caller soon after this method returns.
- (*mdp_iter)->disabled = true;
- dump_providers_.erase(mdp_iter);
-}
-
-bool MemoryDumpManager::IsDumpProviderRegisteredForTesting(
- MemoryDumpProvider* provider) {
- AutoLock lock(lock_);
-
- for (const auto& info : dump_providers_) {
- if (info->dump_provider == provider)
- return true;
- }
- return false;
-}
-
-scoped_refptr<base::SequencedTaskRunner>
-MemoryDumpManager::GetOrCreateBgTaskRunnerLocked() {
- lock_.AssertAcquired();
-
- if (dump_thread_)
- return dump_thread_->task_runner();
-
- dump_thread_ = std::make_unique<Thread>("MemoryInfra");
- bool started = dump_thread_->Start();
- CHECK(started);
-
- return dump_thread_->task_runner();
-}
-
-void MemoryDumpManager::CreateProcessDump(
- const MemoryDumpRequestArgs& args,
- const ProcessMemoryDumpCallback& callback) {
- char guid_str[20];
- sprintf(guid_str, "0x%" PRIx64, args.dump_guid);
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump",
- TRACE_ID_LOCAL(args.dump_guid), "dump_guid",
- TRACE_STR_COPY(guid_str));
-
- // If argument filter is enabled then only background mode dumps should be
- // allowed. In case the trace config passed for background tracing session
- // missed the allowed modes argument, it crashes here instead of creating
- // unexpected dumps.
- if (TraceLog::GetInstance()
- ->GetCurrentTraceConfig()
- .IsArgumentFilterEnabled()) {
- CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail);
- }
-
- std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state;
- {
- AutoLock lock(lock_);
-
- pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
- args, dump_providers_, callback, GetOrCreateBgTaskRunnerLocked()));
- }
-
- // Start the process dump. This involves task runner hops as specified by the
- // MemoryDumpProvider(s) in RegisterDumpProvider()).
- ContinueAsyncProcessDump(pmd_async_state.release());
-}
-
-// Invokes OnMemoryDump() on all MDPs that are next in the pending list and run
-// on the current sequenced task runner. If the next MDP does not run in current
-// sequenced task runner, then switches to that task runner and continues. All
-// OnMemoryDump() invocations are linearized. |lock_| is used in these functions
-// purely to ensure consistency w.r.t. (un)registrations of |dump_providers_|.
-void MemoryDumpManager::ContinueAsyncProcessDump(
- ProcessMemoryDumpAsyncState* owned_pmd_async_state) {
- HEAP_PROFILER_SCOPED_IGNORE;
- // Initalizes the ThreadLocalEventBuffer to guarantee that the TRACE_EVENTs
- // in the PostTask below don't end up registering their own dump providers
- // (for discounting trace memory overhead) while holding the |lock_|.
- TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported();
-
- // In theory |owned_pmd_async_state| should be a unique_ptr. The only reason
- // why it isn't is because of the corner case logic of |did_post_task|
- // above, which needs to take back the ownership of the |pmd_async_state| when
- // the PostTask() fails.
- // Unfortunately, PostTask() destroys the unique_ptr arguments upon failure
- // to prevent accidental leaks. Using a unique_ptr would prevent us to to
- // skip the hop and move on. Hence the manual naked -> unique ptr juggling.
- auto pmd_async_state = WrapUnique(owned_pmd_async_state);
- owned_pmd_async_state = nullptr;
-
- while (!pmd_async_state->pending_dump_providers.empty()) {
- // Read MemoryDumpProviderInfo thread safety considerations in
- // memory_dump_manager.h when accessing |mdpinfo| fields.
- MemoryDumpProviderInfo* mdpinfo =
- pmd_async_state->pending_dump_providers.back().get();
-
- // If we are in background mode, we should invoke only the whitelisted
- // providers. Ignore other providers and continue.
- if (pmd_async_state->req_args.level_of_detail ==
- MemoryDumpLevelOfDetail::BACKGROUND &&
- !mdpinfo->whitelisted_for_background_mode) {
- pmd_async_state->pending_dump_providers.pop_back();
- continue;
- }
-
- // If the dump provider did not specify a task runner affinity, dump on
- // |dump_thread_|.
- scoped_refptr<SequencedTaskRunner> task_runner = mdpinfo->task_runner;
- if (!task_runner) {
- DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner);
- task_runner = pmd_async_state->dump_thread_task_runner;
- DCHECK(task_runner);
- }
-
- // If |RunsTasksInCurrentSequence()| is true then no PostTask is
- // required since we are on the right SequencedTaskRunner.
- if (task_runner->RunsTasksInCurrentSequence()) {
- InvokeOnMemoryDump(mdpinfo, pmd_async_state->process_memory_dump.get());
- pmd_async_state->pending_dump_providers.pop_back();
- continue;
- }
-
- bool did_post_task = task_runner->PostTask(
- FROM_HERE,
- BindOnce(&MemoryDumpManager::ContinueAsyncProcessDump, Unretained(this),
- Unretained(pmd_async_state.get())));
-
- if (did_post_task) {
- // Ownership is tranferred to the posted task.
- ignore_result(pmd_async_state.release());
- return;
- }
-
- // PostTask usually fails only if the process or thread is shut down. So,
- // the dump provider is disabled here. But, don't disable unbound dump
- // providers, since the |dump_thread_| is controlled by MDM.
- if (mdpinfo->task_runner) {
- // A locked access is required to R/W |disabled| (for the
- // UnregisterAndDeleteDumpProviderSoon() case).
- AutoLock lock(lock_);
- mdpinfo->disabled = true;
- }
-
- // PostTask failed. Ignore the dump provider and continue.
- pmd_async_state->pending_dump_providers.pop_back();
- }
-
- FinishAsyncProcessDump(std::move(pmd_async_state));
-}
-
-// This function is called on the right task runner for current MDP. It is
-// either the task runner specified by MDP or |dump_thread_task_runner| if the
-// MDP did not specify task runner. Invokes the dump provider's OnMemoryDump()
-// (unless disabled).
-void MemoryDumpManager::InvokeOnMemoryDump(MemoryDumpProviderInfo* mdpinfo,
- ProcessMemoryDump* pmd) {
- HEAP_PROFILER_SCOPED_IGNORE;
- DCHECK(!mdpinfo->task_runner ||
- mdpinfo->task_runner->RunsTasksInCurrentSequence());
-
- TRACE_EVENT1(kTraceCategory, "MemoryDumpManager::InvokeOnMemoryDump",
- "dump_provider.name", mdpinfo->name);
-
- // Do not add any other TRACE_EVENT macro (or function that might have them)
- // below this point. Under some rare circunstances, they can re-initialize
- // and invalide the current ThreadLocalEventBuffer MDP, making the
- // |should_dump| check below susceptible to TOCTTOU bugs
- // (https://crbug.com/763365).
-
- bool is_thread_bound;
- {
- // A locked access is required to R/W |disabled| (for the
- // UnregisterAndDeleteDumpProviderSoon() case).
- AutoLock lock(lock_);
-
- // Unregister the dump provider if it failed too many times consecutively.
- if (!mdpinfo->disabled &&
- mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) {
- mdpinfo->disabled = true;
- DLOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name
- << "\". Dump failed multiple times consecutively.";
- }
- if (mdpinfo->disabled)
- return;
-
- is_thread_bound = mdpinfo->task_runner != nullptr;
- } // AutoLock lock(lock_);
-
- // Invoke the dump provider.
-
- // A stack allocated string with dump provider name is useful to debug
- // crashes while invoking dump after a |dump_provider| is not unregistered
- // in safe way.
- char provider_name_for_debugging[16];
- strncpy(provider_name_for_debugging, mdpinfo->name,
- sizeof(provider_name_for_debugging) - 1);
- provider_name_for_debugging[sizeof(provider_name_for_debugging) - 1] = '\0';
- base::debug::Alias(provider_name_for_debugging);
-
- ANNOTATE_BENIGN_RACE(&mdpinfo->disabled, "best-effort race detection");
- CHECK(!is_thread_bound ||
- !*(static_cast<volatile bool*>(&mdpinfo->disabled)));
- bool dump_successful =
- mdpinfo->dump_provider->OnMemoryDump(pmd->dump_args(), pmd);
- mdpinfo->consecutive_failures =
- dump_successful ? 0 : mdpinfo->consecutive_failures + 1;
-}
-
-void MemoryDumpManager::FinishAsyncProcessDump(
- std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) {
- HEAP_PROFILER_SCOPED_IGNORE;
- DCHECK(pmd_async_state->pending_dump_providers.empty());
- const uint64_t dump_guid = pmd_async_state->req_args.dump_guid;
- if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) {
- scoped_refptr<SingleThreadTaskRunner> callback_task_runner =
- pmd_async_state->callback_task_runner;
- callback_task_runner->PostTask(
- FROM_HERE, BindOnce(&MemoryDumpManager::FinishAsyncProcessDump,
- Unretained(this), std::move(pmd_async_state)));
- return;
- }
-
- TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinishAsyncProcessDump");
-
- if (!pmd_async_state->callback.is_null()) {
- pmd_async_state->callback.Run(
- true /* success */, dump_guid,
- std::move(pmd_async_state->process_memory_dump));
- pmd_async_state->callback.Reset();
- }
-
- TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump",
- TRACE_ID_LOCAL(dump_guid));
-}
-
-void MemoryDumpManager::SetupForTracing(
- const TraceConfig::MemoryDumpConfig& memory_dump_config) {
- AutoLock lock(lock_);
-
- // At this point we must have the ability to request global dumps.
- DCHECK(can_request_global_dumps());
-
- MemoryDumpScheduler::Config periodic_config;
- for (const auto& trigger : memory_dump_config.triggers) {
- if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) {
- if (periodic_config.triggers.empty()) {
- periodic_config.callback =
- BindRepeating(&DoGlobalDumpWithoutCallback, request_dump_function_,
- MemoryDumpType::PERIODIC_INTERVAL);
- }
- periodic_config.triggers.push_back(
- {trigger.level_of_detail, trigger.min_time_between_dumps_ms});
- }
- }
-
- // Only coordinator process triggers periodic memory dumps.
- if (is_coordinator_ && !periodic_config.triggers.empty()) {
- MemoryDumpScheduler::GetInstance()->Start(periodic_config,
- GetOrCreateBgTaskRunnerLocked());
- }
-}
-
-void MemoryDumpManager::TeardownForTracing() {
- // There might be a memory dump in progress while this happens. Therefore,
- // ensure that the MDM state which depends on the tracing enabled / disabled
- // state is always accessed by the dumping methods holding the |lock_|.
- AutoLock lock(lock_);
-
- MemoryDumpScheduler::GetInstance()->Stop();
-}
-
-MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState(
- MemoryDumpRequestArgs req_args,
- const MemoryDumpProviderInfo::OrderedSet& dump_providers,
- ProcessMemoryDumpCallback callback,
- scoped_refptr<SequencedTaskRunner> dump_thread_task_runner)
- : req_args(req_args),
- callback(callback),
- callback_task_runner(ThreadTaskRunnerHandle::Get()),
- dump_thread_task_runner(std::move(dump_thread_task_runner)) {
- pending_dump_providers.reserve(dump_providers.size());
- pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend());
- MemoryDumpArgs args = {req_args.level_of_detail, req_args.dump_guid};
- process_memory_dump = std::make_unique<ProcessMemoryDump>(args);
-}
-
-MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() =
- default;
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h
deleted file mode 100644
index 6033cfbb51..0000000000
--- a/base/trace_event/memory_dump_manager.h
+++ /dev/null
@@ -1,267 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
-#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <unordered_set>
-#include <vector>
-
-#include "base/atomicops.h"
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/singleton.h"
-#include "base/synchronization/lock.h"
-#include "base/trace_event/memory_allocator_dump.h"
-#include "base/trace_event/memory_dump_provider_info.h"
-#include "base/trace_event/memory_dump_request_args.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-
-class SequencedTaskRunner;
-class SingleThreadTaskRunner;
-class Thread;
-
-namespace trace_event {
-
-class MemoryDumpProvider;
-
-// This is the interface exposed to the rest of the codebase to deal with
-// memory tracing. The main entry point for clients is represented by
-// RequestDumpPoint(). The extension by Un(RegisterDumpProvider).
-class BASE_EXPORT MemoryDumpManager {
- public:
- using RequestGlobalDumpFunction =
- RepeatingCallback<void(MemoryDumpType, MemoryDumpLevelOfDetail)>;
-
- static const char* const kTraceCategory;
-
- // This value is returned as the tracing id of the child processes by
- // GetTracingProcessId() when tracing is not enabled.
- static const uint64_t kInvalidTracingProcessId;
-
- static MemoryDumpManager* GetInstance();
- static std::unique_ptr<MemoryDumpManager> CreateInstanceForTesting();
-
- // Invoked once per process to listen to trace begin / end events.
- // Initialization can happen after (Un)RegisterMemoryDumpProvider() calls
- // and the MemoryDumpManager guarantees to support this.
- // On the other side, the MemoryDumpManager will not be fully operational
- // (any CreateProcessDump() will return a failure) until initialized.
- // Arguments:
- // is_coordinator: True when current process coordinates the periodic dump
- // triggering.
- // request_dump_function: Function to invoke a global dump. Global dump
- // involves embedder-specific behaviors like multiprocess handshaking.
- // TODO(primiano): this is only required to trigger global dumps from
- // the scheduler. Should be removed once they are both moved out of base.
- void Initialize(RequestGlobalDumpFunction request_dump_function,
- bool is_coordinator);
-
- // (Un)Registers a MemoryDumpProvider instance.
- // Args:
- // - mdp: the MemoryDumpProvider instance to be registered. MemoryDumpManager
- // does NOT take memory ownership of |mdp|, which is expected to either
- // be a singleton or unregister itself.
- // - name: a friendly name (duplicates allowed). Used for debugging and
- // run-time profiling of memory-infra internals. Must be a long-lived
- // C string.
- // - task_runner: either a SingleThreadTaskRunner or SequencedTaskRunner. All
- // the calls to |mdp| will be run on the given |task_runner|. If passed
- // null |mdp| should be able to handle calls on arbitrary threads.
- // - options: extra optional arguments. See memory_dump_provider.h.
- void RegisterDumpProvider(MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SingleThreadTaskRunner> task_runner);
- void RegisterDumpProvider(MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- MemoryDumpProvider::Options options);
- void RegisterDumpProviderWithSequencedTaskRunner(
- MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SequencedTaskRunner> task_runner,
- MemoryDumpProvider::Options options);
- void UnregisterDumpProvider(MemoryDumpProvider* mdp);
-
- // Unregisters an unbound dump provider and takes care about its deletion
- // asynchronously. Can be used only for for dump providers with no
- // task-runner affinity.
- // This method takes ownership of the dump provider and guarantees that:
- // - The |mdp| will be deleted at some point in the near future.
- // - Its deletion will not happen concurrently with the OnMemoryDump() call.
- // Note that OnMemoryDump() calls can still happen after this method returns.
- void UnregisterAndDeleteDumpProviderSoon(
- std::unique_ptr<MemoryDumpProvider> mdp);
-
- // Prepare MemoryDumpManager for CreateProcessDump() calls for tracing-related
- // modes (i.e. |level_of_detail| != SUMMARY_ONLY).
- // Also initializes the scheduler with the given config.
- void SetupForTracing(const TraceConfig::MemoryDumpConfig&);
-
- // Tear-down tracing related state.
- // Non-tracing modes (e.g. SUMMARY_ONLY) will continue to work.
- void TeardownForTracing();
-
- // Creates a memory dump for the current process and appends it to the trace.
- // |callback| will be invoked asynchronously upon completion on the same
- // thread on which CreateProcessDump() was called. This method should only be
- // used by the memory-infra service while creating a global memory dump.
- void CreateProcessDump(const MemoryDumpRequestArgs& args,
- const ProcessMemoryDumpCallback& callback);
-
- // Lets tests see if a dump provider is registered.
- bool IsDumpProviderRegisteredForTesting(MemoryDumpProvider*);
-
- // Returns a unique id for identifying the processes. The id can be
- // retrieved by child processes only when tracing is enabled. This is
- // intended to express cross-process sharing of memory dumps on the
- // child-process side, without having to know its own child process id.
- uint64_t GetTracingProcessId() const { return tracing_process_id_; }
- void set_tracing_process_id(uint64_t tracing_process_id) {
- tracing_process_id_ = tracing_process_id;
- }
-
- // Returns the name for a the allocated_objects dump. Use this to declare
- // suballocator dumps from other dump providers.
- // It will return nullptr if there is no dump provider for the system
- // allocator registered (which is currently the case for Mac OS).
- const char* system_allocator_pool_name() const {
- return kSystemAllocatorPoolName;
- };
-
- // When set to true, calling |RegisterMemoryDumpProvider| is a no-op.
- void set_dumper_registrations_ignored_for_testing(bool ignored) {
- dumper_registrations_ignored_for_testing_ = ignored;
- }
-
- private:
- friend std::default_delete<MemoryDumpManager>; // For the testing instance.
- friend struct DefaultSingletonTraits<MemoryDumpManager>;
- friend class MemoryDumpManagerTest;
- FRIEND_TEST_ALL_PREFIXES(MemoryDumpManagerTest,
- NoStackOverflowWithTooManyMDPs);
-
- // Holds the state of a process memory dump that needs to be carried over
- // across task runners in order to fulfill an asynchronous CreateProcessDump()
- // request. At any time exactly one task runner owns a
- // ProcessMemoryDumpAsyncState.
- struct ProcessMemoryDumpAsyncState {
- ProcessMemoryDumpAsyncState(
- MemoryDumpRequestArgs req_args,
- const MemoryDumpProviderInfo::OrderedSet& dump_providers,
- ProcessMemoryDumpCallback callback,
- scoped_refptr<SequencedTaskRunner> dump_thread_task_runner);
- ~ProcessMemoryDumpAsyncState();
-
- // A ProcessMemoryDump to collect data from MemoryDumpProviders.
- std::unique_ptr<ProcessMemoryDump> process_memory_dump;
-
- // The arguments passed to the initial CreateProcessDump() request.
- const MemoryDumpRequestArgs req_args;
-
- // An ordered sequence of dump providers that have to be invoked to complete
- // the dump. This is a copy of |dump_providers_| at the beginning of a dump
- // and becomes empty at the end, when all dump providers have been invoked.
- std::vector<scoped_refptr<MemoryDumpProviderInfo>> pending_dump_providers;
-
- // Callback passed to the initial call to CreateProcessDump().
- ProcessMemoryDumpCallback callback;
-
- // The thread on which FinishAsyncProcessDump() (and hence |callback|)
- // should be invoked. This is the thread on which the initial
- // CreateProcessDump() request was called.
- const scoped_refptr<SingleThreadTaskRunner> callback_task_runner;
-
- // The thread on which unbound dump providers should be invoked.
- // This is essentially |dump_thread_|.task_runner() but needs to be kept
- // as a separate variable as it needs to be accessed by arbitrary dumpers'
- // threads outside of the lock_ to avoid races when disabling tracing.
- // It is immutable for all the duration of a tracing session.
- const scoped_refptr<SequencedTaskRunner> dump_thread_task_runner;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDumpAsyncState);
- };
-
- static const int kMaxConsecutiveFailuresCount;
- static const char* const kSystemAllocatorPoolName;
-
- MemoryDumpManager();
- virtual ~MemoryDumpManager();
-
- static void SetInstanceForTesting(MemoryDumpManager* instance);
-
- // Lazily initializes dump_thread_ and returns its TaskRunner.
- scoped_refptr<base::SequencedTaskRunner> GetOrCreateBgTaskRunnerLocked();
-
- // Calls InvokeOnMemoryDump() for the each MDP that belongs to the current
- // task runner and switches to the task runner of the next MDP. Handles
- // failures in MDP and thread hops, and always calls FinishAsyncProcessDump()
- // at the end.
- void ContinueAsyncProcessDump(
- ProcessMemoryDumpAsyncState* owned_pmd_async_state);
-
- // Invokes OnMemoryDump() of the given MDP. Should be called on the MDP task
- // runner.
- void InvokeOnMemoryDump(MemoryDumpProviderInfo* mdpinfo,
- ProcessMemoryDump* pmd);
-
- void FinishAsyncProcessDump(
- std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state);
-
- // Helper for RegierDumpProvider* functions.
- void RegisterDumpProviderInternal(
- MemoryDumpProvider* mdp,
- const char* name,
- scoped_refptr<SequencedTaskRunner> task_runner,
- const MemoryDumpProvider::Options& options);
-
- // Helper for the public UnregisterDumpProvider* functions.
- void UnregisterDumpProviderInternal(MemoryDumpProvider* mdp,
- bool take_mdp_ownership_and_delete_async);
-
- bool can_request_global_dumps() const {
- return !request_dump_function_.is_null();
- }
-
- // An ordered set of registered MemoryDumpProviderInfo(s), sorted by task
- // runner affinity (MDPs belonging to the same task runners are adjacent).
- MemoryDumpProviderInfo::OrderedSet dump_providers_;
-
- // Function provided by the embedder to handle global dump requests.
- RequestGlobalDumpFunction request_dump_function_;
-
- // True when current process coordinates the periodic dump triggering.
- bool is_coordinator_;
-
- // Protects from concurrent accesses to the local state, eg: to guard against
- // disabling logging while dumping on another thread.
- Lock lock_;
-
- // Thread used for MemoryDumpProviders which don't specify a task runner
- // affinity.
- std::unique_ptr<Thread> dump_thread_;
-
- // The unique id of the child process. This is created only for tracing and is
- // expected to be valid only when tracing is enabled.
- uint64_t tracing_process_id_;
-
- // When true, calling |RegisterMemoryDumpProvider| is a no-op.
- bool dumper_registrations_ignored_for_testing_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryDumpManager);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_H_
diff --git a/base/trace_event/memory_dump_manager_test_utils.h b/base/trace_event/memory_dump_manager_test_utils.h
deleted file mode 100644
index 413017f6c0..0000000000
--- a/base/trace_event/memory_dump_manager_test_utils.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_TEST_UTILS_H_
-#define BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_TEST_UTILS_H_
-
-#include "base/bind.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/memory_dump_request_args.h"
-
-namespace base {
-namespace trace_event {
-
-void RequestGlobalDumpForInProcessTesting(
- base::trace_event::MemoryDumpType dump_type,
- base::trace_event::MemoryDumpLevelOfDetail level_of_detail) {
- MemoryDumpRequestArgs local_args = {0 /* dump_guid */, dump_type,
- level_of_detail};
- MemoryDumpManager::GetInstance()->CreateProcessDump(
- local_args, ProcessMemoryDumpCallback());
-};
-
-// Short circuits the RequestGlobalDumpFunction() to CreateProcessDump(),
-// effectively allowing to use both in unittests with the same behavior.
-// Unittests are in-process only and don't require all the multi-process
-// dump handshaking (which would require bits outside of base).
-void InitializeMemoryDumpManagerForInProcessTesting(bool is_coordinator) {
- MemoryDumpManager* instance = MemoryDumpManager::GetInstance();
- instance->set_dumper_registrations_ignored_for_testing(true);
- instance->Initialize(BindRepeating(&RequestGlobalDumpForInProcessTesting),
- is_coordinator);
-}
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_DUMP_MANAGER_TEST_UTILS_H_
diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
deleted file mode 100644
index 706df2dafe..0000000000
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ /dev/null
@@ -1,840 +0,0 @@
-// Copyright 2015 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/trace_event/memory_dump_manager.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/allocator/buildflags.h"
-#include "base/base_switches.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/debug/thread_heap_usage_tracker.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/test/test_io_thread.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/memory_dump_manager_test_utils.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "base/trace_event/memory_dump_request_args.h"
-#include "base/trace_event/memory_dump_scheduler.h"
-#include "base/trace_event/memory_infra_background_whitelist.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "build/build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::_;
-using testing::AtMost;
-using testing::Between;
-using testing::Invoke;
-using testing::Return;
-
-namespace base {
-namespace trace_event {
-
-// GTest matchers for MemoryDumpRequestArgs arguments.
-MATCHER(IsDetailedDump, "") {
- return arg.level_of_detail == MemoryDumpLevelOfDetail::DETAILED;
-}
-
-MATCHER(IsLightDump, "") {
- return arg.level_of_detail == MemoryDumpLevelOfDetail::LIGHT;
-}
-
-namespace {
-
-const char* kMDPName = "TestDumpProvider";
-const char* kWhitelistedMDPName = "WhitelistedTestDumpProvider";
-const char* const kTestMDPWhitelist[] = {kWhitelistedMDPName, nullptr};
-
-void RegisterDumpProvider(
- MemoryDumpProvider* mdp,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- const MemoryDumpProvider::Options& options,
- const char* name = kMDPName) {
- MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
- mdm->set_dumper_registrations_ignored_for_testing(false);
- mdm->RegisterDumpProvider(mdp, name, std::move(task_runner), options);
- mdm->set_dumper_registrations_ignored_for_testing(true);
-}
-
-void RegisterDumpProvider(
- MemoryDumpProvider* mdp,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- RegisterDumpProvider(mdp, task_runner, MemoryDumpProvider::Options());
-}
-
-void RegisterDumpProviderWithSequencedTaskRunner(
- MemoryDumpProvider* mdp,
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- const MemoryDumpProvider::Options& options) {
- MemoryDumpManager* mdm = MemoryDumpManager::GetInstance();
- mdm->set_dumper_registrations_ignored_for_testing(false);
- mdm->RegisterDumpProviderWithSequencedTaskRunner(mdp, kMDPName, task_runner,
- options);
- mdm->set_dumper_registrations_ignored_for_testing(true);
-}
-
-// Posts |task| to |task_runner| and blocks until it is executed.
-void PostTaskAndWait(const Location& from_here,
- SequencedTaskRunner* task_runner,
- base::OnceClosure task) {
- base::WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner->PostTask(from_here, std::move(task));
- task_runner->PostTask(FROM_HERE, base::BindOnce(&WaitableEvent::Signal,
- base::Unretained(&event)));
- // The SequencedTaskRunner guarantees that |event| will only be signaled after
- // |task| is executed.
- event.Wait();
-}
-
-class MockMemoryDumpProvider : public MemoryDumpProvider {
- public:
- MOCK_METHOD0(Destructor, void());
- MOCK_METHOD2(OnMemoryDump,
- bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd));
-
- MockMemoryDumpProvider() : enable_mock_destructor(false) {
- ON_CALL(*this, OnMemoryDump(_, _))
- .WillByDefault(
- Invoke([](const MemoryDumpArgs&, ProcessMemoryDump* pmd) -> bool {
- return true;
- }));
- }
- ~MockMemoryDumpProvider() override {
- if (enable_mock_destructor)
- Destructor();
- }
-
- bool enable_mock_destructor;
-};
-
-class TestSequencedTaskRunner : public SequencedTaskRunner {
- public:
- TestSequencedTaskRunner() = default;
-
- void set_enabled(bool value) { enabled_ = value; }
- unsigned no_of_post_tasks() const { return num_of_post_tasks_; }
-
- bool PostNonNestableDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override {
- NOTREACHED();
- return false;
- }
-
- bool PostDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override {
- num_of_post_tasks_++;
- if (enabled_) {
- return task_runner_->PostDelayedTask(from_here, std::move(task), delay);
- }
- return false;
- }
-
- bool RunsTasksInCurrentSequence() const override {
- return task_runner_->RunsTasksInCurrentSequence();
- }
-
- private:
- ~TestSequencedTaskRunner() override = default;
-
- const scoped_refptr<SequencedTaskRunner> task_runner_ =
- CreateSequencedTaskRunnerWithTraits({});
- bool enabled_ = true;
- unsigned num_of_post_tasks_ = 0;
-};
-
-class TestingThreadHeapUsageTracker : public debug::ThreadHeapUsageTracker {
- public:
- using ThreadHeapUsageTracker::DisableHeapTrackingForTesting;
-};
-
-} // namespace
-
-class MemoryDumpManagerTest : public testing::Test {
- public:
- MemoryDumpManagerTest(bool is_coordinator = false)
- : is_coordinator_(is_coordinator) {}
-
- void SetUp() override {
- // Bring up and initialize MemoryDumpManager while single-threaded (before
- // instantiating ScopedTaskEnvironment) to avoid data races if worker
- // threads use tracing globals early.
- mdm_ = MemoryDumpManager::CreateInstanceForTesting();
- ASSERT_EQ(mdm_.get(), MemoryDumpManager::GetInstance());
-
- InitializeMemoryDumpManagerForInProcessTesting(is_coordinator_);
-
- scoped_task_environment_ = std::make_unique<test::ScopedTaskEnvironment>();
- }
-
- void TearDown() override {
- scoped_task_environment_.reset();
-
- // Tear down the MemoryDumpManager while single-threaded to mirror logic in
- // SetUp().
- mdm_.reset();
- TraceLog::ResetForTesting();
- }
-
- protected:
- // Blocks the current thread (spinning a nested message loop) until the
- // memory dump is complete. Returns:
- // - return value: the |success| from the CreateProcessDump() callback.
- bool RequestProcessDumpAndWait(MemoryDumpType dump_type,
- MemoryDumpLevelOfDetail level_of_detail) {
- RunLoop run_loop;
- bool success = false;
- static uint64_t test_guid = 1;
- test_guid++;
- MemoryDumpRequestArgs request_args{test_guid, dump_type, level_of_detail};
-
- // The signature of the callback delivered by MemoryDumpManager is:
- // void ProcessMemoryDumpCallback(
- // uint64_t dump_guid,
- // bool success,
- // std::unique_ptr<ProcessMemoryDump> pmd)
- // The extra arguments prepended to the |callback| below (the ones with the
- // "curried_" prefix) are just passed from the Bind(). This is just to get
- // around the limitation of Bind() in supporting only capture-less lambdas.
- ProcessMemoryDumpCallback callback = Bind(
- [](bool* curried_success, Closure curried_quit_closure,
- uint64_t curried_expected_guid, bool success, uint64_t dump_guid,
- std::unique_ptr<ProcessMemoryDump> pmd) {
- *curried_success = success;
- EXPECT_EQ(curried_expected_guid, dump_guid);
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- curried_quit_closure);
- },
- Unretained(&success), run_loop.QuitClosure(), test_guid);
-
- mdm_->CreateProcessDump(request_args, callback);
- run_loop.Run();
- return success;
- }
-
- void EnableForTracing() {
- mdm_->SetupForTracing(TraceConfig::MemoryDumpConfig());
- }
-
- void EnableForTracingWithTraceConfig(const std::string trace_config_string) {
- TraceConfig trace_config(trace_config_string);
- mdm_->SetupForTracing(trace_config.memory_dump_config());
- }
-
- void DisableTracing() { mdm_->TeardownForTracing(); }
-
- int GetMaxConsecutiveFailuresCount() const {
- return MemoryDumpManager::kMaxConsecutiveFailuresCount;
- }
-
- const MemoryDumpProvider::Options kDefaultOptions;
- std::unique_ptr<MemoryDumpManager> mdm_;
-
- private:
- // To tear down the singleton instance after each test.
- ShadowingAtExitManager at_exit_manager_;
-
- std::unique_ptr<test::ScopedTaskEnvironment> scoped_task_environment_;
-
- // Whether the test MemoryDumpManager should be initialized as the
- // coordinator.
- const bool is_coordinator_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerTest);
-};
-
-class MemoryDumpManagerTestAsCoordinator : public MemoryDumpManagerTest {
- public:
- MemoryDumpManagerTestAsCoordinator() : MemoryDumpManagerTest(true) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MemoryDumpManagerTestAsCoordinator);
-};
-
-// Basic sanity checks. Registers a memory dump provider and checks that it is
-// called.
-TEST_F(MemoryDumpManagerTest, SingleDumper) {
- MockMemoryDumpProvider mdp;
- RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
-
- // Now repeat enabling the memory category and check that the dumper is
- // invoked this time.
- EnableForTracing();
- EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(3);
- for (int i = 0; i < 3; ++i) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- }
- DisableTracing();
-
- mdm_->UnregisterDumpProvider(&mdp);
-
- // Finally check the unregister logic: the global dump handler will be invoked
- // but not the dump provider, as it has been unregistered.
- EnableForTracing();
- EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
- for (int i = 0; i < 3; ++i) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- }
- DisableTracing();
-}
-
-// Checks that requesting dumps with high level of detail actually propagates
-// the level of the detail properly to OnMemoryDump() call on dump providers.
-TEST_F(MemoryDumpManagerTest, CheckMemoryDumpArgs) {
- MockMemoryDumpProvider mdp;
-
- RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
- EnableForTracing();
- EXPECT_CALL(mdp, OnMemoryDump(IsDetailedDump(), _));
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
- mdm_->UnregisterDumpProvider(&mdp);
-
- // Check that requesting dumps with low level of detail actually propagates to
- // OnMemoryDump() call on dump providers.
- RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
- EnableForTracing();
- EXPECT_CALL(mdp, OnMemoryDump(IsLightDump(), _));
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::LIGHT));
- DisableTracing();
- mdm_->UnregisterDumpProvider(&mdp);
-}
-
-// Checks that the (Un)RegisterDumpProvider logic behaves sanely.
-TEST_F(MemoryDumpManagerTest, MultipleDumpers) {
- MockMemoryDumpProvider mdp1;
- MockMemoryDumpProvider mdp2;
-
- // Enable only mdp1.
- RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get());
- EnableForTracing();
- EXPECT_CALL(mdp1, OnMemoryDump(_, _));
- EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(0);
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
-
- // Invert: enable mdp2 and disable mdp1.
- mdm_->UnregisterDumpProvider(&mdp1);
- RegisterDumpProvider(&mdp2, nullptr);
- EnableForTracing();
- EXPECT_CALL(mdp1, OnMemoryDump(_, _)).Times(0);
- EXPECT_CALL(mdp2, OnMemoryDump(_, _));
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
-
- // Enable both mdp1 and mdp2.
- RegisterDumpProvider(&mdp1, nullptr);
- EnableForTracing();
- EXPECT_CALL(mdp1, OnMemoryDump(_, _));
- EXPECT_CALL(mdp2, OnMemoryDump(_, _));
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
-}
-
-// Checks that the dump provider invocations depend only on the current
-// registration state and not on previous registrations and dumps.
-// Flaky on iOS, see crbug.com/706874
-#if defined(OS_IOS)
-#define MAYBE_RegistrationConsistency DISABLED_RegistrationConsistency
-#else
-#define MAYBE_RegistrationConsistency RegistrationConsistency
-#endif
-TEST_F(MemoryDumpManagerTest, MAYBE_RegistrationConsistency) {
- MockMemoryDumpProvider mdp;
-
- RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
-
- {
- EXPECT_CALL(mdp, OnMemoryDump(_, _));
- EnableForTracing();
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
- }
-
- mdm_->UnregisterDumpProvider(&mdp);
-
- {
- EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
- EnableForTracing();
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
- }
-
- RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
- mdm_->UnregisterDumpProvider(&mdp);
-
- {
- EXPECT_CALL(mdp, OnMemoryDump(_, _)).Times(0);
- EnableForTracing();
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
- }
-
- RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
- mdm_->UnregisterDumpProvider(&mdp);
- RegisterDumpProvider(&mdp, ThreadTaskRunnerHandle::Get());
-
- {
- EXPECT_CALL(mdp, OnMemoryDump(_, _));
- EnableForTracing();
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- DisableTracing();
- }
-}
-
-// Checks that the MemoryDumpManager respects the thread affinity when a
-// MemoryDumpProvider specifies a task_runner(). The test starts creating 8
-// threads and registering a MemoryDumpProvider on each of them. At each
-// iteration, one thread is removed, to check the live unregistration logic.
-TEST_F(MemoryDumpManagerTest, RespectTaskRunnerAffinity) {
- const uint32_t kNumInitialThreads = 8;
-
- std::vector<std::unique_ptr<Thread>> threads;
- std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
-
- // Create the threads and setup the expectations. Given that at each iteration
- // we will pop out one thread/MemoryDumpProvider, each MDP is supposed to be
- // invoked a number of times equal to its index.
- for (uint32_t i = kNumInitialThreads; i > 0; --i) {
- threads.push_back(WrapUnique(new Thread("test thread")));
- auto* thread = threads.back().get();
- thread->Start();
- scoped_refptr<SingleThreadTaskRunner> task_runner = thread->task_runner();
- mdps.push_back(WrapUnique(new MockMemoryDumpProvider()));
- auto* mdp = mdps.back().get();
- RegisterDumpProvider(mdp, task_runner, kDefaultOptions);
- EXPECT_CALL(*mdp, OnMemoryDump(_, _))
- .Times(i)
- .WillRepeatedly(Invoke(
- [task_runner](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
- EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
- return true;
- }));
- }
- EnableForTracing();
-
- while (!threads.empty()) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
-
- // Unregister a MDP and destroy one thread at each iteration to check the
- // live unregistration logic. The unregistration needs to happen on the same
- // thread the MDP belongs to.
- {
- RunLoop run_loop;
- Closure unregistration =
- Bind(&MemoryDumpManager::UnregisterDumpProvider,
- Unretained(mdm_.get()), Unretained(mdps.back().get()));
- threads.back()->task_runner()->PostTaskAndReply(FROM_HERE, unregistration,
- run_loop.QuitClosure());
- run_loop.Run();
- }
- mdps.pop_back();
- threads.back()->Stop();
- threads.pop_back();
- }
-
- DisableTracing();
-}
-
-// Check that the memory dump calls are always posted on task runner for
-// SequencedTaskRunner case and that the dump provider gets disabled when
-// PostTask fails, but the dump still succeeds.
-TEST_F(MemoryDumpManagerTest, PostTaskForSequencedTaskRunner) {
- std::vector<MockMemoryDumpProvider> mdps(3);
- scoped_refptr<TestSequencedTaskRunner> task_runner1(
- MakeRefCounted<TestSequencedTaskRunner>());
- scoped_refptr<TestSequencedTaskRunner> task_runner2(
- MakeRefCounted<TestSequencedTaskRunner>());
- RegisterDumpProviderWithSequencedTaskRunner(&mdps[0], task_runner1,
- kDefaultOptions);
- RegisterDumpProviderWithSequencedTaskRunner(&mdps[1], task_runner2,
- kDefaultOptions);
- RegisterDumpProviderWithSequencedTaskRunner(&mdps[2], task_runner2,
- kDefaultOptions);
- // |mdps[0]| should be disabled permanently after first dump.
- EXPECT_CALL(mdps[0], OnMemoryDump(_, _)).Times(0);
- EXPECT_CALL(mdps[1], OnMemoryDump(_, _)).Times(2);
- EXPECT_CALL(mdps[2], OnMemoryDump(_, _)).Times(2);
-
- EnableForTracing();
-
- task_runner1->set_enabled(false);
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- EXPECT_EQ(1u, task_runner1->no_of_post_tasks());
- EXPECT_EQ(1u, task_runner2->no_of_post_tasks());
-
- task_runner1->set_enabled(true);
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- EXPECT_EQ(2u, task_runner1->no_of_post_tasks());
- EXPECT_EQ(2u, task_runner2->no_of_post_tasks());
- DisableTracing();
-}
-
-// Checks that providers get disabled after 3 consecutive failures, but not
-// otherwise (e.g., if interleaved).
-TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) {
- MockMemoryDumpProvider mdp1;
- MockMemoryDumpProvider mdp2;
-
- RegisterDumpProvider(&mdp1, nullptr);
- RegisterDumpProvider(&mdp2, nullptr);
- EnableForTracing();
-
- EXPECT_CALL(mdp1, OnMemoryDump(_, _))
- .Times(GetMaxConsecutiveFailuresCount())
- .WillRepeatedly(Return(false));
-
- EXPECT_CALL(mdp2, OnMemoryDump(_, _))
- .WillOnce(Return(false))
- .WillOnce(Return(true))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(true))
- .WillOnce(Return(false));
-
- const int kNumDumps = 2 * GetMaxConsecutiveFailuresCount();
- for (int i = 0; i < kNumDumps; i++) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- }
-
- DisableTracing();
-}
-
-// Sneakily registers an extra memory dump provider while an existing one is
-// dumping and expect it to take part in the already active tracing session.
-TEST_F(MemoryDumpManagerTest, RegisterDumperWhileDumping) {
- MockMemoryDumpProvider mdp1;
- MockMemoryDumpProvider mdp2;
-
- RegisterDumpProvider(&mdp1, nullptr);
- EnableForTracing();
-
- EXPECT_CALL(mdp1, OnMemoryDump(_, _))
- .Times(4)
- .WillOnce(Return(true))
- .WillOnce(
- Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
- RegisterDumpProvider(&mdp2, nullptr);
- return true;
- }))
- .WillRepeatedly(Return(true));
-
- // Depending on the insertion order (before or after mdp1), mdp2 might be
- // called also immediately after it gets registered.
- EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(Between(2, 3));
-
- for (int i = 0; i < 4; i++) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- }
-
- DisableTracing();
-}
-
-// Like RegisterDumperWhileDumping, but unregister the dump provider instead.
-TEST_F(MemoryDumpManagerTest, UnregisterDumperWhileDumping) {
- MockMemoryDumpProvider mdp1;
- MockMemoryDumpProvider mdp2;
-
- RegisterDumpProvider(&mdp1, ThreadTaskRunnerHandle::Get(), kDefaultOptions);
- RegisterDumpProvider(&mdp2, ThreadTaskRunnerHandle::Get(), kDefaultOptions);
- EnableForTracing();
-
- EXPECT_CALL(mdp1, OnMemoryDump(_, _))
- .Times(4)
- .WillOnce(Return(true))
- .WillOnce(
- Invoke([&mdp2](const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
- MemoryDumpManager::GetInstance()->UnregisterDumpProvider(&mdp2);
- return true;
- }))
- .WillRepeatedly(Return(true));
-
- // Depending on the insertion order (before or after mdp1), mdp2 might have
- // been already called when UnregisterDumpProvider happens.
- EXPECT_CALL(mdp2, OnMemoryDump(_, _)).Times(Between(1, 2));
-
- for (int i = 0; i < 4; i++) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- }
-
- DisableTracing();
-}
-
-// Checks that the dump does not abort when unregistering a provider while
-// dumping from a different thread than the dumping thread.
-TEST_F(MemoryDumpManagerTest, UnregisterDumperFromThreadWhileDumping) {
- std::vector<std::unique_ptr<TestIOThread>> threads;
- std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
-
- for (int i = 0; i < 2; i++) {
- threads.push_back(
- WrapUnique(new TestIOThread(TestIOThread::kAutoStart)));
- mdps.push_back(WrapUnique(new MockMemoryDumpProvider()));
- RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(),
- kDefaultOptions);
- }
-
- int on_memory_dump_call_count = 0;
-
- // When OnMemoryDump is called on either of the dump providers, it will
- // unregister the other one.
- for (const std::unique_ptr<MockMemoryDumpProvider>& mdp : mdps) {
- int other_idx = (mdps.front() == mdp);
- // TestIOThread's task runner must be obtained from the main thread but can
- // then be used from other threads.
- scoped_refptr<SingleThreadTaskRunner> other_runner =
- threads[other_idx]->task_runner();
- MockMemoryDumpProvider* other_mdp = mdps[other_idx].get();
- auto on_dump = [this, other_runner, other_mdp, &on_memory_dump_call_count](
- const MemoryDumpArgs& args, ProcessMemoryDump* pmd) {
- PostTaskAndWait(FROM_HERE, other_runner.get(),
- base::BindOnce(&MemoryDumpManager::UnregisterDumpProvider,
- base::Unretained(&*mdm_), other_mdp));
- on_memory_dump_call_count++;
- return true;
- };
-
- // OnMemoryDump is called once for the provider that dumps first, and zero
- // times for the other provider.
- EXPECT_CALL(*mdp, OnMemoryDump(_, _))
- .Times(AtMost(1))
- .WillOnce(Invoke(on_dump));
- }
-
- EnableForTracing();
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- ASSERT_EQ(1, on_memory_dump_call_count);
-
- DisableTracing();
-}
-
-// If a thread (with a dump provider living on it) is torn down during a dump
-// its dump provider should be skipped but the dump itself should succeed.
-TEST_F(MemoryDumpManagerTest, TearDownThreadWhileDumping) {
- std::vector<std::unique_ptr<TestIOThread>> threads;
- std::vector<std::unique_ptr<MockMemoryDumpProvider>> mdps;
-
- for (int i = 0; i < 2; i++) {
- threads.push_back(
- WrapUnique(new TestIOThread(TestIOThread::kAutoStart)));
- mdps.push_back(WrapUnique(new MockMemoryDumpProvider()));
- RegisterDumpProvider(mdps.back().get(), threads.back()->task_runner(),
- kDefaultOptions);
- }
-
- int on_memory_dump_call_count = 0;
-
- // When OnMemoryDump is called on either of the dump providers, it will
- // tear down the thread of the other one.
- for (const std::unique_ptr<MockMemoryDumpProvider>& mdp : mdps) {
- int other_idx = (mdps.front() == mdp);
- TestIOThread* other_thread = threads[other_idx].get();
- // TestIOThread isn't thread-safe and must be stopped on the |main_runner|.
- scoped_refptr<SequencedTaskRunner> main_runner =
- SequencedTaskRunnerHandle::Get();
- auto on_dump = [other_thread, main_runner, &on_memory_dump_call_count](
- const MemoryDumpArgs& args, ProcessMemoryDump* pmd) {
- PostTaskAndWait(
- FROM_HERE, main_runner.get(),
- base::BindOnce(&TestIOThread::Stop, base::Unretained(other_thread)));
- on_memory_dump_call_count++;
- return true;
- };
-
- // OnMemoryDump is called once for the provider that dumps first, and zero
- // times for the other provider.
- EXPECT_CALL(*mdp, OnMemoryDump(_, _))
- .Times(AtMost(1))
- .WillOnce(Invoke(on_dump));
- }
-
- EnableForTracing();
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- ASSERT_EQ(1, on_memory_dump_call_count);
-
- DisableTracing();
-}
-
-// Checks that the callback is invoked if CreateProcessDump() is called when
-// tracing is not enabled.
-TEST_F(MemoryDumpManagerTest, TriggerDumpWithoutTracing) {
- MockMemoryDumpProvider mdp;
- RegisterDumpProvider(&mdp, nullptr);
- EXPECT_CALL(mdp, OnMemoryDump(_, _));
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
-}
-
-TEST_F(MemoryDumpManagerTest, BackgroundWhitelisting) {
- SetDumpProviderWhitelistForTesting(kTestMDPWhitelist);
-
- // Standard provider with default options (create dump for current process).
- MockMemoryDumpProvider backgroundMdp;
- RegisterDumpProvider(&backgroundMdp, nullptr, kDefaultOptions,
- kWhitelistedMDPName);
-
- EnableForTracing();
-
- EXPECT_CALL(backgroundMdp, OnMemoryDump(_, _)).Times(1);
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::SUMMARY_ONLY,
- MemoryDumpLevelOfDetail::BACKGROUND));
- DisableTracing();
-}
-
-// Tests the basics of the UnregisterAndDeleteDumpProviderSoon(): the
-// unregistration should actually delete the providers and not leak them.
-TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoon) {
- static const int kNumProviders = 3;
- int dtor_count = 0;
- std::vector<std::unique_ptr<MemoryDumpProvider>> mdps;
- for (int i = 0; i < kNumProviders; ++i) {
- std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider);
- mdp->enable_mock_destructor = true;
- EXPECT_CALL(*mdp, Destructor())
- .WillOnce(Invoke([&dtor_count]() { dtor_count++; }));
- RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions);
- mdps.push_back(std::move(mdp));
- }
-
- while (!mdps.empty()) {
- mdm_->UnregisterAndDeleteDumpProviderSoon(std::move(mdps.back()));
- mdps.pop_back();
- }
-
- ASSERT_EQ(kNumProviders, dtor_count);
-}
-
-// This test checks against races when unregistering an unbound dump provider
-// from another thread while dumping. It registers one MDP and, when
-// OnMemoryDump() is called, it invokes UnregisterAndDeleteDumpProviderSoon()
-// from another thread. The OnMemoryDump() and the dtor call are expected to
-// happen on the same thread (the MemoryDumpManager utility thread).
-TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoonDuringDump) {
- std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider);
- mdp->enable_mock_destructor = true;
- RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions);
-
- base::PlatformThreadRef thread_ref;
- auto self_unregister_from_another_thread = [&mdp, &thread_ref](
- const MemoryDumpArgs&, ProcessMemoryDump*) -> bool {
- thread_ref = PlatformThread::CurrentRef();
- TestIOThread thread_for_unregistration(TestIOThread::kAutoStart);
- PostTaskAndWait(
- FROM_HERE, thread_for_unregistration.task_runner().get(),
- base::BindOnce(&MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon,
- base::Unretained(MemoryDumpManager::GetInstance()),
- std::move(mdp)));
- thread_for_unregistration.Stop();
- return true;
- };
- EXPECT_CALL(*mdp, OnMemoryDump(_, _))
- .Times(1)
- .WillOnce(Invoke(self_unregister_from_another_thread));
- EXPECT_CALL(*mdp, Destructor())
- .Times(1)
- .WillOnce(Invoke([&thread_ref]() {
- EXPECT_EQ(thread_ref, PlatformThread::CurrentRef());
- }));
-
- EnableForTracing();
- for (int i = 0; i < 2; ++i) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- }
- DisableTracing();
-}
-
-// Mock MDP class that tests if the number of OnMemoryDump() calls are expected.
-// It is implemented without gmocks since EXPECT_CALL implementation is slow
-// when there are 1000s of instances, as required in
-// NoStackOverflowWithTooManyMDPs test.
-class SimpleMockMemoryDumpProvider : public MemoryDumpProvider {
- public:
- SimpleMockMemoryDumpProvider(int expected_num_dump_calls)
- : expected_num_dump_calls_(expected_num_dump_calls), num_dump_calls_(0) {}
-
- ~SimpleMockMemoryDumpProvider() override {
- EXPECT_EQ(expected_num_dump_calls_, num_dump_calls_);
- }
-
- bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) override {
- ++num_dump_calls_;
- return true;
- }
-
- private:
- int expected_num_dump_calls_;
- int num_dump_calls_;
-};
-
-TEST_F(MemoryDumpManagerTest, NoStackOverflowWithTooManyMDPs) {
- SetDumpProviderWhitelistForTesting(kTestMDPWhitelist);
-
- int kMDPCount = 1000;
- std::vector<std::unique_ptr<SimpleMockMemoryDumpProvider>> mdps;
- for (int i = 0; i < kMDPCount; ++i) {
- mdps.push_back(std::make_unique<SimpleMockMemoryDumpProvider>(1));
- RegisterDumpProvider(mdps.back().get(), nullptr);
- }
- for (int i = 0; i < kMDPCount; ++i) {
- mdps.push_back(std::make_unique<SimpleMockMemoryDumpProvider>(3));
- RegisterDumpProvider(mdps.back().get(), nullptr, kDefaultOptions,
- kWhitelistedMDPName);
- }
- std::unique_ptr<Thread> stopped_thread(new Thread("test thread"));
- stopped_thread->Start();
- for (int i = 0; i < kMDPCount; ++i) {
- mdps.push_back(std::make_unique<SimpleMockMemoryDumpProvider>(0));
- RegisterDumpProvider(mdps.back().get(), stopped_thread->task_runner(),
- kDefaultOptions, kWhitelistedMDPName);
- }
- stopped_thread->Stop();
-
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::BACKGROUND));
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::SUMMARY_ONLY,
- MemoryDumpLevelOfDetail::BACKGROUND));
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h
deleted file mode 100644
index f55e2cf471..0000000000
--- a/base/trace_event/memory_dump_provider.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
-#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/process/process_handle.h"
-#include "base/trace_event/memory_dump_request_args.h"
-
-namespace base {
-namespace trace_event {
-
-class ProcessMemoryDump;
-
-// The contract interface that memory dump providers must implement.
-class BASE_EXPORT MemoryDumpProvider {
- public:
- // Optional arguments for MemoryDumpManager::RegisterDumpProvider().
- struct Options {
- Options() : dumps_on_single_thread_task_runner(false) {}
-
- // |dumps_on_single_thread_task_runner| is true if the dump provider runs on
- // a SingleThreadTaskRunner, which is usually the case. It is faster to run
- // all providers that run on the same thread together without thread hops.
- bool dumps_on_single_thread_task_runner;
- };
-
- virtual ~MemoryDumpProvider() = default;
-
- // Called by the MemoryDumpManager when generating memory dumps.
- // The |args| specify if the embedder should generate light/heavy dumps on
- // dump requests. The embedder should return true if the |pmd| was
- // successfully populated, false if something went wrong and the dump should
- // be considered invalid.
- // (Note, the MemoryDumpManager has a fail-safe logic which will disable the
- // MemoryDumpProvider for the entire trace session if it fails consistently).
- virtual bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) = 0;
-
- protected:
- MemoryDumpProvider() = default;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_
diff --git a/base/trace_event/memory_dump_provider_info.cc b/base/trace_event/memory_dump_provider_info.cc
deleted file mode 100644
index 3220476cf9..0000000000
--- a/base/trace_event/memory_dump_provider_info.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 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/trace_event/memory_dump_provider_info.h"
-
-#include <tuple>
-
-#include "base/sequenced_task_runner.h"
-
-namespace base {
-namespace trace_event {
-
-MemoryDumpProviderInfo::MemoryDumpProviderInfo(
- MemoryDumpProvider* dump_provider,
- const char* name,
- scoped_refptr<SequencedTaskRunner> task_runner,
- const MemoryDumpProvider::Options& options,
- bool whitelisted_for_background_mode)
- : dump_provider(dump_provider),
- options(options),
- name(name),
- task_runner(std::move(task_runner)),
- whitelisted_for_background_mode(whitelisted_for_background_mode),
- consecutive_failures(0),
- disabled(false) {}
-
-MemoryDumpProviderInfo::~MemoryDumpProviderInfo() = default;
-
-bool MemoryDumpProviderInfo::Comparator::operator()(
- const scoped_refptr<MemoryDumpProviderInfo>& a,
- const scoped_refptr<MemoryDumpProviderInfo>& b) const {
- if (!a || !b)
- return a.get() < b.get();
- // Ensure that unbound providers (task_runner == nullptr) always run last.
- // Rationale: some unbound dump providers are known to be slow, keep them last
- // to avoid skewing timings of the other dump providers.
- return std::tie(a->task_runner, a->dump_provider) >
- std::tie(b->task_runner, b->dump_provider);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_dump_provider_info.h b/base/trace_event/memory_dump_provider_info.h
deleted file mode 100644
index f0ea1e6bbc..0000000000
--- a/base/trace_event/memory_dump_provider_info.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_INFO_H_
-#define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_INFO_H_
-
-#include <memory>
-#include <set>
-
-#include "base/base_export.h"
-#include "base/memory/ref_counted.h"
-#include "base/trace_event/memory_dump_provider.h"
-
-namespace base {
-
-class SequencedTaskRunner;
-
-namespace trace_event {
-
-// Wraps a MemoryDumpProvider (MDP), which is registered via
-// MemoryDumpManager(MDM)::RegisterDumpProvider(), holding the extra information
-// required to deal with it (which task runner it should be invoked onto,
-// whether it has been disabled, etc.)
-// More importantly, having a refptr to this object guarantees that a MDP that
-// is not thread-bound (hence which can only be unregistered via
-// MDM::UnregisterAndDeleteDumpProviderSoon()) will stay alive as long as the
-// refptr is held.
-//
-// Lifetime:
-// At any time, there is at most one instance of this class for each instance
-// of a given MemoryDumpProvider, but there might be several scoped_refptr
-// holding onto each of this. Specifically:
-// - In nominal conditions, there is a refptr for each registered MDP in the
-// MDM's |dump_providers_| list.
-// - In most cases, the only refptr (in the |dump_providers_| list) is destroyed
-// by MDM::UnregisterDumpProvider().
-// - However, when MDM starts a dump, the list of refptrs is copied into the
-// ProcessMemoryDumpAsyncState. That list is pruned as MDP(s) are invoked.
-// - If UnregisterDumpProvider() is called on a non-thread-bound MDP while a
-// dump is in progress, the extar extra of the handle is destroyed in
-// MDM::SetupNextMemoryDump() or MDM::InvokeOnMemoryDump(), when the copy
-// inside ProcessMemoryDumpAsyncState is erase()-d.
-// - The PeakDetector can keep extra refptrs when enabled.
-struct BASE_EXPORT MemoryDumpProviderInfo
- : public RefCountedThreadSafe<MemoryDumpProviderInfo> {
- public:
- // Define a total order based on the |task_runner| affinity, so that MDPs
- // belonging to the same SequencedTaskRunner are adjacent in the set.
- struct Comparator {
- bool operator()(const scoped_refptr<MemoryDumpProviderInfo>& a,
- const scoped_refptr<MemoryDumpProviderInfo>& b) const;
- };
- using OrderedSet =
- std::set<scoped_refptr<MemoryDumpProviderInfo>, Comparator>;
-
- MemoryDumpProviderInfo(MemoryDumpProvider* dump_provider,
- const char* name,
- scoped_refptr<SequencedTaskRunner> task_runner,
- const MemoryDumpProvider::Options& options,
- bool whitelisted_for_background_mode);
-
- // It is safe to access the const fields below from any thread as they are
- // never mutated.
-
- MemoryDumpProvider* const dump_provider;
-
- // The |options| arg passed to MDM::RegisterDumpProvider().
- const MemoryDumpProvider::Options options;
-
- // Human readable name, not unique (distinct MDP instances might have the same
- // name). Used for debugging, testing and whitelisting for BACKGROUND mode.
- const char* const name;
-
- // The task runner on which the MDP::OnMemoryDump call should be posted onto.
- // Can be nullptr, in which case the MDP will be invoked on a background
- // thread handled by MDM.
- const scoped_refptr<SequencedTaskRunner> task_runner;
-
- // True if the dump provider is whitelisted for background mode.
- const bool whitelisted_for_background_mode;
-
- // These fields below, instead, are not thread safe and can be mutated only:
- // - On the |task_runner|, when not null (i.e. for thread-bound MDPS).
- // - By the MDM's background thread (or in any other way that guarantees
- // sequencing) for non-thread-bound MDPs.
-
- // Used to transfer ownership for UnregisterAndDeleteDumpProviderSoon().
- // nullptr in all other cases.
- std::unique_ptr<MemoryDumpProvider> owned_dump_provider;
-
- // For fail-safe logic (auto-disable failing MDPs).
- int consecutive_failures;
-
- // Flagged either by the auto-disable logic or during unregistration.
- bool disabled;
-
- private:
- friend class base::RefCountedThreadSafe<MemoryDumpProviderInfo>;
- ~MemoryDumpProviderInfo();
-
- DISALLOW_COPY_AND_ASSIGN(MemoryDumpProviderInfo);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_INFO_H_
diff --git a/base/trace_event/memory_dump_request_args.cc b/base/trace_event/memory_dump_request_args.cc
deleted file mode 100644
index 8be3c32404..0000000000
--- a/base/trace_event/memory_dump_request_args.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2015 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/trace_event/memory_dump_request_args.h"
-
-#include "base/logging.h"
-
-namespace base {
-namespace trace_event {
-
-// static
-const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) {
- switch (dump_type) {
- case MemoryDumpType::PERIODIC_INTERVAL:
- return "periodic_interval";
- case MemoryDumpType::EXPLICITLY_TRIGGERED:
- return "explicitly_triggered";
- case MemoryDumpType::SUMMARY_ONLY:
- return "summary_only";
- }
- NOTREACHED();
- return "unknown";
-}
-
-MemoryDumpType StringToMemoryDumpType(const std::string& str) {
- if (str == "periodic_interval")
- return MemoryDumpType::PERIODIC_INTERVAL;
- if (str == "explicitly_triggered")
- return MemoryDumpType::EXPLICITLY_TRIGGERED;
- if (str == "summary_only")
- return MemoryDumpType::SUMMARY_ONLY;
- NOTREACHED();
- return MemoryDumpType::LAST;
-}
-
-const char* MemoryDumpLevelOfDetailToString(
- const MemoryDumpLevelOfDetail& level_of_detail) {
- switch (level_of_detail) {
- case MemoryDumpLevelOfDetail::BACKGROUND:
- return "background";
- case MemoryDumpLevelOfDetail::LIGHT:
- return "light";
- case MemoryDumpLevelOfDetail::DETAILED:
- return "detailed";
- }
- NOTREACHED();
- return "unknown";
-}
-
-MemoryDumpLevelOfDetail StringToMemoryDumpLevelOfDetail(
- const std::string& str) {
- if (str == "background")
- return MemoryDumpLevelOfDetail::BACKGROUND;
- if (str == "light")
- return MemoryDumpLevelOfDetail::LIGHT;
- if (str == "detailed")
- return MemoryDumpLevelOfDetail::DETAILED;
- NOTREACHED();
- return MemoryDumpLevelOfDetail::LAST;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_dump_request_args.h b/base/trace_event/memory_dump_request_args.h
deleted file mode 100644
index f854a4b373..0000000000
--- a/base/trace_event/memory_dump_request_args.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_ARGS_H_
-#define BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_ARGS_H_
-
-// This file defines the types and structs used to issue memory dump requests.
-// These are also used in the IPCs for coordinating inter-process memory dumps.
-
-#include <stdint.h>
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/optional.h"
-#include "base/process/process_handle.h"
-
-namespace base {
-namespace trace_event {
-
-class ProcessMemoryDump;
-
-// Captures the reason why a memory dump is being requested. This is to allow
-// selective enabling of dumps, filtering and post-processing. Keep this
-// consistent with memory_instrumentation.mojo and
-// memory_instrumentation_struct_traits.{h,cc}
-enum class MemoryDumpType {
- PERIODIC_INTERVAL, // Dumping memory at periodic intervals.
- EXPLICITLY_TRIGGERED, // Non maskable dump request.
- SUMMARY_ONLY, // Calculate just the summary & don't add to the trace.
- LAST = SUMMARY_ONLY
-};
-
-// Tells the MemoryDumpProvider(s) how much detailed their dumps should be.
-// Keep this consistent with memory_instrumentation.mojo and
-// memory_instrumentation_struct_traits.{h,cc}
-enum class MemoryDumpLevelOfDetail : uint32_t {
- FIRST,
-
- // For background tracing mode. The dump time is quick, and typically just the
- // totals are expected. Suballocations need not be specified. Dump name must
- // contain only pre-defined strings and string arguments cannot be added.
- BACKGROUND = FIRST,
-
- // For the levels below, MemoryDumpProvider instances must guarantee that the
- // total size reported in the root node is consistent. Only the granularity of
- // the child MemoryAllocatorDump(s) differs with the levels.
-
- // Few entries, typically a fixed number, per dump.
- LIGHT,
-
- // Unrestricted amount of entries per dump.
- DETAILED,
-
- LAST = DETAILED
-};
-
-// Keep this consistent with memory_instrumentation.mojo and
-// memory_instrumentation_struct_traits.{h,cc}
-struct BASE_EXPORT MemoryDumpRequestArgs {
- // Globally unique identifier. In multi-process dumps, all processes issue a
- // local dump with the same guid. This allows the trace importers to
- // reconstruct the global dump.
- uint64_t dump_guid;
-
- MemoryDumpType dump_type;
- MemoryDumpLevelOfDetail level_of_detail;
-};
-
-// Args for ProcessMemoryDump and passed to OnMemoryDump calls for memory dump
-// providers. Dump providers are expected to read the args for creating dumps.
-struct MemoryDumpArgs {
- // Specifies how detailed the dumps should be.
- MemoryDumpLevelOfDetail level_of_detail;
-
- // Globally unique identifier. In multi-process dumps, all processes issue a
- // local dump with the same guid. This allows the trace importers to
- // reconstruct the global dump.
- uint64_t dump_guid;
-};
-
-using ProcessMemoryDumpCallback = Callback<
- void(bool success, uint64_t dump_guid, std::unique_ptr<ProcessMemoryDump>)>;
-
-BASE_EXPORT const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type);
-
-BASE_EXPORT MemoryDumpType StringToMemoryDumpType(const std::string& str);
-
-BASE_EXPORT const char* MemoryDumpLevelOfDetailToString(
- const MemoryDumpLevelOfDetail& level_of_detail);
-
-BASE_EXPORT MemoryDumpLevelOfDetail
-StringToMemoryDumpLevelOfDetail(const std::string& str);
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_DUMP_REQUEST_ARGS_H_
diff --git a/base/trace_event/memory_dump_scheduler.cc b/base/trace_event/memory_dump_scheduler.cc
deleted file mode 100644
index 8b03f5c90b..0000000000
--- a/base/trace_event/memory_dump_scheduler.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2017 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/trace_event/memory_dump_scheduler.h"
-
-#include <algorithm>
-#include <limits>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-
-namespace base {
-namespace trace_event {
-
-// static
-MemoryDumpScheduler* MemoryDumpScheduler::GetInstance() {
- static MemoryDumpScheduler* instance = new MemoryDumpScheduler();
- return instance;
-}
-
-MemoryDumpScheduler::MemoryDumpScheduler() : period_ms_(0), generation_(0) {}
-MemoryDumpScheduler::~MemoryDumpScheduler() {
- // Hit only in tests. Check that tests don't leave without stopping.
- DCHECK(!is_enabled_for_testing());
-}
-
-void MemoryDumpScheduler::Start(
- MemoryDumpScheduler::Config config,
- scoped_refptr<SequencedTaskRunner> task_runner) {
- DCHECK(!task_runner_);
- task_runner_ = task_runner;
- task_runner->PostTask(FROM_HERE, BindOnce(&MemoryDumpScheduler::StartInternal,
- Unretained(this), config));
-}
-
-void MemoryDumpScheduler::Stop() {
- if (!task_runner_)
- return;
- task_runner_->PostTask(FROM_HERE, BindOnce(&MemoryDumpScheduler::StopInternal,
- Unretained(this)));
- task_runner_ = nullptr;
-}
-
-void MemoryDumpScheduler::StartInternal(MemoryDumpScheduler::Config config) {
- uint32_t light_dump_period_ms = 0;
- uint32_t heavy_dump_period_ms = 0;
- uint32_t min_period_ms = std::numeric_limits<uint32_t>::max();
- for (const Config::Trigger& trigger : config.triggers) {
- DCHECK_GT(trigger.period_ms, 0u);
- switch (trigger.level_of_detail) {
- case MemoryDumpLevelOfDetail::BACKGROUND:
- break;
- case MemoryDumpLevelOfDetail::LIGHT:
- DCHECK_EQ(0u, light_dump_period_ms);
- light_dump_period_ms = trigger.period_ms;
- break;
- case MemoryDumpLevelOfDetail::DETAILED:
- DCHECK_EQ(0u, heavy_dump_period_ms);
- heavy_dump_period_ms = trigger.period_ms;
- break;
- }
- min_period_ms = std::min(min_period_ms, trigger.period_ms);
- }
-
- DCHECK_EQ(0u, light_dump_period_ms % min_period_ms);
- DCHECK_EQ(0u, heavy_dump_period_ms % min_period_ms);
- DCHECK(!config.callback.is_null());
- callback_ = config.callback;
- period_ms_ = min_period_ms;
- tick_count_ = 0;
- light_dump_rate_ = light_dump_period_ms / min_period_ms;
- heavy_dump_rate_ = heavy_dump_period_ms / min_period_ms;
-
- // Trigger the first dump after 200ms.
- // TODO(lalitm): this is a tempoarary hack to delay the first scheduled dump
- // so that the child processes get tracing enabled notification via IPC.
- // See crbug.com/770151.
- SequencedTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&MemoryDumpScheduler::Tick, Unretained(this), ++generation_),
- TimeDelta::FromMilliseconds(200));
-}
-
-void MemoryDumpScheduler::StopInternal() {
- period_ms_ = 0;
- generation_++;
- callback_.Reset();
-}
-
-void MemoryDumpScheduler::Tick(uint32_t expected_generation) {
- if (period_ms_ == 0 || generation_ != expected_generation)
- return;
-
- MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND;
- if (light_dump_rate_ > 0 && tick_count_ % light_dump_rate_ == 0)
- level_of_detail = MemoryDumpLevelOfDetail::LIGHT;
- if (heavy_dump_rate_ > 0 && tick_count_ % heavy_dump_rate_ == 0)
- level_of_detail = MemoryDumpLevelOfDetail::DETAILED;
- tick_count_++;
-
- callback_.Run(level_of_detail);
-
- SequencedTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&MemoryDumpScheduler::Tick, Unretained(this),
- expected_generation),
- TimeDelta::FromMilliseconds(period_ms_));
-}
-
-MemoryDumpScheduler::Config::Config() = default;
-MemoryDumpScheduler::Config::~Config() = default;
-MemoryDumpScheduler::Config::Config(const MemoryDumpScheduler::Config&) =
- default;
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_dump_scheduler.h b/base/trace_event/memory_dump_scheduler.h
deleted file mode 100644
index 21334f0edd..0000000000
--- a/base/trace_event/memory_dump_scheduler.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H
-#define BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/trace_event/memory_dump_request_args.h"
-
-namespace base {
-class SequencedTaskRunner;
-
-namespace trace_event {
-
-// Schedules global dump requests based on the triggers added. The methods of
-// this class are NOT thread safe and the client has to take care of invoking
-// all the methods of the class safely.
-class BASE_EXPORT MemoryDumpScheduler {
- public:
- using PeriodicCallback = RepeatingCallback<void(MemoryDumpLevelOfDetail)>;
-
- // Passed to Start().
- struct BASE_EXPORT Config {
- struct Trigger {
- MemoryDumpLevelOfDetail level_of_detail;
- uint32_t period_ms;
- };
-
- Config();
- Config(const Config&);
- ~Config();
-
- std::vector<Trigger> triggers;
- PeriodicCallback callback;
- };
-
- static MemoryDumpScheduler* GetInstance();
-
- void Start(Config, scoped_refptr<SequencedTaskRunner> task_runner);
- void Stop();
- bool is_enabled_for_testing() const { return bool(task_runner_); }
-
- private:
- friend class MemoryDumpSchedulerTest;
- MemoryDumpScheduler();
- ~MemoryDumpScheduler();
-
- void StartInternal(Config);
- void StopInternal();
- void Tick(uint32_t expected_generation);
-
- // Accessed only by the public methods (never from the task runner itself).
- scoped_refptr<SequencedTaskRunner> task_runner_;
-
- // These fields instead are only accessed from within the task runner.
- uint32_t period_ms_; // 0 == disabled.
- uint32_t generation_; // Used to invalidate outstanding tasks after Stop().
- uint32_t tick_count_;
- uint32_t light_dump_rate_;
- uint32_t heavy_dump_rate_;
- PeriodicCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryDumpScheduler);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_DUMP_SCHEDULER_H
diff --git a/base/trace_event/memory_dump_scheduler_unittest.cc b/base/trace_event/memory_dump_scheduler_unittest.cc
deleted file mode 100644
index d5993b6fca..0000000000
--- a/base/trace_event/memory_dump_scheduler_unittest.cc
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2017 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/trace_event/memory_dump_scheduler.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::AtMost;
-using ::testing::Invoke;
-using ::testing::_;
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// Wrapper to use gmock on a callback.
-struct CallbackWrapper {
- MOCK_METHOD1(OnTick, void(MemoryDumpLevelOfDetail));
-};
-
-} // namespace
-
-class MemoryDumpSchedulerTest : public testing::Test {
- public:
- MemoryDumpSchedulerTest()
- : testing::Test(),
- evt_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- bg_thread_("MemoryDumpSchedulerTest Thread") {
- bg_thread_.Start();
- }
-
- protected:
- MemoryDumpScheduler scheduler_;
- WaitableEvent evt_;
- CallbackWrapper on_tick_;
- Thread bg_thread_;
-};
-
-TEST_F(MemoryDumpSchedulerTest, SingleTrigger) {
- const uint32_t kPeriodMs = 1;
- const auto kLevelOfDetail = MemoryDumpLevelOfDetail::DETAILED;
- const uint32_t kTicks = 5;
- MemoryDumpScheduler::Config config;
- config.triggers.push_back({kLevelOfDetail, kPeriodMs});
- config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_));
-
- testing::InSequence sequence;
- EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1);
- EXPECT_CALL(on_tick_, OnTick(_))
- .WillRepeatedly(Invoke(
- [this, kLevelOfDetail](MemoryDumpLevelOfDetail level_of_detail) {
- EXPECT_EQ(kLevelOfDetail, level_of_detail);
- this->evt_.Signal();
- }));
-
- // Check that Stop() before Start() doesn't cause any error.
- scheduler_.Stop();
-
- const TimeTicks tstart = TimeTicks::Now();
- scheduler_.Start(config, bg_thread_.task_runner());
- evt_.Wait();
- const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF();
-
- // It takes N-1 ms to perform N ticks of 1ms each.
- EXPECT_GE(time_ms, kPeriodMs * (kTicks - 1));
-
- // Check that stopping twice doesn't cause any problems.
- scheduler_.Stop();
- scheduler_.Stop();
-}
-
-TEST_F(MemoryDumpSchedulerTest, MultipleTriggers) {
- const uint32_t kPeriodLightMs = 3;
- const uint32_t kPeriodDetailedMs = 9;
- MemoryDumpScheduler::Config config;
- const MemoryDumpLevelOfDetail kLight = MemoryDumpLevelOfDetail::LIGHT;
- const MemoryDumpLevelOfDetail kDetailed = MemoryDumpLevelOfDetail::DETAILED;
- config.triggers.push_back({kLight, kPeriodLightMs});
- config.triggers.push_back({kDetailed, kPeriodDetailedMs});
- config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_));
-
- TimeTicks t1, t2, t3;
-
- testing::InSequence sequence;
- EXPECT_CALL(on_tick_, OnTick(kDetailed))
- .WillOnce(
- Invoke([&t1](MemoryDumpLevelOfDetail) { t1 = TimeTicks::Now(); }));
- EXPECT_CALL(on_tick_, OnTick(kLight)).Times(1);
- EXPECT_CALL(on_tick_, OnTick(kLight)).Times(1);
- EXPECT_CALL(on_tick_, OnTick(kDetailed))
- .WillOnce(
- Invoke([&t2](MemoryDumpLevelOfDetail) { t2 = TimeTicks::Now(); }));
- EXPECT_CALL(on_tick_, OnTick(kLight))
- .WillOnce(
- Invoke([&t3](MemoryDumpLevelOfDetail) { t3 = TimeTicks::Now(); }));
-
- // Rationale for WillRepeatedly and not just WillOnce: Extra ticks might
- // happen if the Stop() takes time. Not an interesting case, but we need to
- // avoid gmock to shout in that case.
- EXPECT_CALL(on_tick_, OnTick(_))
- .WillRepeatedly(
- Invoke([this](MemoryDumpLevelOfDetail) { this->evt_.Signal(); }));
-
- scheduler_.Start(config, bg_thread_.task_runner());
- evt_.Wait();
- scheduler_.Stop();
- EXPECT_GE((t2 - t1).InMillisecondsF(), kPeriodDetailedMs);
- EXPECT_GE((t3 - t2).InMillisecondsF(), kPeriodLightMs);
-}
-
-TEST_F(MemoryDumpSchedulerTest, StartStopQuickly) {
- const uint32_t kPeriodMs = 3;
- const uint32_t kQuickIterations = 5;
- const uint32_t kDetailedTicks = 10;
-
- MemoryDumpScheduler::Config light_config;
- light_config.triggers.push_back({MemoryDumpLevelOfDetail::LIGHT, kPeriodMs});
- light_config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_));
-
- MemoryDumpScheduler::Config detailed_config;
- detailed_config.triggers.push_back(
- {MemoryDumpLevelOfDetail::DETAILED, kPeriodMs});
- detailed_config.callback =
- Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_));
-
- testing::InSequence sequence;
- EXPECT_CALL(on_tick_, OnTick(MemoryDumpLevelOfDetail::LIGHT))
- .Times(AtMost(kQuickIterations));
- EXPECT_CALL(on_tick_, OnTick(MemoryDumpLevelOfDetail::DETAILED))
- .Times(kDetailedTicks - 1);
- EXPECT_CALL(on_tick_, OnTick(MemoryDumpLevelOfDetail::DETAILED))
- .WillRepeatedly(
- Invoke([this](MemoryDumpLevelOfDetail) { this->evt_.Signal(); }));
-
- const TimeTicks tstart = TimeTicks::Now();
- for (unsigned int i = 0; i < kQuickIterations; i++) {
- scheduler_.Start(light_config, bg_thread_.task_runner());
- scheduler_.Stop();
- }
-
- scheduler_.Start(detailed_config, bg_thread_.task_runner());
-
- evt_.Wait();
- const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF();
- scheduler_.Stop();
-
- // It takes N-1 ms to perform N ticks of 1ms each.
- EXPECT_GE(time_ms, kPeriodMs * (kDetailedTicks - 1));
-}
-
-TEST_F(MemoryDumpSchedulerTest, StopAndStartOnAnotherThread) {
- const uint32_t kPeriodMs = 1;
- const uint32_t kTicks = 3;
- MemoryDumpScheduler::Config config;
- config.triggers.push_back({MemoryDumpLevelOfDetail::DETAILED, kPeriodMs});
- config.callback = Bind(&CallbackWrapper::OnTick, Unretained(&on_tick_));
-
- scoped_refptr<TaskRunner> expected_task_runner = bg_thread_.task_runner();
- testing::InSequence sequence;
- EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1);
- EXPECT_CALL(on_tick_, OnTick(_))
- .WillRepeatedly(
- Invoke([this, expected_task_runner](MemoryDumpLevelOfDetail) {
- EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence());
- this->evt_.Signal();
- }));
-
- scheduler_.Start(config, bg_thread_.task_runner());
- evt_.Wait();
- scheduler_.Stop();
- bg_thread_.Stop();
-
- Thread bg_thread_2("MemoryDumpSchedulerTest Thread 2");
- bg_thread_2.Start();
- evt_.Reset();
- expected_task_runner = bg_thread_2.task_runner();
- EXPECT_CALL(on_tick_, OnTick(_)).Times(kTicks - 1);
- EXPECT_CALL(on_tick_, OnTick(_))
- .WillRepeatedly(
- Invoke([this, expected_task_runner](MemoryDumpLevelOfDetail) {
- EXPECT_TRUE(expected_task_runner->RunsTasksInCurrentSequence());
- this->evt_.Signal();
- }));
- scheduler_.Start(config, bg_thread_2.task_runner());
- evt_.Wait();
- scheduler_.Stop();
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_infra_background_whitelist.cc b/base/trace_event/memory_infra_background_whitelist.cc
deleted file mode 100644
index 40f5ac8ccc..0000000000
--- a/base/trace_event/memory_infra_background_whitelist.cc
+++ /dev/null
@@ -1,392 +0,0 @@
-// Copyright 2016 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/trace_event/memory_infra_background_whitelist.h"
-
-#include <ctype.h>
-#include <string.h>
-
-#include <string>
-
-#include "base/strings/string_util.h"
-
-namespace base {
-namespace trace_event {
-namespace {
-
-// The names of dump providers whitelisted for background tracing. Dump
-// providers can be added here only if the background mode dump has very
-// little processor and memory overhead.
-// TODO(ssid): Some dump providers do not create ownership edges on background
-// dump. So, the effective size will not be correct.
-const char* const kDumpProviderWhitelist[] = {
- "android::ResourceManagerImpl",
- "AutocompleteController",
- "BlinkGC",
- "BlinkObjectCounters",
- "BlobStorageContext",
- "ClientDiscardableSharedMemoryManager",
- "DOMStorage",
- "DownloadService",
- "DiscardableSharedMemoryManager",
- "gpu::BufferManager",
- "gpu::RenderbufferManager",
- "gpu::TextureManager",
- "FontCaches",
- "HistoryReport",
- "IPCChannel",
- "IndexedDBBackingStore",
- "InMemoryURLIndex",
- "JavaHeap",
- "LevelDB",
- "LeveldbValueStore",
- "LocalStorage",
- "Malloc",
- "MemoryCache",
- "MojoHandleTable",
- "MojoLevelDB",
- "MojoMessages",
- "PartitionAlloc",
- "ProcessMemoryMetrics",
- "RenderProcessHost",
- "SharedMemoryTracker",
- "Skia",
- "Sql",
- "URLRequestContext",
- "V8Isolate",
- "SyncDirectory",
- "TabRestoreServiceHelper",
- nullptr // End of list marker.
-};
-
-// A list of string names that are allowed for the memory allocator dumps in
-// background mode.
-const char* const kAllocatorDumpNameWhitelist[] = {
- "blink_gc",
- "blink_gc/allocated_objects",
- "blink_objects/AdSubframe",
- "blink_objects/AudioHandler",
- "blink_objects/DetachedScriptState",
- "blink_objects/Document",
- "blink_objects/Frame",
- "blink_objects/JSEventListener",
- "blink_objects/LayoutObject",
- "blink_objects/MediaKeySession",
- "blink_objects/MediaKeys",
- "blink_objects/Node",
- "blink_objects/Resource",
- "blink_objects/RTCPeerConnection",
- "blink_objects/ScriptPromise",
- "blink_objects/PausableObject",
- "blink_objects/V8PerContextData",
- "blink_objects/WorkerGlobalScope",
- "blink_objects/UACSSResource",
- "blink_objects/ResourceFetcher",
- "components/download/controller_0x?",
- "discardable",
- "discardable/child_0x?",
- "extensions/value_store/Extensions.Database.Open.Settings/0x?",
- "extensions/value_store/Extensions.Database.Open.Rules/0x?",
- "extensions/value_store/Extensions.Database.Open.State/0x?",
- "extensions/value_store/Extensions.Database.Open/0x?",
- "extensions/value_store/Extensions.Database.Restore/0x?",
- "extensions/value_store/Extensions.Database.Value.Restore/0x?",
- "font_caches/font_platform_data_cache",
- "font_caches/shape_caches",
- "gpu/gl/buffers/share_group_0x?",
- "gpu/gl/renderbuffers/share_group_0x?",
- "gpu/gl/textures/share_group_0x?",
- "history/delta_file_service/leveldb_0x?",
- "history/usage_reports_buffer/leveldb_0x?",
- "java_heap",
- "java_heap/allocated_objects",
- "leveldatabase",
- "leveldatabase/block_cache/browser",
- "leveldatabase/block_cache/in_memory",
- "leveldatabase/block_cache/unified",
- "leveldatabase/block_cache/web",
- "leveldatabase/db_0x?",
- "leveldatabase/db_0x?/block_cache",
- "leveldatabase/memenv_0x?",
- "malloc",
- "malloc/allocated_objects",
- "malloc/metadata_fragmentation_caches",
- "mojo",
- "mojo/data_pipe_consumer",
- "mojo/data_pipe_producer",
- "mojo/invitation",
- "mojo/messages",
- "mojo/message_pipe",
- "mojo/platform_handle",
- "mojo/queued_ipc_channel_message/0x?",
- "mojo/render_process_host/0x?",
- "mojo/shared_buffer",
- "mojo/unknown",
- "mojo/watcher",
- "net/http_network_session_0x?",
- "net/http_network_session_0x?/quic_stream_factory",
- "net/http_network_session_0x?/socket_pool",
- "net/http_network_session_0x?/spdy_session_pool",
- "net/http_network_session_0x?/stream_factory",
- "net/ssl_session_cache",
- "net/url_request_context",
- "net/url_request_context/app_request",
- "net/url_request_context/app_request/0x?",
- "net/url_request_context/app_request/0x?/cookie_monster",
- "net/url_request_context/app_request/0x?/cookie_monster/cookies",
- "net/url_request_context/app_request/0x?/cookie_monster/"
- "tasks_pending_global",
- "net/url_request_context/app_request/0x?/cookie_monster/"
- "tasks_pending_for_key",
- "net/url_request_context/app_request/0x?/http_cache",
- "net/url_request_context/app_request/0x?/http_cache/memory_backend",
- "net/url_request_context/app_request/0x?/http_cache/simple_backend",
- "net/url_request_context/app_request/0x?/http_network_session",
- "net/url_request_context/extensions",
- "net/url_request_context/extensions/0x?",
- "net/url_request_context/extensions/0x?/cookie_monster",
- "net/url_request_context/extensions/0x?/cookie_monster/cookies",
- "net/url_request_context/extensions/0x?/cookie_monster/"
- "tasks_pending_global",
- "net/url_request_context/extensions/0x?/cookie_monster/"
- "tasks_pending_for_key",
- "net/url_request_context/extensions/0x?/http_cache",
- "net/url_request_context/extensions/0x?/http_cache/memory_backend",
- "net/url_request_context/extensions/0x?/http_cache/simple_backend",
- "net/url_request_context/extensions/0x?/http_network_session",
- "net/url_request_context/isolated_media",
- "net/url_request_context/isolated_media/0x?",
- "net/url_request_context/isolated_media/0x?/cookie_monster",
- "net/url_request_context/isolated_media/0x?/cookie_monster/cookies",
- "net/url_request_context/isolated_media/0x?/cookie_monster/"
- "tasks_pending_global",
- "net/url_request_context/isolated_media/0x?/cookie_monster/"
- "tasks_pending_for_key",
- "net/url_request_context/isolated_media/0x?/http_cache",
- "net/url_request_context/isolated_media/0x?/http_cache/memory_backend",
- "net/url_request_context/isolated_media/0x?/http_cache/simple_backend",
- "net/url_request_context/isolated_media/0x?/http_network_session",
- "net/url_request_context/main",
- "net/url_request_context/main/0x?",
- "net/url_request_context/main/0x?/cookie_monster",
- "net/url_request_context/main/0x?/cookie_monster/cookies",
- "net/url_request_context/main/0x?/cookie_monster/tasks_pending_global",
- "net/url_request_context/main/0x?/cookie_monster/tasks_pending_for_key",
- "net/url_request_context/main/0x?/http_cache",
- "net/url_request_context/main/0x?/http_cache/memory_backend",
- "net/url_request_context/main/0x?/http_cache/simple_backend",
- "net/url_request_context/main/0x?/http_network_session",
- "net/url_request_context/main_media",
- "net/url_request_context/main_media/0x?",
- "net/url_request_context/main_media/0x?/cookie_monster",
- "net/url_request_context/main_media/0x?/cookie_monster/cookies",
- "net/url_request_context/main_media/0x?/cookie_monster/"
- "tasks_pending_global",
- "net/url_request_context/main_media/0x?/cookie_monster/"
- "tasks_pending_for_key",
- "net/url_request_context/main_media/0x?/http_cache",
- "net/url_request_context/main_media/0x?/http_cache/memory_backend",
- "net/url_request_context/main_media/0x?/http_cache/simple_backend",
- "net/url_request_context/main_media/0x?/http_network_session",
- "net/url_request_context/proxy",
- "net/url_request_context/proxy/0x?",
- "net/url_request_context/proxy/0x?/cookie_monster",
- "net/url_request_context/proxy/0x?/cookie_monster/cookies",
- "net/url_request_context/proxy/0x?/cookie_monster/tasks_pending_global",
- "net/url_request_context/proxy/0x?/cookie_monster/tasks_pending_for_key",
- "net/url_request_context/proxy/0x?/http_cache",
- "net/url_request_context/proxy/0x?/http_cache/memory_backend",
- "net/url_request_context/proxy/0x?/http_cache/simple_backend",
- "net/url_request_context/proxy/0x?/http_network_session",
- "net/url_request_context/safe_browsing",
- "net/url_request_context/safe_browsing/0x?",
- "net/url_request_context/safe_browsing/0x?/cookie_monster",
- "net/url_request_context/safe_browsing/0x?/cookie_monster/cookies",
- "net/url_request_context/safe_browsing/0x?/cookie_monster/"
- "tasks_pending_global",
- "net/url_request_context/safe_browsing/0x?/cookie_monster/"
- "tasks_pending_for_key",
- "net/url_request_context/safe_browsing/0x?/http_cache",
- "net/url_request_context/safe_browsing/0x?/http_cache/memory_backend",
- "net/url_request_context/safe_browsing/0x?/http_cache/simple_backend",
- "net/url_request_context/safe_browsing/0x?/http_network_session",
- "net/url_request_context/system",
- "net/url_request_context/system/0x?",
- "net/url_request_context/system/0x?/cookie_monster",
- "net/url_request_context/system/0x?/cookie_monster/cookies",
- "net/url_request_context/system/0x?/cookie_monster/tasks_pending_global",
- "net/url_request_context/system/0x?/cookie_monster/tasks_pending_for_key",
- "net/url_request_context/system/0x?/http_cache",
- "net/url_request_context/system/0x?/http_cache/memory_backend",
- "net/url_request_context/system/0x?/http_cache/simple_backend",
- "net/url_request_context/system/0x?/http_network_session",
- "net/url_request_context/unknown",
- "net/url_request_context/unknown/0x?",
- "net/url_request_context/unknown/0x?/cookie_monster",
- "net/url_request_context/unknown/0x?/cookie_monster/cookies",
- "net/url_request_context/unknown/0x?/cookie_monster/tasks_pending_global",
- "net/url_request_context/unknown/0x?/cookie_monster/tasks_pending_for_key",
- "net/url_request_context/unknown/0x?/http_cache",
- "net/url_request_context/unknown/0x?/http_cache/memory_backend",
- "net/url_request_context/unknown/0x?/http_cache/simple_backend",
- "net/url_request_context/unknown/0x?/http_network_session",
- "omnibox/autocomplete_controller/0x?",
- "omnibox/in_memory_url_index/0x?",
- "web_cache/Image_resources",
- "web_cache/CSS stylesheet_resources",
- "web_cache/Script_resources",
- "web_cache/XSL stylesheet_resources",
- "web_cache/Font_resources",
- "web_cache/Other_resources",
- "partition_alloc/allocated_objects",
- "partition_alloc/partitions",
- "partition_alloc/partitions/array_buffer",
- "partition_alloc/partitions/buffer",
- "partition_alloc/partitions/fast_malloc",
- "partition_alloc/partitions/layout",
- "skia/sk_glyph_cache",
- "skia/sk_resource_cache",
- "sqlite",
- "ui/resource_manager_0x?/default_resource/0x?",
- "ui/resource_manager_0x?/tinted_resource",
- "v8/isolate_0x?/contexts/detached_context",
- "v8/isolate_0x?/contexts/native_context",
- "v8/isolate_0x?/heap_spaces",
- "v8/isolate_0x?/heap_spaces/code_space",
- "v8/isolate_0x?/heap_spaces/large_object_space",
- "v8/isolate_0x?/heap_spaces/map_space",
- "v8/isolate_0x?/heap_spaces/new_space",
- "v8/isolate_0x?/heap_spaces/new_large_object_space",
- "v8/isolate_0x?/heap_spaces/old_space",
- "v8/isolate_0x?/heap_spaces/read_only_space",
- "v8/isolate_0x?/malloc",
- "v8/isolate_0x?/zapped_for_debug",
- "site_storage/blob_storage/0x?",
- "site_storage/index_db/db_0x?",
- "site_storage/index_db/memenv_0x?",
- "site_storage/localstorage/0x?/cache_size",
- "site_storage/localstorage/0x?/leveldb",
- "site_storage/session_storage/0x?",
- "site_storage/session_storage/0x?/cache_size",
- "sync/0x?/kernel",
- "sync/0x?/store",
- "sync/0x?/model_type/APP",
- "sync/0x?/model_type/APP_LIST",
- "sync/0x?/model_type/APP_NOTIFICATION",
- "sync/0x?/model_type/APP_SETTING",
- "sync/0x?/model_type/ARC_PACKAGE",
- "sync/0x?/model_type/ARTICLE",
- "sync/0x?/model_type/AUTOFILL",
- "sync/0x?/model_type/AUTOFILL_PROFILE",
- "sync/0x?/model_type/AUTOFILL_WALLET",
- "sync/0x?/model_type/BOOKMARK",
- "sync/0x?/model_type/DEVICE_INFO",
- "sync/0x?/model_type/DICTIONARY",
- "sync/0x?/model_type/EXPERIMENTS",
- "sync/0x?/model_type/EXTENSION",
- "sync/0x?/model_type/EXTENSION_SETTING",
- "sync/0x?/model_type/FAVICON_IMAGE",
- "sync/0x?/model_type/FAVICON_TRACKING",
- "sync/0x?/model_type/HISTORY_DELETE_DIRECTIVE",
- "sync/0x?/model_type/MANAGED_USER",
- "sync/0x?/model_type/MANAGED_USER_SETTING",
- "sync/0x?/model_type/MANAGED_USER_SHARED_SETTING",
- "sync/0x?/model_type/MANAGED_USER_WHITELIST",
- "sync/0x?/model_type/MOUNTAIN_SHARE",
- "sync/0x?/model_type/NIGORI",
- "sync/0x?/model_type/PASSWORD",
- "sync/0x?/model_type/PREFERENCE",
- "sync/0x?/model_type/PRINTER",
- "sync/0x?/model_type/PRIORITY_PREFERENCE",
- "sync/0x?/model_type/READING_LIST",
- "sync/0x?/model_type/SEARCH_ENGINE",
- "sync/0x?/model_type/SESSION",
- "sync/0x?/model_type/SYNCED_NOTIFICATION",
- "sync/0x?/model_type/SYNCED_NOTIFICATION_APP_INFO",
- "sync/0x?/model_type/THEME",
- "sync/0x?/model_type/TYPED_URL",
- "sync/0x?/model_type/USER_CONSENT",
- "sync/0x?/model_type/USER_EVENT",
- "sync/0x?/model_type/WALLET_METADATA",
- "sync/0x?/model_type/WIFI_CREDENTIAL",
- "tab_restore/service_helper_0x?/entries",
- "tab_restore/service_helper_0x?/entries/tab_0x?",
- "tab_restore/service_helper_0x?/entries/window_0x?",
- "tracing/heap_profiler_blink_gc/AllocationRegister",
- "tracing/heap_profiler_malloc/AllocationRegister",
- "tracing/heap_profiler_partition_alloc/AllocationRegister",
- nullptr // End of list marker.
-};
-
-const char* const* g_dump_provider_whitelist = kDumpProviderWhitelist;
-const char* const* g_allocator_dump_name_whitelist =
- kAllocatorDumpNameWhitelist;
-
-bool IsMemoryDumpProviderInList(const char* mdp_name, const char* const* list) {
- for (size_t i = 0; list[i] != nullptr; ++i) {
- if (strcmp(mdp_name, list[i]) == 0)
- return true;
- }
- return false;
-}
-
-} // namespace
-
-bool IsMemoryDumpProviderWhitelisted(const char* mdp_name) {
- return IsMemoryDumpProviderInList(mdp_name, g_dump_provider_whitelist);
-}
-
-bool IsMemoryAllocatorDumpNameWhitelisted(const std::string& name) {
- // Global dumps are explicitly whitelisted for background use.
- if (base::StartsWith(name, "global/", CompareCase::SENSITIVE)) {
- for (size_t i = strlen("global/"); i < name.size(); i++)
- if (!base::IsHexDigit(name[i]))
- return false;
- return true;
- }
-
- if (base::StartsWith(name, "shared_memory/", CompareCase::SENSITIVE)) {
- for (size_t i = strlen("shared_memory/"); i < name.size(); i++)
- if (!base::IsHexDigit(name[i]))
- return false;
- return true;
- }
-
- // Remove special characters, numbers (including hexadecimal which are marked
- // by '0x') from the given string.
- const size_t length = name.size();
- std::string stripped_str;
- stripped_str.reserve(length);
- bool parsing_hex = false;
- for (size_t i = 0; i < length; ++i) {
- if (parsing_hex && isxdigit(name[i]))
- continue;
- parsing_hex = false;
- if (i + 1 < length && name[i] == '0' && name[i + 1] == 'x') {
- parsing_hex = true;
- stripped_str.append("0x?");
- ++i;
- } else {
- stripped_str.push_back(name[i]);
- }
- }
-
- for (size_t i = 0; g_allocator_dump_name_whitelist[i] != nullptr; ++i) {
- if (stripped_str == g_allocator_dump_name_whitelist[i]) {
- return true;
- }
- }
- return false;
-}
-
-void SetDumpProviderWhitelistForTesting(const char* const* list) {
- g_dump_provider_whitelist = list;
-}
-
-void SetAllocatorDumpNameWhitelistForTesting(const char* const* list) {
- g_allocator_dump_name_whitelist = list;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_infra_background_whitelist.h b/base/trace_event/memory_infra_background_whitelist.h
deleted file mode 100644
index b8d704ae24..0000000000
--- a/base/trace_event/memory_infra_background_whitelist.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_
-#define BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_
-
-// This file contains the whitelists for background mode to limit the tracing
-// overhead and remove sensitive information from traces.
-
-#include <string>
-
-#include "base/base_export.h"
-
-namespace base {
-namespace trace_event {
-
-// Checks if the given |mdp_name| is in the whitelist.
-bool BASE_EXPORT IsMemoryDumpProviderWhitelisted(const char* mdp_name);
-
-// Checks if the given |name| matches any of the whitelisted patterns.
-bool BASE_EXPORT IsMemoryAllocatorDumpNameWhitelisted(const std::string& name);
-
-// The whitelist is replaced with the given list for tests. The last element of
-// the list must be nullptr.
-void BASE_EXPORT SetDumpProviderWhitelistForTesting(const char* const* list);
-void BASE_EXPORT
-SetAllocatorDumpNameWhitelistForTesting(const char* const* list);
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_INFRA_BACKGROUND_WHITELIST_H_
diff --git a/base/trace_event/memory_infra_background_whitelist_unittest.cc b/base/trace_event/memory_infra_background_whitelist_unittest.cc
deleted file mode 100644
index 3037eb1da7..0000000000
--- a/base/trace_event/memory_infra_background_whitelist_unittest.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 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/trace_event/memory_infra_background_whitelist.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace trace_event {
-
-TEST(MemoryInfraBackgroundWhitelist, Whitelist) {
- // Global dumps that are of hex digits are all whitelisted for background use.
- EXPECT_TRUE(IsMemoryAllocatorDumpNameWhitelisted("global/01234ABCDEF"));
- EXPECT_TRUE(
- IsMemoryAllocatorDumpNameWhitelisted("shared_memory/01234ABCDEF"));
-
- // Global dumps that contain non-hex digits are not whitelisted.
- EXPECT_FALSE(IsMemoryAllocatorDumpNameWhitelisted("global/GHIJK"));
- EXPECT_FALSE(IsMemoryAllocatorDumpNameWhitelisted("shared_memory/GHIJK"));
-
- // Test a couple that contain pointer values.
- EXPECT_TRUE(IsMemoryAllocatorDumpNameWhitelisted("net/url_request_context"));
- EXPECT_TRUE(IsMemoryAllocatorDumpNameWhitelisted(
- "net/url_request_context/app_request/0x123/cookie_monster"));
- EXPECT_TRUE(
- IsMemoryAllocatorDumpNameWhitelisted("net/http_network_session_0x123"));
- EXPECT_FALSE(
- IsMemoryAllocatorDumpNameWhitelisted("net/http_network_session/0x123"));
- EXPECT_TRUE(IsMemoryAllocatorDumpNameWhitelisted(
- "net/http_network_session_0x123/quic_stream_factory"));
-}
-
-} // namespace trace_event
-
-} // namespace base
diff --git a/base/trace_event/memory_usage_estimator.cc b/base/trace_event/memory_usage_estimator.cc
deleted file mode 100644
index c769d5b6f1..0000000000
--- a/base/trace_event/memory_usage_estimator.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2016 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/trace_event/memory_usage_estimator.h"
-
-namespace base {
-namespace trace_event {
-
-template size_t EstimateMemoryUsage(const std::string&);
-template size_t EstimateMemoryUsage(const string16&);
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/memory_usage_estimator.h b/base/trace_event/memory_usage_estimator.h
deleted file mode 100644
index 214c64a905..0000000000
--- a/base/trace_event/memory_usage_estimator.h
+++ /dev/null
@@ -1,654 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_
-#define BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_
-
-#include <stdint.h>
-
-#include <array>
-#include <deque>
-#include <list>
-#include <map>
-#include <memory>
-#include <queue>
-#include <set>
-#include <stack>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/containers/circular_deque.h"
-#include "base/containers/flat_map.h"
-#include "base/containers/flat_set.h"
-#include "base/containers/linked_list.h"
-#include "base/containers/mru_cache.h"
-#include "base/containers/queue.h"
-#include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/template_util.h"
-
-// Composable memory usage estimators.
-//
-// This file defines set of EstimateMemoryUsage(object) functions that return
-// approximate memory usage of their argument.
-//
-// The ultimate goal is to make memory usage estimation for a class simply a
-// matter of aggregating EstimateMemoryUsage() results over all fields.
-//
-// That is achieved via composability: if EstimateMemoryUsage() is defined
-// for T then EstimateMemoryUsage() is also defined for any combination of
-// containers holding T (e.g. std::map<int, std::vector<T>>).
-//
-// There are two ways of defining EstimateMemoryUsage() for a type:
-//
-// 1. As a global function 'size_t EstimateMemoryUsage(T)' in
-// in base::trace_event namespace.
-//
-// 2. As 'size_t T::EstimateMemoryUsage() const' method. In this case
-// EstimateMemoryUsage(T) function in base::trace_event namespace is
-// provided automatically.
-//
-// Here is an example implementation:
-//
-// size_t foo::bar::MyClass::EstimateMemoryUsage() const {
-// return base::trace_event::EstimateMemoryUsage(name_) +
-// base::trace_event::EstimateMemoryUsage(id_) +
-// base::trace_event::EstimateMemoryUsage(items_);
-// }
-//
-// The approach is simple: first call EstimateMemoryUsage() on all members,
-// then recursively fix compilation errors that are caused by types not
-// implementing EstimateMemoryUsage().
-
-namespace base {
-namespace trace_event {
-
-// Declarations
-
-// If T declares 'EstimateMemoryUsage() const' member function, then
-// global function EstimateMemoryUsage(T) is available, and just calls
-// the member function.
-template <class T>
-auto EstimateMemoryUsage(const T& object)
- -> decltype(object.EstimateMemoryUsage());
-
-// String
-
-template <class C, class T, class A>
-size_t EstimateMemoryUsage(const std::basic_string<C, T, A>& string);
-
-// Arrays
-
-template <class T, size_t N>
-size_t EstimateMemoryUsage(const std::array<T, N>& array);
-
-template <class T, size_t N>
-size_t EstimateMemoryUsage(T (&array)[N]);
-
-template <class T>
-size_t EstimateMemoryUsage(const T* array, size_t array_length);
-
-// std::unique_ptr
-
-template <class T, class D>
-size_t EstimateMemoryUsage(const std::unique_ptr<T, D>& ptr);
-
-template <class T, class D>
-size_t EstimateMemoryUsage(const std::unique_ptr<T[], D>& array,
- size_t array_length);
-
-// std::shared_ptr
-
-template <class T>
-size_t EstimateMemoryUsage(const std::shared_ptr<T>& ptr);
-
-// Containers
-
-template <class F, class S>
-size_t EstimateMemoryUsage(const std::pair<F, S>& pair);
-
-template <class T, class A>
-size_t EstimateMemoryUsage(const std::vector<T, A>& vector);
-
-template <class T, class A>
-size_t EstimateMemoryUsage(const std::list<T, A>& list);
-
-template <class T>
-size_t EstimateMemoryUsage(const base::LinkedList<T>& list);
-
-template <class T, class C, class A>
-size_t EstimateMemoryUsage(const std::set<T, C, A>& set);
-
-template <class T, class C, class A>
-size_t EstimateMemoryUsage(const std::multiset<T, C, A>& set);
-
-template <class K, class V, class C, class A>
-size_t EstimateMemoryUsage(const std::map<K, V, C, A>& map);
-
-template <class K, class V, class C, class A>
-size_t EstimateMemoryUsage(const std::multimap<K, V, C, A>& map);
-
-template <class T, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_set<T, H, KE, A>& set);
-
-template <class T, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_multiset<T, H, KE, A>& set);
-
-template <class K, class V, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_map<K, V, H, KE, A>& map);
-
-template <class K, class V, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map);
-
-template <class T, class A>
-size_t EstimateMemoryUsage(const std::deque<T, A>& deque);
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const std::queue<T, C>& queue);
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue);
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const std::stack<T, C>& stack);
-
-template <class T>
-size_t EstimateMemoryUsage(const base::circular_deque<T>& deque);
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const base::flat_set<T, C>& set);
-
-template <class K, class V, class C>
-size_t EstimateMemoryUsage(const base::flat_map<K, V, C>& map);
-
-template <class Key,
- class Payload,
- class HashOrComp,
- template <typename, typename, typename> class Map>
-size_t EstimateMemoryUsage(const MRUCacheBase<Key, Payload, HashOrComp, Map>&);
-
-// TODO(dskiba):
-// std::forward_list
-
-// Definitions
-
-namespace internal {
-
-// HasEMU<T>::value is true iff EstimateMemoryUsage(T) is available.
-// (This is the default version, which is false.)
-template <class T, class X = void>
-struct HasEMU : std::false_type {};
-
-// This HasEMU specialization is only picked up if there exists function
-// EstimateMemoryUsage(const T&) that returns size_t. Simpler ways to
-// achieve this don't work on MSVC.
-template <class T>
-struct HasEMU<
- T,
- typename std::enable_if<std::is_same<
- size_t,
- decltype(EstimateMemoryUsage(std::declval<const T&>()))>::value>::type>
- : std::true_type {};
-
-// EMUCaller<T> does three things:
-// 1. Defines Call() method that calls EstimateMemoryUsage(T) if it's
-// available.
-// 2. If EstimateMemoryUsage(T) is not available, but T has trivial dtor
-// (i.e. it's POD, integer, pointer, enum, etc.) then it defines Call()
-// method that returns 0. This is useful for containers, which allocate
-// memory regardless of T (also for cases like std::map<int, MyClass>).
-// 3. Finally, if EstimateMemoryUsage(T) is not available, then it triggers
-// a static_assert with a helpful message. That cuts numbers of errors
-// considerably - if you just call EstimateMemoryUsage(T) but it's not
-// available for T, then compiler will helpfully list *all* possible
-// variants of it, with an explanation for each.
-template <class T, class X = void>
-struct EMUCaller {
- // std::is_same<> below makes static_assert depend on T, in order to
- // prevent it from asserting regardless instantiation.
- static_assert(std::is_same<T, std::false_type>::value,
- "Neither global function 'size_t EstimateMemoryUsage(T)' "
- "nor member function 'size_t T::EstimateMemoryUsage() const' "
- "is defined for the type.");
-
- static size_t Call(const T&) { return 0; }
-};
-
-template <class T>
-struct EMUCaller<T, typename std::enable_if<HasEMU<T>::value>::type> {
- static size_t Call(const T& value) { return EstimateMemoryUsage(value); }
-};
-
-template <template <class...> class Container, class I, class = void>
-struct IsComplexIteratorForContainer : std::false_type {};
-
-template <template <class...> class Container, class I>
-struct IsComplexIteratorForContainer<
- Container,
- I,
- std::enable_if_t<!std::is_pointer<I>::value &&
- base::internal::is_iterator<I>::value>> {
- using value_type = typename std::iterator_traits<I>::value_type;
- using container_type = Container<value_type>;
-
- // We use enum instead of static constexpr bool, beause we don't have inline
- // variables until c++17.
- //
- // The downside is - value is not of type bool.
- enum : bool {
- value =
- std::is_same<typename container_type::iterator, I>::value ||
- std::is_same<typename container_type::const_iterator, I>::value ||
- std::is_same<typename container_type::reverse_iterator, I>::value ||
- std::is_same<typename container_type::const_reverse_iterator, I>::value,
- };
-};
-
-template <class I, template <class...> class... Containers>
-constexpr bool OneOfContainersComplexIterators() {
- // We are forced to create a temporary variable to workaround a compilation
- // error in msvs.
- const bool all_tests[] = {
- IsComplexIteratorForContainer<Containers, I>::value...};
- for (bool test : all_tests)
- if (test)
- return true;
- return false;
-}
-
-// std::array has an extra required template argument. We curry it.
-template <class T>
-using array_test_helper = std::array<T, 1>;
-
-template <class I>
-constexpr bool IsStandardContainerComplexIterator() {
- // TODO(dyaroshev): deal with maps iterators if there is a need.
- // It requires to parse pairs into keys and values.
- // TODO(dyaroshev): deal with unordered containers: they do not have reverse
- // iterators.
- return OneOfContainersComplexIterators<
- I, array_test_helper, std::vector, std::deque,
- /*std::forward_list,*/ std::list, std::set, std::multiset>();
-}
-
-// Work around MSVS bug. For some reason constexpr function doesn't work.
-// However variable template does.
-template <typename T>
-constexpr bool IsKnownNonAllocatingType_v =
- std::is_trivially_destructible<T>::value ||
- IsStandardContainerComplexIterator<T>();
-
-template <class T>
-struct EMUCaller<
- T,
- std::enable_if_t<!HasEMU<T>::value && IsKnownNonAllocatingType_v<T>>> {
- static size_t Call(const T& value) { return 0; }
-};
-
-} // namespace internal
-
-// Proxy that deducts T and calls EMUCaller<T>.
-// To be used by EstimateMemoryUsage() implementations for containers.
-template <class T>
-size_t EstimateItemMemoryUsage(const T& value) {
- return internal::EMUCaller<T>::Call(value);
-}
-
-template <class I>
-size_t EstimateIterableMemoryUsage(const I& iterable) {
- size_t memory_usage = 0;
- for (const auto& item : iterable) {
- memory_usage += EstimateItemMemoryUsage(item);
- }
- return memory_usage;
-}
-
-// Global EstimateMemoryUsage(T) that just calls T::EstimateMemoryUsage().
-template <class T>
-auto EstimateMemoryUsage(const T& object)
- -> decltype(object.EstimateMemoryUsage()) {
- static_assert(
- std::is_same<decltype(object.EstimateMemoryUsage()), size_t>::value,
- "'T::EstimateMemoryUsage() const' must return size_t.");
- return object.EstimateMemoryUsage();
-}
-
-// String
-
-template <class C, class T, class A>
-size_t EstimateMemoryUsage(const std::basic_string<C, T, A>& string) {
- using string_type = std::basic_string<C, T, A>;
- using value_type = typename string_type::value_type;
- // C++11 doesn't leave much room for implementors - std::string can
- // use short string optimization, but that's about it. We detect SSO
- // by checking that c_str() points inside |string|.
- const uint8_t* cstr = reinterpret_cast<const uint8_t*>(string.c_str());
- const uint8_t* inline_cstr = reinterpret_cast<const uint8_t*>(&string);
- if (cstr >= inline_cstr && cstr < inline_cstr + sizeof(string)) {
- // SSO string
- return 0;
- }
- return (string.capacity() + 1) * sizeof(value_type);
-}
-
-// Use explicit instantiations from the .cc file (reduces bloat).
-extern template BASE_EXPORT size_t EstimateMemoryUsage(const std::string&);
-extern template BASE_EXPORT size_t EstimateMemoryUsage(const string16&);
-
-// Arrays
-
-template <class T, size_t N>
-size_t EstimateMemoryUsage(const std::array<T, N>& array) {
- return EstimateIterableMemoryUsage(array);
-}
-
-template <class T, size_t N>
-size_t EstimateMemoryUsage(T (&array)[N]) {
- return EstimateIterableMemoryUsage(array);
-}
-
-template <class T>
-size_t EstimateMemoryUsage(const T* array, size_t array_length) {
- size_t memory_usage = sizeof(T) * array_length;
- for (size_t i = 0; i != array_length; ++i) {
- memory_usage += EstimateItemMemoryUsage(array[i]);
- }
- return memory_usage;
-}
-
-// std::unique_ptr
-
-template <class T, class D>
-size_t EstimateMemoryUsage(const std::unique_ptr<T, D>& ptr) {
- return ptr ? (sizeof(T) + EstimateItemMemoryUsage(*ptr)) : 0;
-}
-
-template <class T, class D>
-size_t EstimateMemoryUsage(const std::unique_ptr<T[], D>& array,
- size_t array_length) {
- return EstimateMemoryUsage(array.get(), array_length);
-}
-
-// std::shared_ptr
-
-template <class T>
-size_t EstimateMemoryUsage(const std::shared_ptr<T>& ptr) {
- auto use_count = ptr.use_count();
- if (use_count == 0) {
- return 0;
- }
- // Model shared_ptr after libc++,
- // see __shared_ptr_pointer from include/memory
- struct SharedPointer {
- void* vtbl;
- long shared_owners;
- long shared_weak_owners;
- T* value;
- };
- // If object of size S shared N > S times we prefer to (potentially)
- // overestimate than to return 0.
- return sizeof(SharedPointer) +
- (EstimateItemMemoryUsage(*ptr) + (use_count - 1)) / use_count;
-}
-
-// std::pair
-
-template <class F, class S>
-size_t EstimateMemoryUsage(const std::pair<F, S>& pair) {
- return EstimateItemMemoryUsage(pair.first) +
- EstimateItemMemoryUsage(pair.second);
-}
-
-// std::vector
-
-template <class T, class A>
-size_t EstimateMemoryUsage(const std::vector<T, A>& vector) {
- return sizeof(T) * vector.capacity() + EstimateIterableMemoryUsage(vector);
-}
-
-// std::list
-
-template <class T, class A>
-size_t EstimateMemoryUsage(const std::list<T, A>& list) {
- using value_type = typename std::list<T, A>::value_type;
- struct Node {
- Node* prev;
- Node* next;
- value_type value;
- };
- return sizeof(Node) * list.size() +
- EstimateIterableMemoryUsage(list);
-}
-
-template <class T>
-size_t EstimateMemoryUsage(const base::LinkedList<T>& list) {
- size_t memory_usage = 0u;
- for (base::LinkNode<T>* node = list.head(); node != list.end();
- node = node->next()) {
- // Since we increment by calling node = node->next() we know that node
- // isn't nullptr.
- memory_usage += EstimateMemoryUsage(*node->value()) + sizeof(T);
- }
- return memory_usage;
-}
-
-// Tree containers
-
-template <class V>
-size_t EstimateTreeMemoryUsage(size_t size) {
- // Tree containers are modeled after libc++
- // (__tree_node from include/__tree)
- struct Node {
- Node* left;
- Node* right;
- Node* parent;
- bool is_black;
- V value;
- };
- return sizeof(Node) * size;
-}
-
-template <class T, class C, class A>
-size_t EstimateMemoryUsage(const std::set<T, C, A>& set) {
- using value_type = typename std::set<T, C, A>::value_type;
- return EstimateTreeMemoryUsage<value_type>(set.size()) +
- EstimateIterableMemoryUsage(set);
-}
-
-template <class T, class C, class A>
-size_t EstimateMemoryUsage(const std::multiset<T, C, A>& set) {
- using value_type = typename std::multiset<T, C, A>::value_type;
- return EstimateTreeMemoryUsage<value_type>(set.size()) +
- EstimateIterableMemoryUsage(set);
-}
-
-template <class K, class V, class C, class A>
-size_t EstimateMemoryUsage(const std::map<K, V, C, A>& map) {
- using value_type = typename std::map<K, V, C, A>::value_type;
- return EstimateTreeMemoryUsage<value_type>(map.size()) +
- EstimateIterableMemoryUsage(map);
-}
-
-template <class K, class V, class C, class A>
-size_t EstimateMemoryUsage(const std::multimap<K, V, C, A>& map) {
- using value_type = typename std::multimap<K, V, C, A>::value_type;
- return EstimateTreeMemoryUsage<value_type>(map.size()) +
- EstimateIterableMemoryUsage(map);
-}
-
-// HashMap containers
-
-namespace internal {
-
-// While hashtable containers model doesn't depend on STL implementation, one
-// detail still crept in: bucket_count. It's used in size estimation, but its
-// value after inserting N items is not predictable.
-// This function is specialized by unittests to return constant value, thus
-// excluding bucket_count from testing.
-template <class V>
-size_t HashMapBucketCountForTesting(size_t bucket_count) {
- return bucket_count;
-}
-
-template <class MruCacheType>
-size_t DoEstimateMemoryUsageForMruCache(const MruCacheType& mru_cache) {
- return EstimateMemoryUsage(mru_cache.ordering_) +
- EstimateMemoryUsage(mru_cache.index_);
-}
-
-} // namespace internal
-
-template <class V>
-size_t EstimateHashMapMemoryUsage(size_t bucket_count, size_t size) {
- // Hashtable containers are modeled after libc++
- // (__hash_node from include/__hash_table)
- struct Node {
- void* next;
- size_t hash;
- V value;
- };
- using Bucket = void*;
- bucket_count = internal::HashMapBucketCountForTesting<V>(bucket_count);
- return sizeof(Bucket) * bucket_count + sizeof(Node) * size;
-}
-
-template <class K, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_set<K, H, KE, A>& set) {
- using value_type = typename std::unordered_set<K, H, KE, A>::value_type;
- return EstimateHashMapMemoryUsage<value_type>(set.bucket_count(),
- set.size()) +
- EstimateIterableMemoryUsage(set);
-}
-
-template <class K, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_multiset<K, H, KE, A>& set) {
- using value_type = typename std::unordered_multiset<K, H, KE, A>::value_type;
- return EstimateHashMapMemoryUsage<value_type>(set.bucket_count(),
- set.size()) +
- EstimateIterableMemoryUsage(set);
-}
-
-template <class K, class V, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_map<K, V, H, KE, A>& map) {
- using value_type = typename std::unordered_map<K, V, H, KE, A>::value_type;
- return EstimateHashMapMemoryUsage<value_type>(map.bucket_count(),
- map.size()) +
- EstimateIterableMemoryUsage(map);
-}
-
-template <class K, class V, class H, class KE, class A>
-size_t EstimateMemoryUsage(const std::unordered_multimap<K, V, H, KE, A>& map) {
- using value_type =
- typename std::unordered_multimap<K, V, H, KE, A>::value_type;
- return EstimateHashMapMemoryUsage<value_type>(map.bucket_count(),
- map.size()) +
- EstimateIterableMemoryUsage(map);
-}
-
-// std::deque
-
-template <class T, class A>
-size_t EstimateMemoryUsage(const std::deque<T, A>& deque) {
-// Since std::deque implementations are wildly different
-// (see crbug.com/674287), we can't have one "good enough"
-// way to estimate.
-
-// kBlockSize - minimum size of a block, in bytes
-// kMinBlockLength - number of elements in a block
-// if sizeof(T) > kBlockSize
-#if defined(_LIBCPP_VERSION)
- size_t kBlockSize = 4096;
- size_t kMinBlockLength = 16;
-#elif defined(__GLIBCXX__)
- size_t kBlockSize = 512;
- size_t kMinBlockLength = 1;
-#elif defined(_MSC_VER)
- size_t kBlockSize = 16;
- size_t kMinBlockLength = 1;
-#else
- size_t kBlockSize = 0;
- size_t kMinBlockLength = 1;
-#endif
-
- size_t block_length =
- (sizeof(T) > kBlockSize) ? kMinBlockLength : kBlockSize / sizeof(T);
-
- size_t blocks = (deque.size() + block_length - 1) / block_length;
-
-#if defined(__GLIBCXX__)
- // libstdc++: deque always has at least one block
- if (!blocks)
- blocks = 1;
-#endif
-
-#if defined(_LIBCPP_VERSION)
- // libc++: deque keeps at most two blocks when it shrinks,
- // so even if the size is zero, deque might be holding up
- // to 4096 * 2 bytes. One way to know whether deque has
- // ever allocated (and hence has 1 or 2 blocks) is to check
- // iterator's pointer. Non-zero value means that deque has
- // at least one block.
- if (!blocks && deque.begin().operator->())
- blocks = 1;
-#endif
-
- return (blocks * block_length * sizeof(T)) +
- EstimateIterableMemoryUsage(deque);
-}
-
-// Container adapters
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const std::queue<T, C>& queue) {
- return EstimateMemoryUsage(GetUnderlyingContainer(queue));
-}
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const std::priority_queue<T, C>& queue) {
- return EstimateMemoryUsage(GetUnderlyingContainer(queue));
-}
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const std::stack<T, C>& stack) {
- return EstimateMemoryUsage(GetUnderlyingContainer(stack));
-}
-
-// base::circular_deque
-
-template <class T>
-size_t EstimateMemoryUsage(const base::circular_deque<T>& deque) {
- return sizeof(T) * deque.capacity() + EstimateIterableMemoryUsage(deque);
-}
-
-// Flat containers
-
-template <class T, class C>
-size_t EstimateMemoryUsage(const base::flat_set<T, C>& set) {
- using value_type = typename base::flat_set<T, C>::value_type;
- return sizeof(value_type) * set.capacity() + EstimateIterableMemoryUsage(set);
-}
-
-template <class K, class V, class C>
-size_t EstimateMemoryUsage(const base::flat_map<K, V, C>& map) {
- using value_type = typename base::flat_map<K, V, C>::value_type;
- return sizeof(value_type) * map.capacity() + EstimateIterableMemoryUsage(map);
-}
-
-template <class Key,
- class Payload,
- class HashOrComp,
- template <typename, typename, typename> class Map>
-size_t EstimateMemoryUsage(
- const MRUCacheBase<Key, Payload, HashOrComp, Map>& mru_cache) {
- return internal::DoEstimateMemoryUsageForMruCache(mru_cache);
-}
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_MEMORY_USAGE_ESTIMATOR_H_
diff --git a/base/trace_event/memory_usage_estimator_unittest.cc b/base/trace_event/memory_usage_estimator_unittest.cc
deleted file mode 100644
index b525990257..0000000000
--- a/base/trace_event/memory_usage_estimator_unittest.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2016 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/trace_event/memory_usage_estimator.h"
-
-#include <stdlib.h>
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/string16.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(ARCH_CPU_64_BITS)
-#define EXPECT_EQ_32_64(_, e, a) EXPECT_EQ(e, a)
-#else
-#define EXPECT_EQ_32_64(e, _, a) EXPECT_EQ(e, a)
-#endif
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// Test class with predictable memory usage.
-class Data {
- public:
- explicit Data(size_t size = 17): size_(size) {
- }
-
- size_t size() const { return size_; }
-
- size_t EstimateMemoryUsage() const {
- return size_;
- }
-
- bool operator < (const Data& other) const {
- return size_ < other.size_;
- }
- bool operator == (const Data& other) const {
- return size_ == other.size_;
- }
-
- struct Hasher {
- size_t operator () (const Data& data) const {
- return data.size();
- }
- };
-
- private:
- size_t size_;
-};
-
-} // namespace
-
-namespace internal {
-
-// This kills variance of bucket_count across STL implementations.
-template <>
-size_t HashMapBucketCountForTesting<Data>(size_t) {
- return 10;
-}
-template <>
-size_t HashMapBucketCountForTesting<std::pair<const Data, short>>(size_t) {
- return 10;
-}
-
-} // namespace internal
-
-TEST(EstimateMemoryUsageTest, String) {
- std::string string(777, 'a');
- EXPECT_EQ(string.capacity() + 1, EstimateMemoryUsage(string));
-}
-
-TEST(EstimateMemoryUsageTest, String16) {
- string16 string(777, 'a');
- EXPECT_EQ(sizeof(char16) * (string.capacity() + 1),
- EstimateMemoryUsage(string));
-}
-
-TEST(EstimateMemoryUsageTest, Arrays) {
- // std::array
- {
- std::array<Data, 10> array;
- EXPECT_EQ(170u, EstimateMemoryUsage(array));
- }
-
- // T[N]
- {
- Data array[10];
- EXPECT_EQ(170u, EstimateMemoryUsage(array));
- }
-
- // C array
- {
- struct Item {
- char payload[10];
- };
- Item* array = new Item[7];
- EXPECT_EQ(70u, EstimateMemoryUsage(array, 7));
- delete[] array;
- }
-}
-
-TEST(EstimateMemoryUsageTest, UniquePtr) {
- // Empty
- {
- std::unique_ptr<Data> ptr;
- EXPECT_EQ(0u, EstimateMemoryUsage(ptr));
- }
-
- // Not empty
- {
- std::unique_ptr<Data> ptr(new Data());
- EXPECT_EQ_32_64(21u, 25u, EstimateMemoryUsage(ptr));
- }
-
- // With a pointer
- {
- std::unique_ptr<Data*> ptr(new Data*());
- EXPECT_EQ(sizeof(void*), EstimateMemoryUsage(ptr));
- }
-
- // With an array
- {
- struct Item {
- uint32_t payload[10];
- };
- std::unique_ptr<Item[]> ptr(new Item[7]);
- EXPECT_EQ(280u, EstimateMemoryUsage(ptr, 7));
- }
-}
-
-TEST(EstimateMemoryUsageTest, Vector) {
- std::vector<Data> vector;
- vector.reserve(1000);
-
- // For an empty vector we should return memory usage of its buffer
- size_t capacity = vector.capacity();
- size_t expected_size = capacity * sizeof(Data);
- EXPECT_EQ(expected_size, EstimateMemoryUsage(vector));
-
- // If vector is not empty, its size should also include memory usages
- // of all elements.
- for (size_t i = 0; i != capacity / 2; ++i) {
- vector.push_back(Data(i));
- expected_size += EstimateMemoryUsage(vector.back());
- }
- EXPECT_EQ(expected_size, EstimateMemoryUsage(vector));
-}
-
-TEST(EstimateMemoryUsageTest, List) {
- struct POD {
- short data;
- };
- std::list<POD> list;
- for (int i = 0; i != 1000; ++i) {
- list.push_back(POD());
- }
- EXPECT_EQ_32_64(12000u, 24000u, EstimateMemoryUsage(list));
-}
-
-TEST(EstimateMemoryUsageTest, Set) {
- std::set<std::pair<int, Data>> set;
- for (int i = 0; i != 1000; ++i) {
- set.insert({i, Data(i)});
- }
- EXPECT_EQ_32_64(523500u, 547500u, EstimateMemoryUsage(set));
-}
-
-TEST(EstimateMemoryUsageTest, MultiSet) {
- std::multiset<bool> set;
- for (int i = 0; i != 1000; ++i) {
- set.insert((i & 1) != 0);
- }
- EXPECT_EQ_32_64(16000u, 32000u, EstimateMemoryUsage(set));
-}
-
-TEST(EstimateMemoryUsageTest, Map) {
- std::map<Data, int> map;
- for (int i = 0; i != 1000; ++i) {
- map.insert({Data(i), i});
- }
- EXPECT_EQ_32_64(523500u, 547500u, EstimateMemoryUsage(map));
-}
-
-TEST(EstimateMemoryUsageTest, MultiMap) {
- std::multimap<char, Data> map;
- for (int i = 0; i != 1000; ++i) {
- map.insert({static_cast<char>(i), Data(i)});
- }
- EXPECT_EQ_32_64(523500u, 547500u, EstimateMemoryUsage(map));
-}
-
-TEST(EstimateMemoryUsageTest, UnorderedSet) {
- std::unordered_set<Data, Data::Hasher> set;
- for (int i = 0; i != 1000; ++i) {
- set.insert(Data(i));
- }
- EXPECT_EQ_32_64(511540u, 523580u, EstimateMemoryUsage(set));
-}
-
-TEST(EstimateMemoryUsageTest, UnorderedMultiSet) {
- std::unordered_multiset<Data, Data::Hasher> set;
- for (int i = 0; i != 500; ++i) {
- set.insert(Data(i));
- set.insert(Data(i));
- }
- EXPECT_EQ_32_64(261540u, 273580u, EstimateMemoryUsage(set));
-}
-
-TEST(EstimateMemoryUsageTest, UnorderedMap) {
- std::unordered_map<Data, short, Data::Hasher> map;
- for (int i = 0; i != 1000; ++i) {
- map.insert({Data(i), static_cast<short>(i)});
- }
- EXPECT_EQ_32_64(515540u, 531580u, EstimateMemoryUsage(map));
-}
-
-TEST(EstimateMemoryUsageTest, UnorderedMultiMap) {
- std::unordered_multimap<Data, short, Data::Hasher> map;
- for (int i = 0; i != 1000; ++i) {
- map.insert({Data(i), static_cast<short>(i)});
- }
- EXPECT_EQ_32_64(515540u, 531580u, EstimateMemoryUsage(map));
-}
-
-TEST(EstimateMemoryUsageTest, Deque) {
- std::deque<Data> deque;
-
- // Pick a large value so that platform-specific accounting
- // for deque's blocks is small compared to usage of all items.
- constexpr size_t kDataSize = 100000;
- for (int i = 0; i != 1500; ++i) {
- deque.push_back(Data(kDataSize));
- }
-
- // Compare against a reasonable minimum (i.e. no overhead).
- size_t min_expected_usage = deque.size() * (sizeof(Data) + kDataSize);
- EXPECT_LE(min_expected_usage, EstimateMemoryUsage(deque));
-}
-
-TEST(EstimateMemoryUsageTest, IsStandardContainerComplexIteratorTest) {
- struct abstract {
- virtual void method() = 0;
- };
-
- static_assert(
- internal::IsStandardContainerComplexIterator<std::list<int>::iterator>(),
- "");
- static_assert(internal::IsStandardContainerComplexIterator<
- std::list<int>::const_iterator>(),
- "");
- static_assert(internal::IsStandardContainerComplexIterator<
- std::list<int>::reverse_iterator>(),
- "");
- static_assert(internal::IsStandardContainerComplexIterator<
- std::list<int>::const_reverse_iterator>(),
- "");
- static_assert(!internal::IsStandardContainerComplexIterator<int>(), "");
- static_assert(!internal::IsStandardContainerComplexIterator<abstract*>(), "");
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc
deleted file mode 100644
index 362641c400..0000000000
--- a/base/trace_event/process_memory_dump.cc
+++ /dev/null
@@ -1,511 +0,0 @@
-// Copyright 2015 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/trace_event/process_memory_dump.h"
-
-#include <errno.h>
-
-#include <vector>
-
-#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory_tracker.h"
-#include "base/process/process_metrics.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/memory_infra_background_whitelist.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/unguessable_token.h"
-#include "build/build_config.h"
-
-#if defined(OS_IOS)
-#include <mach/vm_page_size.h>
-#endif
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include <sys/mman.h>
-#endif
-
-#if defined(OS_WIN)
-#include <windows.h> // Must be in front of other Windows header files
-
-#include <Psapi.h>
-#endif
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-const char kEdgeTypeOwnership[] = "ownership";
-
-std::string GetSharedGlobalAllocatorDumpName(
- const MemoryAllocatorDumpGuid& guid) {
- return "global/" + guid.ToString();
-}
-
-#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
-size_t GetSystemPageCount(size_t mapped_size, size_t page_size) {
- return (mapped_size + page_size - 1) / page_size;
-}
-#endif
-
-UnguessableToken GetTokenForCurrentProcess() {
- static UnguessableToken instance = UnguessableToken::Create();
- return instance;
-}
-
-} // namespace
-
-// static
-bool ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = false;
-
-#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
-// static
-size_t ProcessMemoryDump::GetSystemPageSize() {
-#if defined(OS_IOS)
- // On iOS, getpagesize() returns the user page sizes, but for allocating
- // arrays for mincore(), kernel page sizes is needed. Use vm_kernel_page_size
- // as recommended by Apple, https://forums.developer.apple.com/thread/47532/.
- // Refer to http://crbug.com/542671 and Apple rdar://23651782
- return vm_kernel_page_size;
-#else
- return base::GetPageSize();
-#endif // defined(OS_IOS)
-}
-
-// static
-size_t ProcessMemoryDump::CountResidentBytes(void* start_address,
- size_t mapped_size) {
- const size_t page_size = GetSystemPageSize();
- const uintptr_t start_pointer = reinterpret_cast<uintptr_t>(start_address);
- DCHECK_EQ(0u, start_pointer % page_size);
-
- size_t offset = 0;
- size_t total_resident_pages = 0;
- bool failure = false;
-
- // An array as large as number of pages in memory segment needs to be passed
- // to the query function. To avoid allocating a large array, the given block
- // of memory is split into chunks of size |kMaxChunkSize|.
- const size_t kMaxChunkSize = 8 * 1024 * 1024;
- size_t max_vec_size =
- GetSystemPageCount(std::min(mapped_size, kMaxChunkSize), page_size);
-#if defined(OS_WIN)
- std::unique_ptr<PSAPI_WORKING_SET_EX_INFORMATION[]> vec(
- new PSAPI_WORKING_SET_EX_INFORMATION[max_vec_size]);
-#elif defined(OS_MACOSX)
- std::unique_ptr<char[]> vec(new char[max_vec_size]);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- std::unique_ptr<unsigned char[]> vec(new unsigned char[max_vec_size]);
-#endif
-
- while (offset < mapped_size) {
- uintptr_t chunk_start = (start_pointer + offset);
- const size_t chunk_size = std::min(mapped_size - offset, kMaxChunkSize);
- const size_t page_count = GetSystemPageCount(chunk_size, page_size);
- size_t resident_page_count = 0;
-#if defined(OS_WIN)
- for (size_t i = 0; i < page_count; i++) {
- vec[i].VirtualAddress =
- reinterpret_cast<void*>(chunk_start + i * page_size);
- }
- DWORD vec_size = static_cast<DWORD>(
- page_count * sizeof(PSAPI_WORKING_SET_EX_INFORMATION));
- failure = !QueryWorkingSetEx(GetCurrentProcess(), vec.get(), vec_size);
-
- for (size_t i = 0; i < page_count; i++)
- resident_page_count += vec[i].VirtualAttributes.Valid;
-#elif defined(OS_FUCHSIA)
- // TODO(fuchsia): Port, see https://crbug.com/706592.
- ALLOW_UNUSED_LOCAL(chunk_start);
- ALLOW_UNUSED_LOCAL(page_count);
-#elif defined(OS_MACOSX)
- // mincore in MAC does not fail with EAGAIN.
- failure =
- !!mincore(reinterpret_cast<void*>(chunk_start), chunk_size, vec.get());
- for (size_t i = 0; i < page_count; i++)
- resident_page_count += vec[i] & MINCORE_INCORE ? 1 : 0;
-#elif defined(OS_POSIX)
- int error_counter = 0;
- int result = 0;
- // HANDLE_EINTR tries for 100 times. So following the same pattern.
- do {
- result =
-#if defined(OS_AIX)
- mincore(reinterpret_cast<char*>(chunk_start), chunk_size,
- reinterpret_cast<char*>(vec.get()));
-#else
- mincore(reinterpret_cast<void*>(chunk_start), chunk_size, vec.get());
-#endif
- } while (result == -1 && errno == EAGAIN && error_counter++ < 100);
- failure = !!result;
-
- for (size_t i = 0; i < page_count; i++)
- resident_page_count += vec[i] & 1;
-#endif
-
- if (failure)
- break;
-
- total_resident_pages += resident_page_count * page_size;
- offset += kMaxChunkSize;
- }
-
- DCHECK(!failure);
- if (failure) {
- total_resident_pages = 0;
- LOG(ERROR) << "CountResidentBytes failed. The resident size is invalid";
- }
- return total_resident_pages;
-}
-
-// static
-base::Optional<size_t> ProcessMemoryDump::CountResidentBytesInSharedMemory(
- void* start_address,
- size_t mapped_size) {
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- // On macOS, use mach_vm_region instead of mincore for performance
- // (crbug.com/742042).
- mach_vm_size_t dummy_size = 0;
- mach_vm_address_t address =
- reinterpret_cast<mach_vm_address_t>(start_address);
- vm_region_top_info_data_t info;
- MachVMRegionResult result =
- GetTopInfo(mach_task_self(), &dummy_size, &address, &info);
- if (result == MachVMRegionResult::Error) {
- LOG(ERROR) << "CountResidentBytesInSharedMemory failed. The resident size "
- "is invalid";
- return base::Optional<size_t>();
- }
-
- size_t resident_pages =
- info.private_pages_resident + info.shared_pages_resident;
-
- // On macOS, measurements for private memory footprint overcount by
- // faulted pages in anonymous shared memory. To discount for this, we touch
- // all the resident pages in anonymous shared memory here, thus making them
- // faulted as well. This relies on two assumptions:
- //
- // 1) Consumers use shared memory from front to back. Thus, if there are
- // (N) resident pages, those pages represent the first N * PAGE_SIZE bytes in
- // the shared memory region.
- //
- // 2) This logic is run shortly before the logic that calculates
- // phys_footprint, thus ensuring that the discrepancy between faulted and
- // resident pages is minimal.
- //
- // The performance penalty is expected to be small.
- //
- // * Most of the time, we expect the pages to already be resident and faulted,
- // thus incurring a cache penalty read hit [since we read from each resident
- // page].
- //
- // * Rarely, we expect the pages to be resident but not faulted, resulting in
- // soft faults + cache penalty.
- //
- // * If assumption (1) is invalid, this will potentially fault some
- // previously non-resident pages, thus increasing memory usage, without fixing
- // the accounting.
- //
- // Sanity check in case the mapped size is less than the total size of the
- // region.
- size_t pages_to_fault =
- std::min(resident_pages, (mapped_size + PAGE_SIZE - 1) / PAGE_SIZE);
-
- volatile char* base_address = static_cast<char*>(start_address);
- for (size_t i = 0; i < pages_to_fault; ++i) {
- // Reading from a volatile is a visible side-effect for the purposes of
- // optimization. This guarantees that the optimizer will not kill this line.
- base_address[i * PAGE_SIZE];
- }
-
- return resident_pages * PAGE_SIZE;
-#else
- return CountResidentBytes(start_address, mapped_size);
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
-}
-
-#endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED)
-
-ProcessMemoryDump::ProcessMemoryDump(
- const MemoryDumpArgs& dump_args)
- : process_token_(GetTokenForCurrentProcess()),
- dump_args_(dump_args) {}
-
-ProcessMemoryDump::~ProcessMemoryDump() = default;
-ProcessMemoryDump::ProcessMemoryDump(ProcessMemoryDump&& other) = default;
-ProcessMemoryDump& ProcessMemoryDump::operator=(ProcessMemoryDump&& other) =
- default;
-
-MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
- const std::string& absolute_name) {
- return AddAllocatorDumpInternal(std::make_unique<MemoryAllocatorDump>(
- absolute_name, dump_args_.level_of_detail, GetDumpId(absolute_name)));
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump(
- const std::string& absolute_name,
- const MemoryAllocatorDumpGuid& guid) {
- return AddAllocatorDumpInternal(std::make_unique<MemoryAllocatorDump>(
- absolute_name, dump_args_.level_of_detail, guid));
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::AddAllocatorDumpInternal(
- std::unique_ptr<MemoryAllocatorDump> mad) {
- // In background mode return the black hole dump, if invalid dump name is
- // given.
- if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND &&
- !IsMemoryAllocatorDumpNameWhitelisted(mad->absolute_name())) {
- return GetBlackHoleMad();
- }
-
- auto insertion_result = allocator_dumps_.insert(
- std::make_pair(mad->absolute_name(), std::move(mad)));
- MemoryAllocatorDump* inserted_mad = insertion_result.first->second.get();
- DCHECK(insertion_result.second) << "Duplicate name: "
- << inserted_mad->absolute_name();
- return inserted_mad;
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump(
- const std::string& absolute_name) const {
- auto it = allocator_dumps_.find(absolute_name);
- if (it != allocator_dumps_.end())
- return it->second.get();
- return nullptr;
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::GetOrCreateAllocatorDump(
- const std::string& absolute_name) {
- MemoryAllocatorDump* mad = GetAllocatorDump(absolute_name);
- return mad ? mad : CreateAllocatorDump(absolute_name);
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::CreateSharedGlobalAllocatorDump(
- const MemoryAllocatorDumpGuid& guid) {
- // A shared allocator dump can be shared within a process and the guid could
- // have been created already.
- MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid);
- if (mad && mad != black_hole_mad_.get()) {
- // The weak flag is cleared because this method should create a non-weak
- // dump.
- mad->clear_flags(MemoryAllocatorDump::Flags::WEAK);
- return mad;
- }
- return CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid);
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::CreateWeakSharedGlobalAllocatorDump(
- const MemoryAllocatorDumpGuid& guid) {
- MemoryAllocatorDump* mad = GetSharedGlobalAllocatorDump(guid);
- if (mad && mad != black_hole_mad_.get())
- return mad;
- mad = CreateAllocatorDump(GetSharedGlobalAllocatorDumpName(guid), guid);
- mad->set_flags(MemoryAllocatorDump::Flags::WEAK);
- return mad;
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::GetSharedGlobalAllocatorDump(
- const MemoryAllocatorDumpGuid& guid) const {
- return GetAllocatorDump(GetSharedGlobalAllocatorDumpName(guid));
-}
-
-void ProcessMemoryDump::DumpHeapUsage(
- const std::unordered_map<base::trace_event::AllocationContext,
- base::trace_event::AllocationMetrics>&
- metrics_by_context,
- base::trace_event::TraceEventMemoryOverhead& overhead,
- const char* allocator_name) {
- std::string base_name = base::StringPrintf("tracing/heap_profiler_%s",
- allocator_name);
- overhead.DumpInto(base_name.c_str(), this);
-}
-
-void ProcessMemoryDump::SetAllocatorDumpsForSerialization(
- std::vector<std::unique_ptr<MemoryAllocatorDump>> dumps) {
- DCHECK(allocator_dumps_.empty());
- for (std::unique_ptr<MemoryAllocatorDump>& dump : dumps)
- AddAllocatorDumpInternal(std::move(dump));
-}
-
-std::vector<ProcessMemoryDump::MemoryAllocatorDumpEdge>
-ProcessMemoryDump::GetAllEdgesForSerialization() const {
- std::vector<MemoryAllocatorDumpEdge> edges;
- edges.reserve(allocator_dumps_edges_.size());
- for (const auto& it : allocator_dumps_edges_)
- edges.push_back(it.second);
- return edges;
-}
-
-void ProcessMemoryDump::SetAllEdgesForSerialization(
- const std::vector<ProcessMemoryDump::MemoryAllocatorDumpEdge>& edges) {
- DCHECK(allocator_dumps_edges_.empty());
- for (const MemoryAllocatorDumpEdge& edge : edges) {
- auto it_and_inserted = allocator_dumps_edges_.emplace(edge.source, edge);
- DCHECK(it_and_inserted.second);
- }
-}
-
-void ProcessMemoryDump::Clear() {
- allocator_dumps_.clear();
- allocator_dumps_edges_.clear();
-}
-
-void ProcessMemoryDump::TakeAllDumpsFrom(ProcessMemoryDump* other) {
- // Moves the ownership of all MemoryAllocatorDump(s) contained in |other|
- // into this ProcessMemoryDump, checking for duplicates.
- for (auto& it : other->allocator_dumps_)
- AddAllocatorDumpInternal(std::move(it.second));
- other->allocator_dumps_.clear();
-
- // Move all the edges.
- allocator_dumps_edges_.insert(other->allocator_dumps_edges_.begin(),
- other->allocator_dumps_edges_.end());
- other->allocator_dumps_edges_.clear();
-}
-
-void ProcessMemoryDump::SerializeAllocatorDumpsInto(TracedValue* value) const {
- if (allocator_dumps_.size() > 0) {
- value->BeginDictionary("allocators");
- for (const auto& allocator_dump_it : allocator_dumps_)
- allocator_dump_it.second->AsValueInto(value);
- value->EndDictionary();
- }
-
- value->BeginArray("allocators_graph");
- for (const auto& it : allocator_dumps_edges_) {
- const MemoryAllocatorDumpEdge& edge = it.second;
- value->BeginDictionary();
- value->SetString("source", edge.source.ToString());
- value->SetString("target", edge.target.ToString());
- value->SetInteger("importance", edge.importance);
- value->SetString("type", kEdgeTypeOwnership);
- value->EndDictionary();
- }
- value->EndArray();
-}
-
-void ProcessMemoryDump::AddOwnershipEdge(const MemoryAllocatorDumpGuid& source,
- const MemoryAllocatorDumpGuid& target,
- int importance) {
- // This will either override an existing edge or create a new one.
- auto it = allocator_dumps_edges_.find(source);
- int max_importance = importance;
- if (it != allocator_dumps_edges_.end()) {
- DCHECK_EQ(target.ToUint64(), it->second.target.ToUint64());
- max_importance = std::max(importance, it->second.importance);
- }
- allocator_dumps_edges_[source] = {source, target, max_importance,
- false /* overridable */};
-}
-
-void ProcessMemoryDump::AddOwnershipEdge(
- const MemoryAllocatorDumpGuid& source,
- const MemoryAllocatorDumpGuid& target) {
- AddOwnershipEdge(source, target, 0 /* importance */);
-}
-
-void ProcessMemoryDump::AddOverridableOwnershipEdge(
- const MemoryAllocatorDumpGuid& source,
- const MemoryAllocatorDumpGuid& target,
- int importance) {
- if (allocator_dumps_edges_.count(source) == 0) {
- allocator_dumps_edges_[source] = {source, target, importance,
- true /* overridable */};
- } else {
- // An edge between the source and target already exits. So, do nothing here
- // since the new overridable edge is implicitly overridden by a strong edge
- // which was created earlier.
- DCHECK(!allocator_dumps_edges_[source].overridable);
- }
-}
-
-void ProcessMemoryDump::CreateSharedMemoryOwnershipEdge(
- const MemoryAllocatorDumpGuid& client_local_dump_guid,
- const UnguessableToken& shared_memory_guid,
- int importance) {
- CreateSharedMemoryOwnershipEdgeInternal(client_local_dump_guid,
- shared_memory_guid, importance,
- false /*is_weak*/);
-}
-
-void ProcessMemoryDump::CreateWeakSharedMemoryOwnershipEdge(
- const MemoryAllocatorDumpGuid& client_local_dump_guid,
- const UnguessableToken& shared_memory_guid,
- int importance) {
- CreateSharedMemoryOwnershipEdgeInternal(
- client_local_dump_guid, shared_memory_guid, importance, true /*is_weak*/);
-}
-
-void ProcessMemoryDump::CreateSharedMemoryOwnershipEdgeInternal(
- const MemoryAllocatorDumpGuid& client_local_dump_guid,
- const UnguessableToken& shared_memory_guid,
- int importance,
- bool is_weak) {
- DCHECK(!shared_memory_guid.is_empty());
- // New model where the global dumps created by SharedMemoryTracker are used
- // for the clients.
-
- // The guid of the local dump created by SharedMemoryTracker for the memory
- // segment.
- auto local_shm_guid =
- GetDumpId(SharedMemoryTracker::GetDumpNameForTracing(shared_memory_guid));
-
- // The dump guid of the global dump created by the tracker for the memory
- // segment.
- auto global_shm_guid =
- SharedMemoryTracker::GetGlobalDumpIdForTracing(shared_memory_guid);
-
- // Create an edge between local dump of the client and the local dump of the
- // SharedMemoryTracker. Do not need to create the dumps here since the tracker
- // would create them. The importance is also required here for the case of
- // single process mode.
- AddOwnershipEdge(client_local_dump_guid, local_shm_guid, importance);
-
- // TODO(ssid): Handle the case of weak dumps here. This needs a new function
- // GetOrCreaetGlobalDump() in PMD since we need to change the behavior of the
- // created global dump.
- // Create an edge that overrides the edge created by SharedMemoryTracker.
- AddOwnershipEdge(local_shm_guid, global_shm_guid, importance);
-}
-
-void ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source,
- const std::string& target_node_name) {
- // Do not create new dumps for suballocations in background mode.
- if (dump_args_.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND)
- return;
-
- std::string child_mad_name = target_node_name + "/__" + source.ToString();
- MemoryAllocatorDump* target_child_mad = CreateAllocatorDump(child_mad_name);
- AddOwnershipEdge(source, target_child_mad->guid());
-}
-
-MemoryAllocatorDump* ProcessMemoryDump::GetBlackHoleMad() {
- DCHECK(is_black_hole_non_fatal_for_testing_);
- if (!black_hole_mad_) {
- std::string name = "discarded";
- black_hole_mad_.reset(new MemoryAllocatorDump(
- name, dump_args_.level_of_detail, GetDumpId(name)));
- }
- return black_hole_mad_.get();
-}
-
-MemoryAllocatorDumpGuid ProcessMemoryDump::GetDumpId(
- const std::string& absolute_name) {
- return MemoryAllocatorDumpGuid(StringPrintf(
- "%s:%s", process_token().ToString().c_str(), absolute_name.c_str()));
-}
-
-bool ProcessMemoryDump::MemoryAllocatorDumpEdge::operator==(
- const MemoryAllocatorDumpEdge& other) const {
- return source == other.source && target == other.target &&
- importance == other.importance && overridable == other.overridable;
-}
-
-bool ProcessMemoryDump::MemoryAllocatorDumpEdge::operator!=(
- const MemoryAllocatorDumpEdge& other) const {
- return !(*this == other);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h
deleted file mode 100644
index e2457b7389..0000000000
--- a/base/trace_event/process_memory_dump.h
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
-#define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <unordered_map>
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#include "base/trace_event/memory_allocator_dump.h"
-#include "base/trace_event/memory_allocator_dump_guid.h"
-#include "base/trace_event/memory_dump_request_args.h"
-#include "build/build_config.h"
-
-// Define COUNT_RESIDENT_BYTES_SUPPORTED if platform supports counting of the
-// resident memory.
-#if !defined(OS_NACL)
-#define COUNT_RESIDENT_BYTES_SUPPORTED
-#endif
-
-namespace base {
-
-class SharedMemory;
-class UnguessableToken;
-
-namespace trace_event {
-
-class TracedValue;
-
-// ProcessMemoryDump is as a strongly typed container which holds the dumps
-// produced by the MemoryDumpProvider(s) for a specific process.
-class BASE_EXPORT ProcessMemoryDump {
- public:
- struct BASE_EXPORT MemoryAllocatorDumpEdge {
- bool operator==(const MemoryAllocatorDumpEdge&) const;
- bool operator!=(const MemoryAllocatorDumpEdge&) const;
-
- MemoryAllocatorDumpGuid source;
- MemoryAllocatorDumpGuid target;
- int importance = 0;
- bool overridable = false;
- };
-
- // Maps allocator dumps absolute names (allocator_name/heap/subheap) to
- // MemoryAllocatorDump instances.
- using AllocatorDumpsMap =
- std::map<std::string, std::unique_ptr<MemoryAllocatorDump>>;
-
- // Stores allocator dump edges indexed by source allocator dump GUID.
- using AllocatorDumpEdgesMap =
- std::map<MemoryAllocatorDumpGuid, MemoryAllocatorDumpEdge>;
-
-#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
- // Returns the number of bytes in a kernel memory page. Some platforms may
- // have a different value for kernel page sizes from user page sizes. It is
- // important to use kernel memory page sizes for resident bytes calculation.
- // In most cases, the two are the same.
- static size_t GetSystemPageSize();
-
- // Returns the total bytes resident for a virtual address range, with given
- // |start_address| and |mapped_size|. |mapped_size| is specified in bytes. The
- // value returned is valid only if the given range is currently mmapped by the
- // process. The |start_address| must be page-aligned.
- static size_t CountResidentBytes(void* start_address, size_t mapped_size);
-
- // The same as above, but the given mapped range should belong to the
- // shared_memory's mapped region.
- static base::Optional<size_t> CountResidentBytesInSharedMemory(
- void* start_address,
- size_t mapped_size);
-#endif
-
- explicit ProcessMemoryDump(const MemoryDumpArgs& dump_args);
- ProcessMemoryDump(ProcessMemoryDump&&);
- ~ProcessMemoryDump();
-
- ProcessMemoryDump& operator=(ProcessMemoryDump&&);
-
- // Creates a new MemoryAllocatorDump with the given name and returns the
- // empty object back to the caller.
- // Arguments:
- // absolute_name: a name that uniquely identifies allocator dumps produced
- // by this provider. It is possible to specify nesting by using a
- // path-like string (e.g., v8/isolate1/heap1, v8/isolate1/heap2).
- // Leading or trailing slashes are not allowed.
- // guid: an optional identifier, unique among all processes within the
- // scope of a global dump. This is only relevant when using
- // AddOwnershipEdge() to express memory sharing. If omitted,
- // it will be automatically generated.
- // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps.
- MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name);
- MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name,
- const MemoryAllocatorDumpGuid& guid);
-
- // Looks up a MemoryAllocatorDump given its allocator and heap names, or
- // nullptr if not found.
- MemoryAllocatorDump* GetAllocatorDump(const std::string& absolute_name) const;
-
- // Do NOT use this method. All dump providers should use
- // CreateAllocatorDump(). Tries to create a new MemoryAllocatorDump only if it
- // doesn't already exist. Creating multiple dumps with same name using
- // GetOrCreateAllocatorDump() would override the existing scalars in MAD and
- // cause misreporting. This method is used only in rare cases multiple
- // components create allocator dumps with same name and only one of them adds
- // size.
- MemoryAllocatorDump* GetOrCreateAllocatorDump(
- const std::string& absolute_name);
-
- // Creates a shared MemoryAllocatorDump, to express cross-process sharing.
- // Shared allocator dumps are allowed to have duplicate guids within the
- // global scope, in order to reference the same dump from multiple processes.
- // See the design doc goo.gl/keU6Bf for reference usage patterns.
- MemoryAllocatorDump* CreateSharedGlobalAllocatorDump(
- const MemoryAllocatorDumpGuid& guid);
-
- // Creates a shared MemoryAllocatorDump as CreateSharedGlobalAllocatorDump,
- // but with a WEAK flag. A weak dump will be discarded unless a non-weak dump
- // is created using CreateSharedGlobalAllocatorDump by at least one process.
- // The WEAK flag does not apply if a non-weak dump with the same GUID already
- // exists or is created later. All owners and children of the discarded dump
- // will also be discarded transitively.
- MemoryAllocatorDump* CreateWeakSharedGlobalAllocatorDump(
- const MemoryAllocatorDumpGuid& guid);
-
- // Looks up a shared MemoryAllocatorDump given its guid.
- MemoryAllocatorDump* GetSharedGlobalAllocatorDump(
- const MemoryAllocatorDumpGuid& guid) const;
-
- // Returns the map of the MemoryAllocatorDumps added to this dump.
- const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; }
-
- AllocatorDumpsMap* mutable_allocator_dumps_for_serialization() const {
- // Mojo takes a const input argument even for move-only types that can be
- // mutate while serializing (like this one). Hence the const_cast.
- return const_cast<AllocatorDumpsMap*>(&allocator_dumps_);
- }
- void SetAllocatorDumpsForSerialization(
- std::vector<std::unique_ptr<MemoryAllocatorDump>>);
-
- // Only for mojo serialization.
- std::vector<MemoryAllocatorDumpEdge> GetAllEdgesForSerialization() const;
- void SetAllEdgesForSerialization(const std::vector<MemoryAllocatorDumpEdge>&);
-
- // Dumps heap usage with |allocator_name|.
- void DumpHeapUsage(
- const std::unordered_map<base::trace_event::AllocationContext,
- base::trace_event::AllocationMetrics>&
- metrics_by_context,
- base::trace_event::TraceEventMemoryOverhead& overhead,
- const char* allocator_name);
-
- // Adds an ownership relationship between two MemoryAllocatorDump(s) with the
- // semantics: |source| owns |target|, and has the effect of attributing
- // the memory usage of |target| to |source|. |importance| is optional and
- // relevant only for the cases of co-ownership, where it acts as a z-index:
- // the owner with the highest importance will be attributed |target|'s memory.
- // If an edge is present, its importance will not be updated unless
- // |importance| is larger.
- void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source,
- const MemoryAllocatorDumpGuid& target,
- int importance);
- void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source,
- const MemoryAllocatorDumpGuid& target);
-
- // Adds edges that can be overriden by a later or earlier call to
- // AddOwnershipEdge() with the same source and target with a different
- // |importance| value.
- void AddOverridableOwnershipEdge(const MemoryAllocatorDumpGuid& source,
- const MemoryAllocatorDumpGuid& target,
- int importance);
-
- // Creates ownership edges for memory backed by base::SharedMemory. Handles
- // the case of cross process sharing and importnace of ownership for the case
- // with and without the base::SharedMemory dump provider. The new version
- // should just use global dumps created by SharedMemoryTracker and this
- // function handles the transition until we get SharedMemory IDs through mojo
- // channel crbug.com/713763. The weak version creates a weak global dump.
- // |client_local_dump_guid| The guid of the local dump created by the client
- // of base::SharedMemory.
- // |shared_memory_guid| The ID of the base::SharedMemory that is assigned
- // globally, used to create global dump edges in the new model.
- // |importance| Importance of the global dump edges to say if the current
- // process owns the memory segment.
- void CreateSharedMemoryOwnershipEdge(
- const MemoryAllocatorDumpGuid& client_local_dump_guid,
- const UnguessableToken& shared_memory_guid,
- int importance);
- void CreateWeakSharedMemoryOwnershipEdge(
- const MemoryAllocatorDumpGuid& client_local_dump_guid,
- const UnguessableToken& shared_memory_guid,
- int importance);
-
- const AllocatorDumpEdgesMap& allocator_dumps_edges() const {
- return allocator_dumps_edges_;
- }
-
- // Utility method to add a suballocation relationship with the following
- // semantics: |source| is suballocated from |target_node_name|.
- // This creates a child node of |target_node_name| and adds an ownership edge
- // between |source| and the new child node. As a result, the UI will not
- // account the memory of |source| in the target node.
- void AddSuballocation(const MemoryAllocatorDumpGuid& source,
- const std::string& target_node_name);
-
- // Removes all the MemoryAllocatorDump(s) contained in this instance. This
- // ProcessMemoryDump can be safely reused as if it was new once this returns.
- void Clear();
-
- // Merges all MemoryAllocatorDump(s) contained in |other| inside this
- // ProcessMemoryDump, transferring their ownership to this instance.
- // |other| will be an empty ProcessMemoryDump after this method returns.
- // This is to allow dump providers to pre-populate ProcessMemoryDump instances
- // and later move their contents into the ProcessMemoryDump passed as argument
- // of the MemoryDumpProvider::OnMemoryDump(ProcessMemoryDump*) callback.
- void TakeAllDumpsFrom(ProcessMemoryDump* other);
-
- // Populate the traced value with information about the memory allocator
- // dumps.
- void SerializeAllocatorDumpsInto(TracedValue* value) const;
-
- const MemoryDumpArgs& dump_args() const { return dump_args_; }
-
- private:
- FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, BackgroundModeTest);
- FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, SharedMemoryOwnershipTest);
- FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, GuidsTest);
-
- MemoryAllocatorDump* AddAllocatorDumpInternal(
- std::unique_ptr<MemoryAllocatorDump> mad);
-
- // A per-process token, valid throughout all the lifetime of the current
- // process, used to disambiguate dumps with the same name generated in
- // different processes.
- const UnguessableToken& process_token() const { return process_token_; }
- void set_process_token_for_testing(UnguessableToken token) {
- process_token_ = token;
- };
-
- // Returns the Guid of the dump for the given |absolute_name| for
- // for the given process' token. |process_token| is used to disambiguate GUIDs
- // derived from the same name under different processes.
- MemoryAllocatorDumpGuid GetDumpId(const std::string& absolute_name);
-
- void CreateSharedMemoryOwnershipEdgeInternal(
- const MemoryAllocatorDumpGuid& client_local_dump_guid,
- const UnguessableToken& shared_memory_guid,
- int importance,
- bool is_weak);
-
- MemoryAllocatorDump* GetBlackHoleMad();
-
- UnguessableToken process_token_;
- AllocatorDumpsMap allocator_dumps_;
-
- // Keeps track of relationships between MemoryAllocatorDump(s).
- AllocatorDumpEdgesMap allocator_dumps_edges_;
-
- // Level of detail of the current dump.
- MemoryDumpArgs dump_args_;
-
- // This allocator dump is returned when an invalid dump is created in
- // background mode. The attributes of the dump are ignored and not added to
- // the trace.
- std::unique_ptr<MemoryAllocatorDump> black_hole_mad_;
-
- // When set to true, the DCHECK(s) for invalid dump creations on the
- // background mode are disabled for testing.
- static bool is_black_hole_non_fatal_for_testing_;
-
- DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_
diff --git a/base/trace_event/process_memory_dump_unittest.cc b/base/trace_event/process_memory_dump_unittest.cc
deleted file mode 100644
index d5f771d81b..0000000000
--- a/base/trace_event/process_memory_dump_unittest.cc
+++ /dev/null
@@ -1,565 +0,0 @@
-// Copyright 2015 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/trace_event/process_memory_dump.h"
-
-#include <stddef.h>
-
-#include "base/memory/aligned_memory.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/shared_memory_tracker.h"
-#include "base/process/process_metrics.h"
-#include "base/trace_event/memory_allocator_dump_guid.h"
-#include "base/trace_event/memory_infra_background_whitelist.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/trace_event/trace_log.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include "winbase.h"
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include <sys/mman.h>
-#endif
-
-#if defined(OS_IOS)
-#include "base/ios/ios_util.h"
-#endif
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-const MemoryDumpArgs kDetailedDumpArgs = {MemoryDumpLevelOfDetail::DETAILED};
-const char* const kTestDumpNameWhitelist[] = {
- "Whitelisted/TestName", "Whitelisted/TestName_0x?",
- "Whitelisted/0x?/TestName", "Whitelisted/0x?", nullptr};
-
-void* Map(size_t size) {
-#if defined(OS_WIN)
- return ::VirtualAlloc(nullptr, size, MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- return ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
- 0, 0);
-#endif
-}
-
-void Unmap(void* addr, size_t size) {
-#if defined(OS_WIN)
- ::VirtualFree(addr, 0, MEM_DECOMMIT);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- ::munmap(addr, size);
-#else
-#error This architecture is not (yet) supported.
-#endif
-}
-
-} // namespace
-
-TEST(ProcessMemoryDumpTest, MoveConstructor) {
- ProcessMemoryDump pmd1 = ProcessMemoryDump(kDetailedDumpArgs);
- pmd1.CreateAllocatorDump("mad1");
- pmd1.CreateAllocatorDump("mad2");
- pmd1.AddOwnershipEdge(MemoryAllocatorDumpGuid(42),
- MemoryAllocatorDumpGuid(4242));
-
- ProcessMemoryDump pmd2(std::move(pmd1));
-
- EXPECT_EQ(1u, pmd2.allocator_dumps().count("mad1"));
- EXPECT_EQ(1u, pmd2.allocator_dumps().count("mad2"));
- EXPECT_EQ(MemoryDumpLevelOfDetail::DETAILED,
- pmd2.dump_args().level_of_detail);
- EXPECT_EQ(1u, pmd2.allocator_dumps_edges().size());
-
- // Check that calling serialization routines doesn't cause a crash.
- auto traced_value = std::make_unique<TracedValue>();
- pmd2.SerializeAllocatorDumpsInto(traced_value.get());
-}
-
-TEST(ProcessMemoryDumpTest, MoveAssignment) {
- ProcessMemoryDump pmd1 = ProcessMemoryDump(kDetailedDumpArgs);
- pmd1.CreateAllocatorDump("mad1");
- pmd1.CreateAllocatorDump("mad2");
- pmd1.AddOwnershipEdge(MemoryAllocatorDumpGuid(42),
- MemoryAllocatorDumpGuid(4242));
-
- ProcessMemoryDump pmd2({MemoryDumpLevelOfDetail::BACKGROUND});
- pmd2.CreateAllocatorDump("malloc");
-
- pmd2 = std::move(pmd1);
- EXPECT_EQ(1u, pmd2.allocator_dumps().count("mad1"));
- EXPECT_EQ(1u, pmd2.allocator_dumps().count("mad2"));
- EXPECT_EQ(0u, pmd2.allocator_dumps().count("mad3"));
- EXPECT_EQ(MemoryDumpLevelOfDetail::DETAILED,
- pmd2.dump_args().level_of_detail);
- EXPECT_EQ(1u, pmd2.allocator_dumps_edges().size());
-
- // Check that calling serialization routines doesn't cause a crash.
- auto traced_value = std::make_unique<TracedValue>();
- pmd2.SerializeAllocatorDumpsInto(traced_value.get());
-}
-
-TEST(ProcessMemoryDumpTest, Clear) {
- std::unique_ptr<ProcessMemoryDump> pmd1(
- new ProcessMemoryDump(kDetailedDumpArgs));
- pmd1->CreateAllocatorDump("mad1");
- pmd1->CreateAllocatorDump("mad2");
- ASSERT_FALSE(pmd1->allocator_dumps().empty());
-
- pmd1->AddOwnershipEdge(MemoryAllocatorDumpGuid(42),
- MemoryAllocatorDumpGuid(4242));
-
- MemoryAllocatorDumpGuid shared_mad_guid1(1);
- MemoryAllocatorDumpGuid shared_mad_guid2(2);
- pmd1->CreateSharedGlobalAllocatorDump(shared_mad_guid1);
- pmd1->CreateSharedGlobalAllocatorDump(shared_mad_guid2);
-
- pmd1->Clear();
- ASSERT_TRUE(pmd1->allocator_dumps().empty());
- ASSERT_TRUE(pmd1->allocator_dumps_edges().empty());
- ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad1"));
- ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad2"));
- ASSERT_EQ(nullptr, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1));
- ASSERT_EQ(nullptr, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2));
-
- // Check that calling serialization routines doesn't cause a crash.
- auto traced_value = std::make_unique<TracedValue>();
- pmd1->SerializeAllocatorDumpsInto(traced_value.get());
-
- // Check that the pmd can be reused and behaves as expected.
- auto* mad1 = pmd1->CreateAllocatorDump("mad1");
- auto* mad3 = pmd1->CreateAllocatorDump("mad3");
- auto* shared_mad1 = pmd1->CreateSharedGlobalAllocatorDump(shared_mad_guid1);
- auto* shared_mad2 =
- pmd1->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid2);
- ASSERT_EQ(4u, pmd1->allocator_dumps().size());
- ASSERT_EQ(mad1, pmd1->GetAllocatorDump("mad1"));
- ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad2"));
- ASSERT_EQ(mad3, pmd1->GetAllocatorDump("mad3"));
- ASSERT_EQ(shared_mad1, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1));
- ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags());
- ASSERT_EQ(shared_mad2, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2));
- ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad2->flags());
-
- traced_value.reset(new TracedValue);
- pmd1->SerializeAllocatorDumpsInto(traced_value.get());
-
- pmd1.reset();
-}
-
-TEST(ProcessMemoryDumpTest, TakeAllDumpsFrom) {
- std::unique_ptr<TracedValue> traced_value(new TracedValue);
- std::unordered_map<AllocationContext, AllocationMetrics> metrics_by_context;
- metrics_by_context[AllocationContext()] = {1, 1};
- TraceEventMemoryOverhead overhead;
-
- std::unique_ptr<ProcessMemoryDump> pmd1(
- new ProcessMemoryDump(kDetailedDumpArgs));
- auto* mad1_1 = pmd1->CreateAllocatorDump("pmd1/mad1");
- auto* mad1_2 = pmd1->CreateAllocatorDump("pmd1/mad2");
- pmd1->AddOwnershipEdge(mad1_1->guid(), mad1_2->guid());
- pmd1->DumpHeapUsage(metrics_by_context, overhead, "pmd1/heap_dump1");
- pmd1->DumpHeapUsage(metrics_by_context, overhead, "pmd1/heap_dump2");
-
- std::unique_ptr<ProcessMemoryDump> pmd2(
- new ProcessMemoryDump(kDetailedDumpArgs));
- auto* mad2_1 = pmd2->CreateAllocatorDump("pmd2/mad1");
- auto* mad2_2 = pmd2->CreateAllocatorDump("pmd2/mad2");
- pmd2->AddOwnershipEdge(mad2_1->guid(), mad2_2->guid());
- pmd2->DumpHeapUsage(metrics_by_context, overhead, "pmd2/heap_dump1");
- pmd2->DumpHeapUsage(metrics_by_context, overhead, "pmd2/heap_dump2");
-
- MemoryAllocatorDumpGuid shared_mad_guid1(1);
- MemoryAllocatorDumpGuid shared_mad_guid2(2);
- auto* shared_mad1 = pmd2->CreateSharedGlobalAllocatorDump(shared_mad_guid1);
- auto* shared_mad2 =
- pmd2->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid2);
-
- pmd1->TakeAllDumpsFrom(pmd2.get());
-
- // Make sure that pmd2 is empty but still usable after it has been emptied.
- ASSERT_TRUE(pmd2->allocator_dumps().empty());
- ASSERT_TRUE(pmd2->allocator_dumps_edges().empty());
- pmd2->CreateAllocatorDump("pmd2/this_mad_stays_with_pmd2");
- ASSERT_EQ(1u, pmd2->allocator_dumps().size());
- ASSERT_EQ(1u, pmd2->allocator_dumps().count("pmd2/this_mad_stays_with_pmd2"));
- pmd2->AddOwnershipEdge(MemoryAllocatorDumpGuid(42),
- MemoryAllocatorDumpGuid(4242));
-
- // Check that calling serialization routines doesn't cause a crash.
- pmd2->SerializeAllocatorDumpsInto(traced_value.get());
-
- // Free the |pmd2| to check that the memory ownership of the two MAD(s)
- // has been transferred to |pmd1|.
- pmd2.reset();
-
- // Now check that |pmd1| has been effectively merged.
- ASSERT_EQ(6u, pmd1->allocator_dumps().size());
- ASSERT_EQ(1u, pmd1->allocator_dumps().count("pmd1/mad1"));
- ASSERT_EQ(1u, pmd1->allocator_dumps().count("pmd1/mad2"));
- ASSERT_EQ(1u, pmd1->allocator_dumps().count("pmd2/mad1"));
- ASSERT_EQ(1u, pmd1->allocator_dumps().count("pmd1/mad2"));
- ASSERT_EQ(2u, pmd1->allocator_dumps_edges().size());
- ASSERT_EQ(shared_mad1, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1));
- ASSERT_EQ(shared_mad2, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2));
- ASSERT_TRUE(MemoryAllocatorDump::Flags::WEAK & shared_mad2->flags());
-
- // Check that calling serialization routines doesn't cause a crash.
- traced_value.reset(new TracedValue);
- pmd1->SerializeAllocatorDumpsInto(traced_value.get());
-
- pmd1.reset();
-}
-
-TEST(ProcessMemoryDumpTest, OverrideOwnershipEdge) {
- std::unique_ptr<ProcessMemoryDump> pmd(
- new ProcessMemoryDump(kDetailedDumpArgs));
-
- auto* shm_dump1 = pmd->CreateAllocatorDump("shared_mem/seg1");
- auto* shm_dump2 = pmd->CreateAllocatorDump("shared_mem/seg2");
- auto* shm_dump3 = pmd->CreateAllocatorDump("shared_mem/seg3");
- auto* shm_dump4 = pmd->CreateAllocatorDump("shared_mem/seg4");
-
- // Create one allocation with an auto-assigned guid and mark it as a
- // suballocation of "fakealloc/allocated_objects".
- auto* child1_dump = pmd->CreateAllocatorDump("shared_mem/child/seg1");
- pmd->AddOverridableOwnershipEdge(child1_dump->guid(), shm_dump1->guid(),
- 0 /* importance */);
- auto* child2_dump = pmd->CreateAllocatorDump("shared_mem/child/seg2");
- pmd->AddOwnershipEdge(child2_dump->guid(), shm_dump2->guid(),
- 3 /* importance */);
- MemoryAllocatorDumpGuid shared_mad_guid(1);
- pmd->CreateSharedGlobalAllocatorDump(shared_mad_guid);
- pmd->AddOverridableOwnershipEdge(shm_dump3->guid(), shared_mad_guid,
- 0 /* importance */);
- auto* child4_dump = pmd->CreateAllocatorDump("shared_mem/child/seg4");
- pmd->AddOverridableOwnershipEdge(child4_dump->guid(), shm_dump4->guid(),
- 4 /* importance */);
-
- const ProcessMemoryDump::AllocatorDumpEdgesMap& edges =
- pmd->allocator_dumps_edges();
- EXPECT_EQ(4u, edges.size());
- EXPECT_EQ(shm_dump1->guid(), edges.find(child1_dump->guid())->second.target);
- EXPECT_EQ(0, edges.find(child1_dump->guid())->second.importance);
- EXPECT_TRUE(edges.find(child1_dump->guid())->second.overridable);
- EXPECT_EQ(shm_dump2->guid(), edges.find(child2_dump->guid())->second.target);
- EXPECT_EQ(3, edges.find(child2_dump->guid())->second.importance);
- EXPECT_FALSE(edges.find(child2_dump->guid())->second.overridable);
- EXPECT_EQ(shared_mad_guid, edges.find(shm_dump3->guid())->second.target);
- EXPECT_EQ(0, edges.find(shm_dump3->guid())->second.importance);
- EXPECT_TRUE(edges.find(shm_dump3->guid())->second.overridable);
- EXPECT_EQ(shm_dump4->guid(), edges.find(child4_dump->guid())->second.target);
- EXPECT_EQ(4, edges.find(child4_dump->guid())->second.importance);
- EXPECT_TRUE(edges.find(child4_dump->guid())->second.overridable);
-
- // These should override old edges:
- pmd->AddOwnershipEdge(child1_dump->guid(), shm_dump1->guid(),
- 1 /* importance */);
- pmd->AddOwnershipEdge(shm_dump3->guid(), shared_mad_guid, 2 /* importance */);
- // This should not change the old edges.
- pmd->AddOverridableOwnershipEdge(child2_dump->guid(), shm_dump2->guid(),
- 0 /* importance */);
- pmd->AddOwnershipEdge(child4_dump->guid(), shm_dump4->guid(),
- 0 /* importance */);
-
- EXPECT_EQ(4u, edges.size());
- EXPECT_EQ(shm_dump1->guid(), edges.find(child1_dump->guid())->second.target);
- EXPECT_EQ(1, edges.find(child1_dump->guid())->second.importance);
- EXPECT_FALSE(edges.find(child1_dump->guid())->second.overridable);
- EXPECT_EQ(shm_dump2->guid(), edges.find(child2_dump->guid())->second.target);
- EXPECT_EQ(3, edges.find(child2_dump->guid())->second.importance);
- EXPECT_FALSE(edges.find(child2_dump->guid())->second.overridable);
- EXPECT_EQ(shared_mad_guid, edges.find(shm_dump3->guid())->second.target);
- EXPECT_EQ(2, edges.find(shm_dump3->guid())->second.importance);
- EXPECT_FALSE(edges.find(shm_dump3->guid())->second.overridable);
- EXPECT_EQ(shm_dump4->guid(), edges.find(child4_dump->guid())->second.target);
- EXPECT_EQ(4, edges.find(child4_dump->guid())->second.importance);
- EXPECT_FALSE(edges.find(child4_dump->guid())->second.overridable);
-}
-
-TEST(ProcessMemoryDumpTest, Suballocations) {
- std::unique_ptr<ProcessMemoryDump> pmd(
- new ProcessMemoryDump(kDetailedDumpArgs));
- const std::string allocator_dump_name = "fakealloc/allocated_objects";
- pmd->CreateAllocatorDump(allocator_dump_name);
-
- // Create one allocation with an auto-assigned guid and mark it as a
- // suballocation of "fakealloc/allocated_objects".
- auto* pic1_dump = pmd->CreateAllocatorDump("picturemanager/picture1");
- pmd->AddSuballocation(pic1_dump->guid(), allocator_dump_name);
-
- // Same here, but this time create an allocation with an explicit guid.
- auto* pic2_dump = pmd->CreateAllocatorDump("picturemanager/picture2",
- MemoryAllocatorDumpGuid(0x42));
- pmd->AddSuballocation(pic2_dump->guid(), allocator_dump_name);
-
- // Now check that AddSuballocation() has created anonymous child dumps under
- // "fakealloc/allocated_objects".
- auto anon_node_1_it = pmd->allocator_dumps().find(
- allocator_dump_name + "/__" + pic1_dump->guid().ToString());
- ASSERT_NE(pmd->allocator_dumps().end(), anon_node_1_it);
-
- auto anon_node_2_it =
- pmd->allocator_dumps().find(allocator_dump_name + "/__42");
- ASSERT_NE(pmd->allocator_dumps().end(), anon_node_2_it);
-
- // Finally check that AddSuballocation() has created also the
- // edges between the pictures and the anonymous allocator child dumps.
- bool found_edge[2]{false, false};
- for (const auto& e : pmd->allocator_dumps_edges()) {
- found_edge[0] |= (e.first == pic1_dump->guid() &&
- e.second.target == anon_node_1_it->second->guid());
- found_edge[1] |= (e.first == pic2_dump->guid() &&
- e.second.target == anon_node_2_it->second->guid());
- }
- ASSERT_TRUE(found_edge[0]);
- ASSERT_TRUE(found_edge[1]);
-
- // Check that calling serialization routines doesn't cause a crash.
- std::unique_ptr<TracedValue> traced_value(new TracedValue);
- pmd->SerializeAllocatorDumpsInto(traced_value.get());
-
- pmd.reset();
-}
-
-TEST(ProcessMemoryDumpTest, GlobalAllocatorDumpTest) {
- std::unique_ptr<ProcessMemoryDump> pmd(
- new ProcessMemoryDump(kDetailedDumpArgs));
- MemoryAllocatorDumpGuid shared_mad_guid(1);
- auto* shared_mad1 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid);
- ASSERT_EQ(shared_mad_guid, shared_mad1->guid());
- ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags());
-
- auto* shared_mad2 = pmd->GetSharedGlobalAllocatorDump(shared_mad_guid);
- ASSERT_EQ(shared_mad1, shared_mad2);
- ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags());
-
- auto* shared_mad3 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid);
- ASSERT_EQ(shared_mad1, shared_mad3);
- ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags());
-
- auto* shared_mad4 = pmd->CreateSharedGlobalAllocatorDump(shared_mad_guid);
- ASSERT_EQ(shared_mad1, shared_mad4);
- ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags());
-
- auto* shared_mad5 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid);
- ASSERT_EQ(shared_mad1, shared_mad5);
- ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags());
-}
-
-TEST(ProcessMemoryDumpTest, SharedMemoryOwnershipTest) {
- std::unique_ptr<ProcessMemoryDump> pmd(
- new ProcessMemoryDump(kDetailedDumpArgs));
- const ProcessMemoryDump::AllocatorDumpEdgesMap& edges =
- pmd->allocator_dumps_edges();
-
- auto* client_dump2 = pmd->CreateAllocatorDump("discardable/segment2");
- auto shm_token2 = UnguessableToken::Create();
- MemoryAllocatorDumpGuid shm_local_guid2 =
- pmd->GetDumpId(SharedMemoryTracker::GetDumpNameForTracing(shm_token2));
- MemoryAllocatorDumpGuid shm_global_guid2 =
- SharedMemoryTracker::GetGlobalDumpIdForTracing(shm_token2);
- pmd->AddOverridableOwnershipEdge(shm_local_guid2, shm_global_guid2,
- 0 /* importance */);
-
- pmd->CreateSharedMemoryOwnershipEdge(client_dump2->guid(), shm_token2,
- 1 /* importance */);
- EXPECT_EQ(2u, edges.size());
-
- EXPECT_EQ(shm_global_guid2, edges.find(shm_local_guid2)->second.target);
- EXPECT_EQ(1, edges.find(shm_local_guid2)->second.importance);
- EXPECT_FALSE(edges.find(shm_local_guid2)->second.overridable);
- EXPECT_EQ(shm_local_guid2, edges.find(client_dump2->guid())->second.target);
- EXPECT_EQ(1, edges.find(client_dump2->guid())->second.importance);
- EXPECT_FALSE(edges.find(client_dump2->guid())->second.overridable);
-}
-
-TEST(ProcessMemoryDumpTest, BackgroundModeTest) {
- MemoryDumpArgs background_args = {MemoryDumpLevelOfDetail::BACKGROUND};
- std::unique_ptr<ProcessMemoryDump> pmd(
- new ProcessMemoryDump(background_args));
- ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = true;
- SetAllocatorDumpNameWhitelistForTesting(kTestDumpNameWhitelist);
- MemoryAllocatorDump* black_hole_mad = pmd->GetBlackHoleMad();
-
- // GetAllocatorDump works for uncreated dumps.
- EXPECT_EQ(nullptr, pmd->GetAllocatorDump("NotWhitelisted/TestName"));
- EXPECT_EQ(nullptr, pmd->GetAllocatorDump("Whitelisted/TestName"));
-
- // Invalid dump names.
- EXPECT_EQ(black_hole_mad,
- pmd->CreateAllocatorDump("NotWhitelisted/TestName"));
- EXPECT_EQ(black_hole_mad, pmd->CreateAllocatorDump("TestName"));
- EXPECT_EQ(black_hole_mad, pmd->CreateAllocatorDump("Whitelisted/Test"));
- EXPECT_EQ(black_hole_mad,
- pmd->CreateAllocatorDump("Not/Whitelisted/TestName"));
- EXPECT_EQ(black_hole_mad,
- pmd->CreateAllocatorDump("Whitelisted/TestName/Google"));
- EXPECT_EQ(black_hole_mad,
- pmd->CreateAllocatorDump("Whitelisted/TestName/0x1a2Google"));
- EXPECT_EQ(black_hole_mad,
- pmd->CreateAllocatorDump("Whitelisted/TestName/__12/Google"));
-
- // Suballocations.
- MemoryAllocatorDumpGuid guid(1);
- pmd->AddSuballocation(guid, "malloc/allocated_objects");
- EXPECT_EQ(0u, pmd->allocator_dumps_edges_.size());
- EXPECT_EQ(0u, pmd->allocator_dumps_.size());
-
- // Global dumps.
- EXPECT_NE(black_hole_mad, pmd->CreateSharedGlobalAllocatorDump(guid));
- EXPECT_NE(black_hole_mad, pmd->CreateWeakSharedGlobalAllocatorDump(guid));
- EXPECT_NE(black_hole_mad, pmd->GetSharedGlobalAllocatorDump(guid));
-
- // Valid dump names.
- EXPECT_NE(black_hole_mad, pmd->CreateAllocatorDump("Whitelisted/TestName"));
- EXPECT_NE(black_hole_mad,
- pmd->CreateAllocatorDump("Whitelisted/TestName_0xA1b2"));
- EXPECT_NE(black_hole_mad,
- pmd->CreateAllocatorDump("Whitelisted/0xaB/TestName"));
-
- // GetAllocatorDump is consistent.
- EXPECT_EQ(nullptr, pmd->GetAllocatorDump("NotWhitelisted/TestName"));
- EXPECT_NE(black_hole_mad, pmd->GetAllocatorDump("Whitelisted/TestName"));
-
- // Test whitelisted entries.
- ASSERT_TRUE(IsMemoryAllocatorDumpNameWhitelisted("Whitelisted/TestName"));
-
- // Global dumps should be whitelisted.
- ASSERT_TRUE(IsMemoryAllocatorDumpNameWhitelisted("global/13456"));
-
- // Global dumps with non-guids should not be.
- ASSERT_FALSE(IsMemoryAllocatorDumpNameWhitelisted("global/random"));
-
- // Random names should not.
- ASSERT_FALSE(IsMemoryAllocatorDumpNameWhitelisted("NotWhitelisted/TestName"));
-
- // Check hex processing.
- ASSERT_TRUE(IsMemoryAllocatorDumpNameWhitelisted("Whitelisted/0xA1b2"));
-}
-
-TEST(ProcessMemoryDumpTest, GuidsTest) {
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
-
- const auto process_token_one = UnguessableToken::Create();
- const auto process_token_two = UnguessableToken::Create();
-
- ProcessMemoryDump pmd1(dump_args);
- pmd1.set_process_token_for_testing(process_token_one);
- MemoryAllocatorDump* mad1 = pmd1.CreateAllocatorDump("foo");
-
- ProcessMemoryDump pmd2(dump_args);
- pmd2.set_process_token_for_testing(process_token_one);
- MemoryAllocatorDump* mad2 = pmd2.CreateAllocatorDump("foo");
-
- // If we don't pass the argument we get a random PMD:
- ProcessMemoryDump pmd3(dump_args);
- MemoryAllocatorDump* mad3 = pmd3.CreateAllocatorDump("foo");
-
- // PMD's for different processes produce different GUIDs even for the same
- // names:
- ProcessMemoryDump pmd4(dump_args);
- pmd4.set_process_token_for_testing(process_token_two);
- MemoryAllocatorDump* mad4 = pmd4.CreateAllocatorDump("foo");
-
- ASSERT_EQ(mad1->guid(), mad2->guid());
-
- ASSERT_NE(mad2->guid(), mad3->guid());
- ASSERT_NE(mad3->guid(), mad4->guid());
- ASSERT_NE(mad4->guid(), mad2->guid());
-
- ASSERT_EQ(mad1->guid(), pmd1.GetDumpId("foo"));
-}
-
-#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
-#if defined(OS_FUCHSIA)
-// TODO(crbug.com/851760): Counting resident bytes is not supported on Fuchsia.
-#define MAYBE_CountResidentBytes DISABLED_CountResidentBytes
-#else
-#define MAYBE_CountResidentBytes CountResidentBytes
-#endif
-TEST(ProcessMemoryDumpTest, MAYBE_CountResidentBytes) {
- const size_t page_size = ProcessMemoryDump::GetSystemPageSize();
-
- // Allocate few page of dirty memory and check if it is resident.
- const size_t size1 = 5 * page_size;
- void* memory1 = Map(size1);
- memset(memory1, 0, size1);
- size_t res1 = ProcessMemoryDump::CountResidentBytes(memory1, size1);
- ASSERT_EQ(res1, size1);
- Unmap(memory1, size1);
-
- // Allocate a large memory segment (> 8Mib).
- const size_t kVeryLargeMemorySize = 15 * 1024 * 1024;
- void* memory2 = Map(kVeryLargeMemorySize);
- memset(memory2, 0, kVeryLargeMemorySize);
- size_t res2 =
- ProcessMemoryDump::CountResidentBytes(memory2, kVeryLargeMemorySize);
- ASSERT_EQ(res2, kVeryLargeMemorySize);
- Unmap(memory2, kVeryLargeMemorySize);
-}
-
-#if defined(OS_FUCHSIA)
-// TODO(crbug.com/851760): Counting resident bytes is not supported on Fuchsia.
-#define MAYBE_CountResidentBytesInSharedMemory \
- DISABLED_CountResidentBytesInSharedMemory
-#else
-#define MAYBE_CountResidentBytesInSharedMemory CountResidentBytesInSharedMemory
-#endif
-TEST(ProcessMemoryDumpTest, MAYBE_CountResidentBytesInSharedMemory) {
-#if defined(OS_IOS)
- // TODO(crbug.com/748410): Reenable this test.
- if (!base::ios::IsRunningOnIOS10OrLater()) {
- return;
- }
-#endif
-
- const size_t page_size = ProcessMemoryDump::GetSystemPageSize();
-
- // Allocate few page of dirty memory and check if it is resident.
- const size_t size1 = 5 * page_size;
- SharedMemory shared_memory1;
- shared_memory1.CreateAndMapAnonymous(size1);
- memset(shared_memory1.memory(), 0, size1);
- base::Optional<size_t> res1 =
- ProcessMemoryDump::CountResidentBytesInSharedMemory(
- shared_memory1.memory(), shared_memory1.mapped_size());
- ASSERT_TRUE(res1.has_value());
- ASSERT_EQ(res1.value(), size1);
- shared_memory1.Unmap();
- shared_memory1.Close();
-
- // Allocate a large memory segment (> 8Mib).
- const size_t kVeryLargeMemorySize = 15 * 1024 * 1024;
- SharedMemory shared_memory2;
- shared_memory2.CreateAndMapAnonymous(kVeryLargeMemorySize);
- memset(shared_memory2.memory(), 0, kVeryLargeMemorySize);
- base::Optional<size_t> res2 =
- ProcessMemoryDump::CountResidentBytesInSharedMemory(
- shared_memory2.memory(), shared_memory2.mapped_size());
- ASSERT_TRUE(res2.has_value());
- ASSERT_EQ(res2.value(), kVeryLargeMemorySize);
- shared_memory2.Unmap();
- shared_memory2.Close();
-
- // Allocate a large memory segment, but touch about half of all pages.
- const size_t kTouchedMemorySize = 7 * 1024 * 1024;
- SharedMemory shared_memory3;
- shared_memory3.CreateAndMapAnonymous(kVeryLargeMemorySize);
- memset(shared_memory3.memory(), 0, kTouchedMemorySize);
- base::Optional<size_t> res3 =
- ProcessMemoryDump::CountResidentBytesInSharedMemory(
- shared_memory3.memory(), shared_memory3.mapped_size());
- ASSERT_TRUE(res3.has_value());
- ASSERT_EQ(res3.value(), kTouchedMemorySize);
- shared_memory3.Unmap();
- shared_memory3.Close();
-}
-#endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED)
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_buffer.cc b/base/trace_event/trace_buffer.cc
deleted file mode 100644
index 8de470f0fd..0000000000
--- a/base/trace_event/trace_buffer.cc
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright 2015 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/trace_event/trace_buffer.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/trace_event/heap_profiler.h"
-#include "base/trace_event/trace_event_impl.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-class TraceBufferRingBuffer : public TraceBuffer {
- public:
- TraceBufferRingBuffer(size_t max_chunks)
- : max_chunks_(max_chunks),
- recyclable_chunks_queue_(new size_t[queue_capacity()]),
- queue_head_(0),
- queue_tail_(max_chunks),
- current_iteration_index_(0),
- current_chunk_seq_(1) {
- chunks_.reserve(max_chunks);
- for (size_t i = 0; i < max_chunks; ++i)
- recyclable_chunks_queue_[i] = i;
- }
-
- std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override {
- HEAP_PROFILER_SCOPED_IGNORE;
-
- // Because the number of threads is much less than the number of chunks,
- // the queue should never be empty.
- DCHECK(!QueueIsEmpty());
-
- *index = recyclable_chunks_queue_[queue_head_];
- queue_head_ = NextQueueIndex(queue_head_);
- current_iteration_index_ = queue_head_;
-
- if (*index >= chunks_.size())
- chunks_.resize(*index + 1);
-
- TraceBufferChunk* chunk = chunks_[*index].release();
- chunks_[*index] = nullptr; // Put nullptr in the slot of a in-flight chunk.
- if (chunk)
- chunk->Reset(current_chunk_seq_++);
- else
- chunk = new TraceBufferChunk(current_chunk_seq_++);
-
- return std::unique_ptr<TraceBufferChunk>(chunk);
- }
-
- void ReturnChunk(size_t index,
- std::unique_ptr<TraceBufferChunk> chunk) override {
- // When this method is called, the queue should not be full because it
- // can contain all chunks including the one to be returned.
- DCHECK(!QueueIsFull());
- DCHECK(chunk);
- DCHECK_LT(index, chunks_.size());
- DCHECK(!chunks_[index]);
- chunks_[index] = std::move(chunk);
- recyclable_chunks_queue_[queue_tail_] = index;
- queue_tail_ = NextQueueIndex(queue_tail_);
- }
-
- bool IsFull() const override { return false; }
-
- size_t Size() const override {
- // This is approximate because not all of the chunks are full.
- return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize;
- }
-
- size_t Capacity() const override {
- return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize;
- }
-
- TraceEvent* GetEventByHandle(TraceEventHandle handle) override {
- if (handle.chunk_index >= chunks_.size())
- return nullptr;
- TraceBufferChunk* chunk = chunks_[handle.chunk_index].get();
- if (!chunk || chunk->seq() != handle.chunk_seq)
- return nullptr;
- return chunk->GetEventAt(handle.event_index);
- }
-
- const TraceBufferChunk* NextChunk() override {
- if (chunks_.empty())
- return nullptr;
-
- while (current_iteration_index_ != queue_tail_) {
- size_t chunk_index = recyclable_chunks_queue_[current_iteration_index_];
- current_iteration_index_ = NextQueueIndex(current_iteration_index_);
- if (chunk_index >= chunks_.size()) // Skip uninitialized chunks.
- continue;
- DCHECK(chunks_[chunk_index]);
- return chunks_[chunk_index].get();
- }
- return nullptr;
- }
-
- void EstimateTraceMemoryOverhead(
- TraceEventMemoryOverhead* overhead) override {
- overhead->Add(TraceEventMemoryOverhead::kTraceBuffer, sizeof(*this));
- for (size_t queue_index = queue_head_; queue_index != queue_tail_;
- queue_index = NextQueueIndex(queue_index)) {
- size_t chunk_index = recyclable_chunks_queue_[queue_index];
- if (chunk_index >= chunks_.size()) // Skip uninitialized chunks.
- continue;
- chunks_[chunk_index]->EstimateTraceMemoryOverhead(overhead);
- }
- }
-
- private:
- bool QueueIsEmpty() const { return queue_head_ == queue_tail_; }
-
- size_t QueueSize() const {
- return queue_tail_ > queue_head_
- ? queue_tail_ - queue_head_
- : queue_tail_ + queue_capacity() - queue_head_;
- }
-
- bool QueueIsFull() const { return QueueSize() == queue_capacity() - 1; }
-
- size_t queue_capacity() const {
- // One extra space to help distinguish full state and empty state.
- return max_chunks_ + 1;
- }
-
- size_t NextQueueIndex(size_t index) const {
- index++;
- if (index >= queue_capacity())
- index = 0;
- return index;
- }
-
- size_t max_chunks_;
- std::vector<std::unique_ptr<TraceBufferChunk>> chunks_;
-
- std::unique_ptr<size_t[]> recyclable_chunks_queue_;
- size_t queue_head_;
- size_t queue_tail_;
-
- size_t current_iteration_index_;
- uint32_t current_chunk_seq_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer);
-};
-
-class TraceBufferVector : public TraceBuffer {
- public:
- TraceBufferVector(size_t max_chunks)
- : in_flight_chunk_count_(0),
- current_iteration_index_(0),
- max_chunks_(max_chunks) {
- chunks_.reserve(max_chunks_);
- }
-
- std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override {
- HEAP_PROFILER_SCOPED_IGNORE;
-
- // This function may be called when adding normal events or indirectly from
- // AddMetadataEventsWhileLocked(). We can not DECHECK(!IsFull()) because we
- // have to add the metadata events and flush thread-local buffers even if
- // the buffer is full.
- *index = chunks_.size();
- // Put nullptr in the slot of a in-flight chunk.
- chunks_.push_back(nullptr);
- ++in_flight_chunk_count_;
- // + 1 because zero chunk_seq is not allowed.
- return std::unique_ptr<TraceBufferChunk>(
- new TraceBufferChunk(static_cast<uint32_t>(*index) + 1));
- }
-
- void ReturnChunk(size_t index,
- std::unique_ptr<TraceBufferChunk> chunk) override {
- DCHECK_GT(in_flight_chunk_count_, 0u);
- DCHECK_LT(index, chunks_.size());
- DCHECK(!chunks_[index]);
- --in_flight_chunk_count_;
- chunks_[index] = std::move(chunk);
- }
-
- bool IsFull() const override { return chunks_.size() >= max_chunks_; }
-
- size_t Size() const override {
- // This is approximate because not all of the chunks are full.
- return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize;
- }
-
- size_t Capacity() const override {
- return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize;
- }
-
- TraceEvent* GetEventByHandle(TraceEventHandle handle) override {
- if (handle.chunk_index >= chunks_.size())
- return nullptr;
- TraceBufferChunk* chunk = chunks_[handle.chunk_index].get();
- if (!chunk || chunk->seq() != handle.chunk_seq)
- return nullptr;
- return chunk->GetEventAt(handle.event_index);
- }
-
- const TraceBufferChunk* NextChunk() override {
- while (current_iteration_index_ < chunks_.size()) {
- // Skip in-flight chunks.
- const TraceBufferChunk* chunk = chunks_[current_iteration_index_++].get();
- if (chunk)
- return chunk;
- }
- return nullptr;
- }
-
- void EstimateTraceMemoryOverhead(
- TraceEventMemoryOverhead* overhead) override {
- const size_t chunks_ptr_vector_allocated_size =
- sizeof(*this) + max_chunks_ * sizeof(decltype(chunks_)::value_type);
- const size_t chunks_ptr_vector_resident_size =
- sizeof(*this) + chunks_.size() * sizeof(decltype(chunks_)::value_type);
- overhead->Add(TraceEventMemoryOverhead::kTraceBuffer,
- chunks_ptr_vector_allocated_size,
- chunks_ptr_vector_resident_size);
- for (size_t i = 0; i < chunks_.size(); ++i) {
- TraceBufferChunk* chunk = chunks_[i].get();
- // Skip the in-flight (nullptr) chunks. They will be accounted by the
- // per-thread-local dumpers, see ThreadLocalEventBuffer::OnMemoryDump.
- if (chunk)
- chunk->EstimateTraceMemoryOverhead(overhead);
- }
- }
-
- private:
- size_t in_flight_chunk_count_;
- size_t current_iteration_index_;
- size_t max_chunks_;
- std::vector<std::unique_ptr<TraceBufferChunk>> chunks_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceBufferVector);
-};
-
-} // namespace
-
-TraceBufferChunk::TraceBufferChunk(uint32_t seq) : next_free_(0), seq_(seq) {}
-
-TraceBufferChunk::~TraceBufferChunk() = default;
-
-void TraceBufferChunk::Reset(uint32_t new_seq) {
- for (size_t i = 0; i < next_free_; ++i)
- chunk_[i].Reset();
- next_free_ = 0;
- seq_ = new_seq;
- cached_overhead_estimate_.reset();
-}
-
-TraceEvent* TraceBufferChunk::AddTraceEvent(size_t* event_index) {
- DCHECK(!IsFull());
- *event_index = next_free_++;
- return &chunk_[*event_index];
-}
-
-void TraceBufferChunk::EstimateTraceMemoryOverhead(
- TraceEventMemoryOverhead* overhead) {
- if (!cached_overhead_estimate_) {
- cached_overhead_estimate_.reset(new TraceEventMemoryOverhead);
-
- // When estimating the size of TraceBufferChunk, exclude the array of trace
- // events, as they are computed individually below.
- cached_overhead_estimate_->Add(TraceEventMemoryOverhead::kTraceBufferChunk,
- sizeof(*this) - sizeof(chunk_));
- }
-
- const size_t num_cached_estimated_events =
- cached_overhead_estimate_->GetCount(
- TraceEventMemoryOverhead::kTraceEvent);
- DCHECK_LE(num_cached_estimated_events, size());
-
- if (IsFull() && num_cached_estimated_events == size()) {
- overhead->Update(*cached_overhead_estimate_);
- return;
- }
-
- for (size_t i = num_cached_estimated_events; i < size(); ++i)
- chunk_[i].EstimateTraceMemoryOverhead(cached_overhead_estimate_.get());
-
- if (IsFull()) {
- cached_overhead_estimate_->AddSelf();
- } else {
- // The unused TraceEvents in |chunks_| are not cached. They will keep
- // changing as new TraceEvents are added to this chunk, so they are
- // computed on the fly.
- const size_t num_unused_trace_events = capacity() - size();
- overhead->Add(TraceEventMemoryOverhead::kUnusedTraceEvent,
- num_unused_trace_events * sizeof(TraceEvent));
- }
-
- overhead->Update(*cached_overhead_estimate_);
-}
-
-TraceResultBuffer::OutputCallback
-TraceResultBuffer::SimpleOutput::GetCallback() {
- return Bind(&SimpleOutput::Append, Unretained(this));
-}
-
-void TraceResultBuffer::SimpleOutput::Append(
- const std::string& json_trace_output) {
- json_output += json_trace_output;
-}
-
-TraceResultBuffer::TraceResultBuffer() : append_comma_(false) {}
-
-TraceResultBuffer::~TraceResultBuffer() = default;
-
-void TraceResultBuffer::SetOutputCallback(
- const OutputCallback& json_chunk_callback) {
- output_callback_ = json_chunk_callback;
-}
-
-void TraceResultBuffer::Start() {
- append_comma_ = false;
- output_callback_.Run("[");
-}
-
-void TraceResultBuffer::AddFragment(const std::string& trace_fragment) {
- if (append_comma_)
- output_callback_.Run(",");
- append_comma_ = true;
- output_callback_.Run(trace_fragment);
-}
-
-void TraceResultBuffer::Finish() {
- output_callback_.Run("]");
-}
-
-TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(size_t max_chunks) {
- return new TraceBufferRingBuffer(max_chunks);
-}
-
-TraceBuffer* TraceBuffer::CreateTraceBufferVectorOfSize(size_t max_chunks) {
- return new TraceBufferVector(max_chunks);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_buffer.h b/base/trace_event/trace_buffer.h
deleted file mode 100644
index 3d6465fdc3..0000000000
--- a/base/trace_event/trace_buffer.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_BUFFER_H_
-#define BASE_TRACE_EVENT_TRACE_BUFFER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/base_export.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_impl.h"
-
-namespace base {
-
-namespace trace_event {
-
-// TraceBufferChunk is the basic unit of TraceBuffer.
-class BASE_EXPORT TraceBufferChunk {
- public:
- explicit TraceBufferChunk(uint32_t seq);
- ~TraceBufferChunk();
-
- void Reset(uint32_t new_seq);
- TraceEvent* AddTraceEvent(size_t* event_index);
- bool IsFull() const { return next_free_ == kTraceBufferChunkSize; }
-
- uint32_t seq() const { return seq_; }
- size_t capacity() const { return kTraceBufferChunkSize; }
- size_t size() const { return next_free_; }
-
- TraceEvent* GetEventAt(size_t index) {
- DCHECK(index < size());
- return &chunk_[index];
- }
- const TraceEvent* GetEventAt(size_t index) const {
- DCHECK(index < size());
- return &chunk_[index];
- }
-
- void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
-
- // These values must be kept consistent with the numbers of bits of
- // chunk_index and event_index fields in TraceEventHandle
- // (in trace_event_impl.h).
- static const size_t kMaxChunkIndex = (1u << 26) - 1;
- static const size_t kTraceBufferChunkSize = 64;
-
- private:
- size_t next_free_;
- std::unique_ptr<TraceEventMemoryOverhead> cached_overhead_estimate_;
- TraceEvent chunk_[kTraceBufferChunkSize];
- uint32_t seq_;
-};
-
-// TraceBuffer holds the events as they are collected.
-class BASE_EXPORT TraceBuffer {
- public:
- virtual ~TraceBuffer() = default;
-
- virtual std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) = 0;
- virtual void ReturnChunk(size_t index,
- std::unique_ptr<TraceBufferChunk> chunk) = 0;
-
- virtual bool IsFull() const = 0;
- virtual size_t Size() const = 0;
- virtual size_t Capacity() const = 0;
- virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) = 0;
-
- // For iteration. Each TraceBuffer can only be iterated once.
- virtual const TraceBufferChunk* NextChunk() = 0;
-
-
- // Computes an estimate of the size of the buffer, including all the retained
- // objects.
- virtual void EstimateTraceMemoryOverhead(
- TraceEventMemoryOverhead* overhead) = 0;
-
- static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks);
- static TraceBuffer* CreateTraceBufferVectorOfSize(size_t max_chunks);
-};
-
-// TraceResultBuffer collects and converts trace fragments returned by TraceLog
-// to JSON output.
-class BASE_EXPORT TraceResultBuffer {
- public:
- typedef base::Callback<void(const std::string&)> OutputCallback;
-
- // If you don't need to stream JSON chunks out efficiently, and just want to
- // get a complete JSON string after calling Finish, use this struct to collect
- // JSON trace output.
- struct BASE_EXPORT SimpleOutput {
- OutputCallback GetCallback();
- void Append(const std::string& json_string);
-
- // Do what you want with the json_output_ string after calling
- // TraceResultBuffer::Finish.
- std::string json_output;
- };
-
- TraceResultBuffer();
- ~TraceResultBuffer();
-
- // Set callback. The callback will be called during Start with the initial
- // JSON output and during AddFragment and Finish with following JSON output
- // chunks. The callback target must live past the last calls to
- // TraceResultBuffer::Start/AddFragment/Finish.
- void SetOutputCallback(const OutputCallback& json_chunk_callback);
-
- // Start JSON output. This resets all internal state, so you can reuse
- // the TraceResultBuffer by calling Start.
- void Start();
-
- // Call AddFragment 0 or more times to add trace fragments from TraceLog.
- void AddFragment(const std::string& trace_fragment);
-
- // When all fragments have been added, call Finish to complete the JSON
- // formatted output.
- void Finish();
-
- private:
- OutputCallback output_callback_;
- bool append_comma_;
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_BUFFER_H_
diff --git a/base/trace_event/trace_category.h b/base/trace_event/trace_category.h
deleted file mode 100644
index 792bc5e53e..0000000000
--- a/base/trace_event/trace_category.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_CATEGORY_H_
-#define BASE_TRACE_EVENT_TRACE_CATEGORY_H_
-
-#include <stdint.h>
-
-namespace base {
-namespace trace_event {
-
-// Captures the state of an invidivual trace category. Nothing except tracing
-// internals (e.g., TraceLog) is supposed to have non-const Category pointers.
-struct TraceCategory {
- // The TRACE_EVENT macros should only use this value as a bool.
- // These enum values are effectively a public API and third_party projects
- // depend on their value. Hence, never remove or recycle existing bits, unless
- // you are sure that all the third-party projects that depend on this have
- // been updated.
- enum StateFlags : uint8_t {
- ENABLED_FOR_RECORDING = 1 << 0,
-
- // Not used anymore.
- DEPRECATED_ENABLED_FOR_MONITORING = 1 << 1,
- DEPRECATED_ENABLED_FOR_EVENT_CALLBACK = 1 << 2,
-
- ENABLED_FOR_ETW_EXPORT = 1 << 3,
- ENABLED_FOR_FILTERING = 1 << 4
- };
-
- static const TraceCategory* FromStatePtr(const uint8_t* state_ptr) {
- static_assert(
- offsetof(TraceCategory, state_) == 0,
- "|state_| must be the first field of the TraceCategory class.");
- return reinterpret_cast<const TraceCategory*>(state_ptr);
- }
-
- bool is_valid() const { return name_ != nullptr; }
- void set_name(const char* name) { name_ = name; }
- const char* name() const {
- DCHECK(is_valid());
- return name_;
- }
-
- // TODO(primiano): This is an intermediate solution to deal with the fact that
- // today TRACE_EVENT* macros cache the state ptr. They should just cache the
- // full TraceCategory ptr, which is immutable, and use these helper function
- // here. This will get rid of the need of this awkward ptr getter completely.
- const uint8_t* state_ptr() const {
- return const_cast<const uint8_t*>(&state_);
- }
-
- uint8_t state() const {
- return *const_cast<volatile const uint8_t*>(&state_);
- }
-
- bool is_enabled() const { return state() != 0; }
-
- void set_state(uint8_t state) {
- *const_cast<volatile uint8_t*>(&state_) = state;
- }
-
- void clear_state_flag(StateFlags flag) { set_state(state() & (~flag)); }
- void set_state_flag(StateFlags flag) { set_state(state() | flag); }
-
- uint32_t enabled_filters() const {
- return *const_cast<volatile const uint32_t*>(&enabled_filters_);
- }
-
- bool is_filter_enabled(size_t index) const {
- DCHECK(index < sizeof(enabled_filters_) * 8);
- return (enabled_filters() & (1 << index)) != 0;
- }
-
- void set_enabled_filters(uint32_t enabled_filters) {
- *const_cast<volatile uint32_t*>(&enabled_filters_) = enabled_filters;
- }
-
- void reset_for_testing() {
- set_state(0);
- set_enabled_filters(0);
- }
-
- // These fields should not be accessed directly, not even by tracing code.
- // The only reason why these are not private is because it makes it impossible
- // to have a global array of TraceCategory in category_registry.cc without
- // creating initializers. See discussion on goo.gl/qhZN94 and
- // crbug.com/{660967,660828}.
-
- // The enabled state. TRACE_EVENT* macros will capture events if any of the
- // flags here are set. Since TRACE_EVENTx macros are used in a lot of
- // fast-paths, accesses to this field are non-barriered and racy by design.
- // This field is mutated when starting/stopping tracing and we don't care
- // about missing some events.
- uint8_t state_;
-
- // When ENABLED_FOR_FILTERING is set, this contains a bitmap to the
- // corresponding filter (see event_filters.h).
- uint32_t enabled_filters_;
-
- // TraceCategory group names are long lived static strings.
- const char* name_;
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_CATEGORY_H_
diff --git a/base/trace_event/trace_category_unittest.cc b/base/trace_event/trace_category_unittest.cc
deleted file mode 100644
index 1370f5e906..0000000000
--- a/base/trace_event/trace_category_unittest.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2016 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 <string.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/trace_event/category_registry.h"
-#include "base/trace_event/trace_category.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-// Static initializers are generally forbidden. However, in the past we ran in
-// the case of some test using tracing in a static initializer. This test checks
-// That the category registry doesn't rely on static initializers itself and is
-// functional even if called from another static initializer.
-bool Initializer() {
- return CategoryRegistry::kCategoryMetadata &&
- CategoryRegistry::kCategoryMetadata->is_valid();
-}
-bool g_initializer_check = Initializer();
-
-class TraceCategoryTest : public testing::Test {
- public:
- void SetUp() override { CategoryRegistry::Initialize(); }
-
- void TearDown() override { CategoryRegistry::ResetForTesting(); }
-
- static bool GetOrCreateCategoryByName(const char* name, TraceCategory** cat) {
- static LazyInstance<Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER;
- bool is_new_cat = false;
- *cat = CategoryRegistry::GetCategoryByName(name);
- if (!*cat) {
- AutoLock lock(g_lock.Get());
- is_new_cat = CategoryRegistry::GetOrCreateCategoryLocked(
- name, [](TraceCategory*) {}, cat);
- }
- return is_new_cat;
- };
-
- static CategoryRegistry::Range GetAllCategories() {
- return CategoryRegistry::GetAllCategories();
- }
-
- static void TestRaceThreadMain(WaitableEvent* event) {
- TraceCategory* cat = nullptr;
- event->Wait();
- GetOrCreateCategoryByName("__test_race", &cat);
- EXPECT_NE(nullptr, cat);
- }
-};
-
-TEST_F(TraceCategoryTest, Basic) {
- ASSERT_NE(nullptr, CategoryRegistry::kCategoryMetadata);
- ASSERT_TRUE(CategoryRegistry::kCategoryMetadata->is_valid());
- ASSERT_FALSE(CategoryRegistry::kCategoryMetadata->is_enabled());
-
- // Metadata category is built-in and should create a new category.
- TraceCategory* cat_meta = nullptr;
- const char* kMetadataName = CategoryRegistry::kCategoryMetadata->name();
- ASSERT_FALSE(GetOrCreateCategoryByName(kMetadataName, &cat_meta));
- ASSERT_EQ(CategoryRegistry::kCategoryMetadata, cat_meta);
-
- TraceCategory* cat_1 = nullptr;
- ASSERT_TRUE(GetOrCreateCategoryByName("__test_basic_ab", &cat_1));
- ASSERT_FALSE(cat_1->is_enabled());
- ASSERT_EQ(0u, cat_1->enabled_filters());
- cat_1->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING);
- cat_1->set_state_flag(TraceCategory::ENABLED_FOR_FILTERING);
- ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING |
- TraceCategory::ENABLED_FOR_FILTERING,
- cat_1->state());
-
- cat_1->set_enabled_filters(129);
- ASSERT_EQ(129u, cat_1->enabled_filters());
- ASSERT_EQ(cat_1, CategoryRegistry::GetCategoryByStatePtr(cat_1->state_ptr()));
-
- cat_1->clear_state_flag(TraceCategory::ENABLED_FOR_FILTERING);
- ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, cat_1->state());
- ASSERT_EQ(TraceCategory::ENABLED_FOR_RECORDING, *cat_1->state_ptr());
- ASSERT_TRUE(cat_1->is_enabled());
-
- TraceCategory* cat_2 = nullptr;
- ASSERT_TRUE(GetOrCreateCategoryByName("__test_basic_a", &cat_2));
- ASSERT_FALSE(cat_2->is_enabled());
- cat_2->set_state_flag(TraceCategory::ENABLED_FOR_RECORDING);
-
- TraceCategory* cat_2_copy = nullptr;
- ASSERT_FALSE(GetOrCreateCategoryByName("__test_basic_a", &cat_2_copy));
- ASSERT_EQ(cat_2, cat_2_copy);
-
- TraceCategory* cat_3 = nullptr;
- ASSERT_TRUE(
- GetOrCreateCategoryByName("__test_basic_ab,__test_basic_a", &cat_3));
- ASSERT_FALSE(cat_3->is_enabled());
- ASSERT_EQ(0u, cat_3->enabled_filters());
-
- int num_test_categories_seen = 0;
- for (const TraceCategory& cat : GetAllCategories()) {
- if (strcmp(cat.name(), kMetadataName) == 0)
- ASSERT_TRUE(CategoryRegistry::IsBuiltinCategory(&cat));
-
- if (strncmp(cat.name(), "__test_basic_", 13) == 0) {
- ASSERT_FALSE(CategoryRegistry::IsBuiltinCategory(&cat));
- num_test_categories_seen++;
- }
- }
- ASSERT_EQ(3, num_test_categories_seen);
- ASSERT_TRUE(g_initializer_check);
-}
-
-// Tries to cover the case of multiple threads creating the same category
-// simultaneously. Should never end up with distinct entries with the same name.
-#if defined(OS_FUCHSIA)
-// TODO(crbug.com/738275): This is flaky on Fuchsia.
-#define MAYBE_ThreadRaces DISABLED_ThreadRaces
-#else
-#define MAYBE_ThreadRaces ThreadRaces
-#endif
-TEST_F(TraceCategoryTest, MAYBE_ThreadRaces) {
- const int kNumThreads = 32;
- std::unique_ptr<Thread> threads[kNumThreads];
- for (int i = 0; i < kNumThreads; i++) {
- threads[i].reset(new Thread("test thread"));
- threads[i]->Start();
- }
- WaitableEvent sync_event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- for (int i = 0; i < kNumThreads; i++) {
- threads[i]->task_runner()->PostTask(
- FROM_HERE, BindOnce(&TestRaceThreadMain, Unretained(&sync_event)));
- }
- sync_event.Signal();
- for (int i = 0; i < kNumThreads; i++)
- threads[i]->Stop();
-
- int num_times_seen = 0;
- for (const TraceCategory& cat : GetAllCategories()) {
- if (strcmp(cat.name(), "__test_race") == 0)
- num_times_seen++;
- }
- ASSERT_EQ(1, num_times_seen);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc
deleted file mode 100644
index 9d6a9d4874..0000000000
--- a/base/trace_event/trace_config.cc
+++ /dev/null
@@ -1,618 +0,0 @@
-// Copyright (c) 2015 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/trace_event/trace_config.h"
-
-#include <stddef.h>
-
-#include <utility>
-
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_split.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/memory_dump_request_args.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// String options that can be used to initialize TraceOptions.
-const char kRecordUntilFull[] = "record-until-full";
-const char kRecordContinuously[] = "record-continuously";
-const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible";
-const char kTraceToConsole[] = "trace-to-console";
-const char kEnableSystrace[] = "enable-systrace";
-const char kEnableArgumentFilter[] = "enable-argument-filter";
-
-// String parameters that can be used to parse the trace config string.
-const char kRecordModeParam[] = "record_mode";
-const char kEnableSystraceParam[] = "enable_systrace";
-const char kEnableArgumentFilterParam[] = "enable_argument_filter";
-
-// String parameters that is used to parse memory dump config in trace config
-// string.
-const char kMemoryDumpConfigParam[] = "memory_dump_config";
-const char kAllowedDumpModesParam[] = "allowed_dump_modes";
-const char kTriggersParam[] = "triggers";
-const char kTriggerModeParam[] = "mode";
-const char kMinTimeBetweenDumps[] = "min_time_between_dumps_ms";
-const char kTriggerTypeParam[] = "type";
-const char kPeriodicIntervalLegacyParam[] = "periodic_interval_ms";
-const char kHeapProfilerOptions[] = "heap_profiler_options";
-const char kBreakdownThresholdBytes[] = "breakdown_threshold_bytes";
-
-// String parameters used to parse category event filters.
-const char kEventFiltersParam[] = "event_filters";
-const char kFilterPredicateParam[] = "filter_predicate";
-const char kFilterArgsParam[] = "filter_args";
-
-// String parameter used to parse process filter.
-const char kIncludedProcessesParam[] = "included_process_ids";
-
-class ConvertableTraceConfigToTraceFormat
- : public base::trace_event::ConvertableToTraceFormat {
- public:
- explicit ConvertableTraceConfigToTraceFormat(const TraceConfig& trace_config)
- : trace_config_(trace_config) {}
-
- ~ConvertableTraceConfigToTraceFormat() override = default;
-
- void AppendAsTraceFormat(std::string* out) const override {
- out->append(trace_config_.ToString());
- }
-
- private:
- const TraceConfig trace_config_;
-};
-
-std::set<MemoryDumpLevelOfDetail> GetDefaultAllowedMemoryDumpModes() {
- std::set<MemoryDumpLevelOfDetail> all_modes;
- for (uint32_t mode = static_cast<uint32_t>(MemoryDumpLevelOfDetail::FIRST);
- mode <= static_cast<uint32_t>(MemoryDumpLevelOfDetail::LAST); mode++) {
- all_modes.insert(static_cast<MemoryDumpLevelOfDetail>(mode));
- }
- return all_modes;
-}
-
-} // namespace
-
-TraceConfig::MemoryDumpConfig::HeapProfiler::HeapProfiler()
- : breakdown_threshold_bytes(kDefaultBreakdownThresholdBytes) {}
-
-void TraceConfig::MemoryDumpConfig::HeapProfiler::Clear() {
- breakdown_threshold_bytes = kDefaultBreakdownThresholdBytes;
-}
-
-void TraceConfig::ResetMemoryDumpConfig(
- const TraceConfig::MemoryDumpConfig& memory_dump_config) {
- memory_dump_config_.Clear();
- memory_dump_config_ = memory_dump_config;
-}
-
-TraceConfig::MemoryDumpConfig::MemoryDumpConfig() = default;
-
-TraceConfig::MemoryDumpConfig::MemoryDumpConfig(
- const MemoryDumpConfig& other) = default;
-
-TraceConfig::MemoryDumpConfig::~MemoryDumpConfig() = default;
-
-void TraceConfig::MemoryDumpConfig::Clear() {
- allowed_dump_modes.clear();
- triggers.clear();
- heap_profiler_options.Clear();
-}
-
-void TraceConfig::MemoryDumpConfig::Merge(
- const TraceConfig::MemoryDumpConfig& config) {
- triggers.insert(triggers.end(), config.triggers.begin(),
- config.triggers.end());
- allowed_dump_modes.insert(config.allowed_dump_modes.begin(),
- config.allowed_dump_modes.end());
- heap_profiler_options.breakdown_threshold_bytes =
- std::min(heap_profiler_options.breakdown_threshold_bytes,
- config.heap_profiler_options.breakdown_threshold_bytes);
-}
-
-TraceConfig::ProcessFilterConfig::ProcessFilterConfig() = default;
-
-TraceConfig::ProcessFilterConfig::ProcessFilterConfig(
- const ProcessFilterConfig& other) = default;
-
-TraceConfig::ProcessFilterConfig::ProcessFilterConfig(
- const std::unordered_set<base::ProcessId>& included_process_ids)
- : included_process_ids_(included_process_ids) {}
-
-TraceConfig::ProcessFilterConfig::~ProcessFilterConfig() = default;
-
-void TraceConfig::ProcessFilterConfig::Clear() {
- included_process_ids_.clear();
-}
-
-void TraceConfig::ProcessFilterConfig::Merge(
- const ProcessFilterConfig& config) {
- included_process_ids_.insert(config.included_process_ids_.begin(),
- config.included_process_ids_.end());
-}
-
-void TraceConfig::ProcessFilterConfig::InitializeFromConfigDict(
- const base::DictionaryValue& dict) {
- included_process_ids_.clear();
- const Value* value =
- dict.FindKeyOfType(kIncludedProcessesParam, Value::Type::LIST);
- if (!value)
- return;
- for (auto& pid_value : value->GetList()) {
- if (pid_value.is_int())
- included_process_ids_.insert(pid_value.GetInt());
- }
-}
-
-void TraceConfig::ProcessFilterConfig::ToDict(DictionaryValue* dict) const {
- if (included_process_ids_.empty())
- return;
- Value* list = dict->SetKey(kIncludedProcessesParam, Value(Value::Type::LIST));
- std::set<base::ProcessId> ordered_set(included_process_ids_.begin(),
- included_process_ids_.end());
- for (auto process_id : ordered_set)
- list->GetList().emplace_back(static_cast<int>(process_id));
-}
-
-bool TraceConfig::ProcessFilterConfig::IsEnabled(
- base::ProcessId process_id) const {
- return included_process_ids_.empty() ||
- included_process_ids_.count(process_id);
-}
-
-TraceConfig::EventFilterConfig::EventFilterConfig(
- const std::string& predicate_name)
- : predicate_name_(predicate_name) {}
-
-TraceConfig::EventFilterConfig::~EventFilterConfig() = default;
-
-TraceConfig::EventFilterConfig::EventFilterConfig(const EventFilterConfig& tc) {
- *this = tc;
-}
-
-TraceConfig::EventFilterConfig& TraceConfig::EventFilterConfig::operator=(
- const TraceConfig::EventFilterConfig& rhs) {
- if (this == &rhs)
- return *this;
-
- predicate_name_ = rhs.predicate_name_;
- category_filter_ = rhs.category_filter_;
-
- if (rhs.args_)
- args_ = rhs.args_->CreateDeepCopy();
-
- return *this;
-}
-
-void TraceConfig::EventFilterConfig::InitializeFromConfigDict(
- const base::DictionaryValue* event_filter) {
- category_filter_.InitializeFromConfigDict(*event_filter);
-
- const base::DictionaryValue* args_dict = nullptr;
- if (event_filter->GetDictionary(kFilterArgsParam, &args_dict))
- args_ = args_dict->CreateDeepCopy();
-}
-
-void TraceConfig::EventFilterConfig::SetCategoryFilter(
- const TraceConfigCategoryFilter& category_filter) {
- category_filter_ = category_filter;
-}
-
-void TraceConfig::EventFilterConfig::ToDict(
- DictionaryValue* filter_dict) const {
- filter_dict->SetString(kFilterPredicateParam, predicate_name());
-
- category_filter_.ToDict(filter_dict);
-
- if (args_)
- filter_dict->Set(kFilterArgsParam, args_->CreateDeepCopy());
-}
-
-bool TraceConfig::EventFilterConfig::GetArgAsSet(
- const char* key,
- std::unordered_set<std::string>* out_set) const {
- const ListValue* list = nullptr;
- if (!args_->GetList(key, &list))
- return false;
- for (size_t i = 0; i < list->GetSize(); ++i) {
- std::string value;
- if (list->GetString(i, &value))
- out_set->insert(value);
- }
- return true;
-}
-
-bool TraceConfig::EventFilterConfig::IsCategoryGroupEnabled(
- const StringPiece& category_group_name) const {
- return category_filter_.IsCategoryGroupEnabled(category_group_name);
-}
-
-// static
-std::string TraceConfig::TraceRecordModeToStr(TraceRecordMode record_mode) {
- switch (record_mode) {
- case RECORD_UNTIL_FULL:
- return kRecordUntilFull;
- case RECORD_CONTINUOUSLY:
- return kRecordContinuously;
- case RECORD_AS_MUCH_AS_POSSIBLE:
- return kRecordAsMuchAsPossible;
- case ECHO_TO_CONSOLE:
- return kTraceToConsole;
- default:
- NOTREACHED();
- }
- return kRecordUntilFull;
-}
-
-TraceConfig::TraceConfig() {
- InitializeDefault();
-}
-
-TraceConfig::TraceConfig(StringPiece category_filter_string,
- StringPiece trace_options_string) {
- InitializeFromStrings(category_filter_string, trace_options_string);
-}
-
-TraceConfig::TraceConfig(StringPiece category_filter_string,
- TraceRecordMode record_mode) {
- InitializeFromStrings(category_filter_string,
- TraceConfig::TraceRecordModeToStr(record_mode));
-}
-
-TraceConfig::TraceConfig(const DictionaryValue& config) {
- InitializeFromConfigDict(config);
-}
-
-TraceConfig::TraceConfig(StringPiece config_string) {
- if (!config_string.empty())
- InitializeFromConfigString(config_string);
- else
- InitializeDefault();
-}
-
-TraceConfig::TraceConfig(const TraceConfig& tc) = default;
-
-TraceConfig::~TraceConfig() = default;
-
-TraceConfig& TraceConfig::operator=(const TraceConfig& rhs) {
- if (this == &rhs)
- return *this;
-
- record_mode_ = rhs.record_mode_;
- enable_systrace_ = rhs.enable_systrace_;
- enable_argument_filter_ = rhs.enable_argument_filter_;
- category_filter_ = rhs.category_filter_;
- process_filter_config_ = rhs.process_filter_config_;
- memory_dump_config_ = rhs.memory_dump_config_;
- event_filters_ = rhs.event_filters_;
- return *this;
-}
-
-std::string TraceConfig::ToString() const {
- std::unique_ptr<DictionaryValue> dict = ToDict();
- std::string json;
- JSONWriter::Write(*dict, &json);
- return json;
-}
-
-std::unique_ptr<ConvertableToTraceFormat>
-TraceConfig::AsConvertableToTraceFormat() const {
- return std::make_unique<ConvertableTraceConfigToTraceFormat>(*this);
-}
-
-std::string TraceConfig::ToCategoryFilterString() const {
- return category_filter_.ToFilterString();
-}
-
-bool TraceConfig::IsCategoryGroupEnabled(
- const StringPiece& category_group_name) const {
- // TraceLog should call this method only as part of enabling/disabling
- // categories.
- return category_filter_.IsCategoryGroupEnabled(category_group_name);
-}
-
-void TraceConfig::Merge(const TraceConfig& config) {
- if (record_mode_ != config.record_mode_
- || enable_systrace_ != config.enable_systrace_
- || enable_argument_filter_ != config.enable_argument_filter_) {
- DLOG(ERROR) << "Attempting to merge trace config with a different "
- << "set of options.";
- }
-
- category_filter_.Merge(config.category_filter_);
- memory_dump_config_.Merge(config.memory_dump_config_);
- process_filter_config_.Merge(config.process_filter_config_);
-
- event_filters_.insert(event_filters_.end(), config.event_filters().begin(),
- config.event_filters().end());
-}
-
-void TraceConfig::Clear() {
- record_mode_ = RECORD_UNTIL_FULL;
- enable_systrace_ = false;
- enable_argument_filter_ = false;
- category_filter_.Clear();
- memory_dump_config_.Clear();
- process_filter_config_.Clear();
- event_filters_.clear();
-}
-
-void TraceConfig::InitializeDefault() {
- record_mode_ = RECORD_UNTIL_FULL;
- enable_systrace_ = false;
- enable_argument_filter_ = false;
-}
-
-void TraceConfig::InitializeFromConfigDict(const DictionaryValue& dict) {
- record_mode_ = RECORD_UNTIL_FULL;
- std::string record_mode;
- if (dict.GetString(kRecordModeParam, &record_mode)) {
- if (record_mode == kRecordUntilFull) {
- record_mode_ = RECORD_UNTIL_FULL;
- } else if (record_mode == kRecordContinuously) {
- record_mode_ = RECORD_CONTINUOUSLY;
- } else if (record_mode == kTraceToConsole) {
- record_mode_ = ECHO_TO_CONSOLE;
- } else if (record_mode == kRecordAsMuchAsPossible) {
- record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE;
- }
- }
-
- bool val;
- enable_systrace_ = dict.GetBoolean(kEnableSystraceParam, &val) ? val : false;
- enable_argument_filter_ =
- dict.GetBoolean(kEnableArgumentFilterParam, &val) ? val : false;
-
- category_filter_.InitializeFromConfigDict(dict);
- process_filter_config_.InitializeFromConfigDict(dict);
-
- const base::ListValue* category_event_filters = nullptr;
- if (dict.GetList(kEventFiltersParam, &category_event_filters))
- SetEventFiltersFromConfigList(*category_event_filters);
-
- if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
- // If dump triggers not set, the client is using the legacy with just
- // category enabled. So, use the default periodic dump config.
- const DictionaryValue* memory_dump_config = nullptr;
- if (dict.GetDictionary(kMemoryDumpConfigParam, &memory_dump_config))
- SetMemoryDumpConfigFromConfigDict(*memory_dump_config);
- else
- SetDefaultMemoryDumpConfig();
- }
-}
-
-void TraceConfig::InitializeFromConfigString(StringPiece config_string) {
- auto dict = DictionaryValue::From(JSONReader::Read(config_string));
- if (dict)
- InitializeFromConfigDict(*dict);
- else
- InitializeDefault();
-}
-
-void TraceConfig::InitializeFromStrings(StringPiece category_filter_string,
- StringPiece trace_options_string) {
- if (!category_filter_string.empty())
- category_filter_.InitializeFromString(category_filter_string);
-
- record_mode_ = RECORD_UNTIL_FULL;
- enable_systrace_ = false;
- enable_argument_filter_ = false;
- if (!trace_options_string.empty()) {
- std::vector<std::string> split =
- SplitString(trace_options_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- for (const std::string& token : split) {
- if (token == kRecordUntilFull) {
- record_mode_ = RECORD_UNTIL_FULL;
- } else if (token == kRecordContinuously) {
- record_mode_ = RECORD_CONTINUOUSLY;
- } else if (token == kTraceToConsole) {
- record_mode_ = ECHO_TO_CONSOLE;
- } else if (token == kRecordAsMuchAsPossible) {
- record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE;
- } else if (token == kEnableSystrace) {
- enable_systrace_ = true;
- } else if (token == kEnableArgumentFilter) {
- enable_argument_filter_ = true;
- }
- }
- }
-
- if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
- SetDefaultMemoryDumpConfig();
- }
-}
-
-void TraceConfig::SetMemoryDumpConfigFromConfigDict(
- const DictionaryValue& memory_dump_config) {
- // Set allowed dump modes.
- memory_dump_config_.allowed_dump_modes.clear();
- const ListValue* allowed_modes_list;
- if (memory_dump_config.GetList(kAllowedDumpModesParam, &allowed_modes_list)) {
- for (size_t i = 0; i < allowed_modes_list->GetSize(); ++i) {
- std::string level_of_detail_str;
- allowed_modes_list->GetString(i, &level_of_detail_str);
- memory_dump_config_.allowed_dump_modes.insert(
- StringToMemoryDumpLevelOfDetail(level_of_detail_str));
- }
- } else {
- // If allowed modes param is not given then allow all modes by default.
- memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes();
- }
-
- // Set triggers
- memory_dump_config_.triggers.clear();
- const ListValue* trigger_list = nullptr;
- if (memory_dump_config.GetList(kTriggersParam, &trigger_list) &&
- trigger_list->GetSize() > 0) {
- for (size_t i = 0; i < trigger_list->GetSize(); ++i) {
- const DictionaryValue* trigger = nullptr;
- if (!trigger_list->GetDictionary(i, &trigger))
- continue;
-
- MemoryDumpConfig::Trigger dump_config;
- int interval = 0;
- if (!trigger->GetInteger(kMinTimeBetweenDumps, &interval)) {
- // If "min_time_between_dumps_ms" param was not given, then the trace
- // config uses old format where only periodic dumps are supported.
- trigger->GetInteger(kPeriodicIntervalLegacyParam, &interval);
- dump_config.trigger_type = MemoryDumpType::PERIODIC_INTERVAL;
- } else {
- std::string trigger_type_str;
- trigger->GetString(kTriggerTypeParam, &trigger_type_str);
- dump_config.trigger_type = StringToMemoryDumpType(trigger_type_str);
- }
- DCHECK_GT(interval, 0);
- dump_config.min_time_between_dumps_ms = static_cast<uint32_t>(interval);
-
- std::string level_of_detail_str;
- trigger->GetString(kTriggerModeParam, &level_of_detail_str);
- dump_config.level_of_detail =
- StringToMemoryDumpLevelOfDetail(level_of_detail_str);
-
- memory_dump_config_.triggers.push_back(dump_config);
- }
- }
-
- // Set heap profiler options
- const DictionaryValue* heap_profiler_options = nullptr;
- if (memory_dump_config.GetDictionary(kHeapProfilerOptions,
- &heap_profiler_options)) {
- int min_size_bytes = 0;
- if (heap_profiler_options->GetInteger(kBreakdownThresholdBytes,
- &min_size_bytes)
- && min_size_bytes >= 0) {
- memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes =
- static_cast<size_t>(min_size_bytes);
- } else {
- memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes =
- MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes;
- }
- }
-}
-
-void TraceConfig::SetDefaultMemoryDumpConfig() {
- memory_dump_config_.Clear();
- memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes();
-}
-
-void TraceConfig::SetProcessFilterConfig(const ProcessFilterConfig& config) {
- process_filter_config_ = config;
-}
-
-void TraceConfig::SetEventFiltersFromConfigList(
- const base::ListValue& category_event_filters) {
- event_filters_.clear();
-
- for (size_t event_filter_index = 0;
- event_filter_index < category_event_filters.GetSize();
- ++event_filter_index) {
- const base::DictionaryValue* event_filter = nullptr;
- if (!category_event_filters.GetDictionary(event_filter_index,
- &event_filter))
- continue;
-
- std::string predicate_name;
- CHECK(event_filter->GetString(kFilterPredicateParam, &predicate_name))
- << "Invalid predicate name in category event filter.";
-
- EventFilterConfig new_config(predicate_name);
- new_config.InitializeFromConfigDict(event_filter);
- event_filters_.push_back(new_config);
- }
-}
-
-std::unique_ptr<DictionaryValue> TraceConfig::ToDict() const {
- auto dict = std::make_unique<DictionaryValue>();
- dict->SetString(kRecordModeParam,
- TraceConfig::TraceRecordModeToStr(record_mode_));
- dict->SetBoolean(kEnableSystraceParam, enable_systrace_);
- dict->SetBoolean(kEnableArgumentFilterParam, enable_argument_filter_);
-
- category_filter_.ToDict(dict.get());
- process_filter_config_.ToDict(dict.get());
-
- if (!event_filters_.empty()) {
- std::unique_ptr<base::ListValue> filter_list(new base::ListValue());
- for (const EventFilterConfig& filter : event_filters_) {
- std::unique_ptr<base::DictionaryValue> filter_dict(
- new base::DictionaryValue());
- filter.ToDict(filter_dict.get());
- filter_list->Append(std::move(filter_dict));
- }
- dict->Set(kEventFiltersParam, std::move(filter_list));
- }
-
- if (category_filter_.IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) {
- auto allowed_modes = std::make_unique<ListValue>();
- for (auto dump_mode : memory_dump_config_.allowed_dump_modes)
- allowed_modes->AppendString(MemoryDumpLevelOfDetailToString(dump_mode));
-
- auto memory_dump_config = std::make_unique<DictionaryValue>();
- memory_dump_config->Set(kAllowedDumpModesParam, std::move(allowed_modes));
-
- auto triggers_list = std::make_unique<ListValue>();
- for (const auto& config : memory_dump_config_.triggers) {
- auto trigger_dict = std::make_unique<DictionaryValue>();
- trigger_dict->SetString(kTriggerTypeParam,
- MemoryDumpTypeToString(config.trigger_type));
- trigger_dict->SetInteger(
- kMinTimeBetweenDumps,
- static_cast<int>(config.min_time_between_dumps_ms));
- trigger_dict->SetString(
- kTriggerModeParam,
- MemoryDumpLevelOfDetailToString(config.level_of_detail));
- triggers_list->Append(std::move(trigger_dict));
- }
-
- // Empty triggers will still be specified explicitly since it means that
- // the periodic dumps are not enabled.
- memory_dump_config->Set(kTriggersParam, std::move(triggers_list));
-
- if (memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes !=
- MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes) {
- auto options = std::make_unique<DictionaryValue>();
- options->SetInteger(
- kBreakdownThresholdBytes,
- memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes);
- memory_dump_config->Set(kHeapProfilerOptions, std::move(options));
- }
- dict->Set(kMemoryDumpConfigParam, std::move(memory_dump_config));
- }
- return dict;
-}
-
-std::string TraceConfig::ToTraceOptionsString() const {
- std::string ret;
- switch (record_mode_) {
- case RECORD_UNTIL_FULL:
- ret = kRecordUntilFull;
- break;
- case RECORD_CONTINUOUSLY:
- ret = kRecordContinuously;
- break;
- case RECORD_AS_MUCH_AS_POSSIBLE:
- ret = kRecordAsMuchAsPossible;
- break;
- case ECHO_TO_CONSOLE:
- ret = kTraceToConsole;
- break;
- default:
- NOTREACHED();
- }
- if (enable_systrace_)
- ret = ret + "," + kEnableSystrace;
- if (enable_argument_filter_)
- ret = ret + "," + kEnableArgumentFilter;
- return ret;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_config.h b/base/trace_event/trace_config.h
deleted file mode 100644
index b1d809b58b..0000000000
--- a/base/trace_event/trace_config.h
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_CONFIG_H_
-#define BASE_TRACE_EVENT_TRACE_CONFIG_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <set>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/gtest_prod_util.h"
-#include "base/strings/string_piece.h"
-#include "base/trace_event/memory_dump_request_args.h"
-#include "base/trace_event/trace_config_category_filter.h"
-#include "base/values.h"
-
-namespace base {
-namespace trace_event {
-
-class ConvertableToTraceFormat;
-
-// Options determines how the trace buffer stores data.
-// A Java counterpart will be generated for this enum.
-// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base
-enum TraceRecordMode {
- // Record until the trace buffer is full.
- RECORD_UNTIL_FULL,
-
- // Record until the user ends the trace. The trace buffer is a fixed size
- // and we use it as a ring buffer during recording.
- RECORD_CONTINUOUSLY,
-
- // Record until the trace buffer is full, but with a huge buffer size.
- RECORD_AS_MUCH_AS_POSSIBLE,
-
- // Echo to console. Events are discarded.
- ECHO_TO_CONSOLE,
-};
-
-class BASE_EXPORT TraceConfig {
- public:
- using StringList = std::vector<std::string>;
-
- // Specifies the memory dump config for tracing.
- // Used only when "memory-infra" category is enabled.
- struct BASE_EXPORT MemoryDumpConfig {
- MemoryDumpConfig();
- MemoryDumpConfig(const MemoryDumpConfig& other);
- ~MemoryDumpConfig();
-
- // Specifies the triggers in the memory dump config.
- struct Trigger {
- uint32_t min_time_between_dumps_ms;
- MemoryDumpLevelOfDetail level_of_detail;
- MemoryDumpType trigger_type;
- };
-
- // Specifies the configuration options for the heap profiler.
- struct HeapProfiler {
- // Default value for |breakdown_threshold_bytes|.
- enum { kDefaultBreakdownThresholdBytes = 1024 };
-
- HeapProfiler();
-
- // Reset the options to default.
- void Clear();
-
- uint32_t breakdown_threshold_bytes;
- };
-
- // Reset the values in the config.
- void Clear();
-
- void Merge(const MemoryDumpConfig& config);
-
- // Set of memory dump modes allowed for the tracing session. The explicitly
- // triggered dumps will be successful only if the dump mode is allowed in
- // the config.
- std::set<MemoryDumpLevelOfDetail> allowed_dump_modes;
-
- std::vector<Trigger> triggers;
- HeapProfiler heap_profiler_options;
- };
-
- class BASE_EXPORT ProcessFilterConfig {
- public:
- ProcessFilterConfig();
- explicit ProcessFilterConfig(
- const std::unordered_set<base::ProcessId>& included_process_ids);
- ProcessFilterConfig(const ProcessFilterConfig&);
- ~ProcessFilterConfig();
-
- bool empty() const { return included_process_ids_.empty(); }
-
- void Clear();
- void Merge(const ProcessFilterConfig&);
-
- void InitializeFromConfigDict(const base::DictionaryValue&);
- void ToDict(DictionaryValue*) const;
-
- bool IsEnabled(base::ProcessId) const;
-
- bool operator==(const ProcessFilterConfig& other) const {
- return included_process_ids_ == other.included_process_ids_;
- }
-
- private:
- std::unordered_set<base::ProcessId> included_process_ids_;
- };
-
- class BASE_EXPORT EventFilterConfig {
- public:
- EventFilterConfig(const std::string& predicate_name);
- EventFilterConfig(const EventFilterConfig& tc);
-
- ~EventFilterConfig();
-
- EventFilterConfig& operator=(const EventFilterConfig& rhs);
-
- void InitializeFromConfigDict(const base::DictionaryValue* event_filter);
-
- void SetCategoryFilter(const TraceConfigCategoryFilter& category_filter);
-
- void ToDict(DictionaryValue* filter_dict) const;
-
- bool GetArgAsSet(const char* key, std::unordered_set<std::string>*) const;
-
- bool IsCategoryGroupEnabled(const StringPiece& category_group_name) const;
-
- const std::string& predicate_name() const { return predicate_name_; }
- base::DictionaryValue* filter_args() const { return args_.get(); }
- const TraceConfigCategoryFilter& category_filter() const {
- return category_filter_;
- }
-
- private:
- std::string predicate_name_;
- TraceConfigCategoryFilter category_filter_;
- std::unique_ptr<base::DictionaryValue> args_;
- };
- typedef std::vector<EventFilterConfig> EventFilters;
-
- static std::string TraceRecordModeToStr(TraceRecordMode record_mode);
-
- TraceConfig();
-
- // Create TraceConfig object from category filter and trace options strings.
- //
- // |category_filter_string| is a comma-delimited list of category wildcards.
- // A category can have an optional '-' prefix to make it an excluded category.
- // All the same rules apply above, so for example, having both included and
- // excluded categories in the same list would not be supported.
- //
- // |trace_options_string| is a comma-delimited list of trace options.
- // Possible options are: "record-until-full", "record-continuously",
- // "record-as-much-as-possible", "trace-to-console", "enable-systrace" and
- // "enable-argument-filter".
- // The first 4 options are trace recoding modes and hence
- // mutually exclusive. If more than one trace recording modes appear in the
- // options_string, the last one takes precedence. If none of the trace
- // recording mode is specified, recording mode is RECORD_UNTIL_FULL.
- //
- // The trace option will first be reset to the default option
- // (record_mode set to RECORD_UNTIL_FULL, enable_systrace and
- // enable_argument_filter set to false) before options parsed from
- // |trace_options_string| are applied on it. If |trace_options_string| is
- // invalid, the final state of trace options is undefined.
- //
- // Example: TraceConfig("test_MyTest*", "record-until-full");
- // Example: TraceConfig("test_MyTest*,test_OtherStuff",
- // "record-continuously");
- // Example: TraceConfig("-excluded_category1,-excluded_category2",
- // "record-until-full, trace-to-console");
- // would set ECHO_TO_CONSOLE as the recording mode.
- // Example: TraceConfig("-*,webkit", "");
- // would disable everything but webkit; and use default options.
- // Example: TraceConfig("-webkit", "");
- // would enable everything but webkit; and use default options.
- TraceConfig(StringPiece category_filter_string,
- StringPiece trace_options_string);
-
- TraceConfig(StringPiece category_filter_string, TraceRecordMode record_mode);
-
- // Create TraceConfig object from the trace config string.
- //
- // |config_string| is a dictionary formatted as a JSON string, containing both
- // category filters and trace options.
- //
- // Example:
- // {
- // "record_mode": "record-continuously",
- // "enable_systrace": true,
- // "enable_argument_filter": true,
- // "included_categories": ["included",
- // "inc_pattern*",
- // "disabled-by-default-memory-infra"],
- // "excluded_categories": ["excluded", "exc_pattern*"],
- // "memory_dump_config": {
- // "triggers": [
- // {
- // "mode": "detailed",
- // "periodic_interval_ms": 2000
- // }
- // ]
- // }
- // }
- //
- // Note: memory_dump_config can be specified only if
- // disabled-by-default-memory-infra category is enabled.
- explicit TraceConfig(StringPiece config_string);
-
- // Functionally identical to the above, but takes a parsed dictionary as input
- // instead of its JSON serialization.
- explicit TraceConfig(const DictionaryValue& config);
-
- TraceConfig(const TraceConfig& tc);
-
- ~TraceConfig();
-
- TraceConfig& operator=(const TraceConfig& rhs);
-
- TraceRecordMode GetTraceRecordMode() const { return record_mode_; }
- bool IsSystraceEnabled() const { return enable_systrace_; }
- bool IsArgumentFilterEnabled() const { return enable_argument_filter_; }
-
- void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; }
- void EnableSystrace() { enable_systrace_ = true; }
- void EnableArgumentFilter() { enable_argument_filter_ = true; }
-
- // Writes the string representation of the TraceConfig. The string is JSON
- // formatted.
- std::string ToString() const;
-
- // Returns a copy of the TraceConfig wrapped in a ConvertableToTraceFormat
- std::unique_ptr<ConvertableToTraceFormat> AsConvertableToTraceFormat() const;
-
- // Write the string representation of the CategoryFilter part.
- std::string ToCategoryFilterString() const;
-
- // Returns true if at least one category in the list is enabled by this
- // trace config. This is used to determine if the category filters are
- // enabled in the TRACE_* macros.
- bool IsCategoryGroupEnabled(const StringPiece& category_group_name) const;
-
- // Merges config with the current TraceConfig
- void Merge(const TraceConfig& config);
-
- void Clear();
-
- // Clears and resets the memory dump config.
- void ResetMemoryDumpConfig(const MemoryDumpConfig& memory_dump_config);
-
- const TraceConfigCategoryFilter& category_filter() const {
- return category_filter_;
- }
-
- const MemoryDumpConfig& memory_dump_config() const {
- return memory_dump_config_;
- }
-
- const ProcessFilterConfig& process_filter_config() const {
- return process_filter_config_;
- }
- void SetProcessFilterConfig(const ProcessFilterConfig&);
-
- const EventFilters& event_filters() const { return event_filters_; }
- void SetEventFilters(const EventFilters& filter_configs) {
- event_filters_ = filter_configs;
- }
-
- private:
- FRIEND_TEST_ALL_PREFIXES(TraceConfigTest, TraceConfigFromValidLegacyFormat);
- FRIEND_TEST_ALL_PREFIXES(TraceConfigTest,
- TraceConfigFromInvalidLegacyStrings);
-
- // The default trace config, used when none is provided.
- // Allows all non-disabled-by-default categories through, except if they end
- // in the suffix 'Debug' or 'Test'.
- void InitializeDefault();
-
- // Initialize from a config dictionary.
- void InitializeFromConfigDict(const DictionaryValue& dict);
-
- // Initialize from a config string.
- void InitializeFromConfigString(StringPiece config_string);
-
- // Initialize from category filter and trace options strings
- void InitializeFromStrings(StringPiece category_filter_string,
- StringPiece trace_options_string);
-
- void SetMemoryDumpConfigFromConfigDict(
- const DictionaryValue& memory_dump_config);
- void SetDefaultMemoryDumpConfig();
-
- void SetEventFiltersFromConfigList(const base::ListValue& event_filters);
- std::unique_ptr<DictionaryValue> ToDict() const;
-
- std::string ToTraceOptionsString() const;
-
- TraceRecordMode record_mode_;
- bool enable_systrace_ : 1;
- bool enable_argument_filter_ : 1;
-
- TraceConfigCategoryFilter category_filter_;
-
- MemoryDumpConfig memory_dump_config_;
- ProcessFilterConfig process_filter_config_;
-
- EventFilters event_filters_;
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_CONFIG_H_
diff --git a/base/trace_event/trace_config_category_filter.cc b/base/trace_event/trace_config_category_filter.cc
deleted file mode 100644
index d1884307a9..0000000000
--- a/base/trace_event/trace_config_category_filter.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2017 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/trace_event/trace_config_category_filter.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/pattern.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-const char kIncludedCategoriesParam[] = "included_categories";
-const char kExcludedCategoriesParam[] = "excluded_categories";
-}
-
-TraceConfigCategoryFilter::TraceConfigCategoryFilter() = default;
-
-TraceConfigCategoryFilter::TraceConfigCategoryFilter(
- const TraceConfigCategoryFilter& other) = default;
-
-TraceConfigCategoryFilter::~TraceConfigCategoryFilter() = default;
-
-TraceConfigCategoryFilter& TraceConfigCategoryFilter::operator=(
- const TraceConfigCategoryFilter& rhs) = default;
-
-void TraceConfigCategoryFilter::InitializeFromString(
- const StringPiece& category_filter_string) {
- std::vector<StringPiece> split = SplitStringPiece(
- category_filter_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- for (const StringPiece& category : split) {
- // Ignore empty categories.
- if (category.empty())
- continue;
- if (category.front() == '-') {
- // Excluded categories start with '-'.
- // Remove '-' from category string.
- excluded_categories_.push_back(category.substr(1).as_string());
- } else if (category.starts_with(TRACE_DISABLED_BY_DEFAULT(""))) {
- disabled_categories_.push_back(category.as_string());
- } else {
- included_categories_.push_back(category.as_string());
- }
- }
-}
-
-void TraceConfigCategoryFilter::InitializeFromConfigDict(
- const DictionaryValue& dict) {
- const ListValue* category_list = nullptr;
- if (dict.GetList(kIncludedCategoriesParam, &category_list))
- SetCategoriesFromIncludedList(*category_list);
- if (dict.GetList(kExcludedCategoriesParam, &category_list))
- SetCategoriesFromExcludedList(*category_list);
-}
-
-bool TraceConfigCategoryFilter::IsCategoryGroupEnabled(
- const StringPiece& category_group_name) const {
- bool had_enabled_by_default = false;
- DCHECK(!category_group_name.empty());
- CStringTokenizer category_group_tokens(category_group_name.begin(),
- category_group_name.end(), ",");
- while (category_group_tokens.GetNext()) {
- StringPiece category_group_token = category_group_tokens.token_piece();
- // Don't allow empty tokens, nor tokens with leading or trailing space.
- DCHECK(IsCategoryNameAllowed(category_group_token))
- << "Disallowed category string";
- if (IsCategoryEnabled(category_group_token))
- return true;
-
- if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*")))
- had_enabled_by_default = true;
- }
- // Do a second pass to check for explicitly disabled categories
- // (those explicitly enabled have priority due to first pass).
- category_group_tokens.Reset();
- bool category_group_disabled = false;
- while (category_group_tokens.GetNext()) {
- StringPiece category_group_token = category_group_tokens.token_piece();
- for (const std::string& category : excluded_categories_) {
- if (MatchPattern(category_group_token, category)) {
- // Current token of category_group_name is present in excluded_list.
- // Flag the exclusion and proceed further to check if any of the
- // remaining categories of category_group_name is not present in the
- // excluded_ list.
- category_group_disabled = true;
- break;
- }
- // One of the category of category_group_name is not present in
- // excluded_ list. So, if it's not a disabled-by-default category,
- // it has to be included_ list. Enable the category_group_name
- // for recording.
- if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*")))
- category_group_disabled = false;
- }
- // One of the categories present in category_group_name is not present in
- // excluded_ list. Implies this category_group_name group can be enabled
- // for recording, since one of its groups is enabled for recording.
- if (!category_group_disabled)
- break;
- }
- // If the category group is not excluded, and there are no included patterns
- // we consider this category group enabled, as long as it had categories
- // other than disabled-by-default.
- return !category_group_disabled && had_enabled_by_default &&
- included_categories_.empty();
-}
-
-bool TraceConfigCategoryFilter::IsCategoryEnabled(
- const StringPiece& category_name) const {
- // Check the disabled- filters and the disabled-* wildcard first so that a
- // "*" filter does not include the disabled.
- for (const std::string& category : disabled_categories_) {
- if (MatchPattern(category_name, category))
- return true;
- }
-
- if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*")))
- return false;
-
- for (const std::string& category : included_categories_) {
- if (MatchPattern(category_name, category))
- return true;
- }
-
- return false;
-}
-
-void TraceConfigCategoryFilter::Merge(const TraceConfigCategoryFilter& config) {
- // Keep included patterns only if both filters have an included entry.
- // Otherwise, one of the filter was specifying "*" and we want to honor the
- // broadest filter.
- if (!included_categories_.empty() && !config.included_categories_.empty()) {
- included_categories_.insert(included_categories_.end(),
- config.included_categories_.begin(),
- config.included_categories_.end());
- } else {
- included_categories_.clear();
- }
-
- disabled_categories_.insert(disabled_categories_.end(),
- config.disabled_categories_.begin(),
- config.disabled_categories_.end());
- excluded_categories_.insert(excluded_categories_.end(),
- config.excluded_categories_.begin(),
- config.excluded_categories_.end());
-}
-
-void TraceConfigCategoryFilter::Clear() {
- included_categories_.clear();
- disabled_categories_.clear();
- excluded_categories_.clear();
-}
-
-void TraceConfigCategoryFilter::ToDict(DictionaryValue* dict) const {
- StringList categories(included_categories_);
- categories.insert(categories.end(), disabled_categories_.begin(),
- disabled_categories_.end());
- AddCategoriesToDict(categories, kIncludedCategoriesParam, dict);
- AddCategoriesToDict(excluded_categories_, kExcludedCategoriesParam, dict);
-}
-
-std::string TraceConfigCategoryFilter::ToFilterString() const {
- std::string filter_string;
- WriteCategoryFilterString(included_categories_, &filter_string, true);
- WriteCategoryFilterString(disabled_categories_, &filter_string, true);
- WriteCategoryFilterString(excluded_categories_, &filter_string, false);
- return filter_string;
-}
-
-void TraceConfigCategoryFilter::SetCategoriesFromIncludedList(
- const ListValue& included_list) {
- included_categories_.clear();
- for (size_t i = 0; i < included_list.GetSize(); ++i) {
- std::string category;
- if (!included_list.GetString(i, &category))
- continue;
- if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")),
- TRACE_DISABLED_BY_DEFAULT("")) == 0) {
- disabled_categories_.push_back(category);
- } else {
- included_categories_.push_back(category);
- }
- }
-}
-
-void TraceConfigCategoryFilter::SetCategoriesFromExcludedList(
- const ListValue& excluded_list) {
- excluded_categories_.clear();
- for (size_t i = 0; i < excluded_list.GetSize(); ++i) {
- std::string category;
- if (excluded_list.GetString(i, &category))
- excluded_categories_.push_back(category);
- }
-}
-
-void TraceConfigCategoryFilter::AddCategoriesToDict(
- const StringList& categories,
- const char* param,
- DictionaryValue* dict) const {
- if (categories.empty())
- return;
-
- auto list = std::make_unique<ListValue>();
- for (const std::string& category : categories)
- list->AppendString(category);
- dict->Set(param, std::move(list));
-}
-
-void TraceConfigCategoryFilter::WriteCategoryFilterString(
- const StringList& values,
- std::string* out,
- bool included) const {
- bool prepend_comma = !out->empty();
- int token_cnt = 0;
- for (const std::string& category : values) {
- if (token_cnt > 0 || prepend_comma)
- StringAppendF(out, ",");
- StringAppendF(out, "%s%s", (included ? "" : "-"), category.c_str());
- ++token_cnt;
- }
-}
-
-// static
-bool TraceConfigCategoryFilter::IsCategoryNameAllowed(StringPiece str) {
- return !str.empty() && str.front() != ' ' && str.back() != ' ';
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_config_category_filter.h b/base/trace_event/trace_config_category_filter.h
deleted file mode 100644
index 0140c1d126..0000000000
--- a/base/trace_event/trace_config_category_filter.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_CONFIG_CATEGORY_FILTER_H_
-#define BASE_TRACE_EVENT_TRACE_CONFIG_CATEGORY_FILTER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/base_export.h"
-#include "base/strings/string_piece.h"
-#include "base/values.h"
-
-namespace base {
-namespace trace_event {
-
-// Configuration of categories enabled and disabled in TraceConfig.
-class BASE_EXPORT TraceConfigCategoryFilter {
- public:
- using StringList = std::vector<std::string>;
-
- TraceConfigCategoryFilter();
- TraceConfigCategoryFilter(const TraceConfigCategoryFilter& other);
- ~TraceConfigCategoryFilter();
-
- TraceConfigCategoryFilter& operator=(const TraceConfigCategoryFilter& rhs);
-
- // Initializes from category filter string. See TraceConfig constructor for
- // description of how to write category filter string.
- void InitializeFromString(const StringPiece& category_filter_string);
-
- // Initializes TraceConfigCategoryFilter object from the config dictionary.
- void InitializeFromConfigDict(const DictionaryValue& dict);
-
- // Merges this with category filter config.
- void Merge(const TraceConfigCategoryFilter& config);
- void Clear();
-
- // Returns true if at least one category in the list is enabled by this
- // trace config. This is used to determine if the category filters are
- // enabled in the TRACE_* macros.
- bool IsCategoryGroupEnabled(const StringPiece& category_group_name) const;
-
- // Returns true if the category is enabled according to this trace config.
- // This tells whether a category is enabled from the TraceConfig's
- // perspective. Please refer to IsCategoryGroupEnabled() to determine if a
- // category is enabled from the tracing runtime's perspective.
- bool IsCategoryEnabled(const StringPiece& category_name) const;
-
- void ToDict(DictionaryValue* dict) const;
-
- std::string ToFilterString() const;
-
- // Returns true if category name is a valid string.
- static bool IsCategoryNameAllowed(StringPiece str);
-
- const StringList& included_categories() const { return included_categories_; }
- const StringList& excluded_categories() const { return excluded_categories_; }
-
- private:
- void SetCategoriesFromIncludedList(const ListValue& included_list);
- void SetCategoriesFromExcludedList(const ListValue& excluded_list);
-
- void AddCategoriesToDict(const StringList& categories,
- const char* param,
- DictionaryValue* dict) const;
-
- void WriteCategoryFilterString(const StringList& values,
- std::string* out,
- bool included) const;
-
- StringList included_categories_;
- StringList disabled_categories_;
- StringList excluded_categories_;
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_CONFIG_CATEGORY_FILTER_H_
diff --git a/base/trace_event/trace_config_memory_test_util.h b/base/trace_event/trace_config_memory_test_util.h
deleted file mode 100644
index cc49a65c2b..0000000000
--- a/base/trace_event/trace_config_memory_test_util.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_CONFIG_MEMORY_TEST_UTIL_H_
-#define BASE_TRACE_EVENT_TRACE_CONFIG_MEMORY_TEST_UTIL_H_
-
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/memory_dump_manager.h"
-
-namespace base {
-namespace trace_event {
-
-class TraceConfigMemoryTestUtil {
- public:
- static std::string GetTraceConfig_LegacyPeriodicTriggers(int light_period,
- int heavy_period) {
- return StringPrintf(
- "{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"excluded_categories\":["
- "\"*\""
- "],"
- "\"included_categories\":["
- "\"%s\""
- "],"
- "\"memory_dump_config\":{"
- "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"],"
- "\"heap_profiler_options\":{"
- "\"breakdown_threshold_bytes\":2048"
- "},"
- "\"triggers\":["
- "{"
- "\"mode\":\"light\","
- "\"periodic_interval_ms\":%d"
- "},"
- "{"
- "\"mode\":\"detailed\","
- "\"periodic_interval_ms\":%d"
- "}"
- "]"
- "},"
- "\"record_mode\":\"record-until-full\""
- "}",
- MemoryDumpManager::kTraceCategory, light_period, heavy_period);
- ;
- }
-
- static std::string GetTraceConfig_PeriodicTriggers(int light_period,
- int heavy_period) {
- return StringPrintf(
- "{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"excluded_categories\":["
- "\"*\""
- "],"
- "\"included_categories\":["
- "\"%s\""
- "],"
- "\"memory_dump_config\":{"
- "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"],"
- "\"heap_profiler_options\":{"
- "\"breakdown_threshold_bytes\":2048"
- "},"
- "\"triggers\":["
- "{"
- "\"min_time_between_dumps_ms\":%d,"
- "\"mode\":\"light\","
- "\"type\":\"periodic_interval\""
- "},"
- "{"
- "\"min_time_between_dumps_ms\":%d,"
- "\"mode\":\"detailed\","
- "\"type\":\"periodic_interval\""
- "}"
- "]"
- "},"
- "\"record_mode\":\"record-until-full\""
- "}",
- MemoryDumpManager::kTraceCategory, light_period, heavy_period);
- }
-
- static std::string GetTraceConfig_EmptyTriggers() {
- return StringPrintf(
- "{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"excluded_categories\":["
- "\"*\""
- "],"
- "\"included_categories\":["
- "\"%s\""
- "],"
- "\"memory_dump_config\":{"
- "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"],"
- "\"triggers\":["
- "]"
- "},"
- "\"record_mode\":\"record-until-full\""
- "}",
- MemoryDumpManager::kTraceCategory);
- }
-
- static std::string GetTraceConfig_NoTriggers() {
- return StringPrintf(
- "{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"excluded_categories\":["
- "\"*\""
- "],"
- "\"included_categories\":["
- "\"%s\""
- "],"
- "\"record_mode\":\"record-until-full\""
- "}",
- MemoryDumpManager::kTraceCategory);
- }
-
- static std::string GetTraceConfig_BackgroundTrigger(int period_ms) {
- return StringPrintf(
- "{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"excluded_categories\":["
- "\"*\""
- "],"
- "\"included_categories\":["
- "\"%s\""
- "],"
- "\"memory_dump_config\":{"
- "\"allowed_dump_modes\":[\"background\"],"
- "\"triggers\":["
- "{"
- "\"min_time_between_dumps_ms\":%d,"
- "\"mode\":\"background\","
- "\"type\":\"periodic_interval\""
- "}"
- "]"
- "},"
- "\"record_mode\":\"record-until-full\""
- "}",
- MemoryDumpManager::kTraceCategory, period_ms);
- }
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_CONFIG_MEMORY_TEST_UTIL_H_
diff --git a/base/trace_event/trace_config_unittest.cc b/base/trace_event/trace_config_unittest.cc
deleted file mode 100644
index efdbffb6ef..0000000000
--- a/base/trace_event/trace_config_unittest.cc
+++ /dev/null
@@ -1,663 +0,0 @@
-// Copyright 2015 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 <stddef.h>
-
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/macros.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/trace_config.h"
-#include "base/trace_event/trace_config_memory_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-const char kDefaultTraceConfigString[] =
- "{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"record_mode\":\"record-until-full\""
- "}";
-
-const char kCustomTraceConfigString[] =
- "{"
- "\"enable_argument_filter\":true,"
- "\"enable_systrace\":true,"
- "\"event_filters\":["
- "{"
- "\"excluded_categories\":[\"unfiltered_cat\"],"
- "\"filter_args\":{\"event_name_whitelist\":[\"a snake\",\"a dog\"]},"
- "\"filter_predicate\":\"event_whitelist_predicate\","
- "\"included_categories\":[\"*\"]"
- "}"
- "],"
- "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
- "\"included_categories\":["
- "\"included\","
- "\"inc_pattern*\","
- "\"disabled-by-default-cc\","
- "\"disabled-by-default-memory-infra\"],"
- "\"memory_dump_config\":{"
- "\"allowed_dump_modes\":[\"background\",\"light\",\"detailed\"],"
- "\"heap_profiler_options\":{"
- "\"breakdown_threshold_bytes\":10240"
- "},"
- "\"triggers\":["
- "{"
- "\"min_time_between_dumps_ms\":50,"
- "\"mode\":\"light\","
- "\"type\":\"periodic_interval\""
- "},"
- "{"
- "\"min_time_between_dumps_ms\":1000,"
- "\"mode\":\"detailed\","
- "\"type\":\"periodic_interval\""
- "}"
- "]"
- "},"
- "\"record_mode\":\"record-continuously\""
- "}";
-
-void CheckDefaultTraceConfigBehavior(const TraceConfig& tc) {
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
-
- // Default trace config enables every category filter except the
- // disabled-by-default-* ones.
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("Category1"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("not-excluded-category"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
-
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("Category1,not-excluded-category"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("Category1,disabled-by-default-cc"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled(
- "disabled-by-default-cc,disabled-by-default-cc2"));
-}
-
-} // namespace
-
-TEST(TraceConfigTest, TraceConfigFromValidLegacyFormat) {
- // From trace options strings
- TraceConfig config("", "record-until-full");
- EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", "record-continuously");
- EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-continuously", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", "trace-to-console");
- EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("trace-to-console", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", "record-as-much-as-possible");
- EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-as-much-as-possible",
- config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", "enable-systrace, record-continuously");
- EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
- EXPECT_TRUE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-continuously,enable-systrace",
- config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", "enable-argument-filter,record-as-much-as-possible");
- EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_TRUE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-as-much-as-possible,enable-argument-filter",
- config.ToTraceOptionsString().c_str());
-
- config = TraceConfig(
- "",
- "enable-systrace,trace-to-console,enable-argument-filter");
- EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
- EXPECT_TRUE(config.IsSystraceEnabled());
- EXPECT_TRUE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ(
- "trace-to-console,enable-systrace,enable-argument-filter",
- config.ToTraceOptionsString().c_str());
-
- config = TraceConfig(
- "", "record-continuously, record-until-full, trace-to-console");
- EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("trace-to-console", config.ToTraceOptionsString().c_str());
-
- // From TraceRecordMode
- config = TraceConfig("", RECORD_UNTIL_FULL);
- EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", RECORD_CONTINUOUSLY);
- EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-continuously", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", ECHO_TO_CONSOLE);
- EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("trace-to-console", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("", RECORD_AS_MUCH_AS_POSSIBLE);
- EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("record-as-much-as-possible",
- config.ToTraceOptionsString().c_str());
-
- // From category filter strings
- config = TraceConfig("included,-excluded,inc_pattern*,-exc_pattern*", "");
- EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
- config.ToCategoryFilterString().c_str());
-
- config = TraceConfig("only_inc_cat", "");
- EXPECT_STREQ("only_inc_cat", config.ToCategoryFilterString().c_str());
-
- config = TraceConfig("-only_exc_cat", "");
- EXPECT_STREQ("-only_exc_cat", config.ToCategoryFilterString().c_str());
-
- config = TraceConfig("disabled-by-default-cc,-excluded", "");
- EXPECT_STREQ("disabled-by-default-cc,-excluded",
- config.ToCategoryFilterString().c_str());
-
- config = TraceConfig("disabled-by-default-cc,included", "");
- EXPECT_STREQ("included,disabled-by-default-cc",
- config.ToCategoryFilterString().c_str());
-
- // From both trace options and category filter strings
- config = TraceConfig("", "");
- EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("", config.ToCategoryFilterString().c_str());
- EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("included,-excluded,inc_pattern*,-exc_pattern*",
- "enable-systrace, trace-to-console");
- EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
- EXPECT_TRUE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
- config.ToCategoryFilterString().c_str());
- EXPECT_STREQ("trace-to-console,enable-systrace",
- config.ToTraceOptionsString().c_str());
-
- // From both trace options and category filter strings with spaces.
- config = TraceConfig(" included , -excluded, inc_pattern*, ,-exc_pattern* ",
- "enable-systrace, ,trace-to-console ");
- EXPECT_EQ(ECHO_TO_CONSOLE, config.GetTraceRecordMode());
- EXPECT_TRUE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
- config.ToCategoryFilterString().c_str());
- EXPECT_STREQ("trace-to-console,enable-systrace",
- config.ToTraceOptionsString().c_str());
-
- // From category filter string and TraceRecordMode
- config = TraceConfig("included,-excluded,inc_pattern*,-exc_pattern*",
- RECORD_CONTINUOUSLY);
- EXPECT_EQ(RECORD_CONTINUOUSLY, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("included,inc_pattern*,-excluded,-exc_pattern*",
- config.ToCategoryFilterString().c_str());
- EXPECT_STREQ("record-continuously", config.ToTraceOptionsString().c_str());
-}
-
-TEST(TraceConfigTest, TraceConfigFromInvalidLegacyStrings) {
- TraceConfig config("", "foo-bar-baz");
- EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
- EXPECT_FALSE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("", config.ToCategoryFilterString().c_str());
- EXPECT_STREQ("record-until-full", config.ToTraceOptionsString().c_str());
-
- config = TraceConfig("arbitrary-category", "foo-bar-baz, enable-systrace");
- EXPECT_EQ(RECORD_UNTIL_FULL, config.GetTraceRecordMode());
- EXPECT_TRUE(config.IsSystraceEnabled());
- EXPECT_FALSE(config.IsArgumentFilterEnabled());
- EXPECT_STREQ("arbitrary-category", config.ToCategoryFilterString().c_str());
- EXPECT_STREQ("record-until-full,enable-systrace",
- config.ToTraceOptionsString().c_str());
-}
-
-TEST(TraceConfigTest, ConstructDefaultTraceConfig) {
- TraceConfig tc;
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
- EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
- CheckDefaultTraceConfigBehavior(tc);
-
- // Constructors from category filter string and trace option string.
- TraceConfig tc_asterisk("*", "");
- EXPECT_STREQ("*", tc_asterisk.ToCategoryFilterString().c_str());
- CheckDefaultTraceConfigBehavior(tc_asterisk);
-
- TraceConfig tc_empty_category_filter("", "");
- EXPECT_STREQ("", tc_empty_category_filter.ToCategoryFilterString().c_str());
- EXPECT_STREQ(kDefaultTraceConfigString,
- tc_empty_category_filter.ToString().c_str());
- CheckDefaultTraceConfigBehavior(tc_empty_category_filter);
-
- // Constructor from JSON formated config string.
- TraceConfig tc_empty_json_string("");
- EXPECT_STREQ("", tc_empty_json_string.ToCategoryFilterString().c_str());
- EXPECT_STREQ(kDefaultTraceConfigString,
- tc_empty_json_string.ToString().c_str());
- CheckDefaultTraceConfigBehavior(tc_empty_json_string);
-
- // Constructor from dictionary value.
- DictionaryValue dict;
- TraceConfig tc_dict(dict);
- EXPECT_STREQ("", tc_dict.ToCategoryFilterString().c_str());
- EXPECT_STREQ(kDefaultTraceConfigString, tc_dict.ToString().c_str());
- CheckDefaultTraceConfigBehavior(tc_dict);
-}
-
-TEST(TraceConfigTest, EmptyAndAsteriskCategoryFilterString) {
- TraceConfig tc_empty("", "");
- TraceConfig tc_asterisk("*", "");
-
- EXPECT_STREQ("", tc_empty.ToCategoryFilterString().c_str());
- EXPECT_STREQ("*", tc_asterisk.ToCategoryFilterString().c_str());
-
- // Both fall back to default config.
- CheckDefaultTraceConfigBehavior(tc_empty);
- CheckDefaultTraceConfigBehavior(tc_asterisk);
-
- // They differ only for internal checking.
- EXPECT_FALSE(tc_empty.category_filter().IsCategoryEnabled("Category1"));
- EXPECT_FALSE(
- tc_empty.category_filter().IsCategoryEnabled("not-excluded-category"));
- EXPECT_TRUE(tc_asterisk.category_filter().IsCategoryEnabled("Category1"));
- EXPECT_TRUE(
- tc_asterisk.category_filter().IsCategoryEnabled("not-excluded-category"));
-}
-
-TEST(TraceConfigTest, DisabledByDefaultCategoryFilterString) {
- TraceConfig tc("foo,disabled-by-default-foo", "");
- EXPECT_STREQ("foo,disabled-by-default-foo",
- tc.ToCategoryFilterString().c_str());
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("foo"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-foo"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("bar"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-bar"));
-
- EXPECT_TRUE(tc.event_filters().empty());
- // Enabling only the disabled-by-default-* category means the default ones
- // are also enabled.
- tc = TraceConfig("disabled-by-default-foo", "");
- EXPECT_STREQ("disabled-by-default-foo", tc.ToCategoryFilterString().c_str());
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-foo"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("foo"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("bar"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-bar"));
-}
-
-TEST(TraceConfigTest, TraceConfigFromDict) {
- // Passing in empty dictionary will result in default trace config.
- DictionaryValue dict;
- TraceConfig tc(dict);
- EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
-
- std::unique_ptr<Value> default_value(
- JSONReader::Read(kDefaultTraceConfigString));
- DCHECK(default_value);
- const DictionaryValue* default_dict = nullptr;
- bool is_dict = default_value->GetAsDictionary(&default_dict);
- DCHECK(is_dict);
- TraceConfig default_tc(*default_dict);
- EXPECT_STREQ(kDefaultTraceConfigString, default_tc.ToString().c_str());
- EXPECT_EQ(RECORD_UNTIL_FULL, default_tc.GetTraceRecordMode());
- EXPECT_FALSE(default_tc.IsSystraceEnabled());
- EXPECT_FALSE(default_tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", default_tc.ToCategoryFilterString().c_str());
-
- std::unique_ptr<Value> custom_value(
- JSONReader::Read(kCustomTraceConfigString));
- DCHECK(custom_value);
- const DictionaryValue* custom_dict = nullptr;
- is_dict = custom_value->GetAsDictionary(&custom_dict);
- DCHECK(is_dict);
- TraceConfig custom_tc(*custom_dict);
- EXPECT_STREQ(kCustomTraceConfigString, custom_tc.ToString().c_str());
- EXPECT_EQ(RECORD_CONTINUOUSLY, custom_tc.GetTraceRecordMode());
- EXPECT_TRUE(custom_tc.IsSystraceEnabled());
- EXPECT_TRUE(custom_tc.IsArgumentFilterEnabled());
- EXPECT_STREQ(
- "included,inc_pattern*,"
- "disabled-by-default-cc,disabled-by-default-memory-infra,"
- "-excluded,-exc_pattern*",
- custom_tc.ToCategoryFilterString().c_str());
-}
-
-TEST(TraceConfigTest, TraceConfigFromValidString) {
- // Using some non-empty config string.
- const char config_string[] =
- "{"
- "\"enable_argument_filter\":true,"
- "\"enable_systrace\":true,"
- "\"event_filters\":["
- "{"
- "\"excluded_categories\":[\"unfiltered_cat\"],"
- "\"filter_args\":{\"event_name_whitelist\":[\"a snake\",\"a dog\"]},"
- "\"filter_predicate\":\"event_whitelist_predicate\","
- "\"included_categories\":[\"*\"]"
- "}"
- "],"
- "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
- "\"included_categories\":[\"included\","
- "\"inc_pattern*\","
- "\"disabled-by-default-cc\"],"
- "\"record_mode\":\"record-continuously\""
- "}";
- TraceConfig tc(config_string);
-
- EXPECT_STREQ(config_string, tc.ToString().c_str());
- EXPECT_EQ(RECORD_CONTINUOUSLY, tc.GetTraceRecordMode());
- EXPECT_TRUE(tc.IsSystraceEnabled());
- EXPECT_TRUE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ(
- "included,inc_pattern*,disabled-by-default-cc,-excluded,"
- "-exc_pattern*",
- tc.ToCategoryFilterString().c_str());
-
- EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("included"));
- EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("inc_pattern_category"));
- EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("disabled-by-default-cc"));
- EXPECT_FALSE(tc.category_filter().IsCategoryEnabled("excluded"));
- EXPECT_FALSE(tc.category_filter().IsCategoryEnabled("exc_pattern_category"));
- EXPECT_FALSE(
- tc.category_filter().IsCategoryEnabled("disabled-by-default-others"));
- EXPECT_FALSE(
- tc.category_filter().IsCategoryEnabled("not-excluded-nor-included"));
-
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("included"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("inc_pattern_category"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("exc_pattern_category"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("disabled-by-default-others"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("not-excluded-nor-included"));
-
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("included,excluded"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded,exc_pattern_category"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("included"));
-
- EXPECT_EQ(tc.event_filters().size(), 1u);
- const TraceConfig::EventFilterConfig& event_filter = tc.event_filters()[0];
- EXPECT_STREQ("event_whitelist_predicate",
- event_filter.predicate_name().c_str());
- EXPECT_EQ(1u, event_filter.category_filter().included_categories().size());
- EXPECT_STREQ("*",
- event_filter.category_filter().included_categories()[0].c_str());
- EXPECT_EQ(1u, event_filter.category_filter().excluded_categories().size());
- EXPECT_STREQ("unfiltered_cat",
- event_filter.category_filter().excluded_categories()[0].c_str());
- EXPECT_TRUE(event_filter.filter_args());
-
- std::string json_out;
- base::JSONWriter::Write(*event_filter.filter_args(), &json_out);
- EXPECT_STREQ(json_out.c_str(),
- "{\"event_name_whitelist\":[\"a snake\",\"a dog\"]}");
- std::unordered_set<std::string> filter_values;
- EXPECT_TRUE(event_filter.GetArgAsSet("event_name_whitelist", &filter_values));
- EXPECT_EQ(2u, filter_values.size());
- EXPECT_EQ(1u, filter_values.count("a snake"));
- EXPECT_EQ(1u, filter_values.count("a dog"));
-
- const char config_string_2[] = "{\"included_categories\":[\"*\"]}";
- TraceConfig tc2(config_string_2);
- EXPECT_TRUE(tc2.category_filter().IsCategoryEnabled(
- "non-disabled-by-default-pattern"));
- EXPECT_FALSE(
- tc2.category_filter().IsCategoryEnabled("disabled-by-default-pattern"));
- EXPECT_TRUE(tc2.IsCategoryGroupEnabled("non-disabled-by-default-pattern"));
- EXPECT_FALSE(tc2.IsCategoryGroupEnabled("disabled-by-default-pattern"));
-
- // Clear
- tc.Clear();
- EXPECT_STREQ(tc.ToString().c_str(),
- "{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"record_mode\":\"record-until-full\""
- "}");
-}
-
-TEST(TraceConfigTest, TraceConfigFromInvalidString) {
- // The config string needs to be a dictionary correctly formatted as a JSON
- // string. Otherwise, it will fall back to the default initialization.
- TraceConfig tc("");
- EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
- CheckDefaultTraceConfigBehavior(tc);
-
- tc = TraceConfig("This is an invalid config string.");
- EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
- CheckDefaultTraceConfigBehavior(tc);
-
- tc = TraceConfig("[\"This\", \"is\", \"not\", \"a\", \"dictionary\"]");
- EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
- CheckDefaultTraceConfigBehavior(tc);
-
- tc = TraceConfig("{\"record_mode\": invalid-value-needs-double-quote}");
- EXPECT_STREQ(kDefaultTraceConfigString, tc.ToString().c_str());
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
- CheckDefaultTraceConfigBehavior(tc);
-
- // If the config string a dictionary formatted as a JSON string, it will
- // initialize TraceConfig with best effort.
- tc = TraceConfig("{}");
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
- CheckDefaultTraceConfigBehavior(tc);
-
- tc = TraceConfig("{\"arbitrary-key\":\"arbitrary-value\"}");
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
- EXPECT_STREQ("", tc.ToCategoryFilterString().c_str());
- CheckDefaultTraceConfigBehavior(tc);
-
- const char invalid_config_string[] =
- "{"
- "\"enable_systrace\":1,"
- "\"excluded_categories\":[\"excluded\"],"
- "\"included_categories\":\"not a list\","
- "\"record_mode\":\"arbitrary-mode\""
- "}";
- tc = TraceConfig(invalid_config_string);
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
- EXPECT_FALSE(tc.IsArgumentFilterEnabled());
-
- const char invalid_config_string_2[] =
- "{"
- "\"included_categories\":[\"category\",\"disabled-by-default-pattern\"],"
- "\"excluded_categories\":[\"category\",\"disabled-by-default-pattern\"]"
- "}";
- tc = TraceConfig(invalid_config_string_2);
- EXPECT_TRUE(tc.category_filter().IsCategoryEnabled("category"));
- EXPECT_TRUE(
- tc.category_filter().IsCategoryEnabled("disabled-by-default-pattern"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("category"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-pattern"));
-}
-
-TEST(TraceConfigTest, MergingTraceConfigs) {
- // Merge
- TraceConfig tc;
- TraceConfig tc2("included,-excluded,inc_pattern*,-exc_pattern*", "");
- tc.Merge(tc2);
- EXPECT_STREQ("{"
- "\"enable_argument_filter\":false,"
- "\"enable_systrace\":false,"
- "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
- "\"record_mode\":\"record-until-full\""
- "}",
- tc.ToString().c_str());
-}
-
-TEST(TraceConfigTest, IsCategoryGroupEnabled) {
- // Enabling a disabled- category does not require all categories to be traced
- // to be included.
- TraceConfig tc("disabled-by-default-cc,-excluded", "");
- EXPECT_STREQ("disabled-by-default-cc,-excluded",
- tc.ToCategoryFilterString().c_str());
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("some_other_group"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded"));
-
- // Enabled a disabled- category and also including makes all categories to
- // be traced require including.
- tc = TraceConfig("disabled-by-default-cc,included", "");
- EXPECT_STREQ("included,disabled-by-default-cc",
- tc.ToCategoryFilterString().c_str());
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("disabled-by-default-cc"));
- EXPECT_TRUE(tc.IsCategoryGroupEnabled("included"));
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("other_included"));
-
- // Excluding categories won't enable disabled-by-default ones with the
- // excluded category is also present in the group.
- tc = TraceConfig("-excluded", "");
- EXPECT_STREQ("-excluded", tc.ToCategoryFilterString().c_str());
- EXPECT_FALSE(tc.IsCategoryGroupEnabled("excluded,disabled-by-default-cc"));
-}
-
-TEST(TraceConfigTest, IsCategoryNameAllowed) {
- // Test that IsCategoryNameAllowed actually catches categories that are
- // explicitly forbidden. This method is called in a DCHECK to assert that we
- // don't have these types of strings as categories.
- EXPECT_FALSE(
- TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category "));
- EXPECT_FALSE(
- TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category"));
- EXPECT_FALSE(
- TraceConfigCategoryFilter::IsCategoryNameAllowed("bad_category "));
- EXPECT_FALSE(
- TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category"));
- EXPECT_FALSE(
- TraceConfigCategoryFilter::IsCategoryNameAllowed("bad_category "));
- EXPECT_FALSE(
- TraceConfigCategoryFilter::IsCategoryNameAllowed(" bad_category "));
- EXPECT_FALSE(TraceConfigCategoryFilter::IsCategoryNameAllowed(""));
- EXPECT_TRUE(
- TraceConfigCategoryFilter::IsCategoryNameAllowed("good_category"));
-}
-
-TEST(TraceConfigTest, SetTraceOptionValues) {
- TraceConfig tc;
- EXPECT_EQ(RECORD_UNTIL_FULL, tc.GetTraceRecordMode());
- EXPECT_FALSE(tc.IsSystraceEnabled());
-
- tc.SetTraceRecordMode(RECORD_AS_MUCH_AS_POSSIBLE);
- EXPECT_EQ(RECORD_AS_MUCH_AS_POSSIBLE, tc.GetTraceRecordMode());
-
- tc.EnableSystrace();
- EXPECT_TRUE(tc.IsSystraceEnabled());
-}
-
-TEST(TraceConfigTest, TraceConfigFromMemoryConfigString) {
- std::string tc_str1 =
- TraceConfigMemoryTestUtil::GetTraceConfig_PeriodicTriggers(200, 2000);
- TraceConfig tc1(tc_str1);
- EXPECT_EQ(tc_str1, tc1.ToString());
- TraceConfig tc2(
- TraceConfigMemoryTestUtil::GetTraceConfig_LegacyPeriodicTriggers(200,
- 2000));
- EXPECT_EQ(tc_str1, tc2.ToString());
-
- EXPECT_TRUE(tc1.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
- ASSERT_EQ(2u, tc1.memory_dump_config().triggers.size());
-
- EXPECT_EQ(200u,
- tc1.memory_dump_config().triggers[0].min_time_between_dumps_ms);
- EXPECT_EQ(MemoryDumpLevelOfDetail::LIGHT,
- tc1.memory_dump_config().triggers[0].level_of_detail);
-
- EXPECT_EQ(2000u,
- tc1.memory_dump_config().triggers[1].min_time_between_dumps_ms);
- EXPECT_EQ(MemoryDumpLevelOfDetail::DETAILED,
- tc1.memory_dump_config().triggers[1].level_of_detail);
- EXPECT_EQ(
- 2048u,
- tc1.memory_dump_config().heap_profiler_options.breakdown_threshold_bytes);
-
- std::string tc_str3 =
- TraceConfigMemoryTestUtil::GetTraceConfig_BackgroundTrigger(
- 1 /* period_ms */);
- TraceConfig tc3(tc_str3);
- EXPECT_EQ(tc_str3, tc3.ToString());
- EXPECT_TRUE(tc3.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
- ASSERT_EQ(1u, tc3.memory_dump_config().triggers.size());
- EXPECT_EQ(1u, tc3.memory_dump_config().triggers[0].min_time_between_dumps_ms);
- EXPECT_EQ(MemoryDumpLevelOfDetail::BACKGROUND,
- tc3.memory_dump_config().triggers[0].level_of_detail);
-}
-
-TEST(TraceConfigTest, EmptyMemoryDumpConfigTest) {
- // Empty trigger list should also be specified when converting back to string.
- TraceConfig tc(TraceConfigMemoryTestUtil::GetTraceConfig_EmptyTriggers());
- EXPECT_EQ(TraceConfigMemoryTestUtil::GetTraceConfig_EmptyTriggers(),
- tc.ToString());
- EXPECT_EQ(0u, tc.memory_dump_config().triggers.size());
- EXPECT_EQ(
- static_cast<uint32_t>(TraceConfig::MemoryDumpConfig::HeapProfiler::
- kDefaultBreakdownThresholdBytes),
- tc.memory_dump_config().heap_profiler_options.breakdown_threshold_bytes);
-}
-
-TEST(TraceConfigTest, LegacyStringToMemoryDumpConfig) {
- TraceConfig tc(MemoryDumpManager::kTraceCategory, "");
- EXPECT_TRUE(tc.IsCategoryGroupEnabled(MemoryDumpManager::kTraceCategory));
- EXPECT_NE(std::string::npos, tc.ToString().find("memory_dump_config"));
- EXPECT_EQ(0u, tc.memory_dump_config().triggers.size());
- EXPECT_EQ(
- static_cast<uint32_t>(TraceConfig::MemoryDumpConfig::HeapProfiler::
- kDefaultBreakdownThresholdBytes),
- tc.memory_dump_config().heap_profiler_options.breakdown_threshold_bytes);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
index 016c8ea864..1ce76d9d2a 100644
--- a/base/trace_event/trace_event.h
+++ b/base/trace_event/trace_event.h
@@ -23,12 +23,6 @@ template <typename... Args> void Ignore(Args&&... args) {}
#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(...) \
INTERNAL_IGNORE(__VA_ARGS__)
#define TRACE_ID_MANGLE(val) (val)
-#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(...) INTERNAL_IGNORE(__VA_ARGS__)
-#define INTERNAL_TRACE_EVENT_GET_CATEGORY_ENABLED(...) \
- INTERNAL_IGNORE(__VA_ARGS__)
-#define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE(...) \
- false
-#define INTERNAL_TRACE_EVENT_ADD(...) INTERNAL_IGNORE(__VA_ARGS__)
namespace base {
namespace trace_event {
diff --git a/base/trace_event/trace_event_android.cc b/base/trace_event/trace_event_android.cc
deleted file mode 100644
index 30d9c74a6d..0000000000
--- a/base/trace_event/trace_event_android.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/trace_event/trace_event_impl.h"
-
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-int g_atrace_fd = -1;
-const char kATraceMarkerFile[] = "/sys/kernel/debug/tracing/trace_marker";
-
-void WriteToATrace(int fd, const char* buffer, size_t size) {
- size_t total_written = 0;
- while (total_written < size) {
- ssize_t written = HANDLE_EINTR(write(
- fd, buffer + total_written, size - total_written));
- if (written <= 0)
- break;
- total_written += written;
- }
- if (total_written < size) {
- PLOG(WARNING) << "Failed to write buffer '" << std::string(buffer, size)
- << "' to " << kATraceMarkerFile;
- }
-}
-
-void WriteEvent(
- char phase,
- const char* category_group,
- const char* name,
- unsigned long long id,
- const char** arg_names,
- const unsigned char* arg_types,
- const TraceEvent::TraceValue* arg_values,
- const std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name);
- if (flags & TRACE_EVENT_FLAG_HAS_ID)
- StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id));
- out += '|';
-
- for (int i = 0; i < kTraceMaxNumArgs && arg_names[i];
- ++i) {
- if (i)
- out += ';';
- out += arg_names[i];
- out += '=';
- std::string::size_type value_start = out.length();
- if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
- convertable_values[i]->AppendAsTraceFormat(&out);
- else
- TraceEvent::AppendValueAsJSON(arg_types[i], arg_values[i], &out);
-
- // Remove the quotes which may confuse the atrace script.
- ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'");
- ReplaceSubstringsAfterOffset(&out, value_start, "\"", "");
- // Replace chars used for separators with similar chars in the value.
- std::replace(out.begin() + value_start, out.end(), ';', ',');
- std::replace(out.begin() + value_start, out.end(), '|', '!');
- }
-
- out += '|';
- out += category_group;
- WriteToATrace(g_atrace_fd, out.c_str(), out.size());
-}
-
-void NoOpOutputCallback(WaitableEvent* complete_event,
- const scoped_refptr<RefCountedString>&,
- bool has_more_events) {
- if (!has_more_events)
- complete_event->Signal();
-}
-
-void EndChromeTracing(TraceLog* trace_log,
- WaitableEvent* complete_event) {
- trace_log->SetDisabled();
- // Delete the buffered trace events as they have been sent to atrace.
- trace_log->Flush(Bind(&NoOpOutputCallback, complete_event));
-}
-
-} // namespace
-
-// These functions support Android systrace.py when 'webview' category is
-// traced. With the new adb_profile_chrome, we may have two phases:
-// - before WebView is ready for combined tracing, we can use adb_profile_chrome
-// to trace android categories other than 'webview' and chromium categories.
-// In this way we can avoid the conflict between StartATrace/StopATrace and
-// the intents.
-// - TODO(wangxianzhu): after WebView is ready for combined tracing, remove
-// StartATrace, StopATrace and SendToATrace, and perhaps send Java traces
-// directly to atrace in trace_event_binding.cc.
-
-void TraceLog::StartATrace() {
- if (g_atrace_fd != -1)
- return;
-
- g_atrace_fd = HANDLE_EINTR(open(kATraceMarkerFile, O_WRONLY));
- if (g_atrace_fd == -1) {
- PLOG(WARNING) << "Couldn't open " << kATraceMarkerFile;
- return;
- }
- TraceConfig trace_config;
- trace_config.SetTraceRecordMode(RECORD_CONTINUOUSLY);
- SetEnabled(trace_config, TraceLog::RECORDING_MODE);
-}
-
-void TraceLog::StopATrace() {
- if (g_atrace_fd == -1)
- return;
-
- close(g_atrace_fd);
- g_atrace_fd = -1;
-
- // TraceLog::Flush() requires the current thread to have a message loop, but
- // this thread called from Java may not have one, so flush in another thread.
- Thread end_chrome_tracing_thread("end_chrome_tracing");
- WaitableEvent complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- end_chrome_tracing_thread.Start();
- end_chrome_tracing_thread.task_runner()->PostTask(
- FROM_HERE, base::Bind(&EndChromeTracing, Unretained(this),
- Unretained(&complete_event)));
- complete_event.Wait();
-}
-
-void TraceEvent::SendToATrace() {
- if (g_atrace_fd == -1)
- return;
-
- const char* category_group =
- TraceLog::GetCategoryGroupName(category_group_enabled_);
-
- switch (phase_) {
- case TRACE_EVENT_PHASE_BEGIN:
- WriteEvent('B', category_group, name_, id_,
- arg_names_, arg_types_, arg_values_, convertable_values_,
- flags_);
- break;
-
- case TRACE_EVENT_PHASE_COMPLETE:
- WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E',
- category_group, name_, id_,
- arg_names_, arg_types_, arg_values_, convertable_values_,
- flags_);
- break;
-
- case TRACE_EVENT_PHASE_END:
- // Though a single 'E' is enough, here append pid, name and
- // category_group etc. So that unpaired events can be found easily.
- WriteEvent('E', category_group, name_, id_,
- arg_names_, arg_types_, arg_values_, convertable_values_,
- flags_);
- break;
-
- case TRACE_EVENT_PHASE_INSTANT:
- // Simulate an instance event with a pair of begin/end events.
- WriteEvent('B', category_group, name_, id_,
- arg_names_, arg_types_, arg_values_, convertable_values_,
- flags_);
- WriteToATrace(g_atrace_fd, "E", 1);
- break;
-
- case TRACE_EVENT_PHASE_COUNTER:
- for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
- DCHECK(arg_types_[i] == TRACE_VALUE_TYPE_INT);
- std::string out = base::StringPrintf(
- "C|%d|%s-%s", getpid(), name_, arg_names_[i]);
- if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
- StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id_));
- StringAppendF(&out, "|%d|%s",
- static_cast<int>(arg_values_[i].as_int), category_group);
- WriteToATrace(g_atrace_fd, out.c_str(), out.size());
- }
- break;
-
- default:
- // Do nothing.
- break;
- }
-}
-
-void TraceLog::AddClockSyncMetadataEvent() {
- int atrace_fd = HANDLE_EINTR(open(kATraceMarkerFile, O_WRONLY | O_APPEND));
- if (atrace_fd == -1) {
- PLOG(WARNING) << "Couldn't open " << kATraceMarkerFile;
- return;
- }
-
- // Android's kernel trace system has a trace_marker feature: this is a file on
- // debugfs that takes the written data and pushes it onto the trace
- // buffer. So, to establish clock sync, we write our monotonic clock into that
- // trace buffer.
- double now_in_seconds = (TRACE_TIME_TICKS_NOW() - TimeTicks()).InSecondsF();
- std::string marker = StringPrintf(
- "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds);
- WriteToATrace(atrace_fd, marker.c_str(), marker.size());
- close(atrace_fd);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_android_unittest.cc b/base/trace_event/trace_event_android_unittest.cc
deleted file mode 100644
index 58bd77ed93..0000000000
--- a/base/trace_event/trace_event_android_unittest.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2015 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/trace_event/trace_event.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-TEST(TraceEventAndroidTest, WriteToATrace) {
- // Just a smoke test to ensure no crash.
- TraceLog* trace_log = TraceLog::GetInstance();
- trace_log->StartATrace();
- TRACE_EVENT0("test", "test-event");
- trace_log->StopATrace();
- trace_log->AddClockSyncMetadataEvent();
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_argument.cc b/base/trace_event/trace_event_argument.cc
deleted file mode 100644
index e614b272d5..0000000000
--- a/base/trace_event/trace_event_argument.cc
+++ /dev/null
@@ -1,576 +0,0 @@
-// Copyright (c) 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/trace_event/trace_event_argument.h"
-
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/bits.h"
-#include "base/containers/circular_deque.h"
-#include "base/json/string_escape.h"
-#include "base/memory/ptr_util.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "base/trace_event/trace_event_memory_overhead.h"
-#include "base/values.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-const char kTypeStartDict = '{';
-const char kTypeEndDict = '}';
-const char kTypeStartArray = '[';
-const char kTypeEndArray = ']';
-const char kTypeBool = 'b';
-const char kTypeInt = 'i';
-const char kTypeDouble = 'd';
-const char kTypeString = 's';
-const char kTypeCStr = '*'; // only used for key names
-
-#ifndef NDEBUG
-const bool kStackTypeDict = false;
-const bool kStackTypeArray = true;
-#define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back())
-#define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size())
-#define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x)
-#define DEBUG_POP_CONTAINER() nesting_stack_.pop_back()
-#else
-#define DCHECK_CURRENT_CONTAINER_IS(x) do {} while (0)
-#define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) do {} while (0)
-#define DEBUG_PUSH_CONTAINER(x) do {} while (0)
-#define DEBUG_POP_CONTAINER() do {} while (0)
-#endif
-
-inline void WriteKeyNameAsRawPtr(Pickle& pickle, const char* ptr) {
- pickle.WriteBytes(&kTypeCStr, 1);
- pickle.WriteUInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr)));
-}
-
-inline void WriteKeyNameWithCopy(Pickle& pickle, base::StringPiece str) {
- pickle.WriteBytes(&kTypeString, 1);
- pickle.WriteString(str);
-}
-
-std::string ReadKeyName(PickleIterator& pickle_iterator) {
- const char* type = nullptr;
- bool res = pickle_iterator.ReadBytes(&type, 1);
- std::string key_name;
- if (res && *type == kTypeCStr) {
- uint64_t ptr_value = 0;
- res = pickle_iterator.ReadUInt64(&ptr_value);
- key_name = reinterpret_cast<const char*>(static_cast<uintptr_t>(ptr_value));
- } else if (res && *type == kTypeString) {
- res = pickle_iterator.ReadString(&key_name);
- }
- DCHECK(res);
- return key_name;
-}
-} // namespace
-
-TracedValue::TracedValue() : TracedValue(0) {
-}
-
-TracedValue::TracedValue(size_t capacity) {
- DEBUG_PUSH_CONTAINER(kStackTypeDict);
- if (capacity)
- pickle_.Reserve(capacity);
-}
-
-TracedValue::~TracedValue() {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- DEBUG_POP_CONTAINER();
- DCHECK_CONTAINER_STACK_DEPTH_EQ(0u);
-}
-
-void TracedValue::SetInteger(const char* name, int value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeInt, 1);
- pickle_.WriteInt(value);
- WriteKeyNameAsRawPtr(pickle_, name);
-}
-
-void TracedValue::SetIntegerWithCopiedName(base::StringPiece name, int value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeInt, 1);
- pickle_.WriteInt(value);
- WriteKeyNameWithCopy(pickle_, name);
-}
-
-void TracedValue::SetDouble(const char* name, double value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeDouble, 1);
- pickle_.WriteDouble(value);
- WriteKeyNameAsRawPtr(pickle_, name);
-}
-
-void TracedValue::SetDoubleWithCopiedName(base::StringPiece name,
- double value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeDouble, 1);
- pickle_.WriteDouble(value);
- WriteKeyNameWithCopy(pickle_, name);
-}
-
-void TracedValue::SetBoolean(const char* name, bool value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeBool, 1);
- pickle_.WriteBool(value);
- WriteKeyNameAsRawPtr(pickle_, name);
-}
-
-void TracedValue::SetBooleanWithCopiedName(base::StringPiece name,
- bool value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeBool, 1);
- pickle_.WriteBool(value);
- WriteKeyNameWithCopy(pickle_, name);
-}
-
-void TracedValue::SetString(const char* name, base::StringPiece value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeString, 1);
- pickle_.WriteString(value);
- WriteKeyNameAsRawPtr(pickle_, name);
-}
-
-void TracedValue::SetStringWithCopiedName(base::StringPiece name,
- base::StringPiece value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- pickle_.WriteBytes(&kTypeString, 1);
- pickle_.WriteString(value);
- WriteKeyNameWithCopy(pickle_, name);
-}
-
-void TracedValue::SetValue(const char* name, const TracedValue& value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- BeginDictionary(name);
- pickle_.WriteBytes(value.pickle_.payload(),
- static_cast<int>(value.pickle_.payload_size()));
- EndDictionary();
-}
-
-void TracedValue::SetValueWithCopiedName(base::StringPiece name,
- const TracedValue& value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- BeginDictionaryWithCopiedName(name);
- pickle_.WriteBytes(value.pickle_.payload(),
- static_cast<int>(value.pickle_.payload_size()));
- EndDictionary();
-}
-
-void TracedValue::BeginDictionary(const char* name) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- DEBUG_PUSH_CONTAINER(kStackTypeDict);
- pickle_.WriteBytes(&kTypeStartDict, 1);
- WriteKeyNameAsRawPtr(pickle_, name);
-}
-
-void TracedValue::BeginDictionaryWithCopiedName(base::StringPiece name) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- DEBUG_PUSH_CONTAINER(kStackTypeDict);
- pickle_.WriteBytes(&kTypeStartDict, 1);
- WriteKeyNameWithCopy(pickle_, name);
-}
-
-void TracedValue::BeginArray(const char* name) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- DEBUG_PUSH_CONTAINER(kStackTypeArray);
- pickle_.WriteBytes(&kTypeStartArray, 1);
- WriteKeyNameAsRawPtr(pickle_, name);
-}
-
-void TracedValue::BeginArrayWithCopiedName(base::StringPiece name) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- DEBUG_PUSH_CONTAINER(kStackTypeArray);
- pickle_.WriteBytes(&kTypeStartArray, 1);
- WriteKeyNameWithCopy(pickle_, name);
-}
-
-void TracedValue::EndDictionary() {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- DEBUG_POP_CONTAINER();
- pickle_.WriteBytes(&kTypeEndDict, 1);
-}
-
-void TracedValue::AppendInteger(int value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- pickle_.WriteBytes(&kTypeInt, 1);
- pickle_.WriteInt(value);
-}
-
-void TracedValue::AppendDouble(double value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- pickle_.WriteBytes(&kTypeDouble, 1);
- pickle_.WriteDouble(value);
-}
-
-void TracedValue::AppendBoolean(bool value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- pickle_.WriteBytes(&kTypeBool, 1);
- pickle_.WriteBool(value);
-}
-
-void TracedValue::AppendString(base::StringPiece value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- pickle_.WriteBytes(&kTypeString, 1);
- pickle_.WriteString(value);
-}
-
-void TracedValue::BeginArray() {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- DEBUG_PUSH_CONTAINER(kStackTypeArray);
- pickle_.WriteBytes(&kTypeStartArray, 1);
-}
-
-void TracedValue::BeginDictionary() {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- DEBUG_PUSH_CONTAINER(kStackTypeDict);
- pickle_.WriteBytes(&kTypeStartDict, 1);
-}
-
-void TracedValue::EndArray() {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- DEBUG_POP_CONTAINER();
- pickle_.WriteBytes(&kTypeEndArray, 1);
-}
-
-void TracedValue::SetValue(const char* name,
- std::unique_ptr<base::Value> value) {
- SetBaseValueWithCopiedName(name, *value);
-}
-
-void TracedValue::SetBaseValueWithCopiedName(base::StringPiece name,
- const base::Value& value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- switch (value.type()) {
- case base::Value::Type::NONE:
- case base::Value::Type::BINARY:
- NOTREACHED();
- break;
-
- case base::Value::Type::BOOLEAN: {
- bool bool_value;
- value.GetAsBoolean(&bool_value);
- SetBooleanWithCopiedName(name, bool_value);
- } break;
-
- case base::Value::Type::INTEGER: {
- int int_value;
- value.GetAsInteger(&int_value);
- SetIntegerWithCopiedName(name, int_value);
- } break;
-
- case base::Value::Type::DOUBLE: {
- double double_value;
- value.GetAsDouble(&double_value);
- SetDoubleWithCopiedName(name, double_value);
- } break;
-
- case base::Value::Type::STRING: {
- const Value* string_value;
- value.GetAsString(&string_value);
- SetStringWithCopiedName(name, string_value->GetString());
- } break;
-
- case base::Value::Type::DICTIONARY: {
- const DictionaryValue* dict_value;
- value.GetAsDictionary(&dict_value);
- BeginDictionaryWithCopiedName(name);
- for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd();
- it.Advance()) {
- SetBaseValueWithCopiedName(it.key(), it.value());
- }
- EndDictionary();
- } break;
-
- case base::Value::Type::LIST: {
- const ListValue* list_value;
- value.GetAsList(&list_value);
- BeginArrayWithCopiedName(name);
- for (const auto& base_value : *list_value)
- AppendBaseValue(base_value);
- EndArray();
- } break;
- }
-}
-
-void TracedValue::AppendBaseValue(const base::Value& value) {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
- switch (value.type()) {
- case base::Value::Type::NONE:
- case base::Value::Type::BINARY:
- NOTREACHED();
- break;
-
- case base::Value::Type::BOOLEAN: {
- bool bool_value;
- value.GetAsBoolean(&bool_value);
- AppendBoolean(bool_value);
- } break;
-
- case base::Value::Type::INTEGER: {
- int int_value;
- value.GetAsInteger(&int_value);
- AppendInteger(int_value);
- } break;
-
- case base::Value::Type::DOUBLE: {
- double double_value;
- value.GetAsDouble(&double_value);
- AppendDouble(double_value);
- } break;
-
- case base::Value::Type::STRING: {
- const Value* string_value;
- value.GetAsString(&string_value);
- AppendString(string_value->GetString());
- } break;
-
- case base::Value::Type::DICTIONARY: {
- const DictionaryValue* dict_value;
- value.GetAsDictionary(&dict_value);
- BeginDictionary();
- for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd();
- it.Advance()) {
- SetBaseValueWithCopiedName(it.key(), it.value());
- }
- EndDictionary();
- } break;
-
- case base::Value::Type::LIST: {
- const ListValue* list_value;
- value.GetAsList(&list_value);
- BeginArray();
- for (const auto& base_value : *list_value)
- AppendBaseValue(base_value);
- EndArray();
- } break;
- }
-}
-
-std::unique_ptr<base::Value> TracedValue::ToBaseValue() const {
- base::Value root(base::Value::Type::DICTIONARY);
- Value* cur_dict = &root;
- Value* cur_list = nullptr;
- std::vector<Value*> stack;
- PickleIterator it(pickle_);
- const char* type;
-
- while (it.ReadBytes(&type, 1)) {
- DCHECK((cur_dict && !cur_list) || (cur_list && !cur_dict));
- switch (*type) {
- case kTypeStartDict: {
- base::Value new_dict(base::Value::Type::DICTIONARY);
- if (cur_dict) {
- stack.push_back(cur_dict);
- cur_dict = cur_dict->SetKey(ReadKeyName(it), std::move(new_dict));
- } else {
- cur_list->GetList().push_back(std::move(new_dict));
- // |new_dict| is invalidated at this point, so |cur_dict| needs to be
- // reset.
- cur_dict = &cur_list->GetList().back();
- stack.push_back(cur_list);
- cur_list = nullptr;
- }
- } break;
-
- case kTypeEndArray:
- case kTypeEndDict: {
- if (stack.back()->is_dict()) {
- cur_dict = stack.back();
- cur_list = nullptr;
- } else if (stack.back()->is_list()) {
- cur_list = stack.back();
- cur_dict = nullptr;
- }
- stack.pop_back();
- } break;
-
- case kTypeStartArray: {
- base::Value new_list(base::Value::Type::LIST);
- if (cur_dict) {
- stack.push_back(cur_dict);
- cur_list = cur_dict->SetKey(ReadKeyName(it), std::move(new_list));
- cur_dict = nullptr;
- } else {
- cur_list->GetList().push_back(std::move(new_list));
- stack.push_back(cur_list);
- // |cur_list| is invalidated at this point by the Append, so it needs
- // to be reset.
- cur_list = &cur_list->GetList().back();
- }
- } break;
-
- case kTypeBool: {
- bool value;
- CHECK(it.ReadBool(&value));
- base::Value new_bool(value);
- if (cur_dict) {
- cur_dict->SetKey(ReadKeyName(it), std::move(new_bool));
- } else {
- cur_list->GetList().push_back(std::move(new_bool));
- }
- } break;
-
- case kTypeInt: {
- int value;
- CHECK(it.ReadInt(&value));
- base::Value new_int(value);
- if (cur_dict) {
- cur_dict->SetKey(ReadKeyName(it), std::move(new_int));
- } else {
- cur_list->GetList().push_back(std::move(new_int));
- }
- } break;
-
- case kTypeDouble: {
- double value;
- CHECK(it.ReadDouble(&value));
- base::Value new_double(value);
- if (cur_dict) {
- cur_dict->SetKey(ReadKeyName(it), std::move(new_double));
- } else {
- cur_list->GetList().push_back(std::move(new_double));
- }
- } break;
-
- case kTypeString: {
- std::string value;
- CHECK(it.ReadString(&value));
- base::Value new_str(std::move(value));
- if (cur_dict) {
- cur_dict->SetKey(ReadKeyName(it), std::move(new_str));
- } else {
- cur_list->GetList().push_back(std::move(new_str));
- }
- } break;
-
- default:
- NOTREACHED();
- }
- }
- DCHECK(stack.empty());
- return base::Value::ToUniquePtrValue(std::move(root));
-}
-
-void TracedValue::AppendAsTraceFormat(std::string* out) const {
- DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
- DCHECK_CONTAINER_STACK_DEPTH_EQ(1u);
-
- struct State {
- enum Type { kTypeDict, kTypeArray };
- Type type;
- bool needs_comma;
- };
-
- auto maybe_append_key_name = [](State current_state, PickleIterator* it,
- std::string* out) {
- if (current_state.type == State::kTypeDict) {
- EscapeJSONString(ReadKeyName(*it), true, out);
- out->append(":");
- }
- };
-
- base::circular_deque<State> state_stack;
-
- out->append("{");
- state_stack.push_back({State::kTypeDict});
-
- PickleIterator it(pickle_);
- for (const char* type; it.ReadBytes(&type, 1);) {
- switch (*type) {
- case kTypeEndDict:
- out->append("}");
- state_stack.pop_back();
- continue;
-
- case kTypeEndArray:
- out->append("]");
- state_stack.pop_back();
- continue;
- }
-
- // Use an index so it will stay valid across resizes.
- size_t current_state_index = state_stack.size() - 1;
- if (state_stack[current_state_index].needs_comma)
- out->append(",");
-
- switch (*type) {
- case kTypeStartDict: {
- maybe_append_key_name(state_stack[current_state_index], &it, out);
- out->append("{");
- state_stack.push_back({State::kTypeDict});
- break;
- }
-
- case kTypeStartArray: {
- maybe_append_key_name(state_stack[current_state_index], &it, out);
- out->append("[");
- state_stack.push_back({State::kTypeArray});
- break;
- }
-
- case kTypeBool: {
- TraceEvent::TraceValue json_value;
- CHECK(it.ReadBool(&json_value.as_bool));
- maybe_append_key_name(state_stack[current_state_index], &it, out);
- TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_BOOL, json_value, out);
- break;
- }
-
- case kTypeInt: {
- int value;
- CHECK(it.ReadInt(&value));
- maybe_append_key_name(state_stack[current_state_index], &it, out);
- TraceEvent::TraceValue json_value;
- json_value.as_int = value;
- TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_INT, json_value, out);
- break;
- }
-
- case kTypeDouble: {
- TraceEvent::TraceValue json_value;
- CHECK(it.ReadDouble(&json_value.as_double));
- maybe_append_key_name(state_stack[current_state_index], &it, out);
- TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_DOUBLE, json_value, out);
- break;
- }
-
- case kTypeString: {
- std::string value;
- CHECK(it.ReadString(&value));
- maybe_append_key_name(state_stack[current_state_index], &it, out);
- TraceEvent::TraceValue json_value;
- json_value.as_string = value.c_str();
- TraceEvent::AppendValueAsJSON(TRACE_VALUE_TYPE_STRING, json_value, out);
- break;
- }
-
- default:
- NOTREACHED();
- }
-
- state_stack[current_state_index].needs_comma = true;
- }
-
- out->append("}");
- state_stack.pop_back();
-
- DCHECK(state_stack.empty());
-}
-
-void TracedValue::EstimateTraceMemoryOverhead(
- TraceEventMemoryOverhead* overhead) {
- overhead->Add(TraceEventMemoryOverhead::kTracedValue,
- /* allocated size */
- pickle_.GetTotalAllocatedSize(),
- /* resident size */
- pickle_.size());
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_argument.h b/base/trace_event/trace_event_argument.h
deleted file mode 100644
index 81d8c0172a..0000000000
--- a/base/trace_event/trace_event_argument.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
-#define BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/pickle.h"
-#include "base/strings/string_piece.h"
-#include "base/trace_event/trace_event_impl.h"
-
-namespace base {
-
-class Value;
-
-namespace trace_event {
-
-class BASE_EXPORT TracedValue : public ConvertableToTraceFormat {
- public:
- TracedValue();
- explicit TracedValue(size_t capacity);
- ~TracedValue() override;
-
- void EndDictionary();
- void EndArray();
-
- // These methods assume that |name| is a long lived "quoted" string.
- void SetInteger(const char* name, int value);
- void SetDouble(const char* name, double value);
- void SetBoolean(const char* name, bool value);
- void SetString(const char* name, base::StringPiece value);
- void SetValue(const char* name, const TracedValue& value);
- void BeginDictionary(const char* name);
- void BeginArray(const char* name);
-
- // These, instead, can be safely passed a temporary string.
- void SetIntegerWithCopiedName(base::StringPiece name, int value);
- void SetDoubleWithCopiedName(base::StringPiece name, double value);
- void SetBooleanWithCopiedName(base::StringPiece name, bool value);
- void SetStringWithCopiedName(base::StringPiece name,
- base::StringPiece value);
- void SetValueWithCopiedName(base::StringPiece name,
- const TracedValue& value);
- void BeginDictionaryWithCopiedName(base::StringPiece name);
- void BeginArrayWithCopiedName(base::StringPiece name);
-
- void AppendInteger(int);
- void AppendDouble(double);
- void AppendBoolean(bool);
- void AppendString(base::StringPiece);
- void BeginArray();
- void BeginDictionary();
-
- // ConvertableToTraceFormat implementation.
- void AppendAsTraceFormat(std::string* out) const override;
-
- void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override;
-
- // DEPRECATED: do not use, here only for legacy reasons. These methods causes
- // a copy-and-translation of the base::Value into the equivalent TracedValue.
- // TODO(primiano): migrate the (three) existing clients to the cheaper
- // SetValue(TracedValue) API. crbug.com/495628.
- void SetValue(const char* name, std::unique_ptr<base::Value> value);
- void SetBaseValueWithCopiedName(base::StringPiece name,
- const base::Value& value);
- void AppendBaseValue(const base::Value& value);
-
- // Public for tests only.
- std::unique_ptr<base::Value> ToBaseValue() const;
-
- private:
- Pickle pickle_;
-
-#ifndef NDEBUG
- // In debug builds checks the pairings of {Start,End}{Dictionary,Array}
- std::vector<bool> nesting_stack_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(TracedValue);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_EVENT_ARGUMENT_H_
diff --git a/base/trace_event/trace_event_argument_unittest.cc b/base/trace_event/trace_event_argument_unittest.cc
deleted file mode 100644
index 448b2d5619..0000000000
--- a/base/trace_event/trace_event_argument_unittest.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 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/trace_event/trace_event_argument.h"
-
-#include <stddef.h>
-
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-TEST(TraceEventArgumentTest, FlatDictionary) {
- std::unique_ptr<TracedValue> value(new TracedValue());
- value->SetBoolean("bool", true);
- value->SetDouble("double", 0.0);
- value->SetInteger("int", 2014);
- value->SetString("string", "string");
- std::string json = "PREFIX";
- value->AppendAsTraceFormat(&json);
- EXPECT_EQ(
- "PREFIX{\"bool\":true,\"double\":0.0,\"int\":2014,\"string\":\"string\"}",
- json);
-}
-
-TEST(TraceEventArgumentTest, NoDotPathExpansion) {
- std::unique_ptr<TracedValue> value(new TracedValue());
- value->SetBoolean("bo.ol", true);
- value->SetDouble("doub.le", 0.0);
- value->SetInteger("in.t", 2014);
- value->SetString("str.ing", "str.ing");
- std::string json;
- value->AppendAsTraceFormat(&json);
- EXPECT_EQ(
- "{\"bo.ol\":true,\"doub.le\":0.0,\"in.t\":2014,\"str.ing\":\"str.ing\"}",
- json);
-}
-
-TEST(TraceEventArgumentTest, Hierarchy) {
- std::unique_ptr<TracedValue> value(new TracedValue());
- value->BeginArray("a1");
- value->AppendInteger(1);
- value->AppendBoolean(true);
- value->BeginDictionary();
- value->SetInteger("i2", 3);
- value->EndDictionary();
- value->EndArray();
- value->SetBoolean("b0", true);
- value->SetDouble("d0", 0.0);
- value->BeginDictionary("dict1");
- value->BeginDictionary("dict2");
- value->SetBoolean("b2", false);
- value->EndDictionary();
- value->SetInteger("i1", 2014);
- value->SetString("s1", "foo");
- value->EndDictionary();
- value->SetInteger("i0", 2014);
- value->SetString("s0", "foo");
- std::string json;
- value->AppendAsTraceFormat(&json);
- EXPECT_EQ(
- "{\"a1\":[1,true,{\"i2\":3}],\"b0\":true,\"d0\":0.0,\"dict1\":{\"dict2\":"
- "{\"b2\":false},\"i1\":2014,\"s1\":\"foo\"},\"i0\":2014,\"s0\":"
- "\"foo\"}",
- json);
-}
-
-TEST(TraceEventArgumentTest, LongStrings) {
- std::string kLongString = "supercalifragilisticexpialidocious";
- std::string kLongString2 = "0123456789012345678901234567890123456789";
- char kLongString3[4096];
- for (size_t i = 0; i < sizeof(kLongString3); ++i)
- kLongString3[i] = 'a' + (i % 25);
- kLongString3[sizeof(kLongString3) - 1] = '\0';
-
- std::unique_ptr<TracedValue> value(new TracedValue());
- value->SetString("a", "short");
- value->SetString("b", kLongString);
- value->BeginArray("c");
- value->AppendString(kLongString2);
- value->AppendString("");
- value->BeginDictionary();
- value->SetString("a", kLongString3);
- value->EndDictionary();
- value->EndArray();
-
- std::string json;
- value->AppendAsTraceFormat(&json);
- EXPECT_EQ("{\"a\":\"short\",\"b\":\"" + kLongString + "\",\"c\":[\"" +
- kLongString2 + "\",\"\",{\"a\":\"" + kLongString3 + "\"}]}",
- json);
-}
-
-TEST(TraceEventArgumentTest, PassBaseValue) {
- Value int_value(42);
- Value bool_value(true);
- Value double_value(42.0f);
-
- auto dict_value = WrapUnique(new DictionaryValue);
- dict_value->SetBoolean("bool", true);
- dict_value->SetInteger("int", 42);
- dict_value->SetDouble("double", 42.0f);
- dict_value->SetString("string", std::string("a") + "b");
- dict_value->SetString("string", std::string("a") + "b");
-
- auto list_value = WrapUnique(new ListValue);
- list_value->AppendBoolean(false);
- list_value->AppendInteger(1);
- list_value->AppendString("in_list");
- list_value->Append(std::move(dict_value));
-
- std::unique_ptr<TracedValue> value(new TracedValue());
- value->BeginDictionary("outer_dict");
- value->SetValue("inner_list", std::move(list_value));
- value->EndDictionary();
-
- dict_value.reset();
- list_value.reset();
-
- std::string json;
- value->AppendAsTraceFormat(&json);
- EXPECT_EQ(
- "{\"outer_dict\":{\"inner_list\":[false,1,\"in_list\",{\"bool\":true,"
- "\"double\":42.0,\"int\":42,\"string\":\"ab\"}]}}",
- json);
-}
-
-TEST(TraceEventArgumentTest, PassTracedValue) {
- auto dict_value = std::make_unique<TracedValue>();
- dict_value->SetInteger("a", 1);
-
- auto nested_dict_value = std::make_unique<TracedValue>();
- nested_dict_value->SetInteger("b", 2);
- nested_dict_value->BeginArray("c");
- nested_dict_value->AppendString("foo");
- nested_dict_value->EndArray();
-
- dict_value->SetValue("e", *nested_dict_value);
-
- // Check the merged result.
- std::string json;
- dict_value->AppendAsTraceFormat(&json);
- EXPECT_EQ("{\"a\":1,\"e\":{\"b\":2,\"c\":[\"foo\"]}}", json);
-
- // Check that the passed nestd dict was left unouthced.
- json = "";
- nested_dict_value->AppendAsTraceFormat(&json);
- EXPECT_EQ("{\"b\":2,\"c\":[\"foo\"]}", json);
-
- // And that it is still usable.
- nested_dict_value->SetInteger("f", 3);
- nested_dict_value->BeginDictionary("g");
- nested_dict_value->EndDictionary();
- json = "";
- nested_dict_value->AppendAsTraceFormat(&json);
- EXPECT_EQ("{\"b\":2,\"c\":[\"foo\"],\"f\":3,\"g\":{}}", json);
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_filter.cc b/base/trace_event/trace_event_filter.cc
deleted file mode 100644
index d0b116ee04..0000000000
--- a/base/trace_event/trace_event_filter.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 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/trace_event/trace_event_filter.h"
-
-namespace base {
-namespace trace_event {
-
-TraceEventFilter::TraceEventFilter() = default;
-TraceEventFilter::~TraceEventFilter() = default;
-
-void TraceEventFilter::EndEvent(const char* category_name,
- const char* event_name) const {}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_filter.h b/base/trace_event/trace_event_filter.h
deleted file mode 100644
index 48c6711432..0000000000
--- a/base/trace_event/trace_event_filter.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_EVENT_FILTER_H_
-#define BASE_TRACE_EVENT_TRACE_EVENT_FILTER_H_
-
-#include <memory>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-
-namespace base {
-namespace trace_event {
-
-class TraceEvent;
-
-// TraceEventFilter is like iptables for TRACE_EVENT macros. Filters can be
-// enabled on a per-category basis, hence a single filter instance can serve
-// more than a TraceCategory. There are two use cases for filters:
-// 1. Snooping TRACE_EVENT macros without adding them to the TraceLog. This is
-// possible by setting the ENABLED_FOR_FILTERING flag on a category w/o
-// ENABLED_FOR_RECORDING (see TraceConfig for user-facing configuration).
-// 2. Filtering TRACE_EVENT macros before they are added to the TraceLog. This
-// requires both the ENABLED_FOR_FILTERING and ENABLED_FOR_RECORDING flags
-// on the category.
-// More importantly, filters must be thread-safe. The FilterTraceEvent and
-// EndEvent methods can be called concurrently as trace macros are hit on
-// different threads.
-class BASE_EXPORT TraceEventFilter {
- public:
- TraceEventFilter();
- virtual ~TraceEventFilter();
-
- // If the category is ENABLED_FOR_RECORDING, the event is added iff all the
- // filters enabled for the category return true. false causes the event to be
- // discarded.
- virtual bool FilterTraceEvent(const TraceEvent& trace_event) const = 0;
-
- // Notifies the end of a duration event when the RAII macro goes out of scope.
- virtual void EndEvent(const char* category_name,
- const char* event_name) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TraceEventFilter);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_EVENT_FILTER_H_
diff --git a/base/trace_event/trace_event_filter_test_utils.cc b/base/trace_event/trace_event_filter_test_utils.cc
deleted file mode 100644
index 85b4cfa276..0000000000
--- a/base/trace_event/trace_event_filter_test_utils.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2016 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/trace_event/trace_event_filter_test_utils.h"
-
-#include "base/logging.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-TestEventFilter::HitsCounter* g_hits_counter;
-} // namespace;
-
-// static
-const char TestEventFilter::kName[] = "testing_predicate";
-bool TestEventFilter::filter_return_value_;
-
-// static
-std::unique_ptr<TraceEventFilter> TestEventFilter::Factory(
- const std::string& predicate_name) {
- std::unique_ptr<TraceEventFilter> res;
- if (predicate_name == kName)
- res.reset(new TestEventFilter());
- return res;
-}
-
-TestEventFilter::TestEventFilter() = default;
-TestEventFilter::~TestEventFilter() = default;
-
-bool TestEventFilter::FilterTraceEvent(const TraceEvent& trace_event) const {
- if (g_hits_counter)
- g_hits_counter->filter_trace_event_hit_count++;
- return filter_return_value_;
-}
-
-void TestEventFilter::EndEvent(const char* category_name,
- const char* name) const {
- if (g_hits_counter)
- g_hits_counter->end_event_hit_count++;
-}
-
-TestEventFilter::HitsCounter::HitsCounter() {
- Reset();
- DCHECK(!g_hits_counter);
- g_hits_counter = this;
-}
-
-TestEventFilter::HitsCounter::~HitsCounter() {
- DCHECK(g_hits_counter);
- g_hits_counter = nullptr;
-}
-
-void TestEventFilter::HitsCounter::Reset() {
- filter_trace_event_hit_count = 0;
- end_event_hit_count = 0;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_filter_test_utils.h b/base/trace_event/trace_event_filter_test_utils.h
deleted file mode 100644
index 419068b221..0000000000
--- a/base/trace_event/trace_event_filter_test_utils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_EVENT_FILTER_TEST_UTILS_H_
-#define BASE_TRACE_EVENT_TRACE_EVENT_FILTER_TEST_UTILS_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/trace_event/trace_event_filter.h"
-
-namespace base {
-namespace trace_event {
-
-class TestEventFilter : public TraceEventFilter {
- public:
- struct HitsCounter {
- HitsCounter();
- ~HitsCounter();
- void Reset();
- size_t filter_trace_event_hit_count;
- size_t end_event_hit_count;
- };
-
- static const char kName[];
-
- // Factory method for TraceLog::SetFilterFactoryForTesting().
- static std::unique_ptr<TraceEventFilter> Factory(
- const std::string& predicate_name);
-
- TestEventFilter();
- ~TestEventFilter() override;
-
- // TraceEventFilter implementation.
- bool FilterTraceEvent(const TraceEvent& trace_event) const override;
- void EndEvent(const char* category_name, const char* name) const override;
-
- static void set_filter_return_value(bool value) {
- filter_return_value_ = value;
- }
-
- private:
- static bool filter_return_value_;
-
- DISALLOW_COPY_AND_ASSIGN(TestEventFilter);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_EVENT_FILTER_TEST_UTILS_H_
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
deleted file mode 100644
index c72e1fce7d..0000000000
--- a/base/trace_event/trace_event_impl.cc
+++ /dev/null
@@ -1,489 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/trace_event/trace_event_impl.h"
-
-#include <stddef.h>
-
-#include "base/format_macros.h"
-#include "base/json/string_escape.h"
-#include "base/memory/ptr_util.h"
-#include "base/process/process_handle.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/trace_event/trace_log.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; }
-
-// Copies |*member| into |*buffer|, sets |*member| to point to this new
-// location, and then advances |*buffer| by the amount written.
-void CopyTraceEventParameter(char** buffer,
- const char** member,
- const char* end) {
- if (*member) {
- size_t written = strlcpy(*buffer, *member, end - *buffer) + 1;
- DCHECK_LE(static_cast<int>(written), end - *buffer);
- *member = *buffer;
- *buffer += written;
- }
-}
-
-} // namespace
-
-TraceEvent::TraceEvent()
- : duration_(TimeDelta::FromInternalValue(-1)),
- scope_(trace_event_internal::kGlobalScope),
- id_(0u),
- category_group_enabled_(nullptr),
- name_(nullptr),
- thread_id_(0),
- flags_(0),
- phase_(TRACE_EVENT_PHASE_BEGIN) {
- for (int i = 0; i < kTraceMaxNumArgs; ++i)
- arg_names_[i] = nullptr;
- memset(arg_values_, 0, sizeof(arg_values_));
-}
-
-TraceEvent::~TraceEvent() = default;
-
-void TraceEvent::MoveFrom(std::unique_ptr<TraceEvent> other) {
- timestamp_ = other->timestamp_;
- thread_timestamp_ = other->thread_timestamp_;
- duration_ = other->duration_;
- scope_ = other->scope_;
- id_ = other->id_;
- category_group_enabled_ = other->category_group_enabled_;
- name_ = other->name_;
- if (other->flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID)
- process_id_ = other->process_id_;
- else
- thread_id_ = other->thread_id_;
- phase_ = other->phase_;
- flags_ = other->flags_;
- parameter_copy_storage_ = std::move(other->parameter_copy_storage_);
-
- for (int i = 0; i < kTraceMaxNumArgs; ++i) {
- arg_names_[i] = other->arg_names_[i];
- arg_types_[i] = other->arg_types_[i];
- arg_values_[i] = other->arg_values_[i];
- convertable_values_[i] = std::move(other->convertable_values_[i]);
- }
-}
-
-void TraceEvent::Initialize(
- int thread_id,
- TimeTicks timestamp,
- ThreadTicks thread_timestamp,
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- unsigned long long bind_id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- timestamp_ = timestamp;
- thread_timestamp_ = thread_timestamp;
- duration_ = TimeDelta::FromInternalValue(-1);
- scope_ = scope;
- id_ = id;
- category_group_enabled_ = category_group_enabled;
- name_ = name;
- thread_id_ = thread_id;
- phase_ = phase;
- flags_ = flags;
- bind_id_ = bind_id;
-
- // Clamp num_args since it may have been set by a third_party library.
- num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
- int i = 0;
- for (; i < num_args; ++i) {
- arg_names_[i] = arg_names[i];
- arg_types_[i] = arg_types[i];
-
- if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
- convertable_values_[i] = std::move(convertable_values[i]);
- } else {
- arg_values_[i].as_uint = arg_values[i];
- convertable_values_[i].reset();
- }
- }
- for (; i < kTraceMaxNumArgs; ++i) {
- arg_names_[i] = nullptr;
- arg_values_[i].as_uint = 0u;
- convertable_values_[i].reset();
- arg_types_[i] = TRACE_VALUE_TYPE_UINT;
- }
-
- bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
- size_t alloc_size = 0;
- if (copy) {
- alloc_size += GetAllocLength(name) + GetAllocLength(scope);
- for (i = 0; i < num_args; ++i) {
- alloc_size += GetAllocLength(arg_names_[i]);
- if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
- arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
- }
- }
-
- bool arg_is_copy[kTraceMaxNumArgs];
- for (i = 0; i < num_args; ++i) {
- // No copying of convertable types, we retain ownership.
- if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
- continue;
-
- // We only take a copy of arg_vals if they are of type COPY_STRING.
- arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
- if (arg_is_copy[i])
- alloc_size += GetAllocLength(arg_values_[i].as_string);
- }
-
- if (alloc_size) {
- parameter_copy_storage_.reset(new std::string);
- parameter_copy_storage_->resize(alloc_size);
- char* ptr = base::data(*parameter_copy_storage_);
- const char* end = ptr + alloc_size;
- if (copy) {
- CopyTraceEventParameter(&ptr, &name_, end);
- CopyTraceEventParameter(&ptr, &scope_, end);
- for (i = 0; i < num_args; ++i) {
- CopyTraceEventParameter(&ptr, &arg_names_[i], end);
- }
- }
- for (i = 0; i < num_args; ++i) {
- if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
- continue;
- if (arg_is_copy[i])
- CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end);
- }
- DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
- }
-}
-
-void TraceEvent::Reset() {
- // Only reset fields that won't be initialized in Initialize(), or that may
- // hold references to other objects.
- duration_ = TimeDelta::FromInternalValue(-1);
- parameter_copy_storage_.reset();
- for (int i = 0; i < kTraceMaxNumArgs; ++i)
- convertable_values_[i].reset();
-}
-
-void TraceEvent::UpdateDuration(const TimeTicks& now,
- const ThreadTicks& thread_now) {
- DCHECK_EQ(duration_.ToInternalValue(), -1);
- duration_ = now - timestamp_;
-
- // |thread_timestamp_| can be empty if the thread ticks clock wasn't
- // initialized when it was recorded.
- if (thread_timestamp_ != ThreadTicks())
- thread_duration_ = thread_now - thread_timestamp_;
-}
-
-void TraceEvent::EstimateTraceMemoryOverhead(
- TraceEventMemoryOverhead* overhead) {
- overhead->Add(TraceEventMemoryOverhead::kTraceEvent, sizeof(*this));
-
- if (parameter_copy_storage_)
- overhead->AddString(*parameter_copy_storage_);
-
- for (size_t i = 0; i < kTraceMaxNumArgs; ++i) {
- if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
- convertable_values_[i]->EstimateTraceMemoryOverhead(overhead);
- }
-}
-
-// static
-void TraceEvent::AppendValueAsJSON(unsigned char type,
- TraceEvent::TraceValue value,
- std::string* out) {
- switch (type) {
- case TRACE_VALUE_TYPE_BOOL:
- *out += value.as_bool ? "true" : "false";
- break;
- case TRACE_VALUE_TYPE_UINT:
- StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(value.as_uint));
- break;
- case TRACE_VALUE_TYPE_INT:
- StringAppendF(out, "%" PRId64, static_cast<int64_t>(value.as_int));
- break;
- case TRACE_VALUE_TYPE_DOUBLE: {
- // FIXME: base/json/json_writer.cc is using the same code,
- // should be made into a common method.
- std::string real;
- double val = value.as_double;
- if (std::isfinite(val)) {
- real = NumberToString(val);
- // Ensure that the number has a .0 if there's no decimal or 'e'. This
- // makes sure that when we read the JSON back, it's interpreted as a
- // real rather than an int.
- if (real.find('.') == std::string::npos &&
- real.find('e') == std::string::npos &&
- real.find('E') == std::string::npos) {
- real.append(".0");
- }
- // The JSON spec requires that non-integer values in the range (-1,1)
- // have a zero before the decimal point - ".52" is not valid, "0.52" is.
- if (real[0] == '.') {
- real.insert(0, "0");
- } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
- // "-.1" bad "-0.1" good
- real.insert(1, "0");
- }
- } else if (std::isnan(val)){
- // The JSON spec doesn't allow NaN and Infinity (since these are
- // objects in EcmaScript). Use strings instead.
- real = "\"NaN\"";
- } else if (val < 0) {
- real = "\"-Infinity\"";
- } else {
- real = "\"Infinity\"";
- }
- StringAppendF(out, "%s", real.c_str());
- break;
- }
- case TRACE_VALUE_TYPE_POINTER:
- // JSON only supports double and int numbers.
- // So as not to lose bits from a 64-bit pointer, output as a hex string.
- StringAppendF(
- out, "\"0x%" PRIx64 "\"",
- static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value.as_pointer)));
- break;
- case TRACE_VALUE_TYPE_STRING:
- case TRACE_VALUE_TYPE_COPY_STRING:
- EscapeJSONString(value.as_string ? value.as_string : "NULL", true, out);
- break;
- default:
- NOTREACHED() << "Don't know how to print this value";
- break;
- }
-}
-
-void TraceEvent::AppendAsJSON(
- std::string* out,
- const ArgumentFilterPredicate& argument_filter_predicate) const {
- int64_t time_int64 = timestamp_.ToInternalValue();
- int process_id;
- int thread_id;
- if ((flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID) &&
- process_id_ != kNullProcessId) {
- process_id = process_id_;
- thread_id = -1;
- } else {
- process_id = TraceLog::GetInstance()->process_id();
- thread_id = thread_id_;
- }
- const char* category_group_name =
- TraceLog::GetCategoryGroupName(category_group_enabled_);
-
- // Category group checked at category creation time.
- DCHECK(!strchr(name_, '"'));
- StringAppendF(out, "{\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64
- ",\"ph\":\"%c\",\"cat\":\"%s\",\"name\":",
- process_id, thread_id, time_int64, phase_, category_group_name);
- EscapeJSONString(name_, true, out);
- *out += ",\"args\":";
-
- // Output argument names and values, stop at first NULL argument name.
- // TODO(oysteine): The dual predicates here is a bit ugly; if the filtering
- // capabilities need to grow even more precise we should rethink this
- // approach
- ArgumentNameFilterPredicate argument_name_filter_predicate;
- bool strip_args =
- arg_names_[0] && !argument_filter_predicate.is_null() &&
- !argument_filter_predicate.Run(category_group_name, name_,
- &argument_name_filter_predicate);
-
- if (strip_args) {
- *out += "\"__stripped__\"";
- } else {
- *out += "{";
-
- for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
- if (i > 0)
- *out += ",";
- *out += "\"";
- *out += arg_names_[i];
- *out += "\":";
-
- if (argument_name_filter_predicate.is_null() ||
- argument_name_filter_predicate.Run(arg_names_[i])) {
- if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
- convertable_values_[i]->AppendAsTraceFormat(out);
- else
- AppendValueAsJSON(arg_types_[i], arg_values_[i], out);
- } else {
- *out += "\"__stripped__\"";
- }
- }
-
- *out += "}";
- }
-
- if (phase_ == TRACE_EVENT_PHASE_COMPLETE) {
- int64_t duration = duration_.ToInternalValue();
- if (duration != -1)
- StringAppendF(out, ",\"dur\":%" PRId64, duration);
- if (!thread_timestamp_.is_null()) {
- int64_t thread_duration = thread_duration_.ToInternalValue();
- if (thread_duration != -1)
- StringAppendF(out, ",\"tdur\":%" PRId64, thread_duration);
- }
- }
-
- // Output tts if thread_timestamp is valid.
- if (!thread_timestamp_.is_null()) {
- int64_t thread_time_int64 = thread_timestamp_.ToInternalValue();
- StringAppendF(out, ",\"tts\":%" PRId64, thread_time_int64);
- }
-
- // Output async tts marker field if flag is set.
- if (flags_ & TRACE_EVENT_FLAG_ASYNC_TTS) {
- StringAppendF(out, ", \"use_async_tts\":1");
- }
-
- // If id_ is set, print it out as a hex string so we don't loose any
- // bits (it might be a 64-bit pointer).
- unsigned int id_flags_ = flags_ & (TRACE_EVENT_FLAG_HAS_ID |
- TRACE_EVENT_FLAG_HAS_LOCAL_ID |
- TRACE_EVENT_FLAG_HAS_GLOBAL_ID);
- if (id_flags_) {
- if (scope_ != trace_event_internal::kGlobalScope)
- StringAppendF(out, ",\"scope\":\"%s\"", scope_);
-
- switch (id_flags_) {
- case TRACE_EVENT_FLAG_HAS_ID:
- StringAppendF(out, ",\"id\":\"0x%" PRIx64 "\"",
- static_cast<uint64_t>(id_));
- break;
-
- case TRACE_EVENT_FLAG_HAS_LOCAL_ID:
- StringAppendF(out, ",\"id2\":{\"local\":\"0x%" PRIx64 "\"}",
- static_cast<uint64_t>(id_));
- break;
-
- case TRACE_EVENT_FLAG_HAS_GLOBAL_ID:
- StringAppendF(out, ",\"id2\":{\"global\":\"0x%" PRIx64 "\"}",
- static_cast<uint64_t>(id_));
- break;
-
- default:
- NOTREACHED() << "More than one of the ID flags are set";
- break;
- }
- }
-
- if (flags_ & TRACE_EVENT_FLAG_BIND_TO_ENCLOSING)
- StringAppendF(out, ",\"bp\":\"e\"");
-
- if ((flags_ & TRACE_EVENT_FLAG_FLOW_OUT) ||
- (flags_ & TRACE_EVENT_FLAG_FLOW_IN)) {
- StringAppendF(out, ",\"bind_id\":\"0x%" PRIx64 "\"",
- static_cast<uint64_t>(bind_id_));
- }
- if (flags_ & TRACE_EVENT_FLAG_FLOW_IN)
- StringAppendF(out, ",\"flow_in\":true");
- if (flags_ & TRACE_EVENT_FLAG_FLOW_OUT)
- StringAppendF(out, ",\"flow_out\":true");
-
- // Instant events also output their scope.
- if (phase_ == TRACE_EVENT_PHASE_INSTANT) {
- char scope = '?';
- switch (flags_ & TRACE_EVENT_FLAG_SCOPE_MASK) {
- case TRACE_EVENT_SCOPE_GLOBAL:
- scope = TRACE_EVENT_SCOPE_NAME_GLOBAL;
- break;
-
- case TRACE_EVENT_SCOPE_PROCESS:
- scope = TRACE_EVENT_SCOPE_NAME_PROCESS;
- break;
-
- case TRACE_EVENT_SCOPE_THREAD:
- scope = TRACE_EVENT_SCOPE_NAME_THREAD;
- break;
- }
- StringAppendF(out, ",\"s\":\"%c\"", scope);
- }
-
- *out += "}";
-}
-
-void TraceEvent::AppendPrettyPrinted(std::ostringstream* out) const {
- *out << name_ << "[";
- *out << TraceLog::GetCategoryGroupName(category_group_enabled_);
- *out << "]";
- if (arg_names_[0]) {
- *out << ", {";
- for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
- if (i > 0)
- *out << ", ";
- *out << arg_names_[i] << ":";
- std::string value_as_text;
-
- if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
- convertable_values_[i]->AppendAsTraceFormat(&value_as_text);
- else
- AppendValueAsJSON(arg_types_[i], arg_values_[i], &value_as_text);
-
- *out << value_as_text;
- }
- *out << "}";
- }
-}
-
-} // namespace trace_event
-} // namespace base
-
-namespace trace_event_internal {
-
-std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
-TraceID::AsConvertableToTraceFormat() const {
- auto value = std::make_unique<base::trace_event::TracedValue>();
-
- if (scope_ != kGlobalScope)
- value->SetString("scope", scope_);
-
- const char* id_field_name = "id";
- if (id_flags_ == TRACE_EVENT_FLAG_HAS_GLOBAL_ID) {
- id_field_name = "global";
- value->BeginDictionary("id2");
- } else if (id_flags_ == TRACE_EVENT_FLAG_HAS_LOCAL_ID) {
- id_field_name = "local";
- value->BeginDictionary("id2");
- } else if (id_flags_ != TRACE_EVENT_FLAG_HAS_ID) {
- NOTREACHED() << "Unrecognized ID flag";
- }
-
- if (has_prefix_) {
- value->SetString(id_field_name,
- base::StringPrintf("0x%" PRIx64 "/0x%" PRIx64,
- static_cast<uint64_t>(prefix_),
- static_cast<uint64_t>(raw_id_)));
- } else {
- value->SetString(
- id_field_name,
- base::StringPrintf("0x%" PRIx64, static_cast<uint64_t>(raw_id_)));
- }
-
- if (id_flags_ != TRACE_EVENT_FLAG_HAS_ID)
- value->EndDictionary();
-
- return std::move(value);
-}
-
-} // namespace trace_event_internal
diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
deleted file mode 100644
index 4b4b88f5bd..0000000000
--- a/base/trace_event/trace_event_impl.h
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (c) 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.
-
-
-#ifndef BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
-#define BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/atomicops.h"
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_local.h"
-#include "base/trace_event/trace_event_memory_overhead.h"
-#include "build/build_config.h"
-
-namespace base {
-namespace trace_event {
-
-typedef base::Callback<bool(const char* arg_name)> ArgumentNameFilterPredicate;
-
-typedef base::Callback<bool(const char* category_group_name,
- const char* event_name,
- ArgumentNameFilterPredicate*)>
- ArgumentFilterPredicate;
-
-// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
-// class must implement this interface.
-class BASE_EXPORT ConvertableToTraceFormat {
- public:
- ConvertableToTraceFormat() = default;
- virtual ~ConvertableToTraceFormat() = default;
-
- // Append the class info to the provided |out| string. The appended
- // data must be a valid JSON object. Strings must be properly quoted, and
- // escaped. There is no processing applied to the content after it is
- // appended.
- virtual void AppendAsTraceFormat(std::string* out) const = 0;
-
- virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
-
- std::string ToString() const {
- std::string result;
- AppendAsTraceFormat(&result);
- return result;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat);
-};
-
-const int kTraceMaxNumArgs = 2;
-
-struct TraceEventHandle {
- uint32_t chunk_seq;
- // These numbers of bits must be kept consistent with
- // TraceBufferChunk::kMaxTrunkIndex and
- // TraceBufferChunk::kTraceBufferChunkSize (in trace_buffer.h).
- unsigned chunk_index : 26;
- unsigned event_index : 6;
-};
-
-class BASE_EXPORT TraceEvent {
- public:
- union TraceValue {
- bool as_bool;
- unsigned long long as_uint;
- long long as_int;
- double as_double;
- const void* as_pointer;
- const char* as_string;
- };
-
- TraceEvent();
- ~TraceEvent();
-
- void MoveFrom(std::unique_ptr<TraceEvent> other);
-
- void Initialize(int thread_id,
- TimeTicks timestamp,
- ThreadTicks thread_timestamp,
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- unsigned long long bind_id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags);
-
- void Reset();
-
- void UpdateDuration(const TimeTicks& now, const ThreadTicks& thread_now);
-
- void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
-
- // Serialize event data to JSON
- void AppendAsJSON(
- std::string* out,
- const ArgumentFilterPredicate& argument_filter_predicate) const;
- void AppendPrettyPrinted(std::ostringstream* out) const;
-
- static void AppendValueAsJSON(unsigned char type,
- TraceValue value,
- std::string* out);
-
- TimeTicks timestamp() const { return timestamp_; }
- ThreadTicks thread_timestamp() const { return thread_timestamp_; }
- char phase() const { return phase_; }
- int thread_id() const { return thread_id_; }
- TimeDelta duration() const { return duration_; }
- TimeDelta thread_duration() const { return thread_duration_; }
- const char* scope() const { return scope_; }
- unsigned long long id() const { return id_; }
- unsigned int flags() const { return flags_; }
- unsigned long long bind_id() const { return bind_id_; }
- // Exposed for unittesting:
-
- const std::string* parameter_copy_storage() const {
- return parameter_copy_storage_.get();
- }
-
- const unsigned char* category_group_enabled() const {
- return category_group_enabled_;
- }
-
- const char* name() const { return name_; }
-
- unsigned char arg_type(size_t index) const { return arg_types_[index]; }
- const char* arg_name(size_t index) const { return arg_names_[index]; }
- const TraceValue& arg_value(size_t index) const { return arg_values_[index]; }
-
- const ConvertableToTraceFormat* arg_convertible_value(size_t index) const {
- return convertable_values_[index].get();
- }
-
-#if defined(OS_ANDROID)
- void SendToATrace();
-#endif
-
- private:
- // Note: these are ordered by size (largest first) for optimal packing.
- TimeTicks timestamp_;
- ThreadTicks thread_timestamp_;
- TimeDelta duration_;
- TimeDelta thread_duration_;
- // scope_ and id_ can be used to store phase-specific data.
- const char* scope_;
- unsigned long long id_;
- TraceValue arg_values_[kTraceMaxNumArgs];
- const char* arg_names_[kTraceMaxNumArgs];
- std::unique_ptr<ConvertableToTraceFormat>
- convertable_values_[kTraceMaxNumArgs];
- const unsigned char* category_group_enabled_;
- const char* name_;
- std::unique_ptr<std::string> parameter_copy_storage_;
- // Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either:
- // tid: thread_id_, pid: current_process_id (default case).
- // tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID).
- union {
- int thread_id_;
- int process_id_;
- };
- unsigned int flags_;
- unsigned long long bind_id_;
- unsigned char arg_types_[kTraceMaxNumArgs];
- char phase_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceEvent);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_EVENT_IMPL_H_
diff --git a/base/trace_event/trace_event_memory_overhead.cc b/base/trace_event/trace_event_memory_overhead.cc
deleted file mode 100644
index dd7b30255e..0000000000
--- a/base/trace_event/trace_event_memory_overhead.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright 2015 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/trace_event/trace_event_memory_overhead.h"
-
-#include <algorithm>
-
-#include "base/bits.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/memory_allocator_dump.h"
-#include "base/trace_event/memory_usage_estimator.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/values.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-const char* ObjectTypeToString(TraceEventMemoryOverhead::ObjectType type) {
- switch (type) {
- case TraceEventMemoryOverhead::kOther:
- return "(Other)";
- case TraceEventMemoryOverhead::kTraceBuffer:
- return "TraceBuffer";
- case TraceEventMemoryOverhead::kTraceBufferChunk:
- return "TraceBufferChunk";
- case TraceEventMemoryOverhead::kTraceEvent:
- return "TraceEvent";
- case TraceEventMemoryOverhead::kUnusedTraceEvent:
- return "TraceEvent(Unused)";
- case TraceEventMemoryOverhead::kTracedValue:
- return "TracedValue";
- case TraceEventMemoryOverhead::kConvertableToTraceFormat:
- return "ConvertableToTraceFormat";
- case TraceEventMemoryOverhead::kHeapProfilerAllocationRegister:
- return "AllocationRegister";
- case TraceEventMemoryOverhead::kHeapProfilerTypeNameDeduplicator:
- return "TypeNameDeduplicator";
- case TraceEventMemoryOverhead::kHeapProfilerStackFrameDeduplicator:
- return "StackFrameDeduplicator";
- case TraceEventMemoryOverhead::kStdString:
- return "std::string";
- case TraceEventMemoryOverhead::kBaseValue:
- return "base::Value";
- case TraceEventMemoryOverhead::kTraceEventMemoryOverhead:
- return "TraceEventMemoryOverhead";
- case TraceEventMemoryOverhead::kFrameMetrics:
- return "FrameMetrics";
- case TraceEventMemoryOverhead::kLast:
- NOTREACHED();
- }
- NOTREACHED();
- return "BUG";
-}
-
-} // namespace
-
-TraceEventMemoryOverhead::TraceEventMemoryOverhead() : allocated_objects_() {}
-
-TraceEventMemoryOverhead::~TraceEventMemoryOverhead() = default;
-
-void TraceEventMemoryOverhead::AddInternal(ObjectType object_type,
- size_t count,
- size_t allocated_size_in_bytes,
- size_t resident_size_in_bytes) {
- ObjectCountAndSize& count_and_size =
- allocated_objects_[static_cast<uint32_t>(object_type)];
- count_and_size.count += count;
- count_and_size.allocated_size_in_bytes += allocated_size_in_bytes;
- count_and_size.resident_size_in_bytes += resident_size_in_bytes;
-}
-
-void TraceEventMemoryOverhead::Add(ObjectType object_type,
- size_t allocated_size_in_bytes) {
- Add(object_type, allocated_size_in_bytes, allocated_size_in_bytes);
-}
-
-void TraceEventMemoryOverhead::Add(ObjectType object_type,
- size_t allocated_size_in_bytes,
- size_t resident_size_in_bytes) {
- AddInternal(object_type, 1, allocated_size_in_bytes, resident_size_in_bytes);
-}
-
-void TraceEventMemoryOverhead::AddString(const std::string& str) {
- Add(kStdString, EstimateMemoryUsage(str));
-}
-
-void TraceEventMemoryOverhead::AddRefCountedString(
- const RefCountedString& str) {
- Add(kOther, sizeof(RefCountedString));
- AddString(str.data());
-}
-
-void TraceEventMemoryOverhead::AddValue(const Value& value) {
- switch (value.type()) {
- case Value::Type::NONE:
- case Value::Type::BOOLEAN:
- case Value::Type::INTEGER:
- case Value::Type::DOUBLE:
- Add(kBaseValue, sizeof(Value));
- break;
-
- case Value::Type::STRING: {
- const Value* string_value = nullptr;
- value.GetAsString(&string_value);
- Add(kBaseValue, sizeof(Value));
- AddString(string_value->GetString());
- } break;
-
- case Value::Type::BINARY: {
- Add(kBaseValue, sizeof(Value) + value.GetBlob().size());
- } break;
-
- case Value::Type::DICTIONARY: {
- const DictionaryValue* dictionary_value = nullptr;
- value.GetAsDictionary(&dictionary_value);
- Add(kBaseValue, sizeof(DictionaryValue));
- for (DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd();
- it.Advance()) {
- AddString(it.key());
- AddValue(it.value());
- }
- } break;
-
- case Value::Type::LIST: {
- const ListValue* list_value = nullptr;
- value.GetAsList(&list_value);
- Add(kBaseValue, sizeof(ListValue));
- for (const auto& v : *list_value)
- AddValue(v);
- } break;
-
- default:
- NOTREACHED();
- }
-}
-
-void TraceEventMemoryOverhead::AddSelf() {
- Add(kTraceEventMemoryOverhead, sizeof(*this));
-}
-
-size_t TraceEventMemoryOverhead::GetCount(ObjectType object_type) const {
- CHECK(object_type < kLast);
- return allocated_objects_[static_cast<uint32_t>(object_type)].count;
-}
-
-void TraceEventMemoryOverhead::Update(const TraceEventMemoryOverhead& other) {
- for (uint32_t i = 0; i < kLast; i++) {
- const ObjectCountAndSize& other_entry = other.allocated_objects_[i];
- AddInternal(static_cast<ObjectType>(i), other_entry.count,
- other_entry.allocated_size_in_bytes,
- other_entry.resident_size_in_bytes);
- }
-}
-
-void TraceEventMemoryOverhead::DumpInto(const char* base_name,
- ProcessMemoryDump* pmd) const {
- for (uint32_t i = 0; i < kLast; i++) {
- const ObjectCountAndSize& count_and_size = allocated_objects_[i];
- if (count_and_size.allocated_size_in_bytes == 0)
- continue;
- std::string dump_name = StringPrintf(
- "%s/%s", base_name, ObjectTypeToString(static_cast<ObjectType>(i)));
- MemoryAllocatorDump* mad = pmd->CreateAllocatorDump(dump_name);
- mad->AddScalar(MemoryAllocatorDump::kNameSize,
- MemoryAllocatorDump::kUnitsBytes,
- count_and_size.allocated_size_in_bytes);
- mad->AddScalar("resident_size", MemoryAllocatorDump::kUnitsBytes,
- count_and_size.resident_size_in_bytes);
- mad->AddScalar(MemoryAllocatorDump::kNameObjectCount,
- MemoryAllocatorDump::kUnitsObjects, count_and_size.count);
- }
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_memory_overhead.h b/base/trace_event/trace_event_memory_overhead.h
deleted file mode 100644
index 69468d4640..0000000000
--- a/base/trace_event/trace_event_memory_overhead.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_
-#define BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <unordered_map>
-
-#include "base/base_export.h"
-#include "base/macros.h"
-
-namespace base {
-
-class RefCountedString;
-class Value;
-
-namespace trace_event {
-
-class ProcessMemoryDump;
-
-// Used to estimate the memory overhead of the tracing infrastructure.
-class BASE_EXPORT TraceEventMemoryOverhead {
- public:
- enum ObjectType : uint32_t {
- kOther = 0,
- kTraceBuffer,
- kTraceBufferChunk,
- kTraceEvent,
- kUnusedTraceEvent,
- kTracedValue,
- kConvertableToTraceFormat,
- kHeapProfilerAllocationRegister,
- kHeapProfilerTypeNameDeduplicator,
- kHeapProfilerStackFrameDeduplicator,
- kStdString,
- kBaseValue,
- kTraceEventMemoryOverhead,
- kFrameMetrics,
- kLast
- };
-
- TraceEventMemoryOverhead();
- ~TraceEventMemoryOverhead();
-
- // Use this method to account the overhead of an object for which an estimate
- // is known for both the allocated and resident memory.
- void Add(ObjectType object_type,
- size_t allocated_size_in_bytes,
- size_t resident_size_in_bytes);
-
- // Similar to Add() above, but assumes that
- // |resident_size_in_bytes| == |allocated_size_in_bytes|.
- void Add(ObjectType object_type, size_t allocated_size_in_bytes);
-
- // Specialized profiling functions for commonly used object types.
- void AddString(const std::string& str);
- void AddValue(const Value& value);
- void AddRefCountedString(const RefCountedString& str);
-
- // Call this after all the Add* methods above to account the memory used by
- // this TraceEventMemoryOverhead instance itself.
- void AddSelf();
-
- // Retrieves the count, that is, the count of Add*(|object_type|, ...) calls.
- size_t GetCount(ObjectType object_type) const;
-
- // Adds up and merges all the values from |other| to this instance.
- void Update(const TraceEventMemoryOverhead& other);
-
- void DumpInto(const char* base_name, ProcessMemoryDump* pmd) const;
-
- private:
- struct ObjectCountAndSize {
- size_t count;
- size_t allocated_size_in_bytes;
- size_t resident_size_in_bytes;
- };
- ObjectCountAndSize allocated_objects_[ObjectType::kLast];
-
- void AddInternal(ObjectType object_type,
- size_t count,
- size_t allocated_size_in_bytes,
- size_t resident_size_in_bytes);
-
- DISALLOW_COPY_AND_ASSIGN(TraceEventMemoryOverhead);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_EVENT_MEMORY_OVERHEAD_H_
diff --git a/base/trace_event/trace_event_system_stats_monitor.cc b/base/trace_event/trace_event_system_stats_monitor.cc
deleted file mode 100644
index 7e082f348e..0000000000
--- a/base/trace_event/trace_event_system_stats_monitor.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2013 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/trace_event/trace_event_system_stats_monitor.h"
-
-#include <memory>
-
-#include "base/debug/leak_annotations.h"
-#include "base/json/json_writer.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/process/process_metrics.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/threading/thread_local_storage.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-/////////////////////////////////////////////////////////////////////////////
-// Holds profiled system stats until the tracing system needs to serialize it.
-class SystemStatsHolder : public base::trace_event::ConvertableToTraceFormat {
- public:
- SystemStatsHolder() = default;
- ~SystemStatsHolder() override = default;
-
- // Fills system_metrics_ with profiled system memory and disk stats.
- // Uses the previous stats to compute rates if this is not the first profile.
- void GetSystemProfilingStats();
-
- // base::trace_event::ConvertableToTraceFormat overrides:
- void AppendAsTraceFormat(std::string* out) const override {
- AppendSystemProfileAsTraceFormat(system_stats_, out);
- }
-
- private:
- SystemMetrics system_stats_;
-
- DISALLOW_COPY_AND_ASSIGN(SystemStatsHolder);
-};
-
-void SystemStatsHolder::GetSystemProfilingStats() {
- system_stats_ = SystemMetrics::Sample();
-}
-
-} // namespace
-
-//////////////////////////////////////////////////////////////////////////////
-
-TraceEventSystemStatsMonitor::TraceEventSystemStatsMonitor(
- scoped_refptr<SingleThreadTaskRunner> task_runner)
- : task_runner_(task_runner),
- weak_factory_(this) {
- // Force the "system_stats" category to show up in the trace viewer.
- TraceLog::GetCategoryGroupEnabled(TRACE_DISABLED_BY_DEFAULT("system_stats"));
-
- // Allow this to be instantiated on unsupported platforms, but don't run.
- TraceLog::GetInstance()->AddEnabledStateObserver(this);
-}
-
-TraceEventSystemStatsMonitor::~TraceEventSystemStatsMonitor() {
- if (dump_timer_.IsRunning())
- StopProfiling();
- TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
-}
-
-void TraceEventSystemStatsMonitor::OnTraceLogEnabled() {
- // Check to see if system tracing is enabled.
- bool enabled;
-
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT(
- "system_stats"), &enabled);
- if (!enabled)
- return;
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&TraceEventSystemStatsMonitor::StartProfiling,
- weak_factory_.GetWeakPtr()));
-}
-
-void TraceEventSystemStatsMonitor::OnTraceLogDisabled() {
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&TraceEventSystemStatsMonitor::StopProfiling,
- weak_factory_.GetWeakPtr()));
-}
-
-void TraceEventSystemStatsMonitor::StartProfiling() {
- // Watch for the tracing framework sending enabling more than once.
- if (dump_timer_.IsRunning())
- return;
-
- dump_timer_.Start(FROM_HERE,
- TimeDelta::FromMilliseconds(TraceEventSystemStatsMonitor::
- kSamplingIntervalMilliseconds),
- base::Bind(&TraceEventSystemStatsMonitor::
- DumpSystemStats,
- weak_factory_.GetWeakPtr()));
-}
-
-// If system tracing is enabled, dumps a profile to the tracing system.
-void TraceEventSystemStatsMonitor::DumpSystemStats() {
- std::unique_ptr<SystemStatsHolder> dump_holder(new SystemStatsHolder());
- dump_holder->GetSystemProfilingStats();
-
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("system_stats"),
- "base::TraceEventSystemStatsMonitor::SystemStats", this,
- std::move(dump_holder));
-}
-
-void TraceEventSystemStatsMonitor::StopProfiling() {
- dump_timer_.Stop();
-}
-
-bool TraceEventSystemStatsMonitor::IsTimerRunningForTest() const {
- return dump_timer_.IsRunning();
-}
-
-void AppendSystemProfileAsTraceFormat(const SystemMetrics& system_metrics,
- std::string* output) {
- std::string tmp;
- base::JSONWriter::Write(*system_metrics.ToValue(), &tmp);
- *output += tmp;
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_system_stats_monitor.h b/base/trace_event/trace_event_system_stats_monitor.h
deleted file mode 100644
index 14aa5681fe..0000000000
--- a/base/trace_event/trace_event_system_stats_monitor.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_
-#define BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_
-
-#include "base/base_export.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/process/process_metrics.h"
-#include "base/timer/timer.h"
-#include "base/trace_event/trace_log.h"
-
-namespace base {
-
-class SingleThreadTaskRunner;
-
-namespace trace_event {
-
-// Watches for chrome://tracing to be enabled or disabled. When tracing is
-// enabled, also enables system events profiling. This class is the preferred
-// way to turn system tracing on and off.
-class BASE_EXPORT TraceEventSystemStatsMonitor
- : public TraceLog::EnabledStateObserver {
- public:
- // Length of time interval between stat profiles.
- static const int kSamplingIntervalMilliseconds = 2000;
-
- // |task_runner| must be the primary thread for the client
- // process, e.g. the UI thread in a browser.
- explicit TraceEventSystemStatsMonitor(
- scoped_refptr<SingleThreadTaskRunner> task_runner);
-
- ~TraceEventSystemStatsMonitor() override;
-
- // base::trace_event::TraceLog::EnabledStateChangedObserver overrides:
- void OnTraceLogEnabled() override;
- void OnTraceLogDisabled() override;
-
- // Retrieves system profiling at the current time.
- void DumpSystemStats();
-
- private:
- FRIEND_TEST_ALL_PREFIXES(TraceSystemStatsMonitorTest,
- TraceEventSystemStatsMonitor);
-
- bool IsTimerRunningForTest() const;
-
- void StartProfiling();
-
- void StopProfiling();
-
- // Ensures the observer starts and stops tracing on the primary thread.
- scoped_refptr<SingleThreadTaskRunner> task_runner_;
-
- // Timer to schedule system profile dumps.
- RepeatingTimer dump_timer_;
-
- WeakPtrFactory<TraceEventSystemStatsMonitor> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceEventSystemStatsMonitor);
-};
-
-// Converts system memory profiling stats in |input| to
-// trace event compatible JSON and appends to |output|. Visible for testing.
-BASE_EXPORT void AppendSystemProfileAsTraceFormat(const SystemMetrics&
- system_stats,
- std::string* output);
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_EVENT_SYSTEM_STATS_MONITOR_H_
diff --git a/base/trace_event/trace_event_system_stats_monitor_unittest.cc b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
deleted file mode 100644
index 52a05ba9cd..0000000000
--- a/base/trace_event/trace_event_system_stats_monitor_unittest.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2013 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/trace_event/trace_event_system_stats_monitor.h"
-
-#include <sstream>
-#include <string>
-
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-#if !defined(OS_IOS)
-// Tests for the system stats monitor.
-// Exists as a class so it can be a friend of TraceEventSystemStatsMonitor.
-class TraceSystemStatsMonitorTest : public testing::Test {
- public:
- TraceSystemStatsMonitorTest() = default;
- ~TraceSystemStatsMonitorTest() override = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TraceSystemStatsMonitorTest);
-};
-
-//////////////////////////////////////////////////////////////////////////////
-
-TEST_F(TraceSystemStatsMonitorTest, TraceEventSystemStatsMonitor) {
- MessageLoop message_loop;
-
- // Start with no observers of the TraceLog.
- EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
-
- // Creating a system stats monitor adds it to the TraceLog observer list.
- std::unique_ptr<TraceEventSystemStatsMonitor> system_stats_monitor(
- new TraceEventSystemStatsMonitor(message_loop.task_runner()));
- EXPECT_EQ(1u, TraceLog::GetInstance()->GetObserverCountForTest());
- EXPECT_TRUE(
- TraceLog::GetInstance()->HasEnabledStateObserver(
- system_stats_monitor.get()));
-
- // By default the observer isn't dumping memory profiles.
- EXPECT_FALSE(system_stats_monitor->IsTimerRunningForTest());
-
- // Simulate enabling tracing.
- system_stats_monitor->StartProfiling();
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(system_stats_monitor->IsTimerRunningForTest());
-
- // Simulate disabling tracing.
- system_stats_monitor->StopProfiling();
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(system_stats_monitor->IsTimerRunningForTest());
-
- // Deleting the observer removes it from the TraceLog observer list.
- system_stats_monitor.reset();
- EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
-}
-#endif // !defined(OS_IOS)
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_event_unittest.cc b/base/trace_event/trace_event_unittest.cc
deleted file mode 100644
index a413ee5f0e..0000000000
--- a/base/trace_event/trace_event_unittest.cc
+++ /dev/null
@@ -1,3169 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/trace_event/trace_event.h"
-
-#include <math.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <cstdlib>
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/memory/singleton.h"
-#include "base/process/process_handle.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/pattern.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "base/time/time.h"
-#include "base/trace_event/event_name_filter.h"
-#include "base/trace_event/heap_profiler_event_filter.h"
-#include "base/trace_event/trace_buffer.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_filter.h"
-#include "base/trace_event/trace_event_filter_test_utils.h"
-#include "base/values.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-enum CompareOp {
- IS_EQUAL,
- IS_NOT_EQUAL,
-};
-
-struct JsonKeyValue {
- const char* key;
- const char* value;
- CompareOp op;
-};
-
-const int kThreadId = 42;
-const int kAsyncId = 5;
-const char kAsyncIdStr[] = "0x5";
-const int kAsyncId2 = 6;
-const char kAsyncId2Str[] = "0x6";
-const int kFlowId = 7;
-const char kFlowIdStr[] = "0x7";
-
-const char kRecordAllCategoryFilter[] = "*";
-
-class TraceEventTestFixture : public testing::Test {
- public:
- void OnTraceDataCollected(
- WaitableEvent* flush_complete_event,
- const scoped_refptr<base::RefCountedString>& events_str,
- bool has_more_events);
- DictionaryValue* FindMatchingTraceEntry(const JsonKeyValue* key_values);
- DictionaryValue* FindNamePhase(const char* name, const char* phase);
- DictionaryValue* FindNamePhaseKeyValue(const char* name,
- const char* phase,
- const char* key,
- const char* value);
- void DropTracedMetadataRecords();
- bool FindMatchingValue(const char* key,
- const char* value);
- bool FindNonMatchingValue(const char* key,
- const char* value);
- void Clear() {
- trace_parsed_.Clear();
- json_output_.json_output.clear();
- }
-
- void BeginTrace() {
- BeginSpecificTrace("*");
- }
-
- void BeginSpecificTrace(const std::string& filter) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(filter, ""),
- TraceLog::RECORDING_MODE);
- }
-
- void CancelTrace() {
- WaitableEvent flush_complete_event(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- CancelTraceAsync(&flush_complete_event);
- flush_complete_event.Wait();
- }
-
- void EndTraceAndFlush() {
- num_flush_callbacks_ = 0;
- WaitableEvent flush_complete_event(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- EndTraceAndFlushAsync(&flush_complete_event);
- flush_complete_event.Wait();
- }
-
- // Used when testing thread-local buffers which requires the thread initiating
- // flush to have a message loop.
- void EndTraceAndFlushInThreadWithMessageLoop() {
- WaitableEvent flush_complete_event(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- Thread flush_thread("flush");
- flush_thread.Start();
- flush_thread.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&TraceEventTestFixture::EndTraceAndFlushAsync,
- base::Unretained(this), &flush_complete_event));
- flush_complete_event.Wait();
- }
-
- void CancelTraceAsync(WaitableEvent* flush_complete_event) {
- TraceLog::GetInstance()->CancelTracing(
- base::Bind(&TraceEventTestFixture::OnTraceDataCollected,
- base::Unretained(static_cast<TraceEventTestFixture*>(this)),
- base::Unretained(flush_complete_event)));
- }
-
- void EndTraceAndFlushAsync(WaitableEvent* flush_complete_event) {
- TraceLog::GetInstance()->SetDisabled(TraceLog::RECORDING_MODE |
- TraceLog::FILTERING_MODE);
- TraceLog::GetInstance()->Flush(
- base::Bind(&TraceEventTestFixture::OnTraceDataCollected,
- base::Unretained(static_cast<TraceEventTestFixture*>(this)),
- base::Unretained(flush_complete_event)));
- }
-
- void SetUp() override {
- const char* name = PlatformThread::GetName();
- old_thread_name_ = name ? strdup(name) : nullptr;
-
- TraceLog::ResetForTesting();
- TraceLog* tracelog = TraceLog::GetInstance();
- ASSERT_TRUE(tracelog);
- ASSERT_FALSE(tracelog->IsEnabled());
- trace_buffer_.SetOutputCallback(json_output_.GetCallback());
- num_flush_callbacks_ = 0;
- }
- void TearDown() override {
- if (TraceLog::GetInstance())
- EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled());
- PlatformThread::SetName(old_thread_name_ ? old_thread_name_ : "");
- free(old_thread_name_);
- old_thread_name_ = nullptr;
- // We want our singleton torn down after each test.
- TraceLog::ResetForTesting();
- }
-
- char* old_thread_name_;
- ListValue trace_parsed_;
- TraceResultBuffer trace_buffer_;
- TraceResultBuffer::SimpleOutput json_output_;
- size_t num_flush_callbacks_;
-
- private:
- // We want our singleton torn down after each test.
- ShadowingAtExitManager at_exit_manager_;
- Lock lock_;
-};
-
-void TraceEventTestFixture::OnTraceDataCollected(
- WaitableEvent* flush_complete_event,
- const scoped_refptr<base::RefCountedString>& events_str,
- bool has_more_events) {
- num_flush_callbacks_++;
- if (num_flush_callbacks_ > 1) {
- EXPECT_FALSE(events_str->data().empty());
- }
- AutoLock lock(lock_);
- json_output_.json_output.clear();
- trace_buffer_.Start();
- trace_buffer_.AddFragment(events_str->data());
- trace_buffer_.Finish();
-
- std::unique_ptr<Value> root =
- base::JSONReader::Read(json_output_.json_output, JSON_PARSE_RFC);
-
- if (!root.get()) {
- LOG(ERROR) << json_output_.json_output;
- }
-
- ListValue* root_list = nullptr;
- ASSERT_TRUE(root.get());
- ASSERT_TRUE(root->GetAsList(&root_list));
-
- // Move items into our aggregate collection
- while (root_list->GetSize()) {
- std::unique_ptr<Value> item;
- root_list->Remove(0, &item);
- trace_parsed_.Append(std::move(item));
- }
-
- if (!has_more_events)
- flush_complete_event->Signal();
-}
-
-static bool CompareJsonValues(const std::string& lhs,
- const std::string& rhs,
- CompareOp op) {
- switch (op) {
- case IS_EQUAL:
- return lhs == rhs;
- case IS_NOT_EQUAL:
- return lhs != rhs;
- default:
- CHECK(0);
- }
- return false;
-}
-
-static bool IsKeyValueInDict(const JsonKeyValue* key_value,
- DictionaryValue* dict) {
- Value* value = nullptr;
- std::string value_str;
- if (dict->Get(key_value->key, &value) &&
- value->GetAsString(&value_str) &&
- CompareJsonValues(value_str, key_value->value, key_value->op))
- return true;
-
- // Recurse to test arguments
- DictionaryValue* args_dict = nullptr;
- dict->GetDictionary("args", &args_dict);
- if (args_dict)
- return IsKeyValueInDict(key_value, args_dict);
-
- return false;
-}
-
-static bool IsAllKeyValueInDict(const JsonKeyValue* key_values,
- DictionaryValue* dict) {
- // Scan all key_values, they must all be present and equal.
- while (key_values && key_values->key) {
- if (!IsKeyValueInDict(key_values, dict))
- return false;
- ++key_values;
- }
- return true;
-}
-
-DictionaryValue* TraceEventTestFixture::FindMatchingTraceEntry(
- const JsonKeyValue* key_values) {
- // Scan all items
- size_t trace_parsed_count = trace_parsed_.GetSize();
- for (size_t i = 0; i < trace_parsed_count; i++) {
- Value* value = nullptr;
- trace_parsed_.Get(i, &value);
- if (!value || value->type() != Value::Type::DICTIONARY)
- continue;
- DictionaryValue* dict = static_cast<DictionaryValue*>(value);
-
- if (IsAllKeyValueInDict(key_values, dict))
- return dict;
- }
- return nullptr;
-}
-
-void TraceEventTestFixture::DropTracedMetadataRecords() {
- std::unique_ptr<ListValue> old_trace_parsed(trace_parsed_.CreateDeepCopy());
- size_t old_trace_parsed_size = old_trace_parsed->GetSize();
- trace_parsed_.Clear();
-
- for (size_t i = 0; i < old_trace_parsed_size; i++) {
- Value* value = nullptr;
- old_trace_parsed->Get(i, &value);
- if (!value || value->type() != Value::Type::DICTIONARY) {
- trace_parsed_.Append(value->CreateDeepCopy());
- continue;
- }
- DictionaryValue* dict = static_cast<DictionaryValue*>(value);
- std::string tmp;
- if (dict->GetString("ph", &tmp) && tmp == "M")
- continue;
-
- trace_parsed_.Append(value->CreateDeepCopy());
- }
-}
-
-DictionaryValue* TraceEventTestFixture::FindNamePhase(const char* name,
- const char* phase) {
- JsonKeyValue key_values[] = {{"name", name, IS_EQUAL},
- {"ph", phase, IS_EQUAL},
- {nullptr, nullptr, IS_EQUAL}};
- return FindMatchingTraceEntry(key_values);
-}
-
-DictionaryValue* TraceEventTestFixture::FindNamePhaseKeyValue(
- const char* name,
- const char* phase,
- const char* key,
- const char* value) {
- JsonKeyValue key_values[] = {{"name", name, IS_EQUAL},
- {"ph", phase, IS_EQUAL},
- {key, value, IS_EQUAL},
- {nullptr, nullptr, IS_EQUAL}};
- return FindMatchingTraceEntry(key_values);
-}
-
-bool TraceEventTestFixture::FindMatchingValue(const char* key,
- const char* value) {
- JsonKeyValue key_values[] = {{key, value, IS_EQUAL},
- {nullptr, nullptr, IS_EQUAL}};
- return FindMatchingTraceEntry(key_values);
-}
-
-bool TraceEventTestFixture::FindNonMatchingValue(const char* key,
- const char* value) {
- JsonKeyValue key_values[] = {{key, value, IS_NOT_EQUAL},
- {nullptr, nullptr, IS_EQUAL}};
- return FindMatchingTraceEntry(key_values);
-}
-
-bool IsStringInDict(const char* string_to_match, const DictionaryValue* dict) {
- for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) {
- if (it.key().find(string_to_match) != std::string::npos)
- return true;
-
- std::string value_str;
- it.value().GetAsString(&value_str);
- if (value_str.find(string_to_match) != std::string::npos)
- return true;
- }
-
- // Recurse to test arguments
- const DictionaryValue* args_dict = nullptr;
- dict->GetDictionary("args", &args_dict);
- if (args_dict)
- return IsStringInDict(string_to_match, args_dict);
-
- return false;
-}
-
-const DictionaryValue* FindTraceEntry(
- const ListValue& trace_parsed,
- const char* string_to_match,
- const DictionaryValue* match_after_this_item = nullptr) {
- // Scan all items
- size_t trace_parsed_count = trace_parsed.GetSize();
- for (size_t i = 0; i < trace_parsed_count; i++) {
- const Value* value = nullptr;
- trace_parsed.Get(i, &value);
- if (match_after_this_item) {
- if (value == match_after_this_item)
- match_after_this_item = nullptr;
- continue;
- }
- if (!value || value->type() != Value::Type::DICTIONARY)
- continue;
- const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
-
- if (IsStringInDict(string_to_match, dict))
- return dict;
- }
- return nullptr;
-}
-
-std::vector<const DictionaryValue*> FindTraceEntries(
- const ListValue& trace_parsed,
- const char* string_to_match) {
- std::vector<const DictionaryValue*> hits;
- size_t trace_parsed_count = trace_parsed.GetSize();
- for (size_t i = 0; i < trace_parsed_count; i++) {
- const Value* value = nullptr;
- trace_parsed.Get(i, &value);
- if (!value || value->type() != Value::Type::DICTIONARY)
- continue;
- const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
-
- if (IsStringInDict(string_to_match, dict))
- hits.push_back(dict);
- }
- return hits;
-}
-
-const char kControlCharacters[] = "\001\002\003\n\r";
-
-void TraceWithAllMacroVariants(WaitableEvent* task_complete_event) {
- {
- TRACE_EVENT0("all", "TRACE_EVENT0 call");
- TRACE_EVENT1("all", "TRACE_EVENT1 call", "name1", "value1");
- TRACE_EVENT2("all", "TRACE_EVENT2 call",
- "name1", "\"value1\"",
- "name2", "value\\2");
-
- TRACE_EVENT_INSTANT0("all", "TRACE_EVENT_INSTANT0 call",
- TRACE_EVENT_SCOPE_GLOBAL);
- TRACE_EVENT_INSTANT1("all", "TRACE_EVENT_INSTANT1 call",
- TRACE_EVENT_SCOPE_PROCESS, "name1", "value1");
- TRACE_EVENT_INSTANT2("all", "TRACE_EVENT_INSTANT2 call",
- TRACE_EVENT_SCOPE_THREAD,
- "name1", "value1",
- "name2", "value2");
-
- TRACE_EVENT_BEGIN0("all", "TRACE_EVENT_BEGIN0 call");
- TRACE_EVENT_BEGIN1("all", "TRACE_EVENT_BEGIN1 call", "name1", "value1");
- TRACE_EVENT_BEGIN2("all", "TRACE_EVENT_BEGIN2 call",
- "name1", "value1",
- "name2", "value2");
-
- TRACE_EVENT_END0("all", "TRACE_EVENT_END0 call");
- TRACE_EVENT_END1("all", "TRACE_EVENT_END1 call", "name1", "value1");
- TRACE_EVENT_END2("all", "TRACE_EVENT_END2 call",
- "name1", "value1",
- "name2", "value2");
-
- TRACE_EVENT_ASYNC_BEGIN0("all", "TRACE_EVENT_ASYNC_BEGIN0 call", kAsyncId);
- TRACE_EVENT_ASYNC_BEGIN1("all", "TRACE_EVENT_ASYNC_BEGIN1 call", kAsyncId,
- "name1", "value1");
- TRACE_EVENT_ASYNC_BEGIN2("all", "TRACE_EVENT_ASYNC_BEGIN2 call", kAsyncId,
- "name1", "value1",
- "name2", "value2");
-
- TRACE_EVENT_ASYNC_STEP_INTO0("all", "TRACE_EVENT_ASYNC_STEP_INTO0 call",
- kAsyncId, "step_begin1");
- TRACE_EVENT_ASYNC_STEP_INTO1("all", "TRACE_EVENT_ASYNC_STEP_INTO1 call",
- kAsyncId, "step_begin2", "name1", "value1");
-
- TRACE_EVENT_ASYNC_END0("all", "TRACE_EVENT_ASYNC_END0 call", kAsyncId);
- TRACE_EVENT_ASYNC_END1("all", "TRACE_EVENT_ASYNC_END1 call", kAsyncId,
- "name1", "value1");
- TRACE_EVENT_ASYNC_END2("all", "TRACE_EVENT_ASYNC_END2 call", kAsyncId,
- "name1", "value1",
- "name2", "value2");
-
- TRACE_EVENT_FLOW_BEGIN0("all", "TRACE_EVENT_FLOW_BEGIN0 call", kFlowId);
- TRACE_EVENT_FLOW_STEP0("all", "TRACE_EVENT_FLOW_STEP0 call",
- kFlowId, "step1");
- TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0("all",
- "TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0 call", kFlowId);
-
- TRACE_COUNTER1("all", "TRACE_COUNTER1 call", 31415);
- TRACE_COUNTER2("all", "TRACE_COUNTER2 call",
- "a", 30000,
- "b", 1415);
-
- TRACE_COUNTER_WITH_TIMESTAMP1("all", "TRACE_COUNTER_WITH_TIMESTAMP1 call",
- TimeTicks::FromInternalValue(42), 31415);
- TRACE_COUNTER_WITH_TIMESTAMP2("all", "TRACE_COUNTER_WITH_TIMESTAMP2 call",
- TimeTicks::FromInternalValue(42),
- "a", 30000, "b", 1415);
-
- TRACE_COUNTER_ID1("all", "TRACE_COUNTER_ID1 call", 0x319009, 31415);
- TRACE_COUNTER_ID2("all", "TRACE_COUNTER_ID2 call", 0x319009,
- "a", 30000, "b", 1415);
-
- TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("all",
- "TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0 call",
- kAsyncId, kThreadId, TimeTicks::FromInternalValue(12345));
- TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0("all",
- "TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0 call",
- kAsyncId, kThreadId, TimeTicks::FromInternalValue(23456));
-
- TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0("all",
- "TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0 call",
- kAsyncId2, kThreadId, TimeTicks::FromInternalValue(34567));
- TRACE_EVENT_ASYNC_STEP_PAST0("all", "TRACE_EVENT_ASYNC_STEP_PAST0 call",
- kAsyncId2, "step_end1");
- TRACE_EVENT_ASYNC_STEP_PAST1("all", "TRACE_EVENT_ASYNC_STEP_PAST1 call",
- kAsyncId2, "step_end2", "name1", "value1");
-
- TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0("all",
- "TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0 call",
- kAsyncId2, kThreadId, TimeTicks::FromInternalValue(45678));
-
- TRACE_EVENT_OBJECT_CREATED_WITH_ID("all", "tracked object 1", 0x42);
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- "all", "tracked object 1", 0x42, "hello");
- TRACE_EVENT_OBJECT_DELETED_WITH_ID("all", "tracked object 1", 0x42);
-
- TraceScopedTrackableObject<int> trackable("all", "tracked object 2",
- 0x2128506);
- trackable.snapshot("world");
-
- TRACE_EVENT_OBJECT_CREATED_WITH_ID(
- "all", "tracked object 3", TRACE_ID_WITH_SCOPE("scope", 0x42));
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- "all", "tracked object 3", TRACE_ID_WITH_SCOPE("scope", 0x42), "hello");
- TRACE_EVENT_OBJECT_DELETED_WITH_ID(
- "all", "tracked object 3", TRACE_ID_WITH_SCOPE("scope", 0x42));
-
- TRACE_EVENT1(kControlCharacters, kControlCharacters,
- kControlCharacters, kControlCharacters);
-
- uint64_t context_id = 0x20151021;
-
- TRACE_EVENT_ENTER_CONTEXT("all", "TRACE_EVENT_ENTER_CONTEXT call",
- TRACE_ID_WITH_SCOPE("scope", context_id));
- TRACE_EVENT_LEAVE_CONTEXT("all", "TRACE_EVENT_LEAVE_CONTEXT call",
- TRACE_ID_WITH_SCOPE("scope", context_id));
- TRACE_EVENT_SCOPED_CONTEXT("disabled-by-default-cat",
- "TRACE_EVENT_SCOPED_CONTEXT disabled call",
- context_id);
- TRACE_EVENT_SCOPED_CONTEXT("all", "TRACE_EVENT_SCOPED_CONTEXT call",
- context_id);
-
- TRACE_LINK_IDS("all", "TRACE_LINK_IDS simple call", 0x1000, 0x2000);
- TRACE_LINK_IDS("all", "TRACE_LINK_IDS scoped call",
- TRACE_ID_WITH_SCOPE("scope 1", 0x1000),
- TRACE_ID_WITH_SCOPE("scope 2", 0x2000));
- TRACE_LINK_IDS("all", "TRACE_LINK_IDS to a local ID", 0x1000,
- TRACE_ID_LOCAL(0x2000));
- TRACE_LINK_IDS("all", "TRACE_LINK_IDS to a global ID", 0x1000,
- TRACE_ID_GLOBAL(0x2000));
- TRACE_LINK_IDS("all", "TRACE_LINK_IDS to a composite ID", 0x1000,
- TRACE_ID_WITH_SCOPE("scope 1", 0x2000, 0x3000));
-
- TRACE_EVENT_ASYNC_BEGIN0("all", "async default process scope", 0x1000);
- TRACE_EVENT_ASYNC_BEGIN0("all", "async local id", TRACE_ID_LOCAL(0x2000));
- TRACE_EVENT_ASYNC_BEGIN0("all", "async global id", TRACE_ID_GLOBAL(0x3000));
- TRACE_EVENT_ASYNC_BEGIN0("all", "async global id with scope string",
- TRACE_ID_WITH_SCOPE("scope string",
- TRACE_ID_GLOBAL(0x4000)));
- } // Scope close causes TRACE_EVENT0 etc to send their END events.
-
- if (task_complete_event)
- task_complete_event->Signal();
-}
-
-void ValidateAllTraceMacrosCreatedData(const ListValue& trace_parsed) {
- const DictionaryValue* item = nullptr;
-
-#define EXPECT_FIND_(string) \
- item = FindTraceEntry(trace_parsed, string); \
- EXPECT_TRUE(item);
-#define EXPECT_NOT_FIND_(string) \
- item = FindTraceEntry(trace_parsed, string); \
- EXPECT_FALSE(item);
-#define EXPECT_SUB_FIND_(string) \
- if (item) \
- EXPECT_TRUE(IsStringInDict(string, item));
-
- EXPECT_FIND_("TRACE_EVENT0 call");
- {
- std::string ph;
- std::string ph_end;
- EXPECT_TRUE((item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call")));
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("X", ph);
- item = FindTraceEntry(trace_parsed, "TRACE_EVENT0 call", item);
- EXPECT_FALSE(item);
- }
- EXPECT_FIND_("TRACE_EVENT1 call");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_FIND_("TRACE_EVENT2 call");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("\"value1\"");
- EXPECT_SUB_FIND_("name2");
- EXPECT_SUB_FIND_("value\\2");
-
- EXPECT_FIND_("TRACE_EVENT_INSTANT0 call");
- {
- std::string scope;
- EXPECT_TRUE((item && item->GetString("s", &scope)));
- EXPECT_EQ("g", scope);
- }
- EXPECT_FIND_("TRACE_EVENT_INSTANT1 call");
- {
- std::string scope;
- EXPECT_TRUE((item && item->GetString("s", &scope)));
- EXPECT_EQ("p", scope);
- }
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_FIND_("TRACE_EVENT_INSTANT2 call");
- {
- std::string scope;
- EXPECT_TRUE((item && item->GetString("s", &scope)));
- EXPECT_EQ("t", scope);
- }
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_SUB_FIND_("name2");
- EXPECT_SUB_FIND_("value2");
-
- EXPECT_FIND_("TRACE_EVENT_BEGIN0 call");
- EXPECT_FIND_("TRACE_EVENT_BEGIN1 call");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_FIND_("TRACE_EVENT_BEGIN2 call");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_SUB_FIND_("name2");
- EXPECT_SUB_FIND_("value2");
-
- EXPECT_FIND_("TRACE_EVENT_END0 call");
- EXPECT_FIND_("TRACE_EVENT_END1 call");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_FIND_("TRACE_EVENT_END2 call");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_SUB_FIND_("name2");
- EXPECT_SUB_FIND_("value2");
-
- EXPECT_FIND_("TRACE_EVENT_ASYNC_BEGIN0 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_FIND_("TRACE_EVENT_ASYNC_BEGIN1 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_FIND_("TRACE_EVENT_ASYNC_BEGIN2 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_SUB_FIND_("name2");
- EXPECT_SUB_FIND_("value2");
-
- EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_INTO0 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_SUB_FIND_("step_begin1");
- EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_INTO1 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_SUB_FIND_("step_begin2");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
-
- EXPECT_FIND_("TRACE_EVENT_ASYNC_END0 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_FIND_("TRACE_EVENT_ASYNC_END1 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_FIND_("TRACE_EVENT_ASYNC_END2 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncIdStr);
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- EXPECT_SUB_FIND_("name2");
- EXPECT_SUB_FIND_("value2");
-
- EXPECT_FIND_("TRACE_EVENT_FLOW_BEGIN0 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kFlowIdStr);
- EXPECT_FIND_("TRACE_EVENT_FLOW_STEP0 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kFlowIdStr);
- EXPECT_SUB_FIND_("step1");
- EXPECT_FIND_("TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kFlowIdStr);
-
- EXPECT_FIND_("TRACE_COUNTER1 call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("C", ph);
-
- int value;
- EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
- EXPECT_EQ(31415, value);
- }
-
- EXPECT_FIND_("TRACE_COUNTER2 call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("C", ph);
-
- int value;
- EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
- EXPECT_EQ(30000, value);
-
- EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
- EXPECT_EQ(1415, value);
- }
-
- EXPECT_FIND_("TRACE_COUNTER_WITH_TIMESTAMP1 call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("C", ph);
-
- int value;
- EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
- EXPECT_EQ(31415, value);
-
- int ts;
- EXPECT_TRUE((item && item->GetInteger("ts", &ts)));
- EXPECT_EQ(42, ts);
- }
-
- EXPECT_FIND_("TRACE_COUNTER_WITH_TIMESTAMP2 call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("C", ph);
-
- int value;
- EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
- EXPECT_EQ(30000, value);
-
- EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
- EXPECT_EQ(1415, value);
-
- int ts;
- EXPECT_TRUE((item && item->GetInteger("ts", &ts)));
- EXPECT_EQ(42, ts);
- }
-
- EXPECT_FIND_("TRACE_COUNTER_ID1 call");
- {
- std::string id;
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x319009", id);
-
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("C", ph);
-
- int value;
- EXPECT_TRUE((item && item->GetInteger("args.value", &value)));
- EXPECT_EQ(31415, value);
- }
-
- EXPECT_FIND_("TRACE_COUNTER_ID2 call");
- {
- std::string id;
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x319009", id);
-
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("C", ph);
-
- int value;
- EXPECT_TRUE((item && item->GetInteger("args.a", &value)));
- EXPECT_EQ(30000, value);
-
- EXPECT_TRUE((item && item->GetInteger("args.b", &value)));
- EXPECT_EQ(1415, value);
- }
-
- EXPECT_FIND_("TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0 call");
- {
- int val;
- EXPECT_TRUE((item && item->GetInteger("ts", &val)));
- EXPECT_EQ(12345, val);
- EXPECT_TRUE((item && item->GetInteger("tid", &val)));
- EXPECT_EQ(kThreadId, val);
- std::string id;
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ(kAsyncIdStr, id);
- }
-
- EXPECT_FIND_("TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0 call");
- {
- int val;
- EXPECT_TRUE((item && item->GetInteger("ts", &val)));
- EXPECT_EQ(23456, val);
- EXPECT_TRUE((item && item->GetInteger("tid", &val)));
- EXPECT_EQ(kThreadId, val);
- std::string id;
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ(kAsyncIdStr, id);
- }
-
- EXPECT_FIND_("TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0 call");
- {
- int val;
- EXPECT_TRUE((item && item->GetInteger("ts", &val)));
- EXPECT_EQ(34567, val);
- EXPECT_TRUE((item && item->GetInteger("tid", &val)));
- EXPECT_EQ(kThreadId, val);
- std::string id;
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ(kAsyncId2Str, id);
- }
-
- EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_PAST0 call");
- {
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncId2Str);
- EXPECT_SUB_FIND_("step_end1");
- EXPECT_FIND_("TRACE_EVENT_ASYNC_STEP_PAST1 call");
- EXPECT_SUB_FIND_("id");
- EXPECT_SUB_FIND_(kAsyncId2Str);
- EXPECT_SUB_FIND_("step_end2");
- EXPECT_SUB_FIND_("name1");
- EXPECT_SUB_FIND_("value1");
- }
-
- EXPECT_FIND_("TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0 call");
- {
- int val;
- EXPECT_TRUE((item && item->GetInteger("ts", &val)));
- EXPECT_EQ(45678, val);
- EXPECT_TRUE((item && item->GetInteger("tid", &val)));
- EXPECT_EQ(kThreadId, val);
- std::string id;
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ(kAsyncId2Str, id);
- }
-
- EXPECT_FIND_("tracked object 1");
- {
- std::string phase;
- std::string id;
- std::string snapshot;
-
- EXPECT_TRUE((item && item->GetString("ph", &phase)));
- EXPECT_EQ("N", phase);
- EXPECT_FALSE((item && item->HasKey("scope")));
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x42", id);
-
- item = FindTraceEntry(trace_parsed, "tracked object 1", item);
- EXPECT_TRUE(item);
- EXPECT_TRUE(item && item->GetString("ph", &phase));
- EXPECT_EQ("O", phase);
- EXPECT_FALSE((item && item->HasKey("scope")));
- EXPECT_TRUE(item && item->GetString("id", &id));
- EXPECT_EQ("0x42", id);
- EXPECT_TRUE(item && item->GetString("args.snapshot", &snapshot));
- EXPECT_EQ("hello", snapshot);
-
- item = FindTraceEntry(trace_parsed, "tracked object 1", item);
- EXPECT_TRUE(item);
- EXPECT_TRUE(item && item->GetString("ph", &phase));
- EXPECT_EQ("D", phase);
- EXPECT_FALSE((item && item->HasKey("scope")));
- EXPECT_TRUE(item && item->GetString("id", &id));
- EXPECT_EQ("0x42", id);
- }
-
- EXPECT_FIND_("tracked object 2");
- {
- std::string phase;
- std::string id;
- std::string snapshot;
-
- EXPECT_TRUE(item && item->GetString("ph", &phase));
- EXPECT_EQ("N", phase);
- EXPECT_TRUE(item && item->GetString("id", &id));
- EXPECT_EQ("0x2128506", id);
-
- item = FindTraceEntry(trace_parsed, "tracked object 2", item);
- EXPECT_TRUE(item);
- EXPECT_TRUE(item && item->GetString("ph", &phase));
- EXPECT_EQ("O", phase);
- EXPECT_TRUE(item && item->GetString("id", &id));
- EXPECT_EQ("0x2128506", id);
- EXPECT_TRUE(item && item->GetString("args.snapshot", &snapshot));
- EXPECT_EQ("world", snapshot);
-
- item = FindTraceEntry(trace_parsed, "tracked object 2", item);
- EXPECT_TRUE(item);
- EXPECT_TRUE(item && item->GetString("ph", &phase));
- EXPECT_EQ("D", phase);
- EXPECT_TRUE(item && item->GetString("id", &id));
- EXPECT_EQ("0x2128506", id);
- }
-
- EXPECT_FIND_("tracked object 3");
- {
- std::string phase;
- std::string scope;
- std::string id;
- std::string snapshot;
-
- EXPECT_TRUE((item && item->GetString("ph", &phase)));
- EXPECT_EQ("N", phase);
- EXPECT_TRUE((item && item->GetString("scope", &scope)));
- EXPECT_EQ("scope", scope);
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x42", id);
-
- item = FindTraceEntry(trace_parsed, "tracked object 3", item);
- EXPECT_TRUE(item);
- EXPECT_TRUE(item && item->GetString("ph", &phase));
- EXPECT_EQ("O", phase);
- EXPECT_TRUE((item && item->GetString("scope", &scope)));
- EXPECT_EQ("scope", scope);
- EXPECT_TRUE(item && item->GetString("id", &id));
- EXPECT_EQ("0x42", id);
- EXPECT_TRUE(item && item->GetString("args.snapshot", &snapshot));
- EXPECT_EQ("hello", snapshot);
-
- item = FindTraceEntry(trace_parsed, "tracked object 3", item);
- EXPECT_TRUE(item);
- EXPECT_TRUE(item && item->GetString("ph", &phase));
- EXPECT_EQ("D", phase);
- EXPECT_TRUE((item && item->GetString("scope", &scope)));
- EXPECT_EQ("scope", scope);
- EXPECT_TRUE(item && item->GetString("id", &id));
- EXPECT_EQ("0x42", id);
- }
-
- EXPECT_FIND_(kControlCharacters);
- EXPECT_SUB_FIND_(kControlCharacters);
-
- EXPECT_FIND_("TRACE_EVENT_ENTER_CONTEXT call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("(", ph);
-
- std::string scope;
- std::string id;
- EXPECT_TRUE((item && item->GetString("scope", &scope)));
- EXPECT_EQ("scope", scope);
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x20151021", id);
- }
-
- EXPECT_FIND_("TRACE_EVENT_LEAVE_CONTEXT call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ(")", ph);
-
- std::string scope;
- std::string id;
- EXPECT_TRUE((item && item->GetString("scope", &scope)));
- EXPECT_EQ("scope", scope);
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x20151021", id);
- }
-
- std::vector<const DictionaryValue*> scoped_context_calls =
- FindTraceEntries(trace_parsed, "TRACE_EVENT_SCOPED_CONTEXT call");
- EXPECT_EQ(2u, scoped_context_calls.size());
- {
- item = scoped_context_calls[0];
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("(", ph);
-
- std::string id;
- EXPECT_FALSE((item && item->HasKey("scope")));
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x20151021", id);
- }
-
- {
- item = scoped_context_calls[1];
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ(")", ph);
-
- std::string id;
- EXPECT_FALSE((item && item->HasKey("scope")));
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x20151021", id);
- }
-
- EXPECT_FIND_("TRACE_LINK_IDS simple call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("=", ph);
-
- EXPECT_FALSE((item && item->HasKey("scope")));
- std::string id1;
- EXPECT_TRUE((item && item->GetString("id", &id1)));
- EXPECT_EQ("0x1000", id1);
-
- EXPECT_FALSE((item && item->HasKey("args.linked_id.scope")));
- std::string id2;
- EXPECT_TRUE((item && item->GetString("args.linked_id.id", &id2)));
- EXPECT_EQ("0x2000", id2);
- }
-
- EXPECT_FIND_("TRACE_LINK_IDS scoped call");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("=", ph);
-
- std::string scope1;
- EXPECT_TRUE((item && item->GetString("scope", &scope1)));
- EXPECT_EQ("scope 1", scope1);
- std::string id1;
- EXPECT_TRUE((item && item->GetString("id", &id1)));
- EXPECT_EQ("0x1000", id1);
-
- std::string scope2;
- EXPECT_TRUE((item && item->GetString("args.linked_id.scope", &scope2)));
- EXPECT_EQ("scope 2", scope2);
- std::string id2;
- EXPECT_TRUE((item && item->GetString("args.linked_id.id", &id2)));
- EXPECT_EQ("0x2000", id2);
- }
-
- EXPECT_FIND_("TRACE_LINK_IDS to a local ID");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("=", ph);
-
- EXPECT_FALSE((item && item->HasKey("scope")));
- std::string id1;
- EXPECT_TRUE((item && item->GetString("id", &id1)));
- EXPECT_EQ("0x1000", id1);
-
- EXPECT_FALSE((item && item->HasKey("args.linked_id.scope")));
- std::string id2;
- EXPECT_TRUE((item && item->GetString("args.linked_id.id2.local", &id2)));
- EXPECT_EQ("0x2000", id2);
- }
-
- EXPECT_FIND_("TRACE_LINK_IDS to a global ID");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("=", ph);
-
- EXPECT_FALSE((item && item->HasKey("scope")));
- std::string id1;
- EXPECT_TRUE((item && item->GetString("id", &id1)));
- EXPECT_EQ("0x1000", id1);
-
- EXPECT_FALSE((item && item->HasKey("args.linked_id.scope")));
- std::string id2;
- EXPECT_TRUE((item && item->GetString("args.linked_id.id2.global", &id2)));
- EXPECT_EQ("0x2000", id2);
- }
-
- EXPECT_FIND_("TRACE_LINK_IDS to a composite ID");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("=", ph);
-
- EXPECT_FALSE(item->HasKey("scope"));
- std::string id1;
- EXPECT_TRUE(item->GetString("id", &id1));
- EXPECT_EQ("0x1000", id1);
-
- std::string scope;
- EXPECT_TRUE(item->GetString("args.linked_id.scope", &scope));
- EXPECT_EQ("scope 1", scope);
- std::string id2;
- EXPECT_TRUE(item->GetString("args.linked_id.id", &id2));
- EXPECT_EQ(id2, "0x2000/0x3000");
- }
-
- EXPECT_FIND_("async default process scope");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("S", ph);
-
- std::string id;
- EXPECT_TRUE((item && item->GetString("id", &id)));
- EXPECT_EQ("0x1000", id);
- }
-
- EXPECT_FIND_("async local id");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("S", ph);
-
- std::string id;
- EXPECT_TRUE((item && item->GetString("id2.local", &id)));
- EXPECT_EQ("0x2000", id);
- }
-
- EXPECT_FIND_("async global id");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("S", ph);
-
- std::string id;
- EXPECT_TRUE((item && item->GetString("id2.global", &id)));
- EXPECT_EQ("0x3000", id);
- }
-
- EXPECT_FIND_("async global id with scope string");
- {
- std::string ph;
- EXPECT_TRUE((item && item->GetString("ph", &ph)));
- EXPECT_EQ("S", ph);
-
- std::string id;
- EXPECT_TRUE((item && item->GetString("id2.global", &id)));
- EXPECT_EQ("0x4000", id);
- std::string scope;
- EXPECT_TRUE((item && item->GetString("scope", &scope)));
- EXPECT_EQ("scope string", scope);
- }
-}
-
-void TraceManyInstantEvents(int thread_id, int num_events,
- WaitableEvent* task_complete_event) {
- for (int i = 0; i < num_events; i++) {
- TRACE_EVENT_INSTANT2("all", "multi thread event",
- TRACE_EVENT_SCOPE_THREAD,
- "thread", thread_id,
- "event", i);
- }
-
- if (task_complete_event)
- task_complete_event->Signal();
-}
-
-void ValidateInstantEventPresentOnEveryThread(const ListValue& trace_parsed,
- int num_threads,
- int num_events) {
- std::map<int, std::map<int, bool> > results;
-
- size_t trace_parsed_count = trace_parsed.GetSize();
- for (size_t i = 0; i < trace_parsed_count; i++) {
- const Value* value = nullptr;
- trace_parsed.Get(i, &value);
- if (!value || value->type() != Value::Type::DICTIONARY)
- continue;
- const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
- std::string name;
- dict->GetString("name", &name);
- if (name != "multi thread event")
- continue;
-
- int thread = 0;
- int event = 0;
- EXPECT_TRUE(dict->GetInteger("args.thread", &thread));
- EXPECT_TRUE(dict->GetInteger("args.event", &event));
- results[thread][event] = true;
- }
-
- EXPECT_FALSE(results[-1][-1]);
- for (int thread = 0; thread < num_threads; thread++) {
- for (int event = 0; event < num_events; event++) {
- EXPECT_TRUE(results[thread][event]);
- }
- }
-}
-
-void CheckTraceDefaultCategoryFilters(const TraceLog& trace_log) {
- // Default enables all category filters except the disabled-by-default-* ones.
- EXPECT_TRUE(*trace_log.GetCategoryGroupEnabled("foo"));
- EXPECT_TRUE(*trace_log.GetCategoryGroupEnabled("bar"));
- EXPECT_TRUE(*trace_log.GetCategoryGroupEnabled("foo,bar"));
- EXPECT_TRUE(*trace_log.GetCategoryGroupEnabled(
- "foo,disabled-by-default-foo"));
- EXPECT_FALSE(*trace_log.GetCategoryGroupEnabled(
- "disabled-by-default-foo,disabled-by-default-bar"));
-}
-
-} // namespace
-
-// Simple Test for emitting data and validating it was received.
-TEST_F(TraceEventTestFixture, DataCaptured) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
-
- TraceWithAllMacroVariants(nullptr);
-
- EndTraceAndFlush();
-
- ValidateAllTraceMacrosCreatedData(trace_parsed_);
-}
-
-// Emit some events and validate that only empty strings are received
-// if we tell Flush() to discard events.
-TEST_F(TraceEventTestFixture, DataDiscarded) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
-
- TraceWithAllMacroVariants(nullptr);
-
- CancelTrace();
-
- EXPECT_TRUE(trace_parsed_.empty());
-}
-
-class MockEnabledStateChangedObserver :
- public TraceLog::EnabledStateObserver {
- public:
- MOCK_METHOD0(OnTraceLogEnabled, void());
- MOCK_METHOD0(OnTraceLogDisabled, void());
-};
-
-TEST_F(TraceEventTestFixture, EnabledObserverFiresOnEnable) {
- MockEnabledStateChangedObserver observer;
- TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
-
- EXPECT_CALL(observer, OnTraceLogEnabled())
- .Times(1);
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
- testing::Mock::VerifyAndClear(&observer);
- EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
-
- // Cleanup.
- TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
- TraceLog::GetInstance()->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, EnabledObserverDoesntFireOnSecondEnable) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
-
- testing::StrictMock<MockEnabledStateChangedObserver> observer;
- TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
-
- EXPECT_CALL(observer, OnTraceLogEnabled())
- .Times(0);
- EXPECT_CALL(observer, OnTraceLogDisabled())
- .Times(0);
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
- testing::Mock::VerifyAndClear(&observer);
- EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
-
- // Cleanup.
- TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
- TraceLog::GetInstance()->SetDisabled();
- TraceLog::GetInstance()->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, EnabledObserverFiresOnFirstDisable) {
- TraceConfig tc_inc_all("*", "");
- TraceLog::GetInstance()->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
- TraceLog::GetInstance()->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
-
- testing::StrictMock<MockEnabledStateChangedObserver> observer;
- TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
-
- EXPECT_CALL(observer, OnTraceLogEnabled())
- .Times(0);
- EXPECT_CALL(observer, OnTraceLogDisabled())
- .Times(1);
- TraceLog::GetInstance()->SetDisabled();
- testing::Mock::VerifyAndClear(&observer);
-
- // Cleanup.
- TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
- TraceLog::GetInstance()->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, EnabledObserverFiresOnDisable) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
-
- MockEnabledStateChangedObserver observer;
- TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
-
- EXPECT_CALL(observer, OnTraceLogDisabled())
- .Times(1);
- TraceLog::GetInstance()->SetDisabled();
- testing::Mock::VerifyAndClear(&observer);
-
- // Cleanup.
- TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
-}
-
-// Tests the IsEnabled() state of TraceLog changes before callbacks.
-class AfterStateChangeEnabledStateObserver
- : public TraceLog::EnabledStateObserver {
- public:
- AfterStateChangeEnabledStateObserver() = default;
- ~AfterStateChangeEnabledStateObserver() override = default;
-
- // TraceLog::EnabledStateObserver overrides:
- void OnTraceLogEnabled() override {
- EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
- }
-
- void OnTraceLogDisabled() override {
- EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled());
- }
-};
-
-TEST_F(TraceEventTestFixture, ObserversFireAfterStateChange) {
- AfterStateChangeEnabledStateObserver observer;
- TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
-
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
- EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
-
- TraceLog::GetInstance()->SetDisabled();
- EXPECT_FALSE(TraceLog::GetInstance()->IsEnabled());
-
- TraceLog::GetInstance()->RemoveEnabledStateObserver(&observer);
-}
-
-// Tests that a state observer can remove itself during a callback.
-class SelfRemovingEnabledStateObserver
- : public TraceLog::EnabledStateObserver {
- public:
- SelfRemovingEnabledStateObserver() = default;
- ~SelfRemovingEnabledStateObserver() override = default;
-
- // TraceLog::EnabledStateObserver overrides:
- void OnTraceLogEnabled() override {}
-
- void OnTraceLogDisabled() override {
- TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
- }
-};
-
-TEST_F(TraceEventTestFixture, SelfRemovingObserver) {
- ASSERT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
-
- SelfRemovingEnabledStateObserver observer;
- TraceLog::GetInstance()->AddEnabledStateObserver(&observer);
- EXPECT_EQ(1u, TraceLog::GetInstance()->GetObserverCountForTest());
-
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
- TraceLog::GetInstance()->SetDisabled();
- // The observer removed itself on disable.
- EXPECT_EQ(0u, TraceLog::GetInstance()->GetObserverCountForTest());
-}
-
-bool IsNewTrace() {
- bool is_new_trace;
- TRACE_EVENT_IS_NEW_TRACE(&is_new_trace);
- return is_new_trace;
-}
-
-TEST_F(TraceEventTestFixture, NewTraceRecording) {
- ASSERT_FALSE(IsNewTrace());
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
- // First call to IsNewTrace() should succeed. But, the second shouldn't.
- ASSERT_TRUE(IsNewTrace());
- ASSERT_FALSE(IsNewTrace());
- EndTraceAndFlush();
-
- // IsNewTrace() should definitely be false now.
- ASSERT_FALSE(IsNewTrace());
-
- // Start another trace. IsNewTrace() should become true again, briefly, as
- // before.
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
- ASSERT_TRUE(IsNewTrace());
- ASSERT_FALSE(IsNewTrace());
-
- // Cleanup.
- EndTraceAndFlush();
-}
-
-TEST_F(TraceEventTestFixture, TestTraceFlush) {
- size_t min_traces = 1;
- size_t max_traces = 1;
- do {
- max_traces *= 2;
- TraceLog::GetInstance()->SetEnabled(TraceConfig(),
- TraceLog::RECORDING_MODE);
- for (size_t i = 0; i < max_traces; i++) {
- TRACE_EVENT_INSTANT0("x", "y", TRACE_EVENT_SCOPE_THREAD);
- }
- EndTraceAndFlush();
- } while (num_flush_callbacks_ < 2);
-
- while (min_traces + 50 < max_traces) {
- size_t traces = (min_traces + max_traces) / 2;
- TraceLog::GetInstance()->SetEnabled(TraceConfig(),
- TraceLog::RECORDING_MODE);
- for (size_t i = 0; i < traces; i++) {
- TRACE_EVENT_INSTANT0("x", "y", TRACE_EVENT_SCOPE_THREAD);
- }
- EndTraceAndFlush();
- if (num_flush_callbacks_ < 2) {
- min_traces = traces - 10;
- } else {
- max_traces = traces + 10;
- }
- }
-
- for (size_t traces = min_traces; traces < max_traces; traces++) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(),
- TraceLog::RECORDING_MODE);
- for (size_t i = 0; i < traces; i++) {
- TRACE_EVENT_INSTANT0("x", "y", TRACE_EVENT_SCOPE_THREAD);
- }
- EndTraceAndFlush();
- }
-}
-
-TEST_F(TraceEventTestFixture, AddMetadataEvent) {
- int num_calls = 0;
-
- class Convertable : public ConvertableToTraceFormat {
- public:
- explicit Convertable(int* num_calls) : num_calls_(num_calls) {}
- ~Convertable() override = default;
- void AppendAsTraceFormat(std::string* out) const override {
- (*num_calls_)++;
- out->append("\"metadata_value\"");
- }
-
- private:
- int* num_calls_;
- };
-
- std::unique_ptr<ConvertableToTraceFormat> conv1(new Convertable(&num_calls));
- std::unique_ptr<Convertable> conv2(new Convertable(&num_calls));
-
- BeginTrace();
- TRACE_EVENT_API_ADD_METADATA_EVENT(
- TraceLog::GetCategoryGroupEnabled("__metadata"), "metadata_event_1",
- "metadata_arg_name", std::move(conv1));
- TRACE_EVENT_API_ADD_METADATA_EVENT(
- TraceLog::GetCategoryGroupEnabled("__metadata"), "metadata_event_2",
- "metadata_arg_name", std::move(conv2));
- // |AppendAsTraceFormat| should only be called on flush, not when the event
- // is added.
- ASSERT_EQ(0, num_calls);
- EndTraceAndFlush();
- ASSERT_EQ(2, num_calls);
- EXPECT_TRUE(FindNamePhaseKeyValue("metadata_event_1", "M",
- "metadata_arg_name", "metadata_value"));
- EXPECT_TRUE(FindNamePhaseKeyValue("metadata_event_2", "M",
- "metadata_arg_name", "metadata_value"));
-
- // The metadata event should only be adde to the current trace. In this new
- // trace, the event should not appear.
- BeginTrace();
- EndTraceAndFlush();
- ASSERT_EQ(2, num_calls);
-}
-
-// Test that categories work.
-TEST_F(TraceEventTestFixture, Categories) {
- // Test that categories that are used can be retrieved whether trace was
- // enabled or disabled when the trace event was encountered.
- TRACE_EVENT_INSTANT0("c1", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("c2", "name", TRACE_EVENT_SCOPE_THREAD);
- BeginTrace();
- TRACE_EVENT_INSTANT0("c3", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("c4", "name", TRACE_EVENT_SCOPE_THREAD);
- // Category groups containing more than one category.
- TRACE_EVENT_INSTANT0("c5,c6", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("c7,c8", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("c9"), "name",
- TRACE_EVENT_SCOPE_THREAD);
-
- EndTraceAndFlush();
- std::vector<std::string> cat_groups;
- TraceLog::GetInstance()->GetKnownCategoryGroups(&cat_groups);
- EXPECT_TRUE(ContainsValue(cat_groups, "c1"));
- EXPECT_TRUE(ContainsValue(cat_groups, "c2"));
- EXPECT_TRUE(ContainsValue(cat_groups, "c3"));
- EXPECT_TRUE(ContainsValue(cat_groups, "c4"));
- EXPECT_TRUE(ContainsValue(cat_groups, "c5,c6"));
- EXPECT_TRUE(ContainsValue(cat_groups, "c7,c8"));
- EXPECT_TRUE(ContainsValue(cat_groups, "disabled-by-default-c9"));
- // Make sure metadata isn't returned.
- EXPECT_FALSE(ContainsValue(cat_groups, "__metadata"));
-
- const std::vector<std::string> empty_categories;
- std::vector<std::string> included_categories;
- std::vector<std::string> excluded_categories;
-
- // Test that category filtering works.
-
- // Include nonexistent category -> no events
- Clear();
- included_categories.clear();
- TraceLog::GetInstance()->SetEnabled(TraceConfig("not_found823564786", ""),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT_INSTANT0("cat1", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat2", "name", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
- DropTracedMetadataRecords();
- EXPECT_TRUE(trace_parsed_.empty());
-
- // Include existent category -> only events of that category
- Clear();
- included_categories.clear();
- TraceLog::GetInstance()->SetEnabled(TraceConfig("inc", ""),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT_INSTANT0("inc", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc2", "name", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
- DropTracedMetadataRecords();
- EXPECT_TRUE(FindMatchingValue("cat", "inc"));
- EXPECT_FALSE(FindNonMatchingValue("cat", "inc"));
-
- // Include existent wildcard -> all categories matching wildcard
- Clear();
- included_categories.clear();
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig("inc_wildcard_*,inc_wildchar_?_end", ""),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT_INSTANT0("inc_wildcard_abc", "included",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc_wildcard_", "included", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "included",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "not_inc",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat1", "not_inc", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat2", "not_inc", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc_wildcard_category,other_category", "included",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0(
- "non_included_category,inc_wildcard_category", "included",
- TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
- EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_abc"));
- EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_"));
- EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_x_end"));
- EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
- EXPECT_TRUE(FindMatchingValue("cat", "inc_wildcard_category,other_category"));
- EXPECT_TRUE(FindMatchingValue("cat",
- "non_included_category,inc_wildcard_category"));
-
- included_categories.clear();
-
- // Exclude nonexistent category -> all events
- Clear();
- TraceLog::GetInstance()->SetEnabled(TraceConfig("-not_found823564786", ""),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT_INSTANT0("cat1", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat2", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("category1,category2", "name", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
- EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
- EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
- EXPECT_TRUE(FindMatchingValue("cat", "category1,category2"));
-
- // Exclude existent category -> only events of other categories
- Clear();
- TraceLog::GetInstance()->SetEnabled(TraceConfig("-inc", ""),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT_INSTANT0("inc", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc2", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc2,inc", "name", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc,inc2", "name", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
- EXPECT_TRUE(FindMatchingValue("cat", "inc2"));
- EXPECT_FALSE(FindMatchingValue("cat", "inc"));
- EXPECT_TRUE(FindMatchingValue("cat", "inc2,inc"));
- EXPECT_TRUE(FindMatchingValue("cat", "inc,inc2"));
-
- // Exclude existent wildcard -> all categories not matching wildcard
- Clear();
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig("-inc_wildcard_*,-inc_wildchar_?_end", ""),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT_INSTANT0("inc_wildcard_abc", "not_inc",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc_wildcard_", "not_inc",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc_wildchar_x_end", "not_inc",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("inc_wildchar_bla_end", "included",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat1", "included", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("cat2", "included", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
- EXPECT_TRUE(FindMatchingValue("cat", "inc_wildchar_bla_end"));
- EXPECT_TRUE(FindMatchingValue("cat", "cat1"));
- EXPECT_TRUE(FindMatchingValue("cat", "cat2"));
- EXPECT_FALSE(FindMatchingValue("name", "not_inc"));
-}
-
-
-// Test ASYNC_BEGIN/END events
-TEST_F(TraceEventTestFixture, AsyncBeginEndEvents) {
- BeginTrace();
-
- unsigned long long id = 0xfeedbeeffeedbeefull;
- TRACE_EVENT_ASYNC_BEGIN0("cat", "name1", id);
- TRACE_EVENT_ASYNC_STEP_INTO0("cat", "name1", id, "step1");
- TRACE_EVENT_ASYNC_END0("cat", "name1", id);
- TRACE_EVENT_BEGIN0("cat", "name2");
- TRACE_EVENT_ASYNC_BEGIN0("cat", "name3", 0);
- TRACE_EVENT_ASYNC_STEP_PAST0("cat", "name3", 0, "step2");
-
- EndTraceAndFlush();
-
- EXPECT_TRUE(FindNamePhase("name1", "S"));
- EXPECT_TRUE(FindNamePhase("name1", "T"));
- EXPECT_TRUE(FindNamePhase("name1", "F"));
-
- std::string id_str;
- StringAppendF(&id_str, "0x%llx", id);
-
- EXPECT_TRUE(FindNamePhaseKeyValue("name1", "S", "id", id_str.c_str()));
- EXPECT_TRUE(FindNamePhaseKeyValue("name1", "T", "id", id_str.c_str()));
- EXPECT_TRUE(FindNamePhaseKeyValue("name1", "F", "id", id_str.c_str()));
- EXPECT_TRUE(FindNamePhaseKeyValue("name3", "S", "id", "0x0"));
- EXPECT_TRUE(FindNamePhaseKeyValue("name3", "p", "id", "0x0"));
-
- // BEGIN events should not have id
- EXPECT_FALSE(FindNamePhaseKeyValue("name2", "B", "id", "0"));
-}
-
-// Test ASYNC_BEGIN/END events
-TEST_F(TraceEventTestFixture, AsyncBeginEndPointerMangling) {
- void* ptr = this;
-
- TraceLog::GetInstance()->SetProcessID(100);
- BeginTrace();
- TRACE_EVENT_ASYNC_BEGIN0("cat", "name1", ptr);
- TRACE_EVENT_ASYNC_BEGIN0("cat", "name2", ptr);
- EndTraceAndFlush();
-
- TraceLog::GetInstance()->SetProcessID(200);
- BeginTrace();
- TRACE_EVENT_ASYNC_END0("cat", "name1", ptr);
- EndTraceAndFlush();
-
- DictionaryValue* async_begin = FindNamePhase("name1", "S");
- DictionaryValue* async_begin2 = FindNamePhase("name2", "S");
- DictionaryValue* async_end = FindNamePhase("name1", "F");
- EXPECT_TRUE(async_begin);
- EXPECT_TRUE(async_begin2);
- EXPECT_TRUE(async_end);
-
- Value* value = nullptr;
- std::string async_begin_id_str;
- std::string async_begin2_id_str;
- std::string async_end_id_str;
- ASSERT_TRUE(async_begin->Get("id", &value));
- ASSERT_TRUE(value->GetAsString(&async_begin_id_str));
- ASSERT_TRUE(async_begin2->Get("id", &value));
- ASSERT_TRUE(value->GetAsString(&async_begin2_id_str));
- ASSERT_TRUE(async_end->Get("id", &value));
- ASSERT_TRUE(value->GetAsString(&async_end_id_str));
-
- EXPECT_STREQ(async_begin_id_str.c_str(), async_begin2_id_str.c_str());
- EXPECT_STRNE(async_begin_id_str.c_str(), async_end_id_str.c_str());
-}
-
-// Test that static strings are not copied.
-TEST_F(TraceEventTestFixture, StaticStringVsString) {
- TraceLog* tracer = TraceLog::GetInstance();
- // Make sure old events are flushed:
- EXPECT_EQ(0u, tracer->GetStatus().event_count);
- const unsigned char* category_group_enabled =
- TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED("cat");
-
- {
- BeginTrace();
- // Test that string arguments are copied.
- TraceEventHandle handle1 =
- trace_event_internal::AddTraceEvent(
- TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name1",
- trace_event_internal::kGlobalScope, trace_event_internal::kNoId,
- 0, trace_event_internal::kNoId,
- "arg1", std::string("argval"), "arg2", std::string("argval"));
- // Test that static TRACE_STR_COPY string arguments are copied.
- TraceEventHandle handle2 =
- trace_event_internal::AddTraceEvent(
- TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name2",
- trace_event_internal::kGlobalScope, trace_event_internal::kNoId,
- 0, trace_event_internal::kNoId,
- "arg1", TRACE_STR_COPY("argval"),
- "arg2", TRACE_STR_COPY("argval"));
- EXPECT_GT(tracer->GetStatus().event_count, 1u);
- const TraceEvent* event1 = tracer->GetEventByHandle(handle1);
- const TraceEvent* event2 = tracer->GetEventByHandle(handle2);
- ASSERT_TRUE(event1);
- ASSERT_TRUE(event2);
- EXPECT_STREQ("name1", event1->name());
- EXPECT_STREQ("name2", event2->name());
- EXPECT_TRUE(event1->parameter_copy_storage() != nullptr);
- EXPECT_TRUE(event2->parameter_copy_storage() != nullptr);
- EXPECT_GT(event1->parameter_copy_storage()->size(), 0u);
- EXPECT_GT(event2->parameter_copy_storage()->size(), 0u);
- EndTraceAndFlush();
- }
-
- {
- BeginTrace();
- // Test that static literal string arguments are not copied.
- TraceEventHandle handle1 =
- trace_event_internal::AddTraceEvent(
- TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name1",
- trace_event_internal::kGlobalScope, trace_event_internal::kNoId,
- 0, trace_event_internal::kNoId,
- "arg1", "argval", "arg2", "argval");
- // Test that static TRACE_STR_COPY NULL string arguments are not copied.
- const char* str1 = nullptr;
- const char* str2 = nullptr;
- TraceEventHandle handle2 =
- trace_event_internal::AddTraceEvent(
- TRACE_EVENT_PHASE_INSTANT, category_group_enabled, "name2",
- trace_event_internal::kGlobalScope, trace_event_internal::kNoId,
- 0, trace_event_internal::kNoId,
- "arg1", TRACE_STR_COPY(str1),
- "arg2", TRACE_STR_COPY(str2));
- EXPECT_GT(tracer->GetStatus().event_count, 1u);
- const TraceEvent* event1 = tracer->GetEventByHandle(handle1);
- const TraceEvent* event2 = tracer->GetEventByHandle(handle2);
- ASSERT_TRUE(event1);
- ASSERT_TRUE(event2);
- EXPECT_STREQ("name1", event1->name());
- EXPECT_STREQ("name2", event2->name());
- EXPECT_TRUE(event1->parameter_copy_storage() == nullptr);
- EXPECT_TRUE(event2->parameter_copy_storage() == nullptr);
- EndTraceAndFlush();
- }
-}
-
-// Test that data sent from other threads is gathered
-TEST_F(TraceEventTestFixture, DataCapturedOnThread) {
- BeginTrace();
-
- Thread thread("1");
- WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- thread.Start();
-
- thread.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
- task_complete_event.Wait();
- thread.Stop();
-
- EndTraceAndFlush();
- ValidateAllTraceMacrosCreatedData(trace_parsed_);
-}
-
-// Test that data sent from multiple threads is gathered
-TEST_F(TraceEventTestFixture, DataCapturedManyThreads) {
- BeginTrace();
-
- const int num_threads = 4;
- const int num_events = 4000;
- Thread* threads[num_threads];
- WaitableEvent* task_complete_events[num_threads];
- for (int i = 0; i < num_threads; i++) {
- threads[i] = new Thread(StringPrintf("Thread %d", i));
- task_complete_events[i] =
- new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- threads[i]->Start();
- threads[i]->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&TraceManyInstantEvents, i, num_events,
- task_complete_events[i]));
- }
-
- for (int i = 0; i < num_threads; i++) {
- task_complete_events[i]->Wait();
- }
-
- // Let half of the threads end before flush.
- for (int i = 0; i < num_threads / 2; i++) {
- threads[i]->Stop();
- delete threads[i];
- delete task_complete_events[i];
- }
-
- EndTraceAndFlushInThreadWithMessageLoop();
- ValidateInstantEventPresentOnEveryThread(trace_parsed_,
- num_threads, num_events);
-
- // Let the other half of the threads end after flush.
- for (int i = num_threads / 2; i < num_threads; i++) {
- threads[i]->Stop();
- delete threads[i];
- delete task_complete_events[i];
- }
-}
-
-// Test that thread and process names show up in the trace
-TEST_F(TraceEventTestFixture, ThreadNames) {
- // Create threads before we enable tracing to make sure
- // that tracelog still captures them.
- const int kNumThreads = 4;
- const int kNumEvents = 10;
- Thread* threads[kNumThreads];
- PlatformThreadId thread_ids[kNumThreads];
- for (int i = 0; i < kNumThreads; i++)
- threads[i] = new Thread(StringPrintf("Thread %d", i));
-
- // Enable tracing.
- BeginTrace();
-
- // Now run some trace code on these threads.
- WaitableEvent* task_complete_events[kNumThreads];
- for (int i = 0; i < kNumThreads; i++) {
- task_complete_events[i] =
- new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- threads[i]->Start();
- thread_ids[i] = threads[i]->GetThreadId();
- threads[i]->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&TraceManyInstantEvents, i, kNumEvents,
- task_complete_events[i]));
- }
- for (int i = 0; i < kNumThreads; i++) {
- task_complete_events[i]->Wait();
- }
-
- // Shut things down.
- for (int i = 0; i < kNumThreads; i++) {
- threads[i]->Stop();
- delete threads[i];
- delete task_complete_events[i];
- }
-
- EndTraceAndFlush();
-
- std::string tmp;
- int tmp_int;
- const DictionaryValue* item;
-
- // Make sure we get thread name metadata.
- // Note, the test suite may have created a ton of threads.
- // So, we'll have thread names for threads we didn't create.
- std::vector<const DictionaryValue*> items =
- FindTraceEntries(trace_parsed_, "thread_name");
- for (int i = 0; i < static_cast<int>(items.size()); i++) {
- item = items[i];
- ASSERT_TRUE(item);
- EXPECT_TRUE(item->GetInteger("tid", &tmp_int));
-
- // See if this thread name is one of the threads we just created
- for (int j = 0; j < kNumThreads; j++) {
- if (static_cast<int>(thread_ids[j]) != tmp_int)
- continue;
-
- std::string expected_name = StringPrintf("Thread %d", j);
- EXPECT_TRUE(item->GetString("ph", &tmp) && tmp == "M");
- EXPECT_TRUE(item->GetInteger("pid", &tmp_int) &&
- tmp_int == static_cast<int>(base::GetCurrentProcId()));
- // If the thread name changes or the tid gets reused, the name will be
- // a comma-separated list of thread names, so look for a substring.
- EXPECT_TRUE(item->GetString("args.name", &tmp) &&
- tmp.find(expected_name) != std::string::npos);
- }
- }
-}
-
-TEST_F(TraceEventTestFixture, ThreadNameChanges) {
- BeginTrace();
-
- PlatformThread::SetName("");
- TRACE_EVENT_INSTANT0("drink", "water", TRACE_EVENT_SCOPE_THREAD);
-
- PlatformThread::SetName("cafe");
- TRACE_EVENT_INSTANT0("drink", "coffee", TRACE_EVENT_SCOPE_THREAD);
-
- PlatformThread::SetName("shop");
- // No event here, so won't appear in combined name.
-
- PlatformThread::SetName("pub");
- TRACE_EVENT_INSTANT0("drink", "beer", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("drink", "wine", TRACE_EVENT_SCOPE_THREAD);
-
- PlatformThread::SetName(" bar");
- TRACE_EVENT_INSTANT0("drink", "whisky", TRACE_EVENT_SCOPE_THREAD);
-
- EndTraceAndFlush();
-
- std::vector<const DictionaryValue*> items =
- FindTraceEntries(trace_parsed_, "thread_name");
- EXPECT_EQ(1u, items.size());
- ASSERT_GT(items.size(), 0u);
- const DictionaryValue* item = items[0];
- ASSERT_TRUE(item);
- int tid;
- EXPECT_TRUE(item->GetInteger("tid", &tid));
- EXPECT_EQ(PlatformThread::CurrentId(), static_cast<PlatformThreadId>(tid));
-
- std::string expected_name = "cafe,pub, bar";
- std::string tmp;
- EXPECT_TRUE(item->GetString("args.name", &tmp));
- EXPECT_EQ(expected_name, tmp);
-}
-
-// Test that the disabled trace categories are included/excluded from the
-// trace output correctly.
-TEST_F(TraceEventTestFixture, DisabledCategories) {
- BeginTrace();
- TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("cc"), "first",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("included", "first", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
- {
- const DictionaryValue* item = nullptr;
- ListValue& trace_parsed = trace_parsed_;
- EXPECT_NOT_FIND_("disabled-by-default-cc");
- EXPECT_FIND_("included");
- }
- Clear();
-
- BeginSpecificTrace("disabled-by-default-cc");
- TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("cc"), "second",
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("other_included", "second", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
-
- {
- const DictionaryValue* item = nullptr;
- ListValue& trace_parsed = trace_parsed_;
- EXPECT_FIND_("disabled-by-default-cc");
- EXPECT_FIND_("other_included");
- }
-
- Clear();
-
- BeginSpecificTrace("other_included");
- TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("cc") ",other_included",
- "first", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_INSTANT0("other_included," TRACE_DISABLED_BY_DEFAULT("cc"),
- "second", TRACE_EVENT_SCOPE_THREAD);
- EndTraceAndFlush();
-
- {
- const DictionaryValue* item = nullptr;
- ListValue& trace_parsed = trace_parsed_;
- EXPECT_FIND_("disabled-by-default-cc,other_included");
- EXPECT_FIND_("other_included,disabled-by-default-cc");
- }
-}
-
-TEST_F(TraceEventTestFixture, NormallyNoDeepCopy) {
- // Test that the TRACE_EVENT macros do not deep-copy their string. If they
- // do so it may indicate a performance regression, but more-over it would
- // make the DEEP_COPY overloads redundant.
- std::string name_string("event name");
-
- BeginTrace();
- TRACE_EVENT_INSTANT0("category", name_string.c_str(),
- TRACE_EVENT_SCOPE_THREAD);
-
- // Modify the string in place (a wholesale reassignment may leave the old
- // string intact on the heap).
- name_string[0] = '@';
-
- EndTraceAndFlush();
-
- EXPECT_FALSE(FindTraceEntry(trace_parsed_, "event name"));
- EXPECT_TRUE(FindTraceEntry(trace_parsed_, name_string.c_str()));
-}
-
-TEST_F(TraceEventTestFixture, DeepCopy) {
- static const char kOriginalName1[] = "name1";
- static const char kOriginalName2[] = "name2";
- static const char kOriginalName3[] = "name3";
- std::string name1(kOriginalName1);
- std::string name2(kOriginalName2);
- std::string name3(kOriginalName3);
- std::string arg1("arg1");
- std::string arg2("arg2");
- std::string val1("val1");
- std::string val2("val2");
-
- BeginTrace();
- TRACE_EVENT_COPY_INSTANT0("category", name1.c_str(),
- TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_COPY_BEGIN1("category", name2.c_str(),
- arg1.c_str(), 5);
- TRACE_EVENT_COPY_END2("category", name3.c_str(),
- arg1.c_str(), val1,
- arg2.c_str(), val2);
-
- // As per NormallyNoDeepCopy, modify the strings in place.
- name1[0] = name2[0] = name3[0] = arg1[0] = arg2[0] = val1[0] = val2[0] = '@';
-
- EndTraceAndFlush();
-
- EXPECT_FALSE(FindTraceEntry(trace_parsed_, name1.c_str()));
- EXPECT_FALSE(FindTraceEntry(trace_parsed_, name2.c_str()));
- EXPECT_FALSE(FindTraceEntry(trace_parsed_, name3.c_str()));
-
- const DictionaryValue* entry1 = FindTraceEntry(trace_parsed_, kOriginalName1);
- const DictionaryValue* entry2 = FindTraceEntry(trace_parsed_, kOriginalName2);
- const DictionaryValue* entry3 = FindTraceEntry(trace_parsed_, kOriginalName3);
- ASSERT_TRUE(entry1);
- ASSERT_TRUE(entry2);
- ASSERT_TRUE(entry3);
-
- int i;
- EXPECT_FALSE(entry2->GetInteger("args.@rg1", &i));
- EXPECT_TRUE(entry2->GetInteger("args.arg1", &i));
- EXPECT_EQ(5, i);
-
- std::string s;
- EXPECT_TRUE(entry3->GetString("args.arg1", &s));
- EXPECT_EQ("val1", s);
- EXPECT_TRUE(entry3->GetString("args.arg2", &s));
- EXPECT_EQ("val2", s);
-}
-
-// Test that TraceResultBuffer outputs the correct result whether it is added
-// in chunks or added all at once.
-TEST_F(TraceEventTestFixture, TraceResultBuffer) {
- Clear();
-
- trace_buffer_.Start();
- trace_buffer_.AddFragment("bla1");
- trace_buffer_.AddFragment("bla2");
- trace_buffer_.AddFragment("bla3,bla4");
- trace_buffer_.Finish();
- EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
-
- Clear();
-
- trace_buffer_.Start();
- trace_buffer_.AddFragment("bla1,bla2,bla3,bla4");
- trace_buffer_.Finish();
- EXPECT_STREQ(json_output_.json_output.c_str(), "[bla1,bla2,bla3,bla4]");
-}
-
-// Test that trace_event parameters are not evaluated if the tracing
-// system is disabled.
-TEST_F(TraceEventTestFixture, TracingIsLazy) {
- BeginTrace();
-
- int a = 0;
- TRACE_EVENT_INSTANT1("category", "test", TRACE_EVENT_SCOPE_THREAD, "a", a++);
- EXPECT_EQ(1, a);
-
- TraceLog::GetInstance()->SetDisabled();
-
- TRACE_EVENT_INSTANT1("category", "test", TRACE_EVENT_SCOPE_THREAD, "a", a++);
- EXPECT_EQ(1, a);
-
- EndTraceAndFlush();
-}
-
-TEST_F(TraceEventTestFixture, TraceEnableDisable) {
- TraceLog* trace_log = TraceLog::GetInstance();
- TraceConfig tc_inc_all("*", "");
- trace_log->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
- EXPECT_TRUE(trace_log->IsEnabled());
- trace_log->SetDisabled();
- EXPECT_FALSE(trace_log->IsEnabled());
-
- trace_log->SetEnabled(tc_inc_all, TraceLog::RECORDING_MODE);
- EXPECT_TRUE(trace_log->IsEnabled());
- const std::vector<std::string> empty;
- trace_log->SetEnabled(TraceConfig(), TraceLog::RECORDING_MODE);
- EXPECT_TRUE(trace_log->IsEnabled());
- trace_log->SetDisabled();
- EXPECT_FALSE(trace_log->IsEnabled());
- trace_log->SetDisabled();
- EXPECT_FALSE(trace_log->IsEnabled());
-}
-
-TEST_F(TraceEventTestFixture, TraceCategoriesAfterNestedEnable) {
- TraceLog* trace_log = TraceLog::GetInstance();
- trace_log->SetEnabled(TraceConfig("foo,bar", ""), TraceLog::RECORDING_MODE);
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("bar"));
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("baz"));
- trace_log->SetEnabled(TraceConfig("foo2", ""), TraceLog::RECORDING_MODE);
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo2"));
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("baz"));
- // The "" becomes the default catergory set when applied.
- trace_log->SetEnabled(TraceConfig(), TraceLog::RECORDING_MODE);
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("baz"));
- EXPECT_STREQ(
- "",
- trace_log->GetCurrentTraceConfig().ToCategoryFilterString().c_str());
- trace_log->SetDisabled();
- trace_log->SetDisabled();
- trace_log->SetDisabled();
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("foo"));
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("baz"));
-
- trace_log->SetEnabled(TraceConfig("-foo,-bar", ""), TraceLog::RECORDING_MODE);
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("foo"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("baz"));
- trace_log->SetEnabled(TraceConfig("moo", ""), TraceLog::RECORDING_MODE);
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("baz"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("moo"));
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("foo"));
- EXPECT_STREQ(
- "-foo,-bar",
- trace_log->GetCurrentTraceConfig().ToCategoryFilterString().c_str());
- trace_log->SetDisabled();
- trace_log->SetDisabled();
-
- // Make sure disabled categories aren't cleared if we set in the second.
- trace_log->SetEnabled(TraceConfig("disabled-by-default-cc,foo", ""),
- TraceLog::RECORDING_MODE);
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("bar"));
- trace_log->SetEnabled(TraceConfig("disabled-by-default-gpu", ""),
- TraceLog::RECORDING_MODE);
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-cc"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-gpu"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("bar"));
- EXPECT_STREQ(
- "disabled-by-default-cc,disabled-by-default-gpu",
- trace_log->GetCurrentTraceConfig().ToCategoryFilterString().c_str());
- trace_log->SetDisabled();
- trace_log->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, TraceWithDefaultCategoryFilters) {
- TraceLog* trace_log = TraceLog::GetInstance();
-
- trace_log->SetEnabled(TraceConfig(), TraceLog::RECORDING_MODE);
- CheckTraceDefaultCategoryFilters(*trace_log);
- trace_log->SetDisabled();
-
- trace_log->SetEnabled(TraceConfig("", ""), TraceLog::RECORDING_MODE);
- CheckTraceDefaultCategoryFilters(*trace_log);
- trace_log->SetDisabled();
-
- trace_log->SetEnabled(TraceConfig("*", ""), TraceLog::RECORDING_MODE);
- CheckTraceDefaultCategoryFilters(*trace_log);
- trace_log->SetDisabled();
-
- trace_log->SetEnabled(TraceConfig(""), TraceLog::RECORDING_MODE);
- CheckTraceDefaultCategoryFilters(*trace_log);
- trace_log->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, TraceWithDisabledByDefaultCategoryFilters) {
- TraceLog* trace_log = TraceLog::GetInstance();
-
- trace_log->SetEnabled(TraceConfig("foo,disabled-by-default-foo", ""),
- TraceLog::RECORDING_MODE);
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-foo"));
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("bar"));
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-bar"));
- trace_log->SetDisabled();
-
- // Enabling only the disabled-by-default-* category means the default ones
- // are also enabled.
- trace_log->SetEnabled(TraceConfig("disabled-by-default-foo", ""),
- TraceLog::RECORDING_MODE);
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-foo"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("foo"));
- EXPECT_TRUE(*trace_log->GetCategoryGroupEnabled("bar"));
- EXPECT_FALSE(*trace_log->GetCategoryGroupEnabled("disabled-by-default-bar"));
- trace_log->SetDisabled();
-}
-
-class MyData : public ConvertableToTraceFormat {
- public:
- MyData() = default;
- ~MyData() override = default;
-
- void AppendAsTraceFormat(std::string* out) const override {
- out->append("{\"foo\":1}");
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MyData);
-};
-
-TEST_F(TraceEventTestFixture, ConvertableTypes) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
-
- std::unique_ptr<ConvertableToTraceFormat> data(new MyData());
- std::unique_ptr<ConvertableToTraceFormat> data1(new MyData());
- std::unique_ptr<ConvertableToTraceFormat> data2(new MyData());
- TRACE_EVENT1("foo", "bar", "data", std::move(data));
- TRACE_EVENT2("foo", "baz", "data1", std::move(data1), "data2",
- std::move(data2));
-
- // Check that std::unique_ptr<DerivedClassOfConvertable> are properly treated
- // as
- // convertable and not accidentally casted to bool.
- std::unique_ptr<MyData> convertData1(new MyData());
- std::unique_ptr<MyData> convertData2(new MyData());
- std::unique_ptr<MyData> convertData3(new MyData());
- std::unique_ptr<MyData> convertData4(new MyData());
- TRACE_EVENT2("foo", "string_first", "str", "string value 1", "convert",
- std::move(convertData1));
- TRACE_EVENT2("foo", "string_second", "convert", std::move(convertData2),
- "str", "string value 2");
- TRACE_EVENT2("foo", "both_conv", "convert1", std::move(convertData3),
- "convert2", std::move(convertData4));
- EndTraceAndFlush();
-
- // One arg version.
- DictionaryValue* dict = FindNamePhase("bar", "X");
- ASSERT_TRUE(dict);
-
- const DictionaryValue* args_dict = nullptr;
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
-
- const Value* value = nullptr;
- const DictionaryValue* convertable_dict = nullptr;
- EXPECT_TRUE(args_dict->Get("data", &value));
- ASSERT_TRUE(value->GetAsDictionary(&convertable_dict));
-
- int foo_val;
- EXPECT_TRUE(convertable_dict->GetInteger("foo", &foo_val));
- EXPECT_EQ(1, foo_val);
-
- // Two arg version.
- dict = FindNamePhase("baz", "X");
- ASSERT_TRUE(dict);
-
- args_dict = nullptr;
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
-
- value = nullptr;
- convertable_dict = nullptr;
- EXPECT_TRUE(args_dict->Get("data1", &value));
- ASSERT_TRUE(value->GetAsDictionary(&convertable_dict));
-
- value = nullptr;
- convertable_dict = nullptr;
- EXPECT_TRUE(args_dict->Get("data2", &value));
- ASSERT_TRUE(value->GetAsDictionary(&convertable_dict));
-
- // Convertable with other types.
- dict = FindNamePhase("string_first", "X");
- ASSERT_TRUE(dict);
-
- args_dict = nullptr;
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
-
- std::string str_value;
- EXPECT_TRUE(args_dict->GetString("str", &str_value));
- EXPECT_STREQ("string value 1", str_value.c_str());
-
- value = nullptr;
- convertable_dict = nullptr;
- foo_val = 0;
- EXPECT_TRUE(args_dict->Get("convert", &value));
- ASSERT_TRUE(value->GetAsDictionary(&convertable_dict));
- EXPECT_TRUE(convertable_dict->GetInteger("foo", &foo_val));
- EXPECT_EQ(1, foo_val);
-
- dict = FindNamePhase("string_second", "X");
- ASSERT_TRUE(dict);
-
- args_dict = nullptr;
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
-
- EXPECT_TRUE(args_dict->GetString("str", &str_value));
- EXPECT_STREQ("string value 2", str_value.c_str());
-
- value = nullptr;
- convertable_dict = nullptr;
- foo_val = 0;
- EXPECT_TRUE(args_dict->Get("convert", &value));
- ASSERT_TRUE(value->GetAsDictionary(&convertable_dict));
- EXPECT_TRUE(convertable_dict->GetInteger("foo", &foo_val));
- EXPECT_EQ(1, foo_val);
-
- dict = FindNamePhase("both_conv", "X");
- ASSERT_TRUE(dict);
-
- args_dict = nullptr;
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
-
- value = nullptr;
- convertable_dict = nullptr;
- foo_val = 0;
- EXPECT_TRUE(args_dict->Get("convert1", &value));
- ASSERT_TRUE(value->GetAsDictionary(&convertable_dict));
- EXPECT_TRUE(args_dict->Get("convert2", &value));
- ASSERT_TRUE(value->GetAsDictionary(&convertable_dict));
-}
-
-TEST_F(TraceEventTestFixture, PrimitiveArgs) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
-
- TRACE_EVENT1("foo", "event1", "int_one", 1);
- TRACE_EVENT1("foo", "event2", "int_neg_ten", -10);
- TRACE_EVENT1("foo", "event3", "float_one", 1.0f);
- TRACE_EVENT1("foo", "event4", "float_half", .5f);
- TRACE_EVENT1("foo", "event5", "float_neghalf", -.5f);
- TRACE_EVENT1("foo", "event6", "float_infinity",
- std::numeric_limits<float>::infinity());
- TRACE_EVENT1("foo", "event6b", "float_neg_infinity",
- -std::numeric_limits<float>::infinity());
- TRACE_EVENT1("foo", "event7", "double_nan",
- std::numeric_limits<double>::quiet_NaN());
- void* p = nullptr;
- TRACE_EVENT1("foo", "event8", "pointer_null", p);
- p = reinterpret_cast<void*>(0xbadf00d);
- TRACE_EVENT1("foo", "event9", "pointer_badf00d", p);
- TRACE_EVENT1("foo", "event10", "bool_true", true);
- TRACE_EVENT1("foo", "event11", "bool_false", false);
- TRACE_EVENT1("foo", "event12", "time_null",
- base::Time());
- TRACE_EVENT1("foo", "event13", "time_one",
- base::Time::FromInternalValue(1));
- TRACE_EVENT1("foo", "event14", "timeticks_null",
- base::TimeTicks());
- TRACE_EVENT1("foo", "event15", "timeticks_one",
- base::TimeTicks::FromInternalValue(1));
- EndTraceAndFlush();
-
- const DictionaryValue* args_dict = nullptr;
- DictionaryValue* dict = nullptr;
- const Value* value = nullptr;
- std::string str_value;
- int int_value;
- double double_value;
- bool bool_value;
-
- dict = FindNamePhase("event1", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetInteger("int_one", &int_value));
- EXPECT_EQ(1, int_value);
-
- dict = FindNamePhase("event2", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetInteger("int_neg_ten", &int_value));
- EXPECT_EQ(-10, int_value);
-
- // 1f must be serlized to JSON as "1.0" in order to be a double, not an int.
- dict = FindNamePhase("event3", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->Get("float_one", &value));
- EXPECT_TRUE(value->is_double());
- EXPECT_TRUE(value->GetAsDouble(&double_value));
- EXPECT_EQ(1, double_value);
-
- // .5f must be serlized to JSON as "0.5".
- dict = FindNamePhase("event4", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->Get("float_half", &value));
- EXPECT_TRUE(value->is_double());
- EXPECT_TRUE(value->GetAsDouble(&double_value));
- EXPECT_EQ(0.5, double_value);
-
- // -.5f must be serlized to JSON as "-0.5".
- dict = FindNamePhase("event5", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->Get("float_neghalf", &value));
- EXPECT_TRUE(value->is_double());
- EXPECT_TRUE(value->GetAsDouble(&double_value));
- EXPECT_EQ(-0.5, double_value);
-
- // Infinity is serialized to JSON as a string.
- dict = FindNamePhase("event6", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetString("float_infinity", &str_value));
- EXPECT_STREQ("Infinity", str_value.c_str());
- dict = FindNamePhase("event6b", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetString("float_neg_infinity", &str_value));
- EXPECT_STREQ("-Infinity", str_value.c_str());
-
- // NaN is serialized to JSON as a string.
- dict = FindNamePhase("event7", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetString("double_nan", &str_value));
- EXPECT_STREQ("NaN", str_value.c_str());
-
- // NULL pointers should be serialized as "0x0".
- dict = FindNamePhase("event8", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetString("pointer_null", &str_value));
- EXPECT_STREQ("0x0", str_value.c_str());
-
- // Other pointers should be serlized as a hex string.
- dict = FindNamePhase("event9", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetString("pointer_badf00d", &str_value));
- EXPECT_STREQ("0xbadf00d", str_value.c_str());
-
- dict = FindNamePhase("event10", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetBoolean("bool_true", &bool_value));
- EXPECT_TRUE(bool_value);
-
- dict = FindNamePhase("event11", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetBoolean("bool_false", &bool_value));
- EXPECT_FALSE(bool_value);
-
- dict = FindNamePhase("event12", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetInteger("time_null", &int_value));
- EXPECT_EQ(0, int_value);
-
- dict = FindNamePhase("event13", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetInteger("time_one", &int_value));
- EXPECT_EQ(1, int_value);
-
- dict = FindNamePhase("event14", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetInteger("timeticks_null", &int_value));
- EXPECT_EQ(0, int_value);
-
- dict = FindNamePhase("event15", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetInteger("timeticks_one", &int_value));
- EXPECT_EQ(1, int_value);
-}
-
-TEST_F(TraceEventTestFixture, NameIsEscaped) {
- TraceLog::GetInstance()->SetEnabled(TraceConfig(kRecordAllCategoryFilter, ""),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT0("category", "name\\with\\backspaces");
- EndTraceAndFlush();
-
- EXPECT_TRUE(FindMatchingValue("cat", "category"));
- EXPECT_TRUE(FindMatchingValue("name", "name\\with\\backspaces"));
-}
-
-namespace {
-
-bool IsArgNameWhitelisted(const char* arg_name) {
- return base::MatchPattern(arg_name, "granular_arg_whitelisted");
-}
-
-bool IsTraceEventArgsWhitelisted(const char* category_group_name,
- const char* event_name,
- ArgumentNameFilterPredicate* arg_filter) {
- if (base::MatchPattern(category_group_name, "toplevel") &&
- base::MatchPattern(event_name, "*")) {
- return true;
- }
-
- if (base::MatchPattern(category_group_name, "benchmark") &&
- base::MatchPattern(event_name, "granularly_whitelisted")) {
- *arg_filter = base::Bind(&IsArgNameWhitelisted);
- return true;
- }
-
- return false;
-}
-
-} // namespace
-
-TEST_F(TraceEventTestFixture, ArgsWhitelisting) {
- TraceLog::GetInstance()->SetArgumentFilterPredicate(
- base::Bind(&IsTraceEventArgsWhitelisted));
-
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, "enable-argument-filter"),
- TraceLog::RECORDING_MODE);
-
- TRACE_EVENT1("toplevel", "event1", "int_one", 1);
- TRACE_EVENT1("whitewashed", "event2", "int_two", 1);
-
- TRACE_EVENT2("benchmark", "granularly_whitelisted",
- "granular_arg_whitelisted", "whitelisted_value",
- "granular_arg_blacklisted", "blacklisted_value");
-
- EndTraceAndFlush();
-
- const DictionaryValue* args_dict = nullptr;
- DictionaryValue* dict = nullptr;
- int int_value;
-
- dict = FindNamePhase("event1", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_TRUE(args_dict->GetInteger("int_one", &int_value));
- EXPECT_EQ(1, int_value);
-
- dict = FindNamePhase("event2", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
- EXPECT_FALSE(args_dict->GetInteger("int_two", &int_value));
-
- std::string args_string;
- EXPECT_TRUE(dict->GetString("args", &args_string));
- EXPECT_EQ(args_string, "__stripped__");
-
- dict = FindNamePhase("granularly_whitelisted", "X");
- ASSERT_TRUE(dict);
- dict->GetDictionary("args", &args_dict);
- ASSERT_TRUE(args_dict);
-
- EXPECT_TRUE(args_dict->GetString("granular_arg_whitelisted", &args_string));
- EXPECT_EQ(args_string, "whitelisted_value");
-
- EXPECT_TRUE(args_dict->GetString("granular_arg_blacklisted", &args_string));
- EXPECT_EQ(args_string, "__stripped__");
-}
-
-TEST_F(TraceEventTestFixture, TraceBufferVectorReportFull) {
- TraceLog* trace_log = TraceLog::GetInstance();
- trace_log->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, ""), TraceLog::RECORDING_MODE);
- trace_log->logged_events_.reset(
- TraceBuffer::CreateTraceBufferVectorOfSize(100));
- do {
- TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(
- "all", "with_timestamp", 0, 0, TimeTicks::Now());
- TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(
- "all", "with_timestamp", 0, 0, TimeTicks::Now());
- } while (!trace_log->BufferIsFull());
-
- EndTraceAndFlush();
-
- const DictionaryValue* trace_full_metadata = nullptr;
-
- trace_full_metadata = FindTraceEntry(trace_parsed_,
- "overflowed_at_ts");
- std::string phase;
- double buffer_limit_reached_timestamp = 0;
-
- EXPECT_TRUE(trace_full_metadata);
- EXPECT_TRUE(trace_full_metadata->GetString("ph", &phase));
- EXPECT_EQ("M", phase);
- EXPECT_TRUE(trace_full_metadata->GetDouble(
- "args.overflowed_at_ts", &buffer_limit_reached_timestamp));
- EXPECT_DOUBLE_EQ(
- static_cast<double>(
- trace_log->buffer_limit_reached_timestamp_.ToInternalValue()),
- buffer_limit_reached_timestamp);
-
- // Test that buffer_limit_reached_timestamp's value is between the timestamp
- // of the last trace event and current time.
- DropTracedMetadataRecords();
- const DictionaryValue* last_trace_event = nullptr;
- double last_trace_event_timestamp = 0;
- EXPECT_TRUE(trace_parsed_.GetDictionary(trace_parsed_.GetSize() - 1,
- &last_trace_event));
- EXPECT_TRUE(last_trace_event->GetDouble("ts", &last_trace_event_timestamp));
- EXPECT_LE(last_trace_event_timestamp, buffer_limit_reached_timestamp);
- EXPECT_LE(buffer_limit_reached_timestamp,
- trace_log->OffsetNow().ToInternalValue());
-}
-
-TEST_F(TraceEventTestFixture, TraceBufferRingBufferGetReturnChunk) {
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY),
- TraceLog::RECORDING_MODE);
- TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
- size_t capacity = buffer->Capacity();
- size_t num_chunks = capacity / TraceBufferChunk::kTraceBufferChunkSize;
- uint32_t last_seq = 0;
- size_t chunk_index;
- EXPECT_EQ(0u, buffer->Size());
-
- std::unique_ptr<TraceBufferChunk* []> chunks(
- new TraceBufferChunk*[num_chunks]);
- for (size_t i = 0; i < num_chunks; ++i) {
- chunks[i] = buffer->GetChunk(&chunk_index).release();
- EXPECT_TRUE(chunks[i]);
- EXPECT_EQ(i, chunk_index);
- EXPECT_GT(chunks[i]->seq(), last_seq);
- EXPECT_EQ((i + 1) * TraceBufferChunk::kTraceBufferChunkSize,
- buffer->Size());
- last_seq = chunks[i]->seq();
- }
-
- // Ring buffer is never full.
- EXPECT_FALSE(buffer->IsFull());
-
- // Return all chunks in original order.
- for (size_t i = 0; i < num_chunks; ++i)
- buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
-
- // Should recycle the chunks in the returned order.
- for (size_t i = 0; i < num_chunks; ++i) {
- chunks[i] = buffer->GetChunk(&chunk_index).release();
- EXPECT_TRUE(chunks[i]);
- EXPECT_EQ(i, chunk_index);
- EXPECT_GT(chunks[i]->seq(), last_seq);
- last_seq = chunks[i]->seq();
- }
-
- // Return all chunks in reverse order.
- for (size_t i = 0; i < num_chunks; ++i) {
- buffer->ReturnChunk(num_chunks - i - 1, std::unique_ptr<TraceBufferChunk>(
- chunks[num_chunks - i - 1]));
- }
-
- // Should recycle the chunks in the returned order.
- for (size_t i = 0; i < num_chunks; ++i) {
- chunks[i] = buffer->GetChunk(&chunk_index).release();
- EXPECT_TRUE(chunks[i]);
- EXPECT_EQ(num_chunks - i - 1, chunk_index);
- EXPECT_GT(chunks[i]->seq(), last_seq);
- last_seq = chunks[i]->seq();
- }
-
- for (size_t i = 0; i < num_chunks; ++i)
- buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
-
- TraceLog::GetInstance()->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, TraceBufferRingBufferHalfIteration) {
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY),
- TraceLog::RECORDING_MODE);
- TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
- size_t capacity = buffer->Capacity();
- size_t num_chunks = capacity / TraceBufferChunk::kTraceBufferChunkSize;
- size_t chunk_index;
- EXPECT_EQ(0u, buffer->Size());
- EXPECT_FALSE(buffer->NextChunk());
-
- size_t half_chunks = num_chunks / 2;
- std::unique_ptr<TraceBufferChunk* []> chunks(
- new TraceBufferChunk*[half_chunks]);
-
- for (size_t i = 0; i < half_chunks; ++i) {
- chunks[i] = buffer->GetChunk(&chunk_index).release();
- EXPECT_TRUE(chunks[i]);
- EXPECT_EQ(i, chunk_index);
- }
- for (size_t i = 0; i < half_chunks; ++i)
- buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
-
- for (size_t i = 0; i < half_chunks; ++i)
- EXPECT_EQ(chunks[i], buffer->NextChunk());
- EXPECT_FALSE(buffer->NextChunk());
- TraceLog::GetInstance()->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, TraceBufferRingBufferFullIteration) {
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY),
- TraceLog::RECORDING_MODE);
- TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
- size_t capacity = buffer->Capacity();
- size_t num_chunks = capacity / TraceBufferChunk::kTraceBufferChunkSize;
- size_t chunk_index;
- EXPECT_EQ(0u, buffer->Size());
- EXPECT_FALSE(buffer->NextChunk());
-
- std::unique_ptr<TraceBufferChunk* []> chunks(
- new TraceBufferChunk*[num_chunks]);
-
- for (size_t i = 0; i < num_chunks; ++i) {
- chunks[i] = buffer->GetChunk(&chunk_index).release();
- EXPECT_TRUE(chunks[i]);
- EXPECT_EQ(i, chunk_index);
- }
- for (size_t i = 0; i < num_chunks; ++i)
- buffer->ReturnChunk(i, std::unique_ptr<TraceBufferChunk>(chunks[i]));
-
- for (size_t i = 0; i < num_chunks; ++i)
- EXPECT_TRUE(chunks[i] == buffer->NextChunk());
- EXPECT_FALSE(buffer->NextChunk());
- TraceLog::GetInstance()->SetDisabled();
-}
-
-TEST_F(TraceEventTestFixture, TraceRecordAsMuchAsPossibleMode) {
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, RECORD_AS_MUCH_AS_POSSIBLE),
- TraceLog::RECORDING_MODE);
- TraceBuffer* buffer = TraceLog::GetInstance()->trace_buffer();
- EXPECT_EQ(512000000UL, buffer->Capacity());
- TraceLog::GetInstance()->SetDisabled();
-}
-
-void BlockUntilStopped(WaitableEvent* task_start_event,
- WaitableEvent* task_stop_event) {
- task_start_event->Signal();
- task_stop_event->Wait();
-}
-
-TEST_F(TraceEventTestFixture, SetCurrentThreadBlocksMessageLoopBeforeTracing) {
- BeginTrace();
-
- Thread thread("1");
- WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- thread.Start();
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TraceLog::SetCurrentThreadBlocksMessageLoop,
- Unretained(TraceLog::GetInstance())));
-
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
- task_complete_event.Wait();
-
- WaitableEvent task_start_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_stop_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- thread.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&BlockUntilStopped, &task_start_event, &task_stop_event));
- task_start_event.Wait();
-
- EndTraceAndFlush();
- ValidateAllTraceMacrosCreatedData(trace_parsed_);
-
- task_stop_event.Signal();
- thread.Stop();
-}
-
-TEST_F(TraceEventTestFixture, ConvertTraceConfigToInternalOptions) {
- TraceLog* trace_log = TraceLog::GetInstance();
- EXPECT_EQ(TraceLog::kInternalRecordUntilFull,
- trace_log->GetInternalOptionsFromTraceConfig(
- TraceConfig(kRecordAllCategoryFilter, RECORD_UNTIL_FULL)));
-
- EXPECT_EQ(TraceLog::kInternalRecordContinuously,
- trace_log->GetInternalOptionsFromTraceConfig(
- TraceConfig(kRecordAllCategoryFilter, RECORD_CONTINUOUSLY)));
-
- EXPECT_EQ(TraceLog::kInternalEchoToConsole,
- trace_log->GetInternalOptionsFromTraceConfig(
- TraceConfig(kRecordAllCategoryFilter, ECHO_TO_CONSOLE)));
-
- EXPECT_EQ(TraceLog::kInternalEchoToConsole,
- trace_log->GetInternalOptionsFromTraceConfig(
- TraceConfig("*", "trace-to-console,enable-systrace")));
-}
-
-void SetBlockingFlagAndBlockUntilStopped(WaitableEvent* task_start_event,
- WaitableEvent* task_stop_event) {
- TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop();
- BlockUntilStopped(task_start_event, task_stop_event);
-}
-
-TEST_F(TraceEventTestFixture, SetCurrentThreadBlocksMessageLoopAfterTracing) {
- BeginTrace();
-
- Thread thread("1");
- WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- thread.Start();
-
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
- task_complete_event.Wait();
-
- WaitableEvent task_start_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_stop_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- thread.task_runner()->PostTask(FROM_HERE,
- BindOnce(&SetBlockingFlagAndBlockUntilStopped,
- &task_start_event, &task_stop_event));
- task_start_event.Wait();
-
- EndTraceAndFlush();
- ValidateAllTraceMacrosCreatedData(trace_parsed_);
-
- task_stop_event.Signal();
- thread.Stop();
-}
-
-TEST_F(TraceEventTestFixture, ThreadOnceBlocking) {
- BeginTrace();
-
- Thread thread("1");
- WaitableEvent task_complete_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- thread.Start();
-
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
- task_complete_event.Wait();
-
- WaitableEvent task_start_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_stop_event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- thread.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&BlockUntilStopped, &task_start_event, &task_stop_event));
- task_start_event.Wait();
-
- // The thread will timeout in this flush.
- EndTraceAndFlushInThreadWithMessageLoop();
- Clear();
-
- // Let the thread's message loop continue to spin.
- task_stop_event.Signal();
-
- // The following sequence ensures that the FlushCurrentThread task has been
- // executed in the thread before continuing.
- thread.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&BlockUntilStopped, &task_start_event, &task_stop_event));
- task_start_event.Wait();
- task_stop_event.Signal();
- Clear();
-
- // TraceLog should discover the generation mismatch and recover the thread
- // local buffer for the thread without any error.
- BeginTrace();
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TraceWithAllMacroVariants, &task_complete_event));
- task_complete_event.Wait();
- EndTraceAndFlushInThreadWithMessageLoop();
- ValidateAllTraceMacrosCreatedData(trace_parsed_);
-}
-
-std::string* g_log_buffer = nullptr;
-bool MockLogMessageHandler(int, const char*, int, size_t,
- const std::string& str) {
- if (!g_log_buffer)
- g_log_buffer = new std::string();
- g_log_buffer->append(str);
- return false;
-}
-
-TEST_F(TraceEventTestFixture, EchoToConsole) {
- logging::LogMessageHandlerFunction old_log_message_handler =
- logging::GetLogMessageHandler();
- logging::SetLogMessageHandler(MockLogMessageHandler);
-
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, ECHO_TO_CONSOLE),
- TraceLog::RECORDING_MODE);
- TRACE_EVENT_BEGIN0("a", "begin_end");
- {
- TRACE_EVENT0("b", "duration");
- TRACE_EVENT0("b1", "duration1");
- }
- TRACE_EVENT_INSTANT0("c", "instant", TRACE_EVENT_SCOPE_GLOBAL);
- TRACE_EVENT_END0("a", "begin_end");
-
- EXPECT_NE(std::string::npos, g_log_buffer->find("begin_end[a]\x1b"));
- EXPECT_NE(std::string::npos, g_log_buffer->find("| duration[b]\x1b"));
- EXPECT_NE(std::string::npos, g_log_buffer->find("| | duration1[b1]\x1b"));
- EXPECT_NE(std::string::npos, g_log_buffer->find("| | duration1[b1] ("));
- EXPECT_NE(std::string::npos, g_log_buffer->find("| duration[b] ("));
- EXPECT_NE(std::string::npos, g_log_buffer->find("| instant[c]\x1b"));
- EXPECT_NE(std::string::npos, g_log_buffer->find("begin_end[a] ("));
-
- EndTraceAndFlush();
- delete g_log_buffer;
- logging::SetLogMessageHandler(old_log_message_handler);
- g_log_buffer = nullptr;
-}
-
-bool LogMessageHandlerWithTraceEvent(int, const char*, int, size_t,
- const std::string&) {
- TRACE_EVENT0("log", "trace_event");
- return false;
-}
-
-TEST_F(TraceEventTestFixture, EchoToConsoleTraceEventRecursion) {
- logging::LogMessageHandlerFunction old_log_message_handler =
- logging::GetLogMessageHandler();
- logging::SetLogMessageHandler(LogMessageHandlerWithTraceEvent);
-
- TraceLog::GetInstance()->SetEnabled(
- TraceConfig(kRecordAllCategoryFilter, ECHO_TO_CONSOLE),
- TraceLog::RECORDING_MODE);
- {
- // This should not cause deadlock or infinite recursion.
- TRACE_EVENT0("b", "duration");
- }
-
- EndTraceAndFlush();
- logging::SetLogMessageHandler(old_log_message_handler);
-}
-
-TEST_F(TraceEventTestFixture, TimeOffset) {
- BeginTrace();
- // Let TraceLog timer start from 0.
- TimeDelta time_offset = TimeTicks::Now() - TimeTicks();
- TraceLog::GetInstance()->SetTimeOffset(time_offset);
-
- {
- TRACE_EVENT0("all", "duration1");
- TRACE_EVENT0("all", "duration2");
- }
- TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(
- "all", "with_timestamp", 0, 0, TimeTicks::Now());
- TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(
- "all", "with_timestamp", 0, 0, TimeTicks::Now());
-
- EndTraceAndFlush();
- DropTracedMetadataRecords();
-
- double end_time = static_cast<double>(
- (TimeTicks::Now() - time_offset).ToInternalValue());
- double last_timestamp = 0;
- for (size_t i = 0; i < trace_parsed_.GetSize(); ++i) {
- const DictionaryValue* item;
- EXPECT_TRUE(trace_parsed_.GetDictionary(i, &item));
- double timestamp;
- EXPECT_TRUE(item->GetDouble("ts", &timestamp));
- EXPECT_GE(timestamp, last_timestamp);
- EXPECT_LE(timestamp, end_time);
- last_timestamp = timestamp;
- }
-}
-
-TEST_F(TraceEventTestFixture, TraceFilteringMode) {
- const char config_json[] =
- "{"
- " \"event_filters\": ["
- " {"
- " \"filter_predicate\": \"testing_predicate\", "
- " \"included_categories\": [\"*\"]"
- " }"
- " ]"
- "}";
-
- // Run RECORDING_MODE within FILTERING_MODE:
- TestEventFilter::HitsCounter filter_hits_counter;
- TestEventFilter::set_filter_return_value(true);
- TraceLog::GetInstance()->SetFilterFactoryForTesting(TestEventFilter::Factory);
-
- // Only filtering mode is enabled with test filters.
- TraceLog::GetInstance()->SetEnabled(TraceConfig(config_json),
- TraceLog::FILTERING_MODE);
- EXPECT_EQ(TraceLog::FILTERING_MODE, TraceLog::GetInstance()->enabled_modes());
- {
- void* ptr = this;
- TRACE_EVENT0("c0", "name0");
- TRACE_EVENT_ASYNC_BEGIN0("c1", "name1", ptr);
- TRACE_EVENT_INSTANT0("c0", "name0", TRACE_EVENT_SCOPE_THREAD);
- TRACE_EVENT_ASYNC_END0("c1", "name1", ptr);
- }
-
- // Recording mode is enabled when filtering mode is turned on.
- TraceLog::GetInstance()->SetEnabled(TraceConfig("", ""),
- TraceLog::RECORDING_MODE);
- EXPECT_EQ(TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE,
- TraceLog::GetInstance()->enabled_modes());
- {
- TRACE_EVENT0("c2", "name2");
- }
- // Only recording mode is disabled and filtering mode will continue to run.
- TraceLog::GetInstance()->SetDisabled(TraceLog::RECORDING_MODE);
- EXPECT_EQ(TraceLog::FILTERING_MODE, TraceLog::GetInstance()->enabled_modes());
-
- {
- TRACE_EVENT0("c0", "name0");
- }
- // Filtering mode is disabled and no tracing mode should be enabled.
- TraceLog::GetInstance()->SetDisabled(TraceLog::FILTERING_MODE);
- EXPECT_EQ(0, TraceLog::GetInstance()->enabled_modes());
-
- EndTraceAndFlush();
- EXPECT_FALSE(FindMatchingValue("cat", "c0"));
- EXPECT_FALSE(FindMatchingValue("cat", "c1"));
- EXPECT_FALSE(FindMatchingValue("name", "name0"));
- EXPECT_FALSE(FindMatchingValue("name", "name1"));
- EXPECT_TRUE(FindMatchingValue("cat", "c2"));
- EXPECT_TRUE(FindMatchingValue("name", "name2"));
- EXPECT_EQ(6u, filter_hits_counter.filter_trace_event_hit_count);
- EXPECT_EQ(3u, filter_hits_counter.end_event_hit_count);
- Clear();
- filter_hits_counter.Reset();
-
- // Run FILTERING_MODE within RECORDING_MODE:
- // Only recording mode is enabled and all events must be recorded.
- TraceLog::GetInstance()->SetEnabled(TraceConfig("", ""),
- TraceLog::RECORDING_MODE);
- EXPECT_EQ(TraceLog::RECORDING_MODE, TraceLog::GetInstance()->enabled_modes());
- {
- TRACE_EVENT0("c0", "name0");
- }
-
- // Filtering mode is also enabled and all events must be filtered-out.
- TestEventFilter::set_filter_return_value(false);
- TraceLog::GetInstance()->SetEnabled(TraceConfig(config_json),
- TraceLog::FILTERING_MODE);
- EXPECT_EQ(TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE,
- TraceLog::GetInstance()->enabled_modes());
- {
- TRACE_EVENT0("c1", "name1");
- }
- // Only filtering mode is disabled and recording mode should continue to run
- // with all events being recorded.
- TraceLog::GetInstance()->SetDisabled(TraceLog::FILTERING_MODE);
- EXPECT_EQ(TraceLog::RECORDING_MODE, TraceLog::GetInstance()->enabled_modes());
-
- {
- TRACE_EVENT0("c2", "name2");
- }
- // Recording mode is disabled and no tracing mode should be enabled.
- TraceLog::GetInstance()->SetDisabled(TraceLog::RECORDING_MODE);
- EXPECT_EQ(0, TraceLog::GetInstance()->enabled_modes());
-
- EndTraceAndFlush();
- EXPECT_TRUE(FindMatchingValue("cat", "c0"));
- EXPECT_TRUE(FindMatchingValue("cat", "c2"));
- EXPECT_TRUE(FindMatchingValue("name", "name0"));
- EXPECT_TRUE(FindMatchingValue("name", "name2"));
- EXPECT_FALSE(FindMatchingValue("cat", "c1"));
- EXPECT_FALSE(FindMatchingValue("name", "name1"));
- EXPECT_EQ(1u, filter_hits_counter.filter_trace_event_hit_count);
- EXPECT_EQ(1u, filter_hits_counter.end_event_hit_count);
- Clear();
-}
-
-TEST_F(TraceEventTestFixture, EventFiltering) {
- const char config_json[] =
- "{"
- " \"included_categories\": ["
- " \"filtered_cat\","
- " \"unfiltered_cat\","
- " \"" TRACE_DISABLED_BY_DEFAULT("filtered_cat") "\","
- " \"" TRACE_DISABLED_BY_DEFAULT("unfiltered_cat") "\"],"
- " \"event_filters\": ["
- " {"
- " \"filter_predicate\": \"testing_predicate\", "
- " \"included_categories\": ["
- " \"filtered_cat\","
- " \"" TRACE_DISABLED_BY_DEFAULT("filtered_cat") "\"]"
- " }"
- " "
- " ]"
- "}";
-
- TestEventFilter::HitsCounter filter_hits_counter;
- TestEventFilter::set_filter_return_value(true);
- TraceLog::GetInstance()->SetFilterFactoryForTesting(TestEventFilter::Factory);
-
- TraceConfig trace_config(config_json);
- TraceLog::GetInstance()->SetEnabled(
- trace_config, TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE);
- ASSERT_TRUE(TraceLog::GetInstance()->IsEnabled());
-
- TRACE_EVENT0("filtered_cat", "a snake");
- TRACE_EVENT0("filtered_cat", "a mushroom");
- TRACE_EVENT0("unfiltered_cat", "a horse");
-
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("filtered_cat"), "a dog");
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("unfiltered_cat"), "a pony");
-
- // This is scoped so we can test the end event being filtered.
- { TRACE_EVENT0("filtered_cat", "another cat whoa"); }
-
- EndTraceAndFlush();
-
- EXPECT_EQ(4u, filter_hits_counter.filter_trace_event_hit_count);
- EXPECT_EQ(1u, filter_hits_counter.end_event_hit_count);
-}
-
-TEST_F(TraceEventTestFixture, EventWhitelistFiltering) {
- std::string config_json = StringPrintf(
- "{"
- " \"included_categories\": ["
- " \"filtered_cat\","
- " \"unfiltered_cat\","
- " \"" TRACE_DISABLED_BY_DEFAULT("filtered_cat") "\"],"
- " \"event_filters\": ["
- " {"
- " \"filter_predicate\": \"%s\", "
- " \"included_categories\": ["
- " \"filtered_cat\","
- " \"" TRACE_DISABLED_BY_DEFAULT("*") "\"], "
- " \"filter_args\": {"
- " \"event_name_whitelist\": [\"a snake\", \"a dog\"]"
- " }"
- " }"
- " "
- " ]"
- "}",
- EventNameFilter::kName);
-
- TraceConfig trace_config(config_json);
- TraceLog::GetInstance()->SetEnabled(
- trace_config, TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE);
- EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
-
- TRACE_EVENT0("filtered_cat", "a snake");
- TRACE_EVENT0("filtered_cat", "a mushroom");
- TRACE_EVENT0("unfiltered_cat", "a cat");
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("filtered_cat"), "a dog");
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("filtered_cat"), "a pony");
-
- EndTraceAndFlush();
-
- EXPECT_TRUE(FindMatchingValue("name", "a snake"));
- EXPECT_FALSE(FindMatchingValue("name", "a mushroom"));
- EXPECT_TRUE(FindMatchingValue("name", "a cat"));
- EXPECT_TRUE(FindMatchingValue("name", "a dog"));
- EXPECT_FALSE(FindMatchingValue("name", "a pony"));
-}
-
-TEST_F(TraceEventTestFixture, HeapProfilerFiltering) {
- std::string config_json = StringPrintf(
- "{"
- " \"included_categories\": ["
- " \"filtered_cat\","
- " \"unfiltered_cat\","
- " \"" TRACE_DISABLED_BY_DEFAULT("filtered_cat") "\","
- " \"" TRACE_DISABLED_BY_DEFAULT("unfiltered_cat") "\"],"
- " \"excluded_categories\": [\"excluded_cat\"],"
- " \"event_filters\": ["
- " {"
- " \"filter_predicate\": \"%s\", "
- " \"included_categories\": ["
- " \"*\","
- " \"" TRACE_DISABLED_BY_DEFAULT("filtered_cat") "\"]"
- " }"
- " ]"
- "}",
- HeapProfilerEventFilter::kName);
-
- TraceConfig trace_config(config_json);
- TraceLog::GetInstance()->SetEnabled(
- trace_config, TraceLog::RECORDING_MODE | TraceLog::FILTERING_MODE);
- EXPECT_TRUE(TraceLog::GetInstance()->IsEnabled());
-
- TRACE_EVENT0("filtered_cat", "a snake");
- TRACE_EVENT0("excluded_cat", "a mushroom");
- TRACE_EVENT0("unfiltered_cat", "a cat");
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("filtered_cat"), "a dog");
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("unfiltered_cat"), "a pony");
-
- EndTraceAndFlush();
-
- // The predicate should not change behavior of the trace events.
- EXPECT_TRUE(FindMatchingValue("name", "a snake"));
- EXPECT_FALSE(FindMatchingValue("name", "a mushroom"));
- EXPECT_TRUE(FindMatchingValue("name", "a cat"));
- EXPECT_TRUE(FindMatchingValue("name", "a dog"));
- EXPECT_TRUE(FindMatchingValue("name", "a pony"));
-}
-
-TEST_F(TraceEventTestFixture, ClockSyncEventsAreAlwaysAddedToTrace) {
- BeginSpecificTrace("-*");
- TRACE_EVENT_CLOCK_SYNC_RECEIVER(1);
- EndTraceAndFlush();
- EXPECT_TRUE(FindNamePhase("clock_sync", "c"));
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
deleted file mode 100644
index 4eb6958472..0000000000
--- a/base/trace_event/trace_log.cc
+++ /dev/null
@@ -1,1787 +0,0 @@
-// Copyright 2015 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/trace_event/trace_log.h"
-
-#include <algorithm>
-#include <cmath>
-#include <memory>
-#include <utility>
-
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/debug/leak_annotations.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/no_destructor.h"
-#include "base/process/process_info.h"
-#include "base/process/process_metrics.h"
-#include "base/stl_util.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/thread_id_name_manager.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/trace_event/category_registry.h"
-#include "base/trace_event/event_name_filter.h"
-#include "base/trace_event/heap_profiler.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "base/trace_event/heap_profiler_event_filter.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_buffer.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include "base/trace_event/trace_event_etw_export_win.h"
-#endif
-
-#if defined(OS_ANDROID)
-// The linker assigns the virtual address of the start of current library to
-// this symbol.
-extern char __executable_start;
-#endif
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// Controls the number of trace events we will buffer in-memory
-// before throwing them away.
-const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize;
-
-const size_t kTraceEventVectorBigBufferChunks =
- 512000000 / kTraceBufferChunkSize;
-static_assert(
- kTraceEventVectorBigBufferChunks <= TraceBufferChunk::kMaxChunkIndex,
- "Too many big buffer chunks");
-const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize;
-static_assert(
- kTraceEventVectorBufferChunks <= TraceBufferChunk::kMaxChunkIndex,
- "Too many vector buffer chunks");
-const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4;
-
-// ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events.
-const size_t kEchoToConsoleTraceEventBufferChunks = 256;
-
-const size_t kTraceEventBufferSizeInBytes = 100 * 1024;
-const int kThreadFlushTimeoutMs = 3000;
-
-TraceLog* g_trace_log_for_testing = nullptr;
-
-#define MAX_TRACE_EVENT_FILTERS 32
-
-// List of TraceEventFilter objects from the most recent tracing session.
-std::vector<std::unique_ptr<TraceEventFilter>>& GetCategoryGroupFilters() {
- static auto* filters = new std::vector<std::unique_ptr<TraceEventFilter>>();
- return *filters;
-}
-
-ThreadTicks ThreadNow() {
- return ThreadTicks::IsSupported()
- ? base::subtle::ThreadTicksNowIgnoringOverride()
- : ThreadTicks();
-}
-
-template <typename T>
-void InitializeMetadataEvent(TraceEvent* trace_event,
- int thread_id,
- const char* metadata_name,
- const char* arg_name,
- const T& value) {
- if (!trace_event)
- return;
-
- int num_args = 1;
- unsigned char arg_type;
- unsigned long long arg_value;
- ::trace_event_internal::SetTraceValue(value, &arg_type, &arg_value);
- trace_event->Initialize(
- thread_id,
- TimeTicks(),
- ThreadTicks(),
- TRACE_EVENT_PHASE_METADATA,
- CategoryRegistry::kCategoryMetadata->state_ptr(),
- metadata_name,
- trace_event_internal::kGlobalScope, // scope
- trace_event_internal::kNoId, // id
- trace_event_internal::kNoId, // bind_id
- num_args,
- &arg_name,
- &arg_type,
- &arg_value,
- nullptr,
- TRACE_EVENT_FLAG_NONE);
-}
-
-class AutoThreadLocalBoolean {
- public:
- explicit AutoThreadLocalBoolean(ThreadLocalBoolean* thread_local_boolean)
- : thread_local_boolean_(thread_local_boolean) {
- DCHECK(!thread_local_boolean_->Get());
- thread_local_boolean_->Set(true);
- }
- ~AutoThreadLocalBoolean() { thread_local_boolean_->Set(false); }
-
- private:
- ThreadLocalBoolean* thread_local_boolean_;
- DISALLOW_COPY_AND_ASSIGN(AutoThreadLocalBoolean);
-};
-
-// Use this function instead of TraceEventHandle constructor to keep the
-// overhead of ScopedTracer (trace_event.h) constructor minimum.
-void MakeHandle(uint32_t chunk_seq,
- size_t chunk_index,
- size_t event_index,
- TraceEventHandle* handle) {
- DCHECK(chunk_seq);
- DCHECK(chunk_index <= TraceBufferChunk::kMaxChunkIndex);
- DCHECK(event_index < TraceBufferChunk::kTraceBufferChunkSize);
- DCHECK(chunk_index <= std::numeric_limits<uint16_t>::max());
- handle->chunk_seq = chunk_seq;
- handle->chunk_index = static_cast<uint16_t>(chunk_index);
- handle->event_index = static_cast<uint16_t>(event_index);
-}
-
-template <typename Function>
-void ForEachCategoryFilter(const unsigned char* category_group_enabled,
- Function filter_fn) {
- const TraceCategory* category =
- CategoryRegistry::GetCategoryByStatePtr(category_group_enabled);
- uint32_t filter_bitmap = category->enabled_filters();
- for (int index = 0; filter_bitmap != 0; filter_bitmap >>= 1, index++) {
- if (filter_bitmap & 1 && GetCategoryGroupFilters()[index])
- filter_fn(GetCategoryGroupFilters()[index].get());
- }
-}
-
-} // namespace
-
-// A helper class that allows the lock to be acquired in the middle of the scope
-// and unlocks at the end of scope if locked.
-class TraceLog::OptionalAutoLock {
- public:
- explicit OptionalAutoLock(Lock* lock) : lock_(lock), locked_(false) {}
-
- ~OptionalAutoLock() {
- if (locked_)
- lock_->Release();
- }
-
- void EnsureAcquired() {
- if (!locked_) {
- lock_->Acquire();
- locked_ = true;
- }
- }
-
- private:
- Lock* lock_;
- bool locked_;
- DISALLOW_COPY_AND_ASSIGN(OptionalAutoLock);
-};
-
-class TraceLog::ThreadLocalEventBuffer
- : public MessageLoopCurrent::DestructionObserver,
- public MemoryDumpProvider {
- public:
- explicit ThreadLocalEventBuffer(TraceLog* trace_log);
- ~ThreadLocalEventBuffer() override;
-
- TraceEvent* AddTraceEvent(TraceEventHandle* handle);
-
- TraceEvent* GetEventByHandle(TraceEventHandle handle) {
- if (!chunk_ || handle.chunk_seq != chunk_->seq() ||
- handle.chunk_index != chunk_index_) {
- return nullptr;
- }
-
- return chunk_->GetEventAt(handle.event_index);
- }
-
- int generation() const { return generation_; }
-
- private:
- // MessageLoopCurrent::DestructionObserver
- void WillDestroyCurrentMessageLoop() override;
-
- // MemoryDumpProvider implementation.
- bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) override;
-
- void FlushWhileLocked();
-
- void CheckThisIsCurrentBuffer() const {
- DCHECK(trace_log_->thread_local_event_buffer_.Get() == this);
- }
-
- // Since TraceLog is a leaky singleton, trace_log_ will always be valid
- // as long as the thread exists.
- TraceLog* trace_log_;
- std::unique_ptr<TraceBufferChunk> chunk_;
- size_t chunk_index_;
- int generation_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadLocalEventBuffer);
-};
-
-TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log)
- : trace_log_(trace_log),
- chunk_index_(0),
- generation_(trace_log->generation()) {
- // ThreadLocalEventBuffer is created only if the thread has a message loop, so
- // the following message_loop won't be NULL.
- MessageLoop* message_loop = MessageLoop::current();
- message_loop->AddDestructionObserver(this);
-
- // This is to report the local memory usage when memory-infra is enabled.
- MemoryDumpManager::GetInstance()->RegisterDumpProvider(
- this, "ThreadLocalEventBuffer", ThreadTaskRunnerHandle::Get());
-
- AutoLock lock(trace_log->lock_);
- trace_log->thread_message_loops_.insert(message_loop);
-}
-
-TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() {
- CheckThisIsCurrentBuffer();
- MessageLoop::current()->RemoveDestructionObserver(this);
- MemoryDumpManager::GetInstance()->UnregisterDumpProvider(this);
-
- {
- AutoLock lock(trace_log_->lock_);
- FlushWhileLocked();
- trace_log_->thread_message_loops_.erase(MessageLoop::current());
- }
- trace_log_->thread_local_event_buffer_.Set(nullptr);
-}
-
-TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
- TraceEventHandle* handle) {
- CheckThisIsCurrentBuffer();
-
- if (chunk_ && chunk_->IsFull()) {
- AutoLock lock(trace_log_->lock_);
- FlushWhileLocked();
- chunk_.reset();
- }
- if (!chunk_) {
- AutoLock lock(trace_log_->lock_);
- chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_);
- trace_log_->CheckIfBufferIsFullWhileLocked();
- }
- if (!chunk_)
- return nullptr;
-
- size_t event_index;
- TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index);
- if (trace_event && handle)
- MakeHandle(chunk_->seq(), chunk_index_, event_index, handle);
-
- return trace_event;
-}
-
-void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() {
- delete this;
-}
-
-bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) {
- if (!chunk_)
- return true;
- std::string dump_base_name = StringPrintf(
- "tracing/thread_%d", static_cast<int>(PlatformThread::CurrentId()));
- TraceEventMemoryOverhead overhead;
- chunk_->EstimateTraceMemoryOverhead(&overhead);
- overhead.DumpInto(dump_base_name.c_str(), pmd);
- return true;
-}
-
-void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() {
- if (!chunk_)
- return;
-
- trace_log_->lock_.AssertAcquired();
- if (trace_log_->CheckGeneration(generation_)) {
- // Return the chunk to the buffer only if the generation matches.
- trace_log_->logged_events_->ReturnChunk(chunk_index_, std::move(chunk_));
- }
- // Otherwise this method may be called from the destructor, or TraceLog will
- // find the generation mismatch and delete this buffer soon.
-}
-
-void TraceLog::SetAddTraceEventOverride(
- const AddTraceEventOverrideCallback& override) {
- subtle::NoBarrier_Store(&trace_event_override_,
- reinterpret_cast<subtle::AtomicWord>(override));
-}
-
-struct TraceLog::RegisteredAsyncObserver {
- explicit RegisteredAsyncObserver(WeakPtr<AsyncEnabledStateObserver> observer)
- : observer(observer), task_runner(ThreadTaskRunnerHandle::Get()) {}
- ~RegisteredAsyncObserver() = default;
-
- WeakPtr<AsyncEnabledStateObserver> observer;
- scoped_refptr<SequencedTaskRunner> task_runner;
-};
-
-TraceLogStatus::TraceLogStatus() : event_capacity(0), event_count(0) {}
-
-TraceLogStatus::~TraceLogStatus() = default;
-
-// static
-TraceLog* TraceLog::GetInstance() {
- static base::NoDestructor<TraceLog> instance;
- return instance.get();
-}
-
-// static
-void TraceLog::ResetForTesting() {
- if (!g_trace_log_for_testing)
- return;
- CategoryRegistry::ResetForTesting();
- g_trace_log_for_testing->~TraceLog();
- new (g_trace_log_for_testing) TraceLog;
-}
-
-TraceLog::TraceLog()
- : enabled_modes_(0),
- num_traces_recorded_(0),
- dispatching_to_observer_list_(false),
- process_sort_index_(0),
- process_id_hash_(0),
- process_id_(0),
- trace_options_(kInternalRecordUntilFull),
- trace_config_(TraceConfig()),
- thread_shared_chunk_index_(0),
- generation_(0),
- use_worker_thread_(false),
- trace_event_override_(0),
- filter_factory_for_testing_(nullptr) {
- CategoryRegistry::Initialize();
-
-#if defined(OS_NACL) // NaCl shouldn't expose the process id.
- SetProcessID(0);
-#else
- SetProcessID(static_cast<int>(GetCurrentProcId()));
-#endif
-
-// Linux renderer processes and Android O processes are not allowed to read
-// "proc/stat" file, crbug.com/788870.
-#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
- process_creation_time_ = CurrentProcessInfo::CreationTime();
-#else
- // Use approximate time when creation time is not available.
- process_creation_time_ = TRACE_TIME_NOW();
-#endif
-
- logged_events_.reset(CreateTraceBuffer());
-
- MemoryDumpManager::GetInstance()->RegisterDumpProvider(this, "TraceLog",
- nullptr);
- g_trace_log_for_testing = this;
-}
-
-TraceLog::~TraceLog() = default;
-
-void TraceLog::InitializeThreadLocalEventBufferIfSupported() {
- // A ThreadLocalEventBuffer needs the message loop
- // - to know when the thread exits;
- // - to handle the final flush.
- // For a thread without a message loop or the message loop may be blocked, the
- // trace events will be added into the main buffer directly.
- if (thread_blocks_message_loop_.Get() || !MessageLoopCurrent::IsSet())
- return;
- HEAP_PROFILER_SCOPED_IGNORE;
- auto* thread_local_event_buffer = thread_local_event_buffer_.Get();
- if (thread_local_event_buffer &&
- !CheckGeneration(thread_local_event_buffer->generation())) {
- delete thread_local_event_buffer;
- thread_local_event_buffer = nullptr;
- }
- if (!thread_local_event_buffer) {
- thread_local_event_buffer = new ThreadLocalEventBuffer(this);
- thread_local_event_buffer_.Set(thread_local_event_buffer);
- }
-}
-
-bool TraceLog::OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) {
- // TODO(ssid): Use MemoryDumpArgs to create light dumps when requested
- // (crbug.com/499731).
- TraceEventMemoryOverhead overhead;
- overhead.Add(TraceEventMemoryOverhead::kOther, sizeof(*this));
- {
- AutoLock lock(lock_);
- if (logged_events_)
- logged_events_->EstimateTraceMemoryOverhead(&overhead);
-
- for (auto& metadata_event : metadata_events_)
- metadata_event->EstimateTraceMemoryOverhead(&overhead);
- }
- overhead.AddSelf();
- overhead.DumpInto("tracing/main_trace_log", pmd);
- return true;
-}
-
-const unsigned char* TraceLog::GetCategoryGroupEnabled(
- const char* category_group) {
- TraceLog* tracelog = GetInstance();
- if (!tracelog) {
- DCHECK(!CategoryRegistry::kCategoryAlreadyShutdown->is_enabled());
- return CategoryRegistry::kCategoryAlreadyShutdown->state_ptr();
- }
- TraceCategory* category = CategoryRegistry::GetCategoryByName(category_group);
- if (!category) {
- // Slow path: in the case of a new category we have to repeat the check
- // holding the lock, as multiple threads might have reached this point
- // at the same time.
- auto category_initializer = [](TraceCategory* category) {
- TraceLog::GetInstance()->UpdateCategoryState(category);
- };
- AutoLock lock(tracelog->lock_);
- CategoryRegistry::GetOrCreateCategoryLocked(
- category_group, category_initializer, &category);
- }
- DCHECK(category->state_ptr());
- return category->state_ptr();
-}
-
-const char* TraceLog::GetCategoryGroupName(
- const unsigned char* category_group_enabled) {
- return CategoryRegistry::GetCategoryByStatePtr(category_group_enabled)
- ->name();
-}
-
-void TraceLog::UpdateCategoryState(TraceCategory* category) {
- lock_.AssertAcquired();
- DCHECK(category->is_valid());
- unsigned char state_flags = 0;
- if (enabled_modes_ & RECORDING_MODE &&
- trace_config_.IsCategoryGroupEnabled(category->name())) {
- state_flags |= TraceCategory::ENABLED_FOR_RECORDING;
- }
-
- // TODO(primiano): this is a temporary workaround for catapult:#2341,
- // to guarantee that metadata events are always added even if the category
- // filter is "-*". See crbug.com/618054 for more details and long-term fix.
- if (enabled_modes_ & RECORDING_MODE &&
- category == CategoryRegistry::kCategoryMetadata) {
- state_flags |= TraceCategory::ENABLED_FOR_RECORDING;
- }
-
-#if defined(OS_WIN)
- if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled(
- category->name())) {
- state_flags |= TraceCategory::ENABLED_FOR_ETW_EXPORT;
- }
-#endif
-
- uint32_t enabled_filters_bitmap = 0;
- int index = 0;
- for (const auto& event_filter : enabled_event_filters_) {
- if (event_filter.IsCategoryGroupEnabled(category->name())) {
- state_flags |= TraceCategory::ENABLED_FOR_FILTERING;
- DCHECK(GetCategoryGroupFilters()[index]);
- enabled_filters_bitmap |= 1 << index;
- }
- if (index++ >= MAX_TRACE_EVENT_FILTERS) {
- NOTREACHED();
- break;
- }
- }
- category->set_enabled_filters(enabled_filters_bitmap);
- category->set_state(state_flags);
-}
-
-void TraceLog::UpdateCategoryRegistry() {
- lock_.AssertAcquired();
- CreateFiltersForTraceConfig();
- for (TraceCategory& category : CategoryRegistry::GetAllCategories()) {
- UpdateCategoryState(&category);
- }
-}
-
-void TraceLog::CreateFiltersForTraceConfig() {
- if (!(enabled_modes_ & FILTERING_MODE))
- return;
-
- // Filters were already added and tracing could be enabled. Filters list
- // cannot be changed when trace events are using them.
- if (GetCategoryGroupFilters().size())
- return;
-
- for (auto& filter_config : enabled_event_filters_) {
- if (GetCategoryGroupFilters().size() >= MAX_TRACE_EVENT_FILTERS) {
- NOTREACHED()
- << "Too many trace event filters installed in the current session";
- break;
- }
-
- std::unique_ptr<TraceEventFilter> new_filter;
- const std::string& predicate_name = filter_config.predicate_name();
- if (predicate_name == EventNameFilter::kName) {
- auto whitelist = std::make_unique<std::unordered_set<std::string>>();
- CHECK(filter_config.GetArgAsSet("event_name_whitelist", &*whitelist));
- new_filter = std::make_unique<EventNameFilter>(std::move(whitelist));
- } else if (predicate_name == HeapProfilerEventFilter::kName) {
- new_filter = std::make_unique<HeapProfilerEventFilter>();
- } else {
- if (filter_factory_for_testing_)
- new_filter = filter_factory_for_testing_(predicate_name);
- CHECK(new_filter) << "Unknown trace filter " << predicate_name;
- }
- GetCategoryGroupFilters().push_back(std::move(new_filter));
- }
-}
-
-void TraceLog::GetKnownCategoryGroups(
- std::vector<std::string>* category_groups) {
- for (const auto& category : CategoryRegistry::GetAllCategories()) {
- if (!CategoryRegistry::IsBuiltinCategory(&category))
- category_groups->push_back(category.name());
- }
-}
-
-void TraceLog::SetEnabled(const TraceConfig& trace_config,
- uint8_t modes_to_enable) {
- DCHECK(trace_config.process_filter_config().IsEnabled(process_id_));
-
- std::vector<EnabledStateObserver*> observer_list;
- std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> observer_map;
- {
- AutoLock lock(lock_);
-
- // Can't enable tracing when Flush() is in progress.
- DCHECK(!flush_task_runner_);
-
- InternalTraceOptions new_options =
- GetInternalOptionsFromTraceConfig(trace_config);
-
- InternalTraceOptions old_options = trace_options();
-
- if (dispatching_to_observer_list_) {
- // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170.
- DLOG(ERROR)
- << "Cannot manipulate TraceLog::Enabled state from an observer.";
- return;
- }
-
- // Clear all filters from previous tracing session. These filters are not
- // cleared at the end of tracing because some threads which hit trace event
- // when disabling, could try to use the filters.
- if (!enabled_modes_)
- GetCategoryGroupFilters().clear();
-
- // Update trace config for recording.
- const bool already_recording = enabled_modes_ & RECORDING_MODE;
- if (modes_to_enable & RECORDING_MODE) {
- if (already_recording) {
- // TODO(ssid): Stop suporting enabling of RECODING_MODE when already
- // enabled crbug.com/625170.
- DCHECK_EQ(new_options, old_options) << "Attempting to re-enable "
- "tracing with a different set "
- "of options.";
- trace_config_.Merge(trace_config);
- } else {
- trace_config_ = trace_config;
- }
- }
-
- // Update event filters only if filtering was not enabled.
- if (modes_to_enable & FILTERING_MODE && enabled_event_filters_.empty()) {
- DCHECK(!trace_config.event_filters().empty());
- enabled_event_filters_ = trace_config.event_filters();
- }
- // Keep the |trace_config_| updated with only enabled filters in case anyone
- // tries to read it using |GetCurrentTraceConfig| (even if filters are
- // empty).
- trace_config_.SetEventFilters(enabled_event_filters_);
-
- enabled_modes_ |= modes_to_enable;
- UpdateCategoryRegistry();
-
- // Do not notify observers or create trace buffer if only enabled for
- // filtering or if recording was already enabled.
- if (!(modes_to_enable & RECORDING_MODE) || already_recording)
- return;
-
- if (new_options != old_options) {
- subtle::NoBarrier_Store(&trace_options_, new_options);
- UseNextTraceBuffer();
- }
-
- num_traces_recorded_++;
-
- UpdateCategoryRegistry();
-
- dispatching_to_observer_list_ = true;
- observer_list = enabled_state_observer_list_;
- observer_map = async_observers_;
- }
- // Notify observers outside the lock in case they trigger trace events.
- for (EnabledStateObserver* observer : observer_list)
- observer->OnTraceLogEnabled();
- for (const auto& it : observer_map) {
- it.second.task_runner->PostTask(
- FROM_HERE, BindOnce(&AsyncEnabledStateObserver::OnTraceLogEnabled,
- it.second.observer));
- }
-
- {
- AutoLock lock(lock_);
- dispatching_to_observer_list_ = false;
- }
-}
-
-void TraceLog::SetArgumentFilterPredicate(
- const ArgumentFilterPredicate& argument_filter_predicate) {
- AutoLock lock(lock_);
- DCHECK(!argument_filter_predicate.is_null());
- DCHECK(argument_filter_predicate_.is_null());
- argument_filter_predicate_ = argument_filter_predicate;
-}
-
-TraceLog::InternalTraceOptions TraceLog::GetInternalOptionsFromTraceConfig(
- const TraceConfig& config) {
- InternalTraceOptions ret = config.IsArgumentFilterEnabled()
- ? kInternalEnableArgumentFilter
- : kInternalNone;
- switch (config.GetTraceRecordMode()) {
- case RECORD_UNTIL_FULL:
- return ret | kInternalRecordUntilFull;
- case RECORD_CONTINUOUSLY:
- return ret | kInternalRecordContinuously;
- case ECHO_TO_CONSOLE:
- return ret | kInternalEchoToConsole;
- case RECORD_AS_MUCH_AS_POSSIBLE:
- return ret | kInternalRecordAsMuchAsPossible;
- }
- NOTREACHED();
- return kInternalNone;
-}
-
-TraceConfig TraceLog::GetCurrentTraceConfig() const {
- AutoLock lock(lock_);
- return trace_config_;
-}
-
-void TraceLog::SetDisabled() {
- AutoLock lock(lock_);
- SetDisabledWhileLocked(RECORDING_MODE);
-}
-
-void TraceLog::SetDisabled(uint8_t modes_to_disable) {
- AutoLock lock(lock_);
- SetDisabledWhileLocked(modes_to_disable);
-}
-
-void TraceLog::SetDisabledWhileLocked(uint8_t modes_to_disable) {
- lock_.AssertAcquired();
-
- if (!(enabled_modes_ & modes_to_disable))
- return;
-
- if (dispatching_to_observer_list_) {
- // TODO(ssid): Change to NOTREACHED after fixing crbug.com/625170.
- DLOG(ERROR)
- << "Cannot manipulate TraceLog::Enabled state from an observer.";
- return;
- }
-
- bool is_recording_mode_disabled =
- (enabled_modes_ & RECORDING_MODE) && (modes_to_disable & RECORDING_MODE);
- enabled_modes_ &= ~modes_to_disable;
-
- if (modes_to_disable & FILTERING_MODE)
- enabled_event_filters_.clear();
-
- if (modes_to_disable & RECORDING_MODE)
- trace_config_.Clear();
-
- UpdateCategoryRegistry();
-
- // Add metadata events and notify observers only if recording mode was
- // disabled now.
- if (!is_recording_mode_disabled)
- return;
-
- AddMetadataEventsWhileLocked();
-
- // Remove metadata events so they will not get added to a subsequent trace.
- metadata_events_.clear();
-
- dispatching_to_observer_list_ = true;
- std::vector<EnabledStateObserver*> observer_list =
- enabled_state_observer_list_;
- std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver> observer_map =
- async_observers_;
-
- {
- // Dispatch to observers outside the lock in case the observer triggers a
- // trace event.
- AutoUnlock unlock(lock_);
- for (EnabledStateObserver* observer : observer_list)
- observer->OnTraceLogDisabled();
- for (const auto& it : observer_map) {
- it.second.task_runner->PostTask(
- FROM_HERE, BindOnce(&AsyncEnabledStateObserver::OnTraceLogDisabled,
- it.second.observer));
- }
- }
- dispatching_to_observer_list_ = false;
-}
-
-int TraceLog::GetNumTracesRecorded() {
- AutoLock lock(lock_);
- if (!IsEnabled())
- return -1;
- return num_traces_recorded_;
-}
-
-void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) {
- AutoLock lock(lock_);
- enabled_state_observer_list_.push_back(listener);
-}
-
-void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) {
- AutoLock lock(lock_);
- std::vector<EnabledStateObserver*>::iterator it =
- std::find(enabled_state_observer_list_.begin(),
- enabled_state_observer_list_.end(), listener);
- if (it != enabled_state_observer_list_.end())
- enabled_state_observer_list_.erase(it);
-}
-
-bool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const {
- AutoLock lock(lock_);
- return ContainsValue(enabled_state_observer_list_, listener);
-}
-
-TraceLogStatus TraceLog::GetStatus() const {
- AutoLock lock(lock_);
- TraceLogStatus result;
- result.event_capacity = static_cast<uint32_t>(logged_events_->Capacity());
- result.event_count = static_cast<uint32_t>(logged_events_->Size());
- return result;
-}
-
-bool TraceLog::BufferIsFull() const {
- AutoLock lock(lock_);
- return logged_events_->IsFull();
-}
-
-TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
- TraceEventHandle* handle,
- bool check_buffer_is_full) {
- lock_.AssertAcquired();
-
- if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) {
- logged_events_->ReturnChunk(thread_shared_chunk_index_,
- std::move(thread_shared_chunk_));
- }
-
- if (!thread_shared_chunk_) {
- thread_shared_chunk_ =
- logged_events_->GetChunk(&thread_shared_chunk_index_);
- if (check_buffer_is_full)
- CheckIfBufferIsFullWhileLocked();
- }
- if (!thread_shared_chunk_)
- return nullptr;
-
- size_t event_index;
- TraceEvent* trace_event = thread_shared_chunk_->AddTraceEvent(&event_index);
- if (trace_event && handle) {
- MakeHandle(thread_shared_chunk_->seq(), thread_shared_chunk_index_,
- event_index, handle);
- }
- return trace_event;
-}
-
-void TraceLog::CheckIfBufferIsFullWhileLocked() {
- lock_.AssertAcquired();
- if (logged_events_->IsFull()) {
- if (buffer_limit_reached_timestamp_.is_null()) {
- buffer_limit_reached_timestamp_ = OffsetNow();
- }
- SetDisabledWhileLocked(RECORDING_MODE);
- }
-}
-
-// Flush() works as the following:
-// 1. Flush() is called in thread A whose task runner is saved in
-// flush_task_runner_;
-// 2. If thread_message_loops_ is not empty, thread A posts task to each message
-// loop to flush the thread local buffers; otherwise finish the flush;
-// 3. FlushCurrentThread() deletes the thread local event buffer:
-// - The last batch of events of the thread are flushed into the main buffer;
-// - The message loop will be removed from thread_message_loops_;
-// If this is the last message loop, finish the flush;
-// 4. If any thread hasn't finish its flush in time, finish the flush.
-void TraceLog::Flush(const TraceLog::OutputCallback& cb,
- bool use_worker_thread) {
- FlushInternal(cb, use_worker_thread, false);
-}
-
-void TraceLog::CancelTracing(const OutputCallback& cb) {
- SetDisabled();
- FlushInternal(cb, false, true);
-}
-
-void TraceLog::FlushInternal(const TraceLog::OutputCallback& cb,
- bool use_worker_thread,
- bool discard_events) {
- use_worker_thread_ = use_worker_thread;
- if (IsEnabled()) {
- // Can't flush when tracing is enabled because otherwise PostTask would
- // - generate more trace events;
- // - deschedule the calling thread on some platforms causing inaccurate
- // timing of the trace events.
- scoped_refptr<RefCountedString> empty_result = new RefCountedString;
- if (!cb.is_null())
- cb.Run(empty_result, false);
- LOG(WARNING) << "Ignored TraceLog::Flush called when tracing is enabled";
- return;
- }
-
- int gen = generation();
- // Copy of thread_message_loops_ to be used without locking.
- std::vector<scoped_refptr<SingleThreadTaskRunner>>
- thread_message_loop_task_runners;
- {
- AutoLock lock(lock_);
- DCHECK(!flush_task_runner_);
- flush_task_runner_ = SequencedTaskRunnerHandle::IsSet()
- ? SequencedTaskRunnerHandle::Get()
- : nullptr;
- DCHECK(thread_message_loops_.empty() || flush_task_runner_);
- flush_output_callback_ = cb;
-
- if (thread_shared_chunk_) {
- logged_events_->ReturnChunk(thread_shared_chunk_index_,
- std::move(thread_shared_chunk_));
- }
-
- for (MessageLoop* loop : thread_message_loops_)
- thread_message_loop_task_runners.push_back(loop->task_runner());
- }
-
- if (!thread_message_loop_task_runners.empty()) {
- for (auto& task_runner : thread_message_loop_task_runners) {
- task_runner->PostTask(
- FROM_HERE, BindOnce(&TraceLog::FlushCurrentThread, Unretained(this),
- gen, discard_events));
- }
- flush_task_runner_->PostDelayedTask(
- FROM_HERE,
- BindOnce(&TraceLog::OnFlushTimeout, Unretained(this), gen,
- discard_events),
- TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs));
- return;
- }
-
- FinishFlush(gen, discard_events);
-}
-
-// Usually it runs on a different thread.
-void TraceLog::ConvertTraceEventsToTraceFormat(
- std::unique_ptr<TraceBuffer> logged_events,
- const OutputCallback& flush_output_callback,
- const ArgumentFilterPredicate& argument_filter_predicate) {
- if (flush_output_callback.is_null())
- return;
-
- HEAP_PROFILER_SCOPED_IGNORE;
- // The callback need to be called at least once even if there is no events
- // to let the caller know the completion of flush.
- scoped_refptr<RefCountedString> json_events_str_ptr = new RefCountedString();
- const size_t kReserveCapacity = kTraceEventBufferSizeInBytes * 5 / 4;
- json_events_str_ptr->data().reserve(kReserveCapacity);
- while (const TraceBufferChunk* chunk = logged_events->NextChunk()) {
- for (size_t j = 0; j < chunk->size(); ++j) {
- size_t size = json_events_str_ptr->size();
- if (size > kTraceEventBufferSizeInBytes) {
- flush_output_callback.Run(json_events_str_ptr, true);
- json_events_str_ptr = new RefCountedString();
- json_events_str_ptr->data().reserve(kReserveCapacity);
- } else if (size) {
- json_events_str_ptr->data().append(",\n");
- }
- chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()),
- argument_filter_predicate);
- }
- }
- flush_output_callback.Run(json_events_str_ptr, false);
-}
-
-void TraceLog::FinishFlush(int generation, bool discard_events) {
- std::unique_ptr<TraceBuffer> previous_logged_events;
- OutputCallback flush_output_callback;
- ArgumentFilterPredicate argument_filter_predicate;
-
- if (!CheckGeneration(generation))
- return;
-
- {
- AutoLock lock(lock_);
-
- previous_logged_events.swap(logged_events_);
- UseNextTraceBuffer();
- thread_message_loops_.clear();
-
- flush_task_runner_ = nullptr;
- flush_output_callback = flush_output_callback_;
- flush_output_callback_.Reset();
-
- if (trace_options() & kInternalEnableArgumentFilter) {
- CHECK(!argument_filter_predicate_.is_null());
- argument_filter_predicate = argument_filter_predicate_;
- }
- }
-
- if (discard_events) {
- if (!flush_output_callback.is_null()) {
- scoped_refptr<RefCountedString> empty_result = new RefCountedString;
- flush_output_callback.Run(empty_result, false);
- }
- return;
- }
-
- if (use_worker_thread_) {
- base::PostTaskWithTraits(
- FROM_HERE,
- {MayBlock(), TaskPriority::BACKGROUND,
- TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- BindOnce(&TraceLog::ConvertTraceEventsToTraceFormat,
- std::move(previous_logged_events), flush_output_callback,
- argument_filter_predicate));
- return;
- }
-
- ConvertTraceEventsToTraceFormat(std::move(previous_logged_events),
- flush_output_callback,
- argument_filter_predicate);
-}
-
-// Run in each thread holding a local event buffer.
-void TraceLog::FlushCurrentThread(int generation, bool discard_events) {
- {
- AutoLock lock(lock_);
- if (!CheckGeneration(generation) || !flush_task_runner_) {
- // This is late. The corresponding flush has finished.
- return;
- }
- }
-
- // This will flush the thread local buffer.
- delete thread_local_event_buffer_.Get();
-
- // Scheduler uses TRACE_EVENT macros when posting a task, which can lead
- // to acquiring a tracing lock. Given that posting a task requires grabbing
- // a scheduler lock, we need to post this task outside tracing lock to avoid
- // deadlocks.
- scoped_refptr<SequencedTaskRunner> cached_flush_task_runner;
- {
- AutoLock lock(lock_);
- cached_flush_task_runner = flush_task_runner_;
- if (!CheckGeneration(generation) || !flush_task_runner_ ||
- !thread_message_loops_.empty())
- return;
- }
- cached_flush_task_runner->PostTask(
- FROM_HERE, BindOnce(&TraceLog::FinishFlush, Unretained(this), generation,
- discard_events));
-}
-
-void TraceLog::OnFlushTimeout(int generation, bool discard_events) {
- {
- AutoLock lock(lock_);
- if (!CheckGeneration(generation) || !flush_task_runner_) {
- // Flush has finished before timeout.
- return;
- }
-
- LOG(WARNING)
- << "The following threads haven't finished flush in time. "
- "If this happens stably for some thread, please call "
- "TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop() from "
- "the thread to avoid its trace events from being lost.";
- for (hash_set<MessageLoop*>::const_iterator it =
- thread_message_loops_.begin();
- it != thread_message_loops_.end(); ++it) {
- LOG(WARNING) << "Thread: " << (*it)->GetThreadName();
- }
- }
- FinishFlush(generation, discard_events);
-}
-
-void TraceLog::UseNextTraceBuffer() {
- logged_events_.reset(CreateTraceBuffer());
- subtle::NoBarrier_AtomicIncrement(&generation_, 1);
- thread_shared_chunk_.reset();
- thread_shared_chunk_index_ = 0;
-}
-
-TraceEventHandle TraceLog::AddTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
- base::TimeTicks now = TRACE_TIME_TICKS_NOW();
- return AddTraceEventWithThreadIdAndTimestamp(
- phase,
- category_group_enabled,
- name,
- scope,
- id,
- trace_event_internal::kNoId, // bind_id
- thread_id,
- now,
- num_args,
- arg_names,
- arg_types,
- arg_values,
- convertable_values,
- flags);
-}
-
-TraceEventHandle TraceLog::AddTraceEventWithBindId(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- unsigned long long bind_id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
- base::TimeTicks now = TRACE_TIME_TICKS_NOW();
- return AddTraceEventWithThreadIdAndTimestamp(
- phase,
- category_group_enabled,
- name,
- scope,
- id,
- bind_id,
- thread_id,
- now,
- num_args,
- arg_names,
- arg_types,
- arg_values,
- convertable_values,
- flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID);
-}
-
-TraceEventHandle TraceLog::AddTraceEventWithProcessId(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- int process_id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- base::TimeTicks now = TRACE_TIME_TICKS_NOW();
- return AddTraceEventWithThreadIdAndTimestamp(
- phase,
- category_group_enabled,
- name,
- scope,
- id,
- trace_event_internal::kNoId, // bind_id
- process_id,
- now,
- num_args,
- arg_names,
- arg_types,
- arg_values,
- convertable_values,
- flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
-}
-
-// Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp
-// with kNoId as bind_id
-TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- int thread_id,
- const TimeTicks& timestamp,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- return AddTraceEventWithThreadIdAndTimestamp(
- phase,
- category_group_enabled,
- name,
- scope,
- id,
- trace_event_internal::kNoId, // bind_id
- thread_id,
- timestamp,
- num_args,
- arg_names,
- arg_types,
- arg_values,
- convertable_values,
- flags);
-}
-
-TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- unsigned long long bind_id,
- int thread_id,
- const TimeTicks& timestamp,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- TraceEventHandle handle = {0, 0, 0};
- if (!*category_group_enabled)
- return handle;
-
- // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when
- // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) ->
- // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ...
- if (thread_is_in_trace_event_.Get())
- return handle;
-
- AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
-
- DCHECK(name);
- DCHECK(!timestamp.is_null());
-
- if (flags & TRACE_EVENT_FLAG_MANGLE_ID) {
- if ((flags & TRACE_EVENT_FLAG_FLOW_IN) ||
- (flags & TRACE_EVENT_FLAG_FLOW_OUT))
- bind_id = MangleEventId(bind_id);
- id = MangleEventId(id);
- }
-
- TimeTicks offset_event_timestamp = OffsetTimestamp(timestamp);
- ThreadTicks thread_now = ThreadNow();
-
- ThreadLocalEventBuffer* thread_local_event_buffer = nullptr;
- if (*category_group_enabled & RECORDING_MODE) {
- // |thread_local_event_buffer_| can be null if the current thread doesn't
- // have a message loop or the message loop is blocked.
- InitializeThreadLocalEventBufferIfSupported();
- thread_local_event_buffer = thread_local_event_buffer_.Get();
- }
-
- // Check and update the current thread name only if the event is for the
- // current thread to avoid locks in most cases.
- if (thread_id == static_cast<int>(PlatformThread::CurrentId())) {
- const char* new_name =
- ThreadIdNameManager::GetInstance()->GetName(thread_id);
- // Check if the thread name has been set or changed since the previous
- // call (if any), but don't bother if the new name is empty. Note this will
- // not detect a thread name change within the same char* buffer address: we
- // favor common case performance over corner case correctness.
- static auto* current_thread_name = new ThreadLocalPointer<const char>();
- if (new_name != current_thread_name->Get() && new_name && *new_name) {
- current_thread_name->Set(new_name);
-
- AutoLock thread_info_lock(thread_info_lock_);
-
- auto existing_name = thread_names_.find(thread_id);
- if (existing_name == thread_names_.end()) {
- // This is a new thread id, and a new name.
- thread_names_[thread_id] = new_name;
- } else {
- // This is a thread id that we've seen before, but potentially with a
- // new name.
- std::vector<StringPiece> existing_names = base::SplitStringPiece(
- existing_name->second, ",", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
- if (!ContainsValue(existing_names, new_name)) {
- if (!existing_names.empty())
- existing_name->second.push_back(',');
- existing_name->second.append(new_name);
- }
- }
- }
- }
-
-#if defined(OS_WIN)
- // This is done sooner rather than later, to avoid creating the event and
- // acquiring the lock, which is not needed for ETW as it's already threadsafe.
- if (*category_group_enabled & TraceCategory::ENABLED_FOR_ETW_EXPORT)
- TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id,
- num_args, arg_names, arg_types, arg_values,
- convertable_values);
-#endif // OS_WIN
-
- AddTraceEventOverrideCallback trace_event_override =
- reinterpret_cast<AddTraceEventOverrideCallback>(
- subtle::NoBarrier_Load(&trace_event_override_));
- if (trace_event_override) {
- TraceEvent new_trace_event;
- // If we have an override in place for events, rather than sending
- // them to the tracelog, we don't have a way of going back and updating
- // the duration of _COMPLETE events. Instead, we emit separate _BEGIN
- // and _END events.
- if (phase == TRACE_EVENT_PHASE_COMPLETE)
- phase = TRACE_EVENT_PHASE_BEGIN;
-
- new_trace_event.Initialize(thread_id, offset_event_timestamp, thread_now,
- phase, category_group_enabled, name, scope, id,
- bind_id, num_args, arg_names, arg_types,
- arg_values, convertable_values, flags);
-
- trace_event_override(new_trace_event);
- return handle;
- }
-
- std::string console_message;
- std::unique_ptr<TraceEvent> filtered_trace_event;
- bool disabled_by_filters = false;
- if (*category_group_enabled & TraceCategory::ENABLED_FOR_FILTERING) {
- std::unique_ptr<TraceEvent> new_trace_event(new TraceEvent);
- new_trace_event->Initialize(thread_id, offset_event_timestamp, thread_now,
- phase, category_group_enabled, name, scope, id,
- bind_id, num_args, arg_names, arg_types,
- arg_values, convertable_values, flags);
-
- disabled_by_filters = true;
- ForEachCategoryFilter(
- category_group_enabled, [&new_trace_event, &disabled_by_filters](
- TraceEventFilter* trace_event_filter) {
- if (trace_event_filter->FilterTraceEvent(*new_trace_event))
- disabled_by_filters = false;
- });
- if (!disabled_by_filters)
- filtered_trace_event = std::move(new_trace_event);
- }
-
- // If enabled for recording, the event should be added only if one of the
- // filters indicates or category is not enabled for filtering.
- if ((*category_group_enabled & TraceCategory::ENABLED_FOR_RECORDING) &&
- !disabled_by_filters) {
- OptionalAutoLock lock(&lock_);
-
- TraceEvent* trace_event = nullptr;
- if (thread_local_event_buffer) {
- trace_event = thread_local_event_buffer->AddTraceEvent(&handle);
- } else {
- lock.EnsureAcquired();
- trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true);
- }
-
- if (trace_event) {
- if (filtered_trace_event) {
- trace_event->MoveFrom(std::move(filtered_trace_event));
- } else {
- trace_event->Initialize(thread_id, offset_event_timestamp, thread_now,
- phase, category_group_enabled, name, scope, id,
- bind_id, num_args, arg_names, arg_types,
- arg_values, convertable_values, flags);
- }
-
-#if defined(OS_ANDROID)
- trace_event->SendToATrace();
-#endif
- }
-
- if (trace_options() & kInternalEchoToConsole) {
- console_message = EventToConsoleMessage(
- phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase,
- timestamp, trace_event);
- }
- }
-
- if (!console_message.empty())
- LOG(ERROR) << console_message;
-
- return handle;
-}
-
-void TraceLog::AddMetadataEvent(
- const unsigned char* category_group_enabled,
- const char* name,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags) {
- HEAP_PROFILER_SCOPED_IGNORE;
- std::unique_ptr<TraceEvent> trace_event(new TraceEvent);
- int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
- ThreadTicks thread_now = ThreadNow();
- TimeTicks now = OffsetNow();
- AutoLock lock(lock_);
- trace_event->Initialize(
- thread_id, now, thread_now, TRACE_EVENT_PHASE_METADATA,
- category_group_enabled, name,
- trace_event_internal::kGlobalScope, // scope
- trace_event_internal::kNoId, // id
- trace_event_internal::kNoId, // bind_id
- num_args, arg_names, arg_types, arg_values, convertable_values, flags);
- metadata_events_.push_back(std::move(trace_event));
-}
-
-// May be called when a COMPELETE event ends and the unfinished event has been
-// recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL).
-std::string TraceLog::EventToConsoleMessage(unsigned char phase,
- const TimeTicks& timestamp,
- TraceEvent* trace_event) {
- HEAP_PROFILER_SCOPED_IGNORE;
- AutoLock thread_info_lock(thread_info_lock_);
-
- // The caller should translate TRACE_EVENT_PHASE_COMPLETE to
- // TRACE_EVENT_PHASE_BEGIN or TRACE_EVENT_END.
- DCHECK(phase != TRACE_EVENT_PHASE_COMPLETE);
-
- TimeDelta duration;
- int thread_id =
- trace_event ? trace_event->thread_id() : PlatformThread::CurrentId();
- if (phase == TRACE_EVENT_PHASE_END) {
- duration = timestamp - thread_event_start_times_[thread_id].top();
- thread_event_start_times_[thread_id].pop();
- }
-
- std::string thread_name = thread_names_[thread_id];
- if (thread_colors_.find(thread_name) == thread_colors_.end()) {
- size_t next_color = (thread_colors_.size() % 6) + 1;
- thread_colors_[thread_name] = next_color;
- }
-
- std::ostringstream log;
- log << base::StringPrintf("%s: \x1b[0;3%dm", thread_name.c_str(),
- thread_colors_[thread_name]);
-
- size_t depth = 0;
- auto it = thread_event_start_times_.find(thread_id);
- if (it != thread_event_start_times_.end())
- depth = it->second.size();
-
- for (size_t i = 0; i < depth; ++i)
- log << "| ";
-
- if (trace_event)
- trace_event->AppendPrettyPrinted(&log);
- if (phase == TRACE_EVENT_PHASE_END)
- log << base::StringPrintf(" (%.3f ms)", duration.InMillisecondsF());
-
- log << "\x1b[0;m";
-
- if (phase == TRACE_EVENT_PHASE_BEGIN)
- thread_event_start_times_[thread_id].push(timestamp);
-
- return log.str();
-}
-
-void TraceLog::EndFilteredEvent(const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle handle) {
- const char* category_name = GetCategoryGroupName(category_group_enabled);
- ForEachCategoryFilter(
- category_group_enabled,
- [name, category_name](TraceEventFilter* trace_event_filter) {
- trace_event_filter->EndEvent(category_name, name);
- });
-}
-
-void TraceLog::UpdateTraceEventDuration(
- const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle handle) {
- char category_group_enabled_local = *category_group_enabled;
- if (!category_group_enabled_local)
- return;
-
- UpdateTraceEventDurationExplicit(category_group_enabled, name, handle,
- OffsetNow(), ThreadNow());
-}
-
-void TraceLog::UpdateTraceEventDurationExplicit(
- const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle handle,
- const TimeTicks& now,
- const ThreadTicks& thread_now) {
- char category_group_enabled_local = *category_group_enabled;
- if (!category_group_enabled_local)
- return;
-
- // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when
- // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) ->
- // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ...
- if (thread_is_in_trace_event_.Get())
- return;
- AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
-
-#if defined(OS_WIN)
- // Generate an ETW event that marks the end of a complete event.
- if (category_group_enabled_local & TraceCategory::ENABLED_FOR_ETW_EXPORT)
- TraceEventETWExport::AddCompleteEndEvent(name);
-#endif // OS_WIN
-
- std::string console_message;
- if (category_group_enabled_local & TraceCategory::ENABLED_FOR_RECORDING) {
- AddTraceEventOverrideCallback trace_event_override =
- reinterpret_cast<AddTraceEventOverrideCallback>(
- subtle::NoBarrier_Load(&trace_event_override_));
-
- // If we send events off to an override instead of the TraceBuffer,
- // we don't have way of updating the prior event so we'll emit a
- // separate _END event instead.
- if (trace_event_override) {
- TraceEvent new_trace_event;
- new_trace_event.Initialize(
- static_cast<int>(base::PlatformThread::CurrentId()), now, thread_now,
- TRACE_EVENT_PHASE_END, category_group_enabled, name,
- trace_event_internal::kGlobalScope,
- trace_event_internal::kNoId /* id */,
- trace_event_internal::kNoId /* bind_id */, 0, nullptr, nullptr,
- nullptr, nullptr, TRACE_EVENT_FLAG_NONE);
- trace_event_override(new_trace_event);
- return;
- }
-
- OptionalAutoLock lock(&lock_);
-
- TraceEvent* trace_event = GetEventByHandleInternal(handle, &lock);
- if (trace_event) {
- DCHECK(trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE);
- // TEMP(oysteine) to debug crbug.com/638744
- if (trace_event->duration().ToInternalValue() != -1) {
- DVLOG(1) << "TraceHandle: chunk_seq " << handle.chunk_seq
- << ", chunk_index " << handle.chunk_index << ", event_index "
- << handle.event_index;
-
- std::string serialized_event;
- trace_event->AppendAsJSON(&serialized_event, ArgumentFilterPredicate());
- DVLOG(1) << "TraceEvent: " << serialized_event;
- lock_.AssertAcquired();
- }
-
- trace_event->UpdateDuration(now, thread_now);
-#if defined(OS_ANDROID)
- trace_event->SendToATrace();
-#endif
- }
-
- if (trace_options() & kInternalEchoToConsole) {
- console_message =
- EventToConsoleMessage(TRACE_EVENT_PHASE_END, now, trace_event);
- }
- }
-
- if (!console_message.empty())
- LOG(ERROR) << console_message;
-
- if (category_group_enabled_local & TraceCategory::ENABLED_FOR_FILTERING)
- EndFilteredEvent(category_group_enabled, name, handle);
-}
-
-uint64_t TraceLog::MangleEventId(uint64_t id) {
- return id ^ process_id_hash_;
-}
-
-void TraceLog::AddMetadataEventsWhileLocked() {
- lock_.AssertAcquired();
-
- // Move metadata added by |AddMetadataEvent| into the trace log.
- while (!metadata_events_.empty()) {
- TraceEvent* event = AddEventToThreadSharedChunkWhileLocked(nullptr, false);
- event->MoveFrom(std::move(metadata_events_.back()));
- metadata_events_.pop_back();
- }
-
-#if !defined(OS_NACL) // NaCl shouldn't expose the process id.
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false), 0, "num_cpus",
- "number", base::SysInfo::NumberOfProcessors());
-#endif
-
- int current_thread_id = static_cast<int>(base::PlatformThread::CurrentId());
- if (process_sort_index_ != 0) {
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false),
- current_thread_id, "process_sort_index", "sort_index",
- process_sort_index_);
- }
-
- if (!process_name_.empty()) {
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false),
- current_thread_id, "process_name", "name", process_name_);
- }
-
- TimeDelta process_uptime = TRACE_TIME_NOW() - process_creation_time_;
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false), current_thread_id,
- "process_uptime_seconds", "uptime", process_uptime.InSeconds());
-
-#if defined(OS_ANDROID)
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false), current_thread_id,
- "chrome_library_address", "start_address",
- base::StringPrintf("%p", &__executable_start));
-#endif
-
- if (!process_labels_.empty()) {
- std::vector<base::StringPiece> labels;
- for (const auto& it : process_labels_)
- labels.push_back(it.second);
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false),
- current_thread_id, "process_labels", "labels",
- base::JoinString(labels, ","));
- }
-
- // Thread sort indices.
- for (const auto& it : thread_sort_indices_) {
- if (it.second == 0)
- continue;
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false), it.first,
- "thread_sort_index", "sort_index", it.second);
- }
-
- // Thread names.
- AutoLock thread_info_lock(thread_info_lock_);
- for (const auto& it : thread_names_) {
- if (it.second.empty())
- continue;
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false), it.first,
- "thread_name", "name", it.second);
- }
-
- // If buffer is full, add a metadata record to report this.
- if (!buffer_limit_reached_timestamp_.is_null()) {
- InitializeMetadataEvent(
- AddEventToThreadSharedChunkWhileLocked(nullptr, false),
- current_thread_id, "trace_buffer_overflowed", "overflowed_at_ts",
- buffer_limit_reached_timestamp_);
- }
-}
-
-TraceEvent* TraceLog::GetEventByHandle(TraceEventHandle handle) {
- return GetEventByHandleInternal(handle, nullptr);
-}
-
-TraceEvent* TraceLog::GetEventByHandleInternal(TraceEventHandle handle,
- OptionalAutoLock* lock) {
- if (!handle.chunk_seq)
- return nullptr;
-
- DCHECK(handle.chunk_seq);
- DCHECK(handle.chunk_index <= TraceBufferChunk::kMaxChunkIndex);
- DCHECK(handle.event_index <= TraceBufferChunk::kTraceBufferChunkSize - 1);
-
- if (thread_local_event_buffer_.Get()) {
- TraceEvent* trace_event =
- thread_local_event_buffer_.Get()->GetEventByHandle(handle);
- if (trace_event)
- return trace_event;
- }
-
- // The event has been out-of-control of the thread local buffer.
- // Try to get the event from the main buffer with a lock.
- if (lock)
- lock->EnsureAcquired();
-
- if (thread_shared_chunk_ &&
- handle.chunk_index == thread_shared_chunk_index_) {
- return handle.chunk_seq == thread_shared_chunk_->seq()
- ? thread_shared_chunk_->GetEventAt(handle.event_index)
- : nullptr;
- }
-
- return logged_events_->GetEventByHandle(handle);
-}
-
-void TraceLog::SetProcessID(int process_id) {
- process_id_ = process_id;
- // Create a FNV hash from the process ID for XORing.
- // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details.
- const unsigned long long kOffsetBasis = 14695981039346656037ull;
- const unsigned long long kFnvPrime = 1099511628211ull;
- const unsigned long long pid = static_cast<unsigned long long>(process_id_);
- process_id_hash_ = (kOffsetBasis ^ pid) * kFnvPrime;
-}
-
-void TraceLog::SetProcessSortIndex(int sort_index) {
- AutoLock lock(lock_);
- process_sort_index_ = sort_index;
-}
-
-void TraceLog::UpdateProcessLabel(int label_id,
- const std::string& current_label) {
- if (!current_label.length())
- return RemoveProcessLabel(label_id);
-
- AutoLock lock(lock_);
- process_labels_[label_id] = current_label;
-}
-
-void TraceLog::RemoveProcessLabel(int label_id) {
- AutoLock lock(lock_);
- process_labels_.erase(label_id);
-}
-
-void TraceLog::SetThreadSortIndex(PlatformThreadId thread_id, int sort_index) {
- AutoLock lock(lock_);
- thread_sort_indices_[static_cast<int>(thread_id)] = sort_index;
-}
-
-void TraceLog::SetTimeOffset(TimeDelta offset) {
- time_offset_ = offset;
-}
-
-size_t TraceLog::GetObserverCountForTest() const {
- return enabled_state_observer_list_.size();
-}
-
-void TraceLog::SetCurrentThreadBlocksMessageLoop() {
- thread_blocks_message_loop_.Set(true);
- // This will flush the thread local buffer.
- delete thread_local_event_buffer_.Get();
-}
-
-TraceBuffer* TraceLog::CreateTraceBuffer() {
- HEAP_PROFILER_SCOPED_IGNORE;
- InternalTraceOptions options = trace_options();
- if (options & kInternalRecordContinuously) {
- return TraceBuffer::CreateTraceBufferRingBuffer(
- kTraceEventRingBufferChunks);
- }
- if (options & kInternalEchoToConsole) {
- return TraceBuffer::CreateTraceBufferRingBuffer(
- kEchoToConsoleTraceEventBufferChunks);
- }
- if (options & kInternalRecordAsMuchAsPossible) {
- return TraceBuffer::CreateTraceBufferVectorOfSize(
- kTraceEventVectorBigBufferChunks);
- }
- return TraceBuffer::CreateTraceBufferVectorOfSize(
- kTraceEventVectorBufferChunks);
-}
-
-#if defined(OS_WIN)
-void TraceLog::UpdateETWCategoryGroupEnabledFlags() {
- // Go through each category and set/clear the ETW bit depending on whether the
- // category is enabled.
- for (TraceCategory& category : CategoryRegistry::GetAllCategories()) {
- if (base::trace_event::TraceEventETWExport::IsCategoryGroupEnabled(
- category.name())) {
- category.set_state_flag(TraceCategory::ENABLED_FOR_ETW_EXPORT);
- } else {
- category.clear_state_flag(TraceCategory::ENABLED_FOR_ETW_EXPORT);
- }
- }
-}
-#endif // defined(OS_WIN)
-
-void TraceLog::SetTraceBufferForTesting(
- std::unique_ptr<TraceBuffer> trace_buffer) {
- AutoLock lock(lock_);
- logged_events_ = std::move(trace_buffer);
-}
-
-void ConvertableToTraceFormat::EstimateTraceMemoryOverhead(
- TraceEventMemoryOverhead* overhead) {
- overhead->Add(TraceEventMemoryOverhead::kConvertableToTraceFormat,
- sizeof(*this));
-}
-
-void TraceLog::AddAsyncEnabledStateObserver(
- WeakPtr<AsyncEnabledStateObserver> listener) {
- AutoLock lock(lock_);
- async_observers_.insert(
- std::make_pair(listener.get(), RegisteredAsyncObserver(listener)));
-}
-
-void TraceLog::RemoveAsyncEnabledStateObserver(
- AsyncEnabledStateObserver* listener) {
- AutoLock lock(lock_);
- async_observers_.erase(listener);
-}
-
-bool TraceLog::HasAsyncEnabledStateObserver(
- AsyncEnabledStateObserver* listener) const {
- AutoLock lock(lock_);
- return ContainsKey(async_observers_, listener);
-}
-
-} // namespace trace_event
-} // namespace base
-
-namespace trace_event_internal {
-
-ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient(
- const char* category_group,
- const char* name) {
- // The single atom works because for now the category_group can only be "gpu".
- DCHECK_EQ(strcmp(category_group, "gpu"), 0);
- static TRACE_EVENT_API_ATOMIC_WORD atomic = 0;
- INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(
- category_group, atomic, category_group_enabled_);
- name_ = name;
- if (*category_group_enabled_) {
- event_handle_ =
- TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
- TRACE_EVENT_PHASE_COMPLETE, category_group_enabled_, name,
- trace_event_internal::kGlobalScope, // scope
- trace_event_internal::kNoId, // id
- static_cast<int>(base::PlatformThread::CurrentId()), // thread_id
- TRACE_TIME_TICKS_NOW(), trace_event_internal::kZeroNumArgs, nullptr,
- nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_NONE);
- }
-}
-
-ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() {
- if (*category_group_enabled_) {
- TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_,
- event_handle_);
- }
-}
-
-} // namespace trace_event_internal
diff --git a/base/trace_event/trace_log.h b/base/trace_event/trace_log.h
deleted file mode 100644
index 8fc914d724..0000000000
--- a/base/trace_event/trace_log.h
+++ /dev/null
@@ -1,528 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_TRACE_LOG_H_
-#define BASE_TRACE_EVENT_TRACE_LOG_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "base/atomicops.h"
-#include "base/containers/stack.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/time/time_override.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "base/trace_event/trace_config.h"
-#include "base/trace_event/trace_event_impl.h"
-#include "build/build_config.h"
-
-namespace base {
-
-class MessageLoop;
-class RefCountedString;
-
-template <typename T>
-class NoDestructor;
-
-namespace trace_event {
-
-struct TraceCategory;
-class TraceBuffer;
-class TraceBufferChunk;
-class TraceEvent;
-class TraceEventFilter;
-class TraceEventMemoryOverhead;
-
-struct BASE_EXPORT TraceLogStatus {
- TraceLogStatus();
- ~TraceLogStatus();
- uint32_t event_capacity;
- uint32_t event_count;
-};
-
-class BASE_EXPORT TraceLog : public MemoryDumpProvider {
- public:
- // Argument passed to TraceLog::SetEnabled.
- enum Mode : uint8_t {
- // Enables normal tracing (recording trace events in the trace buffer).
- RECORDING_MODE = 1 << 0,
-
- // Trace events are enabled just for filtering but not for recording. Only
- // event filters config of |trace_config| argument is used.
- FILTERING_MODE = 1 << 1
- };
-
- static TraceLog* GetInstance();
-
- // Get set of known category groups. This can change as new code paths are
- // reached. The known category groups are inserted into |category_groups|.
- void GetKnownCategoryGroups(std::vector<std::string>* category_groups);
-
- // Retrieves a copy (for thread-safety) of the current TraceConfig.
- TraceConfig GetCurrentTraceConfig() const;
-
- // Initializes the thread-local event buffer, if not already initialized and
- // if the current thread supports that (has a message loop).
- void InitializeThreadLocalEventBufferIfSupported();
-
- // See TraceConfig comments for details on how to control which categories
- // will be traced. SetDisabled must be called distinctly for each mode that is
- // enabled. If tracing has already been enabled for recording, category filter
- // (enabled and disabled categories) will be merged into the current category
- // filter. Enabling RECORDING_MODE does not enable filters. Trace event
- // filters will be used only if FILTERING_MODE is set on |modes_to_enable|.
- // Conversely to RECORDING_MODE, FILTERING_MODE doesn't support upgrading,
- // i.e. filters can only be enabled if not previously enabled.
- void SetEnabled(const TraceConfig& trace_config, uint8_t modes_to_enable);
-
- // TODO(ssid): Remove the default SetEnabled and IsEnabled. They should take
- // Mode as argument.
-
- // Disables tracing for all categories for the specified |modes_to_disable|
- // only. Only RECORDING_MODE is taken as default |modes_to_disable|.
- void SetDisabled();
- void SetDisabled(uint8_t modes_to_disable);
-
- // Returns true if TraceLog is enabled on recording mode.
- // Note: Returns false even if FILTERING_MODE is enabled.
- bool IsEnabled() { return enabled_modes_ & RECORDING_MODE; }
-
- // Returns a bitmap of enabled modes from TraceLog::Mode.
- uint8_t enabled_modes() { return enabled_modes_; }
-
- // The number of times we have begun recording traces. If tracing is off,
- // returns -1. If tracing is on, then it returns the number of times we have
- // recorded a trace. By watching for this number to increment, you can
- // passively discover when a new trace has begun. This is then used to
- // implement the TRACE_EVENT_IS_NEW_TRACE() primitive.
- int GetNumTracesRecorded();
-
-#if defined(OS_ANDROID)
- void StartATrace();
- void StopATrace();
- void AddClockSyncMetadataEvent();
-#endif
-
- // Enabled state listeners give a callback when tracing is enabled or
- // disabled. This can be used to tie into other library's tracing systems
- // on-demand.
- class BASE_EXPORT EnabledStateObserver {
- public:
- virtual ~EnabledStateObserver() = default;
-
- // Called just after the tracing system becomes enabled, outside of the
- // |lock_|. TraceLog::IsEnabled() is true at this point.
- virtual void OnTraceLogEnabled() = 0;
-
- // Called just after the tracing system disables, outside of the |lock_|.
- // TraceLog::IsEnabled() is false at this point.
- virtual void OnTraceLogDisabled() = 0;
- };
- void AddEnabledStateObserver(EnabledStateObserver* listener);
- void RemoveEnabledStateObserver(EnabledStateObserver* listener);
- bool HasEnabledStateObserver(EnabledStateObserver* listener) const;
-
- // Asynchronous enabled state listeners. When tracing is enabled or disabled,
- // for each observer, a task for invoking its appropriate callback is posted
- // to the thread from which AddAsyncEnabledStateObserver() was called. This
- // allows the observer to be safely destroyed, provided that it happens on the
- // same thread that invoked AddAsyncEnabledStateObserver().
- class BASE_EXPORT AsyncEnabledStateObserver {
- public:
- virtual ~AsyncEnabledStateObserver() = default;
-
- // Posted just after the tracing system becomes enabled, outside |lock_|.
- // TraceLog::IsEnabled() is true at this point.
- virtual void OnTraceLogEnabled() = 0;
-
- // Posted just after the tracing system becomes disabled, outside |lock_|.
- // TraceLog::IsEnabled() is false at this point.
- virtual void OnTraceLogDisabled() = 0;
- };
- void AddAsyncEnabledStateObserver(
- WeakPtr<AsyncEnabledStateObserver> listener);
- void RemoveAsyncEnabledStateObserver(AsyncEnabledStateObserver* listener);
- bool HasAsyncEnabledStateObserver(AsyncEnabledStateObserver* listener) const;
-
- TraceLogStatus GetStatus() const;
- bool BufferIsFull() const;
-
- // Computes an estimate of the size of the TraceLog including all the retained
- // objects.
- void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
-
- void SetArgumentFilterPredicate(
- const ArgumentFilterPredicate& argument_filter_predicate);
-
- // Flush all collected events to the given output callback. The callback will
- // be called one or more times either synchronously or asynchronously from
- // the current thread with IPC-bite-size chunks. The string format is
- // undefined. Use TraceResultBuffer to convert one or more trace strings to
- // JSON. The callback can be null if the caller doesn't want any data.
- // Due to the implementation of thread-local buffers, flush can't be
- // done when tracing is enabled. If called when tracing is enabled, the
- // callback will be called directly with (empty_string, false) to indicate
- // the end of this unsuccessful flush. Flush does the serialization
- // on the same thread if the caller doesn't set use_worker_thread explicitly.
- typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&,
- bool has_more_events)> OutputCallback;
- void Flush(const OutputCallback& cb, bool use_worker_thread = false);
-
- // Cancels tracing and discards collected data.
- void CancelTracing(const OutputCallback& cb);
-
- typedef void (*AddTraceEventOverrideCallback)(const TraceEvent&);
- // The callback will be called up until the point where the flush is
- // finished, i.e. must be callable until OutputCallback is called with
- // has_more_events==false.
- void SetAddTraceEventOverride(const AddTraceEventOverrideCallback& override);
-
- // Called by TRACE_EVENT* macros, don't call this directly.
- // The name parameter is a category group for example:
- // TRACE_EVENT0("renderer,webkit", "WebViewImpl::HandleInputEvent")
- static const unsigned char* GetCategoryGroupEnabled(const char* name);
- static const char* GetCategoryGroupName(
- const unsigned char* category_group_enabled);
-
- // Called by TRACE_EVENT* macros, don't call this directly.
- // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied
- // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above.
- TraceEventHandle AddTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags);
- TraceEventHandle AddTraceEventWithBindId(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- unsigned long long bind_id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags);
- TraceEventHandle AddTraceEventWithProcessId(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- int process_id,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags);
- TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- int thread_id,
- const TimeTicks& timestamp,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags);
- TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- const char* scope,
- unsigned long long id,
- unsigned long long bind_id,
- int thread_id,
- const TimeTicks& timestamp,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags);
-
- // Adds a metadata event that will be written when the trace log is flushed.
- void AddMetadataEvent(
- const unsigned char* category_group_enabled,
- const char* name,
- int num_args,
- const char* const* arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- std::unique_ptr<ConvertableToTraceFormat>* convertable_values,
- unsigned int flags);
-
- void UpdateTraceEventDuration(const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle handle);
-
- void UpdateTraceEventDurationExplicit(
- const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle handle,
- const TimeTicks& now,
- const ThreadTicks& thread_now);
-
- void EndFilteredEvent(const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle handle);
-
- int process_id() const { return process_id_; }
-
- uint64_t MangleEventId(uint64_t id);
-
- // Exposed for unittesting:
-
- // Testing factory for TraceEventFilter.
- typedef std::unique_ptr<TraceEventFilter> (*FilterFactoryForTesting)(
- const std::string& /* predicate_name */);
- void SetFilterFactoryForTesting(FilterFactoryForTesting factory) {
- filter_factory_for_testing_ = factory;
- }
-
- // Allows clearing up our singleton instance.
- static void ResetForTesting();
-
- // Allow tests to inspect TraceEvents.
- TraceEvent* GetEventByHandle(TraceEventHandle handle);
-
- void SetProcessID(int process_id);
-
- // Process sort indices, if set, override the order of a process will appear
- // relative to other processes in the trace viewer. Processes are sorted first
- // on their sort index, ascending, then by their name, and then tid.
- void SetProcessSortIndex(int sort_index);
-
- // Sets the name of the process.
- void set_process_name(const std::string& process_name) {
- AutoLock lock(lock_);
- process_name_ = process_name;
- }
-
- bool IsProcessNameEmpty() const { return process_name_.empty(); }
-
- // Processes can have labels in addition to their names. Use labels, for
- // instance, to list out the web page titles that a process is handling.
- void UpdateProcessLabel(int label_id, const std::string& current_label);
- void RemoveProcessLabel(int label_id);
-
- // Thread sort indices, if set, override the order of a thread will appear
- // within its process in the trace viewer. Threads are sorted first on their
- // sort index, ascending, then by their name, and then tid.
- void SetThreadSortIndex(PlatformThreadId thread_id, int sort_index);
-
- // Allow setting an offset between the current TimeTicks time and the time
- // that should be reported.
- void SetTimeOffset(TimeDelta offset);
-
- size_t GetObserverCountForTest() const;
-
- // Call this method if the current thread may block the message loop to
- // prevent the thread from using the thread-local buffer because the thread
- // may not handle the flush request in time causing lost of unflushed events.
- void SetCurrentThreadBlocksMessageLoop();
-
-#if defined(OS_WIN)
- // This function is called by the ETW exporting module whenever the ETW
- // keyword (flags) changes. This keyword indicates which categories should be
- // exported, so whenever it changes, we adjust accordingly.
- void UpdateETWCategoryGroupEnabledFlags();
-#endif
-
- // Replaces |logged_events_| with a new TraceBuffer for testing.
- void SetTraceBufferForTesting(std::unique_ptr<TraceBuffer> trace_buffer);
-
- private:
- typedef unsigned int InternalTraceOptions;
-
- FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
- TraceBufferRingBufferGetReturnChunk);
- FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
- TraceBufferRingBufferHalfIteration);
- FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
- TraceBufferRingBufferFullIteration);
- FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture, TraceBufferVectorReportFull);
- FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
- ConvertTraceConfigToInternalOptions);
- FRIEND_TEST_ALL_PREFIXES(TraceEventTestFixture,
- TraceRecordAsMuchAsPossibleMode);
-
- friend class base::NoDestructor<TraceLog>;
-
- // MemoryDumpProvider implementation.
- bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) override;
-
- // Enable/disable each category group based on the current mode_,
- // category_filter_ and event_filters_enabled_.
- // Enable the category group in the recording mode if category_filter_ matches
- // the category group, is not null. Enable category for filtering if any
- // filter in event_filters_enabled_ enables it.
- void UpdateCategoryRegistry();
- void UpdateCategoryState(TraceCategory* category);
-
- void CreateFiltersForTraceConfig();
-
- InternalTraceOptions GetInternalOptionsFromTraceConfig(
- const TraceConfig& config);
-
- class ThreadLocalEventBuffer;
- class OptionalAutoLock;
- struct RegisteredAsyncObserver;
-
- TraceLog();
- ~TraceLog() override;
- void AddMetadataEventsWhileLocked();
-
- InternalTraceOptions trace_options() const {
- return static_cast<InternalTraceOptions>(
- subtle::NoBarrier_Load(&trace_options_));
- }
-
- TraceBuffer* trace_buffer() const { return logged_events_.get(); }
- TraceBuffer* CreateTraceBuffer();
-
- std::string EventToConsoleMessage(unsigned char phase,
- const TimeTicks& timestamp,
- TraceEvent* trace_event);
-
- TraceEvent* AddEventToThreadSharedChunkWhileLocked(TraceEventHandle* handle,
- bool check_buffer_is_full);
- void CheckIfBufferIsFullWhileLocked();
- void SetDisabledWhileLocked(uint8_t modes);
-
- TraceEvent* GetEventByHandleInternal(TraceEventHandle handle,
- OptionalAutoLock* lock);
-
- void FlushInternal(const OutputCallback& cb,
- bool use_worker_thread,
- bool discard_events);
-
- // |generation| is used in the following callbacks to check if the callback
- // is called for the flush of the current |logged_events_|.
- void FlushCurrentThread(int generation, bool discard_events);
- // Usually it runs on a different thread.
- static void ConvertTraceEventsToTraceFormat(
- std::unique_ptr<TraceBuffer> logged_events,
- const TraceLog::OutputCallback& flush_output_callback,
- const ArgumentFilterPredicate& argument_filter_predicate);
- void FinishFlush(int generation, bool discard_events);
- void OnFlushTimeout(int generation, bool discard_events);
-
- int generation() const {
- return static_cast<int>(subtle::NoBarrier_Load(&generation_));
- }
- bool CheckGeneration(int generation) const {
- return generation == this->generation();
- }
- void UseNextTraceBuffer();
-
- TimeTicks OffsetNow() const {
- // This should be TRACE_TIME_TICKS_NOW but include order makes that hard.
- return OffsetTimestamp(base::subtle::TimeTicksNowIgnoringOverride());
- }
- TimeTicks OffsetTimestamp(const TimeTicks& timestamp) const {
- return timestamp - time_offset_;
- }
-
- // Internal representation of trace options since we store the currently used
- // trace option as an AtomicWord.
- static const InternalTraceOptions kInternalNone;
- static const InternalTraceOptions kInternalRecordUntilFull;
- static const InternalTraceOptions kInternalRecordContinuously;
- static const InternalTraceOptions kInternalEchoToConsole;
- static const InternalTraceOptions kInternalRecordAsMuchAsPossible;
- static const InternalTraceOptions kInternalEnableArgumentFilter;
-
- // This lock protects TraceLog member accesses (except for members protected
- // by thread_info_lock_) from arbitrary threads.
- mutable Lock lock_;
- // This lock protects accesses to thread_names_, thread_event_start_times_
- // and thread_colors_.
- Lock thread_info_lock_;
- uint8_t enabled_modes_; // See TraceLog::Mode.
- int num_traces_recorded_;
- std::unique_ptr<TraceBuffer> logged_events_;
- std::vector<std::unique_ptr<TraceEvent>> metadata_events_;
- bool dispatching_to_observer_list_;
- std::vector<EnabledStateObserver*> enabled_state_observer_list_;
- std::map<AsyncEnabledStateObserver*, RegisteredAsyncObserver>
- async_observers_;
-
- std::string process_name_;
- std::unordered_map<int, std::string> process_labels_;
- int process_sort_index_;
- std::unordered_map<int, int> thread_sort_indices_;
- std::unordered_map<int, std::string> thread_names_;
- base::Time process_creation_time_;
-
- // The following two maps are used only when ECHO_TO_CONSOLE.
- std::unordered_map<int, base::stack<TimeTicks>> thread_event_start_times_;
- std::unordered_map<std::string, int> thread_colors_;
-
- TimeTicks buffer_limit_reached_timestamp_;
-
- // XORed with TraceID to make it unlikely to collide with other processes.
- unsigned long long process_id_hash_;
-
- int process_id_;
-
- TimeDelta time_offset_;
-
- subtle::AtomicWord /* Options */ trace_options_;
-
- TraceConfig trace_config_;
- TraceConfig::EventFilters enabled_event_filters_;
-
- ThreadLocalPointer<ThreadLocalEventBuffer> thread_local_event_buffer_;
- ThreadLocalBoolean thread_blocks_message_loop_;
- ThreadLocalBoolean thread_is_in_trace_event_;
-
- // Contains the message loops of threads that have had at least one event
- // added into the local event buffer. Not using SingleThreadTaskRunner
- // because we need to know the life time of the message loops.
- hash_set<MessageLoop*> thread_message_loops_;
-
- // For events which can't be added into the thread local buffer, e.g. events
- // from threads without a message loop.
- std::unique_ptr<TraceBufferChunk> thread_shared_chunk_;
- size_t thread_shared_chunk_index_;
-
- // Set when asynchronous Flush is in progress.
- OutputCallback flush_output_callback_;
- scoped_refptr<SequencedTaskRunner> flush_task_runner_;
- ArgumentFilterPredicate argument_filter_predicate_;
- subtle::AtomicWord generation_;
- bool use_worker_thread_;
- subtle::AtomicWord trace_event_override_;
-
- FilterFactoryForTesting filter_factory_for_testing_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceLog);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACE_LOG_H_
diff --git a/base/trace_event/trace_log_constants.cc b/base/trace_event/trace_log_constants.cc
deleted file mode 100644
index 65dca2e4d6..0000000000
--- a/base/trace_event/trace_log_constants.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2013 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/trace_event/trace_log.h"
-
-namespace base {
-namespace trace_event {
-
-// Constant used by TraceLog's internal implementation of trace_option.
-const TraceLog::InternalTraceOptions
- TraceLog::kInternalNone = 0;
-const TraceLog::InternalTraceOptions
- TraceLog::kInternalRecordUntilFull = 1 << 0;
-const TraceLog::InternalTraceOptions
- TraceLog::kInternalRecordContinuously = 1 << 1;
-// 1 << 2 is reserved for the DEPRECATED kInternalEnableSampling. DO NOT USE.
-const TraceLog::InternalTraceOptions
- TraceLog::kInternalEchoToConsole = 1 << 3;
-const TraceLog::InternalTraceOptions
- TraceLog::kInternalRecordAsMuchAsPossible = 1 << 4;
-const TraceLog::InternalTraceOptions
- TraceLog::kInternalEnableArgumentFilter = 1 << 5;
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/tracing_agent.cc b/base/trace_event/tracing_agent.cc
deleted file mode 100644
index e48feff6fc..0000000000
--- a/base/trace_event/tracing_agent.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2015 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/trace_event/tracing_agent.h"
-
-namespace base {
-namespace trace_event {
-
-TracingAgent::~TracingAgent() = default;
-
-bool TracingAgent::SupportsExplicitClockSync() {
- return false;
-}
-
-void TracingAgent::RecordClockSyncMarker(
- const std::string& sync_id,
- RecordClockSyncMarkerCallback callback) {
- DCHECK(SupportsExplicitClockSync());
-}
-
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/tracing_agent.h b/base/trace_event/tracing_agent.h
deleted file mode 100644
index f818457c58..0000000000
--- a/base/trace_event/tracing_agent.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef BASE_TRACE_EVENT_TRACING_AGENT_H_
-#define BASE_TRACE_EVENT_TRACING_AGENT_H_
-
-#include "base/base_export.h"
-#include "base/callback.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/values.h"
-
-namespace base {
-
-class TimeTicks;
-
-namespace trace_event {
-
-class TraceConfig;
-
-// A tracing agent is an entity that records its own sort of trace. Each
-// tracing method that produces its own trace log should implement this
-// interface. All tracing agents must only be controlled by TracingController.
-// Some existing examples include TracingControllerImpl for Chrome trace events,
-// DebugDaemonClient for CrOs system trace, EtwTracingAgent for Windows system
-// trace and PowerTracingAgent for BattOr power trace.
-class BASE_EXPORT TracingAgent {
- public:
- using StartAgentTracingCallback =
- base::OnceCallback<void(const std::string& agent_name, bool success)>;
- // Passing a null or empty events_str_ptr indicates that no trace data is
- // available for the specified agent.
- using StopAgentTracingCallback = base::OnceCallback<void(
- const std::string& agent_name,
- const std::string& events_label,
- const scoped_refptr<base::RefCountedString>& events_str_ptr)>;
- using RecordClockSyncMarkerCallback =
- base::OnceCallback<void(const std::string& sync_id,
- const TimeTicks& issue_ts,
- const TimeTicks& issue_end_ts)>;
-
- virtual ~TracingAgent();
-
- // Gets the name of the tracing agent. Each tracing agent's name should be
- // unique.
- virtual std::string GetTracingAgentName() = 0;
-
- // Gets the trace event label of this tracing agent. The label will be used to
- // label this agent's trace when all traces from different tracing agents are
- // combined. Multiple tracing agents could have the same label. The tracing
- // agents using the same label should not be able to run at the same time. For
- // example, ETW on Windows and CrOS system tracing both use
- // "systemTraceEvents" as the label. Those two agents never run at the same
- // time because they are for different platforms.
- virtual std::string GetTraceEventLabel() = 0;
-
- // Starts tracing on the tracing agent with the trace configuration.
- virtual void StartAgentTracing(const TraceConfig& trace_config,
- StartAgentTracingCallback callback) = 0;
-
- // Stops tracing on the tracing agent. The trace data will be passed back to
- // the TracingController via the callback.
- virtual void StopAgentTracing(StopAgentTracingCallback callback) = 0;
-
- // Checks if the tracing agent supports explicit clock synchronization.
- virtual bool SupportsExplicitClockSync();
-
- // Records a clock sync marker issued by another tracing agent. This is only
- // used if the tracing agent supports explicit clock synchronization.
- //
- // Two things need to be done:
- // 1. The issuer asks the receiver to record the clock sync marker.
- // 2. The issuer records how long the receiver takes to do the recording.
- //
- // In Chrome, the receiver thread also runs in Chrome and it will talk to the
- // real receiver entity, e.g., power monitor or Android device system, via
- // different communication methods, e.g., through USB or file reading/writing.
- // The 2nd task measures that communication latency.
- //
- // Having a reliable timing measurement for the 2nd task requires synchronous
- // function call without any cross-thread or cross-process activity. However,
- // tracing agents in Chrome run in their own threads. Therefore, the issuer
- // needs to dedicate the 2nd task to the receiver to take time measurements
- // in the receiver thread, and the receiver thread needs to pass them back to
- // the issuer in the callback.
- //
- // The assumption is that the receiver thread knows the issuer's clock, which
- // is true in Chrome because all agent threads' clocks are Chrome clock.
- virtual void RecordClockSyncMarker(const std::string& sync_id,
- RecordClockSyncMarkerCallback callback);
-};
-
-} // namespace trace_event
-} // namespace base
-
-#endif // BASE_TRACE_EVENT_TRACING_AGENT_H_
diff --git a/base/unguessable_token_unittest.cc b/base/unguessable_token_unittest.cc
deleted file mode 100644
index b70cc72444..0000000000
--- a/base/unguessable_token_unittest.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2016 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/unguessable_token.h"
-
-#include <memory>
-#include <sstream>
-#include <type_traits>
-
-#include "base/value_conversions.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-void TestSmallerThanOperator(const UnguessableToken& a,
- const UnguessableToken& b) {
- EXPECT_TRUE(a < b);
- EXPECT_FALSE(b < a);
-}
-
-TEST(UnguessableTokenTest, VerifyEqualityOperators) {
- // Deserialize is used for testing purposes.
- // Use UnguessableToken::Create() in production code instead.
- UnguessableToken token = UnguessableToken::Deserialize(1, 2);
- UnguessableToken same_token = UnguessableToken::Deserialize(1, 2);
- UnguessableToken diff_token = UnguessableToken::Deserialize(1, 3);
-
- EXPECT_TRUE(token == token);
- EXPECT_FALSE(token != token);
-
- EXPECT_TRUE(token == same_token);
- EXPECT_FALSE(token != same_token);
-
- EXPECT_FALSE(token == diff_token);
- EXPECT_FALSE(diff_token == token);
- EXPECT_TRUE(token != diff_token);
- EXPECT_TRUE(diff_token != token);
-}
-
-TEST(UnguessableTokenTest, VerifyConstructors) {
- UnguessableToken token = UnguessableToken::Create();
- EXPECT_FALSE(token.is_empty());
- EXPECT_TRUE(token);
-
- UnguessableToken copied_token(token);
- EXPECT_TRUE(copied_token);
- EXPECT_EQ(token, copied_token);
-
- UnguessableToken uninitialized;
- EXPECT_TRUE(uninitialized.is_empty());
- EXPECT_FALSE(uninitialized);
-
- EXPECT_TRUE(UnguessableToken().is_empty());
- EXPECT_FALSE(UnguessableToken());
-}
-
-TEST(UnguessableTokenTest, VerifySerialization) {
- UnguessableToken token = UnguessableToken::Create();
-
- uint64_t high = token.GetHighForSerialization();
- uint64_t low = token.GetLowForSerialization();
-
- EXPECT_TRUE(high);
- EXPECT_TRUE(low);
-
- UnguessableToken Deserialized = UnguessableToken::Deserialize(high, low);
- EXPECT_EQ(token, Deserialized);
-}
-
-TEST(UnguessableTokenTest, VerifyValueSerialization) {
- UnguessableToken token = UnguessableToken::Create();
- std::unique_ptr<Value> value = CreateUnguessableTokenValue(token);
-
- UnguessableToken deserialized;
- EXPECT_TRUE(GetValueAsUnguessableToken(*value, &deserialized));
- EXPECT_EQ(token, deserialized);
-}
-
-// Common case (~88% of the time) - no leading zeroes in high_ nor low_.
-TEST(UnguessableTokenTest, VerifyToString1) {
- UnguessableToken token =
- UnguessableToken::Deserialize(0x1234567890ABCDEF, 0xFEDCBA0987654321);
- std::string expected = "1234567890ABCDEFFEDCBA0987654321";
-
- EXPECT_EQ(expected, token.ToString());
-
- std::string expected_stream = "(1234567890ABCDEFFEDCBA0987654321)";
- std::stringstream stream;
- stream << token;
- EXPECT_EQ(expected_stream, stream.str());
-}
-
-// Less common case - leading zeroes in high_ or low_ (testing with both).
-TEST(UnguessableTokenTest, VerifyToString2) {
- UnguessableToken token = UnguessableToken::Deserialize(0x123, 0xABC);
- std::string expected = "00000000000001230000000000000ABC";
-
- EXPECT_EQ(expected, token.ToString());
-
- std::string expected_stream = "(00000000000001230000000000000ABC)";
- std::stringstream stream;
- stream << token;
- EXPECT_EQ(expected_stream, stream.str());
-}
-
-TEST(UnguessableTokenTest, VerifyToStringUniqueness) {
- const UnguessableToken token1 =
- UnguessableToken::Deserialize(0x0000000012345678, 0x0000000123456789);
- const UnguessableToken token2 =
- UnguessableToken::Deserialize(0x0000000123456781, 0x0000000023456789);
- EXPECT_NE(token1.ToString(), token2.ToString());
-}
-
-TEST(UnguessableTokenTest, VerifySmallerThanOperator) {
- // Deserialize is used for testing purposes.
- // Use UnguessableToken::Create() in production code instead.
- {
- SCOPED_TRACE("a.low < b.low and a.high == b.high.");
- TestSmallerThanOperator(UnguessableToken::Deserialize(0, 1),
- UnguessableToken::Deserialize(0, 5));
- }
- {
- SCOPED_TRACE("a.low == b.low and a.high < b.high.");
- TestSmallerThanOperator(UnguessableToken::Deserialize(1, 0),
- UnguessableToken::Deserialize(5, 0));
- }
- {
- SCOPED_TRACE("a.low < b.low and a.high < b.high.");
- TestSmallerThanOperator(UnguessableToken::Deserialize(1, 1),
- UnguessableToken::Deserialize(5, 5));
- }
- {
- SCOPED_TRACE("a.low > b.low and a.high < b.high.");
- TestSmallerThanOperator(UnguessableToken::Deserialize(1, 10),
- UnguessableToken::Deserialize(10, 1));
- }
-}
-
-TEST(UnguessableTokenTest, VerifyHash) {
- UnguessableToken token = UnguessableToken::Create();
-
- EXPECT_EQ(base::HashInts64(token.GetHighForSerialization(),
- token.GetLowForSerialization()),
- UnguessableTokenHash()(token));
-}
-
-TEST(UnguessableTokenTest, VerifyBasicUniqueness) {
- EXPECT_NE(UnguessableToken::Create(), UnguessableToken::Create());
-
- UnguessableToken token = UnguessableToken::Create();
- EXPECT_NE(token.GetHighForSerialization(), token.GetLowForSerialization());
-}
-}
diff --git a/base/value_conversions.cc b/base/value_conversions.cc
deleted file mode 100644
index 7e3fd94551..0000000000
--- a/base/value_conversions.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 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.
-
-#include "base/value_conversions.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/time/time.h"
-#include "base/unguessable_token.h"
-#include "base/values.h"
-
-namespace base {
-namespace {
-// Helper for serialize/deserialize UnguessableToken.
-union UnguessableTokenRepresentation {
- struct Field {
- uint64_t high;
- uint64_t low;
- } field;
-
- uint8_t buffer[sizeof(Field)];
-};
-} // namespace
-
-// |Value| internally stores strings in UTF-8, so we have to convert from the
-// system native code to UTF-8 and back.
-std::unique_ptr<Value> CreateFilePathValue(const FilePath& in_value) {
- return std::make_unique<Value>(in_value.AsUTF8Unsafe());
-}
-
-bool GetValueAsFilePath(const Value& value, FilePath* file_path) {
- std::string str;
- if (!value.GetAsString(&str))
- return false;
- if (file_path)
- *file_path = FilePath::FromUTF8Unsafe(str);
- return true;
-}
-
-// |Value| does not support 64-bit integers, and doubles do not have enough
-// precision, so we store the 64-bit time value as a string instead.
-std::unique_ptr<Value> CreateTimeDeltaValue(const TimeDelta& time) {
- std::string string_value = base::Int64ToString(time.ToInternalValue());
- return std::make_unique<Value>(string_value);
-}
-
-bool GetValueAsTimeDelta(const Value& value, TimeDelta* time) {
- std::string str;
- int64_t int_value;
- if (!value.GetAsString(&str) || !base::StringToInt64(str, &int_value))
- return false;
- if (time)
- *time = TimeDelta::FromInternalValue(int_value);
- return true;
-}
-
-std::unique_ptr<Value> CreateUnguessableTokenValue(
- const UnguessableToken& token) {
- UnguessableTokenRepresentation representation;
- representation.field.high = token.GetHighForSerialization();
- representation.field.low = token.GetLowForSerialization();
-
- return std::make_unique<Value>(
- HexEncode(representation.buffer, sizeof(representation.buffer)));
-}
-
-bool GetValueAsUnguessableToken(const Value& value, UnguessableToken* token) {
- if (!value.is_string()) {
- return false;
- }
-
- // TODO(dcheng|yucliu): Make a function that accepts non vector variant and
- // reads a fixed number of bytes.
- std::vector<uint8_t> high_low_bytes;
- if (!HexStringToBytes(value.GetString(), &high_low_bytes)) {
- return false;
- }
-
- UnguessableTokenRepresentation representation;
- if (high_low_bytes.size() != sizeof(representation.buffer)) {
- return false;
- }
-
- std::copy(high_low_bytes.begin(), high_low_bytes.end(),
- std::begin(representation.buffer));
- *token = UnguessableToken::Deserialize(representation.field.high,
- representation.field.low);
- return true;
-}
-
-} // namespace base
diff --git a/base/value_conversions.h b/base/value_conversions.h
deleted file mode 100644
index bd095cdc4c..0000000000
--- a/base/value_conversions.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef BASE_VALUE_CONVERSIONS_H_
-#define BASE_VALUE_CONVERSIONS_H_
-
-// This file contains methods to convert things to a |Value| and back.
-
-#include <memory>
-#include "base/base_export.h"
-
-namespace base {
-
-class FilePath;
-class TimeDelta;
-class UnguessableToken;
-class Value;
-
-// The caller takes ownership of the returned value.
-BASE_EXPORT std::unique_ptr<Value> CreateFilePathValue(
- const FilePath& in_value);
-BASE_EXPORT bool GetValueAsFilePath(const Value& value, FilePath* file_path);
-
-BASE_EXPORT std::unique_ptr<Value> CreateTimeDeltaValue(const TimeDelta& time);
-BASE_EXPORT bool GetValueAsTimeDelta(const Value& value, TimeDelta* time);
-
-BASE_EXPORT std::unique_ptr<Value> CreateUnguessableTokenValue(
- const UnguessableToken& token);
-BASE_EXPORT bool GetValueAsUnguessableToken(const Value& value,
- UnguessableToken* token);
-
-} // namespace base
-
-#endif // BASE_VALUE_CONVERSIONS_H_
diff --git a/build/android/gyp/util/build_utils_test.py b/build/android/gyp/util/build_utils_test.py
deleted file mode 100755
index bcc892f39b..0000000000
--- a/build/android/gyp/util/build_utils_test.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2018 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.
-
-import collections
-import unittest
-
-import build_utils # pylint: disable=W0403
-
-_DEPS = collections.OrderedDict()
-_DEPS['a'] = []
-_DEPS['b'] = []
-_DEPS['c'] = ['a']
-_DEPS['d'] = ['a']
-_DEPS['e'] = ['f']
-_DEPS['f'] = ['a', 'd']
-_DEPS['g'] = []
-_DEPS['h'] = ['d', 'b', 'f']
-_DEPS['i'] = ['f']
-
-
-class BuildUtilsTest(unittest.TestCase):
- def testGetSortedTransitiveDependencies_all(self):
- TOP = _DEPS.keys()
- EXPECTED = ['a', 'b', 'c', 'd', 'f', 'e', 'g', 'h', 'i']
- actual = build_utils.GetSortedTransitiveDependencies(TOP, _DEPS.get)
- self.assertEqual(EXPECTED, actual)
-
- def testGetSortedTransitiveDependencies_leaves(self):
- TOP = ['c', 'e', 'g', 'h', 'i']
- EXPECTED = ['a', 'c', 'd', 'f', 'e', 'g', 'b', 'h', 'i']
- actual = build_utils.GetSortedTransitiveDependencies(TOP, _DEPS.get)
- self.assertEqual(EXPECTED, actual)
-
- def testGetSortedTransitiveDependencies_leavesReverse(self):
- TOP = ['i', 'h', 'g', 'e', 'c']
- EXPECTED = ['a', 'd', 'f', 'i', 'b', 'h', 'g', 'e', 'c']
- actual = build_utils.GetSortedTransitiveDependencies(TOP, _DEPS.get)
- self.assertEqual(EXPECTED, actual)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/build/android/gyp/util/jar_info_utils.py b/build/android/gyp/util/jar_info_utils.py
deleted file mode 100644
index 987ee9dcf1..0000000000
--- a/build/android/gyp/util/jar_info_utils.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2018 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.
-
-import os
-
-# Utilities to read and write .jar.info files.
-#
-# A .jar.info file contains a simple mapping from fully-qualified Java class
-# names to the source file that actually defines it.
-#
-# For APKs, the .jar.info maps the class names to the .jar file that which
-# contains its .class definition instead.
-
-
-def ParseJarInfoFile(info_path):
- """Parse a given .jar.info file as a dictionary.
-
- Args:
- info_path: input .jar.info file path.
- Returns:
- A new dictionary mapping fully-qualified Java class names to file paths.
- """
- info_data = dict()
- if os.path.exists(info_path):
- with open(info_path, 'r') as info_file:
- for line in info_file:
- line = line.strip()
- if line:
- fully_qualified_name, path = line.split(',', 1)
- info_data[fully_qualified_name] = path
- return info_data
-
-
-def WriteJarInfoFile(info_path, info_data, source_file_map=None):
- """Generate a .jar.info file from a given dictionary.
-
- Args:
- info_path: output file path.
- info_data: a mapping of fully qualified Java class names to filepaths.
- source_file_map: an optional mapping from java source file paths to the
- corresponding source .srcjar. This is because info_data may contain the
- path of Java source files that where extracted from an .srcjar into a
- temporary location.
- """
- with open(info_path, 'w') as info_file:
- for fully_qualified_name, path in info_data.iteritems():
- if source_file_map and path in source_file_map:
- path = source_file_map[path]
- assert not path.startswith('/tmp'), (
- 'Java file path should not be in temp dir: {}'.format(path))
- info_file.write('{},{}\n'.format(fully_qualified_name, path))
diff --git a/build/android/gyp/util/md5_check_test.py b/build/android/gyp/util/md5_check_test.py
deleted file mode 100755
index 312d4a98cb..0000000000
--- a/build/android/gyp/util/md5_check_test.py
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2013 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.
-
-import fnmatch
-import tempfile
-import unittest
-import zipfile
-
-import md5_check # pylint: disable=W0403
-
-
-def _WriteZipFile(path, entries):
- with zipfile.ZipFile(path, 'w') as zip_file:
- for subpath, data in entries:
- zip_file.writestr(subpath, data)
-
-
-class TestMd5Check(unittest.TestCase):
- def setUp(self):
- self.called = False
- self.changes = None
-
- def testCallAndRecordIfStale(self):
- input_strings = ['string1', 'string2']
- input_file1 = tempfile.NamedTemporaryFile(suffix='.txt')
- input_file2 = tempfile.NamedTemporaryFile(suffix='.zip')
- file1_contents = 'input file 1'
- input_file1.write(file1_contents)
- input_file1.flush()
- # Test out empty zip file to start.
- _WriteZipFile(input_file2.name, [])
- input_files = [input_file1.name, input_file2.name]
-
- record_path = tempfile.NamedTemporaryFile(suffix='.stamp')
-
- def CheckCallAndRecord(should_call, message, force=False,
- outputs_specified=False, outputs_missing=False,
- expected_changes=None, added_or_modified_only=None):
- output_paths = None
- if outputs_specified:
- output_file1 = tempfile.NamedTemporaryFile()
- if outputs_missing:
- output_file1.close() # Gets deleted on close().
- output_paths = [output_file1.name]
-
- self.called = False
- self.changes = None
- if expected_changes or added_or_modified_only is not None:
- def MarkCalled(changes):
- self.called = True
- self.changes = changes
- else:
- def MarkCalled():
- self.called = True
-
- md5_check.CallAndRecordIfStale(
- MarkCalled,
- record_path=record_path.name,
- input_paths=input_files,
- input_strings=input_strings,
- output_paths=output_paths,
- force=force,
- pass_changes=(expected_changes or added_or_modified_only) is not None)
- self.assertEqual(should_call, self.called, message)
- if expected_changes:
- description = self.changes.DescribeDifference()
- self.assertTrue(fnmatch.fnmatch(description, expected_changes),
- 'Expected %s to match %s' % (
- repr(description), repr(expected_changes)))
- if should_call and added_or_modified_only is not None:
- self.assertEqual(added_or_modified_only,
- self.changes.AddedOrModifiedOnly())
-
- CheckCallAndRecord(True, 'should call when record doesn\'t exist',
- expected_changes='Previous stamp file not found.',
- added_or_modified_only=False)
- CheckCallAndRecord(False, 'should not call when nothing changed')
- CheckCallAndRecord(False, 'should not call when nothing changed #2',
- outputs_specified=True, outputs_missing=False)
- CheckCallAndRecord(True, 'should call when output missing',
- outputs_specified=True, outputs_missing=True,
- expected_changes='Outputs do not exist:*',
- added_or_modified_only=False)
- CheckCallAndRecord(True, force=True, message='should call when forced',
- expected_changes='force=True',
- added_or_modified_only=False)
-
- input_file1.write('some more input')
- input_file1.flush()
- CheckCallAndRecord(True, 'changed input file should trigger call',
- expected_changes='*Modified: %s' % input_file1.name,
- added_or_modified_only=True)
-
- input_files = input_files[::-1]
- CheckCallAndRecord(False, 'reordering of inputs shouldn\'t trigger call')
-
- input_files = input_files[:1]
- CheckCallAndRecord(True, 'removing file should trigger call',
- expected_changes='*Removed: %s' % input_file1.name,
- added_or_modified_only=False)
-
- input_files.append(input_file1.name)
- CheckCallAndRecord(True, 'added input file should trigger call',
- expected_changes='*Added: %s' % input_file1.name,
- added_or_modified_only=True)
-
- input_strings[0] = input_strings[0] + ' a bit longer'
- CheckCallAndRecord(True, 'changed input string should trigger call',
- expected_changes='*Input strings changed*',
- added_or_modified_only=False)
-
- input_strings = input_strings[::-1]
- CheckCallAndRecord(True, 'reordering of string inputs should trigger call',
- expected_changes='*Input strings changed*')
-
- input_strings = input_strings[:1]
- CheckCallAndRecord(True, 'removing a string should trigger call')
-
- input_strings.append('a brand new string')
- CheckCallAndRecord(True, 'added input string should trigger call')
-
- _WriteZipFile(input_file2.name, [('path/1.txt', '1')])
- CheckCallAndRecord(True, 'added subpath should trigger call',
- expected_changes='*Modified: %s*Subpath added: %s' % (
- input_file2.name, 'path/1.txt'),
- added_or_modified_only=True)
- _WriteZipFile(input_file2.name, [('path/1.txt', '2')])
- CheckCallAndRecord(True, 'changed subpath should trigger call',
- expected_changes='*Modified: %s*Subpath modified: %s' % (
- input_file2.name, 'path/1.txt'),
- added_or_modified_only=True)
- CheckCallAndRecord(False, 'should not call when nothing changed')
-
- _WriteZipFile(input_file2.name, [])
- CheckCallAndRecord(True, 'removed subpath should trigger call',
- expected_changes='*Modified: %s*Subpath removed: %s' % (
- input_file2.name, 'path/1.txt'),
- added_or_modified_only=False)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/build/android/gyp/util/proguard_util.py b/build/android/gyp/util/proguard_util.py
deleted file mode 100644
index fd657e2aa7..0000000000
--- a/build/android/gyp/util/proguard_util.py
+++ /dev/null
@@ -1,212 +0,0 @@
-# Copyright 2015 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.
-
-import os
-import re
-from util import build_utils
-
-
-class ProguardOutputFilter(object):
- """ProGuard outputs boring stuff to stdout (proguard version, jar path, etc)
- as well as interesting stuff (notes, warnings, etc). If stdout is entirely
- boring, this class suppresses the output.
- """
-
- IGNORE_RE = re.compile(
- r'Pro.*version|Note:|Reading|Preparing|Printing|ProgramClass:|Searching|'
- r'jar \[|\d+ class path entries checked')
-
- def __init__(self):
- self._last_line_ignored = False
- self._ignore_next_line = False
-
- def __call__(self, output):
- ret = []
- for line in output.splitlines(True):
- if self._ignore_next_line:
- self._ignore_next_line = False
- continue
-
- if '***BINARY RUN STATS***' in line:
- self._last_line_ignored = True
- self._ignore_next_line = True
- elif not line.startswith(' '):
- self._last_line_ignored = bool(self.IGNORE_RE.match(line))
- elif 'You should check if you need to specify' in line:
- self._last_line_ignored = True
-
- if not self._last_line_ignored:
- ret.append(line)
- return ''.join(ret)
-
-
-class ProguardCmdBuilder(object):
- def __init__(self, proguard_jar):
- assert os.path.exists(proguard_jar)
- self._proguard_jar_path = proguard_jar
- self._mapping = None
- self._libraries = None
- self._injars = None
- self._configs = None
- self._config_exclusions = None
- self._outjar = None
- self._verbose = False
- self._disabled_optimizations = []
-
- def outjar(self, path):
- assert self._outjar is None
- self._outjar = path
-
- def mapping(self, path):
- assert self._mapping is None
- assert os.path.exists(path), path
- self._mapping = path
-
- def libraryjars(self, paths):
- assert self._libraries is None
- for p in paths:
- assert os.path.exists(p), p
- self._libraries = paths
-
- def injars(self, paths):
- assert self._injars is None
- for p in paths:
- assert os.path.exists(p), p
- self._injars = paths
-
- def configs(self, paths):
- assert self._configs is None
- self._configs = paths
- for p in self._configs:
- assert os.path.exists(p), p
-
- def config_exclusions(self, paths):
- assert self._config_exclusions is None
- self._config_exclusions = paths
-
- def verbose(self, verbose):
- self._verbose = verbose
-
- def disable_optimizations(self, optimizations):
- self._disabled_optimizations += optimizations
-
- def build(self):
- assert self._injars is not None
- assert self._outjar is not None
- assert self._configs is not None
- cmd = [
- 'java', '-jar', self._proguard_jar_path,
- '-forceprocessing',
- ]
-
- if self._mapping:
- cmd += ['-applymapping', self._mapping]
-
- if self._libraries:
- cmd += ['-libraryjars', ':'.join(self._libraries)]
-
- for optimization in self._disabled_optimizations:
- cmd += [ '-optimizations', '!' + optimization ]
-
- # Filter to just .class files to avoid warnings about multiple inputs having
- # the same files in META_INF/.
- cmd += [
- '-injars',
- ':'.join('{}(**.class)'.format(x) for x in self._injars)
- ]
-
- for config_file in self.GetConfigs():
- cmd += ['-include', config_file]
-
- # The output jar must be specified after inputs.
- cmd += [
- '-outjars', self._outjar,
- '-printseeds', self._outjar + '.seeds',
- '-printusage', self._outjar + '.usage',
- '-printmapping', self._outjar + '.mapping',
- ]
-
- if self._verbose:
- cmd.append('-verbose')
-
- return cmd
-
- def GetDepfileDeps(self):
- # The list of inputs that the GN target does not directly know about.
- inputs = self._configs + self._injars
- if self._libraries:
- inputs += self._libraries
- return inputs
-
- def GetConfigs(self):
- ret = list(self._configs)
- for path in self._config_exclusions:
- ret.remove(path)
- return ret
-
- def GetInputs(self):
- inputs = self.GetDepfileDeps()
- inputs += [self._proguard_jar_path]
- if self._mapping:
- inputs.append(self._mapping)
- return inputs
-
- def GetOutputs(self):
- return [
- self._outjar,
- self._outjar + '.flags',
- self._outjar + '.mapping',
- self._outjar + '.seeds',
- self._outjar + '.usage',
- ]
-
- def _WriteFlagsFile(self, cmd, out):
- # Quite useful for auditing proguard flags.
- for config in sorted(self._configs):
- out.write('#' * 80 + '\n')
- out.write(config + '\n')
- out.write('#' * 80 + '\n')
- with open(config) as config_file:
- contents = config_file.read().rstrip()
- # Remove numbers from generated rule comments to make file more
- # diff'able.
- contents = re.sub(r' #generated:\d+', '', contents)
- out.write(contents)
- out.write('\n\n')
- out.write('#' * 80 + '\n')
- out.write('Command-line\n')
- out.write('#' * 80 + '\n')
- out.write(' '.join(cmd) + '\n')
-
- def CheckOutput(self):
- cmd = self.build()
-
- # There are a couple scenarios (.mapping files and switching from no
- # proguard -> proguard) where GN's copy() target is used on output
- # paths. These create hardlinks, so we explicitly unlink here to avoid
- # updating files with multiple links.
- for path in self.GetOutputs():
- if os.path.exists(path):
- os.unlink(path)
-
- with open(self._outjar + '.flags', 'w') as out:
- self._WriteFlagsFile(cmd, out)
-
- # Warning: and Error: are sent to stderr, but messages and Note: are sent
- # to stdout.
- stdout_filter = None
- stderr_filter = None
- if not self._verbose:
- stdout_filter = ProguardOutputFilter()
- stderr_filter = ProguardOutputFilter()
- build_utils.CheckOutput(cmd, print_stdout=True,
- print_stderr=True,
- stdout_filter=stdout_filter,
- stderr_filter=stderr_filter)
-
- # Proguard will skip writing -printseeds / -printusage / -printmapping if
- # the files would be empty, but ninja needs all outputs to exist.
- open(self._outjar + '.seeds', 'a').close()
- open(self._outjar + '.usage', 'a').close()
- open(self._outjar + '.mapping', 'a').close()
diff --git a/build/android/gyp/util/resource_utils.py b/build/android/gyp/util/resource_utils.py
deleted file mode 100644
index 875fd12631..0000000000
--- a/build/android/gyp/util/resource_utils.py
+++ /dev/null
@@ -1,511 +0,0 @@
-# Copyright 2018 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.
-
-import argparse
-import collections
-import contextlib
-import os
-import re
-import shutil
-import sys
-import tempfile
-from xml.etree import ElementTree
-
-import util.build_utils as build_utils
-
-_SOURCE_ROOT = os.path.abspath(
- os.path.join(os.path.dirname(__file__), '..', '..', '..', '..'))
-# Import jinja2 from third_party/jinja2
-sys.path.insert(1, os.path.join(_SOURCE_ROOT, 'third_party'))
-from jinja2 import Template # pylint: disable=F0401
-
-
-EMPTY_ANDROID_MANIFEST_PATH = os.path.join(
- _SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml')
-
-
-# A variation of this lists also exists in:
-# //base/android/java/src/org/chromium/base/LocaleUtils.java
-# //ui/android/java/src/org/chromium/base/LocalizationUtils.java
-CHROME_TO_ANDROID_LOCALE_MAP = {
- 'en-GB': 'en-rGB',
- 'en-US': 'en-rUS',
- 'es-419': 'es-rUS',
- 'fil': 'tl',
- 'he': 'iw',
- 'id': 'in',
- 'pt-PT': 'pt-rPT',
- 'pt-BR': 'pt-rBR',
- 'yi': 'ji',
- 'zh-CN': 'zh-rCN',
- 'zh-TW': 'zh-rTW',
-}
-
-# Represents a line from a R.txt file.
-_TextSymbolEntry = collections.namedtuple('RTextEntry',
- ('java_type', 'resource_type', 'name', 'value'))
-
-
-def CreateResourceInfoFile(files_to_zip, zip_path):
- """Given a mapping of archive paths to their source, write an info file.
-
- The info file contains lines of '{archive_path},{source_path}' for ease of
- parsing. Assumes that there is no comma in the file names.
-
- Args:
- files_to_zip: Dict mapping path in the zip archive to original source.
- zip_path: Path where the zip file ends up, this is where the info file goes.
- """
- info_file_path = zip_path + '.info'
- with open(info_file_path, 'w') as info_file:
- for archive_path, source_path in files_to_zip.iteritems():
- info_file.write('{},{}\n'.format(archive_path, source_path))
-
-
-def _ParseTextSymbolsFile(path, fix_package_ids=False):
- """Given an R.txt file, returns a list of _TextSymbolEntry.
-
- Args:
- path: Input file path.
- fix_package_ids: if True, all packaged IDs read from the file
- will be fixed to 0x7f.
- Returns:
- A list of _TextSymbolEntry instances.
- Raises:
- Exception: An unexpected line was detected in the input.
- """
- ret = []
- with open(path) as f:
- for line in f:
- m = re.match(r'(int(?:\[\])?) (\w+) (\w+) (.+)$', line)
- if not m:
- raise Exception('Unexpected line in R.txt: %s' % line)
- java_type, resource_type, name, value = m.groups()
- if fix_package_ids:
- value = _FixPackageIds(value)
- ret.append(_TextSymbolEntry(java_type, resource_type, name, value))
- return ret
-
-
-def _FixPackageIds(resource_value):
- # Resource IDs for resources belonging to regular APKs have their first byte
- # as 0x7f (package id). However with webview, since it is not a regular apk
- # but used as a shared library, aapt is passed the --shared-resources flag
- # which changes some of the package ids to 0x02 and 0x00. This function just
- # normalises all package ids to 0x7f, which the generated code in R.java
- # changes to the correct package id at runtime.
- # resource_value is a string with either, a single value '0x12345678', or an
- # array of values like '{ 0xfedcba98, 0x01234567, 0x56789abc }'
- return re.sub(r'0x(?!01)\d\d', r'0x7f', resource_value)
-
-
-def _GetRTxtResourceNames(r_txt_path):
- """Parse an R.txt file and extract the set of resource names from it."""
- result = set()
- for entry in _ParseTextSymbolsFile(r_txt_path):
- result.add(entry.name)
- return result
-
-
-class RJavaBuildOptions:
- """A class used to model the various ways to build an R.java file.
-
- This is used to control which resource ID variables will be final or
- non-final, and whether an onResourcesLoaded() method will be generated
- to adjust the non-final ones, when the corresponding library is loaded
- at runtime.
-
- Note that by default, all resources are final, and there is no
- method generated, which corresponds to calling ExportNoResources().
- """
- def __init__(self):
- self.has_constant_ids = True
- self.resources_whitelist = None
- self.has_on_resources_loaded = False
- self.export_const_styleable = False
-
- def ExportNoResources(self):
- """Make all resource IDs final, and don't generate a method."""
- self.has_constant_ids = True
- self.resources_whitelist = None
- self.has_on_resources_loaded = False
- self.export_const_styleable = False
-
- def ExportAllResources(self):
- """Make all resource IDs non-final in the R.java file."""
- self.has_constant_ids = False
- self.resources_whitelist = None
-
- def ExportSomeResources(self, r_txt_file_path):
- """Only select specific resource IDs to be non-final.
-
- Args:
- r_txt_file_path: The path to an R.txt file. All resources named
- int it will be non-final in the generated R.java file, all others
- will be final.
- """
- self.has_constant_ids = True
- self.resources_whitelist = _GetRTxtResourceNames(r_txt_file_path)
-
- def ExportAllStyleables(self):
- """Make all styleable constants non-final, even non-resources ones.
-
- Resources that are styleable but not of int[] type are not actually
- resource IDs but constants. By default they are always final. Call this
- method to make them non-final anyway in the final R.java file.
- """
- self.export_const_styleable = True
-
- def GenerateOnResourcesLoaded(self):
- """Generate an onResourcesLoaded() method.
-
- This Java method will be called at runtime by the framework when
- the corresponding library (which includes the R.java source file)
- will be loaded at runtime. This corresponds to the --shared-resources
- or --app-as-shared-lib flags of 'aapt package'.
- """
- self.has_on_resources_loaded = True
-
- def _IsResourceFinal(self, entry):
- """Determines whether a resource should be final or not.
-
- Args:
- entry: A _TextSymbolEntry instance.
- Returns:
- True iff the corresponding entry should be final.
- """
- if entry.resource_type == 'styleable' and entry.java_type != 'int[]':
- # A styleable constant may be exported as non-final after all.
- return not self.export_const_styleable
- elif not self.has_constant_ids:
- # Every resource is non-final
- return False
- elif not self.resources_whitelist:
- # No whitelist means all IDs are non-final.
- return True
- else:
- # Otherwise, only those in the
- return entry.name not in self.resources_whitelist
-
-
-def CreateRJavaFiles(srcjar_dir, package, main_r_txt_file,
- extra_res_packages, extra_r_txt_files,
- rjava_build_options):
- """Create all R.java files for a set of packages and R.txt files.
-
- Args:
- srcjar_dir: The top-level output directory for the generated files.
- package: Top-level package name.
- main_r_txt_file: The main R.txt file containing the valid values
- of _all_ resource IDs.
- extra_res_packages: A list of extra package names.
- extra_r_txt_files: A list of extra R.txt files. One per item in
- |extra_res_packages|. Note that all resource IDs in them will be ignored,
- |and replaced by the values extracted from |main_r_txt_file|.
- rjava_build_options: An RJavaBuildOptions instance that controls how
- exactly the R.java file is generated.
- Raises:
- Exception if a package name appears several times in |extra_res_packages|
- """
- assert len(extra_res_packages) == len(extra_r_txt_files), \
- 'Need one R.txt file per package'
-
- packages = list(extra_res_packages)
- r_txt_files = list(extra_r_txt_files)
-
- if package and package not in packages:
- # Sometimes, an apk target and a resources target share the same
- # AndroidManifest.xml and thus |package| will already be in |packages|.
- packages.append(package)
- r_txt_files.append(main_r_txt_file)
-
- # Map of (resource_type, name) -> Entry.
- # Contains the correct values for resources.
- all_resources = {}
- for entry in _ParseTextSymbolsFile(main_r_txt_file, fix_package_ids=True):
- all_resources[(entry.resource_type, entry.name)] = entry
-
- # Map of package_name->resource_type->entry
- resources_by_package = (
- collections.defaultdict(lambda: collections.defaultdict(list)))
- # Build the R.java files using each package's R.txt file, but replacing
- # each entry's placeholder value with correct values from all_resources.
- for package, r_txt_file in zip(packages, r_txt_files):
- if package in resources_by_package:
- raise Exception(('Package name "%s" appeared twice. All '
- 'android_resources() targets must use unique package '
- 'names, or no package name at all.') % package)
- resources_by_type = resources_by_package[package]
- # The sub-R.txt files have the wrong values at this point. Read them to
- # figure out which entries belong to them, but use the values from the
- # main R.txt file.
- for entry in _ParseTextSymbolsFile(r_txt_file):
- entry = all_resources.get((entry.resource_type, entry.name))
- # For most cases missing entry here is an error. It means that some
- # library claims to have or depend on a resource that isn't included into
- # the APK. There is one notable exception: Google Play Services (GMS).
- # GMS is shipped as a bunch of AARs. One of them - basement - contains
- # R.txt with ids of all resources, but most of the resources are in the
- # other AARs. However, all other AARs reference their resources via
- # basement's R.java so the latter must contain all ids that are in its
- # R.txt. Most targets depend on only a subset of GMS AARs so some
- # resources are missing, which is okay because the code that references
- # them is missing too. We can't get an id for a resource that isn't here
- # so the only solution is to skip the resource entry entirely.
- #
- # We can verify that all entries referenced in the code were generated
- # correctly by running Proguard on the APK: it will report missing
- # fields.
- if entry:
- resources_by_type[entry.resource_type].append(entry)
-
- for package, resources_by_type in resources_by_package.iteritems():
- _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
- rjava_build_options)
-
-
-def _CreateRJavaSourceFile(srcjar_dir, package, resources_by_type,
- rjava_build_options):
- """Generates an R.java source file."""
- package_r_java_dir = os.path.join(srcjar_dir, *package.split('.'))
- build_utils.MakeDirectory(package_r_java_dir)
- package_r_java_path = os.path.join(package_r_java_dir, 'R.java')
- java_file_contents = _RenderRJavaSource(package, resources_by_type,
- rjava_build_options)
- with open(package_r_java_path, 'w') as f:
- f.write(java_file_contents)
-
-
-# Resource IDs inside resource arrays are sorted. Application resource IDs start
-# with 0x7f but system resource IDs start with 0x01 thus system resource ids are
-# always at the start of the array. This function finds the index of the first
-# non system resource id to be used for package ID rewriting (we should not
-# rewrite system resource ids).
-def _GetNonSystemIndex(entry):
- """Get the index of the first application resource ID within a resource
- array."""
- res_ids = re.findall(r'0x[0-9a-f]{8}', entry.value)
- for i, res_id in enumerate(res_ids):
- if res_id.startswith('0x7f'):
- return i
- return len(res_ids)
-
-
-def _RenderRJavaSource(package, resources_by_type, rjava_build_options):
- """Render an R.java source file. See _CreateRJaveSourceFile for args info."""
- final_resources_by_type = collections.defaultdict(list)
- non_final_resources_by_type = collections.defaultdict(list)
- for res_type, resources in resources_by_type.iteritems():
- for entry in resources:
- # Entries in stylable that are not int[] are not actually resource ids
- # but constants.
- if rjava_build_options._IsResourceFinal(entry):
- final_resources_by_type[res_type].append(entry)
- else:
- non_final_resources_by_type[res_type].append(entry)
-
- # Keep these assignments all on one line to make diffing against regular
- # aapt-generated files easier.
- create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
- create_id_arr = ('{{ e.resource_type }}.{{ e.name }}[i] ^='
- ' packageIdTransform;')
- for_loop_condition = ('int i = {{ startIndex(e) }}; i < '
- '{{ e.resource_type }}.{{ e.name }}.length; ++i')
-
- # Here we diverge from what aapt does. Because we have so many
- # resources, the onResourcesLoaded method was exceeding the 64KB limit that
- # Java imposes. For this reason we split onResourcesLoaded into different
- # methods for each resource type.
- template = Template("""/* AUTO-GENERATED FILE. DO NOT MODIFY. */
-
-package {{ package }};
-
-public final class R {
- private static boolean sResourcesDidLoad;
- {% for resource_type in resource_types %}
- public static final class {{ resource_type }} {
- {% for e in final_resources[resource_type] %}
- public static final {{ e.java_type }} {{ e.name }} = {{ e.value }};
- {% endfor %}
- {% for e in non_final_resources[resource_type] %}
- public static {{ e.java_type }} {{ e.name }} = {{ e.value }};
- {% endfor %}
- }
- {% endfor %}
- {% if has_on_resources_loaded %}
- public static void onResourcesLoaded(int packageId) {
- assert !sResourcesDidLoad;
- sResourcesDidLoad = true;
- int packageIdTransform = (packageId ^ 0x7f) << 24;
- {% for resource_type in resource_types %}
- onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
- {% for e in non_final_resources[resource_type] %}
- {% if e.java_type == 'int[]' %}
- for(""" + for_loop_condition + """) {
- """ + create_id_arr + """
- }
- {% endif %}
- {% endfor %}
- {% endfor %}
- }
- {% for res_type in resource_types %}
- private static void onResourcesLoaded{{ res_type|title }} (
- int packageIdTransform) {
- {% for e in non_final_resources[res_type] %}
- {% if res_type != 'styleable' and e.java_type != 'int[]' %}
- """ + create_id + """
- {% endif %}
- {% endfor %}
- }
- {% endfor %}
- {% endif %}
-}
-""", trim_blocks=True, lstrip_blocks=True)
-
- return template.render(
- package=package,
- resource_types=sorted(resources_by_type),
- has_on_resources_loaded=rjava_build_options.has_on_resources_loaded,
- final_resources=final_resources_by_type,
- non_final_resources=non_final_resources_by_type,
- startIndex=_GetNonSystemIndex)
-
-
-def ExtractPackageFromManifest(manifest_path):
- """Extract package name from Android manifest file."""
- doc = ElementTree.parse(manifest_path)
- return doc.getroot().get('package')
-
-
-def ExtractDeps(dep_zips, deps_dir):
- """Extract a list of resource dependency zip files.
-
- Args:
- dep_zips: A list of zip file paths, each one will be extracted to
- a subdirectory of |deps_dir|, named after the zip file (e.g.
- '/some/path/foo.zip' -> '{deps_dir}/foo/').
- deps_dir: Top-level extraction directory.
- Returns:
- The list of all sub-directory paths, relative to |deps_dir|.
- Raises:
- Exception: If a sub-directory already exists with the same name before
- extraction.
- """
- dep_subdirs = []
- for z in dep_zips:
- subdir = os.path.join(deps_dir, os.path.basename(z))
- if os.path.exists(subdir):
- raise Exception('Resource zip name conflict: ' + os.path.basename(z))
- build_utils.ExtractAll(z, path=subdir)
- dep_subdirs.append(subdir)
- return dep_subdirs
-
-
-class _ResourceBuildContext(object):
- """A temporary directory for packaging and compiling Android resources."""
- def __init__(self):
- """Initialized the context."""
- # The top-level temporary directory.
- self.temp_dir = tempfile.mkdtemp()
- # A location to store resources extracted form dependency zip files.
- self.deps_dir = os.path.join(self.temp_dir, 'deps')
- os.mkdir(self.deps_dir)
- # A location to place aapt-generated files.
- self.gen_dir = os.path.join(self.temp_dir, 'gen')
- os.mkdir(self.gen_dir)
- # Location of the generated R.txt file.
- self.r_txt_path = os.path.join(self.gen_dir, 'R.txt')
- # A location to place generated R.java files.
- self.srcjar_dir = os.path.join(self.temp_dir, 'java')
- os.mkdir(self.srcjar_dir)
-
- def Close(self):
- """Close the context and destroy all temporary files."""
- shutil.rmtree(self.temp_dir)
-
-
-@contextlib.contextmanager
-def BuildContext():
- """Generator for a _ResourceBuildContext instance."""
- try:
- context = _ResourceBuildContext()
- yield context
- finally:
- context.Close()
-
-
-def ResourceArgsParser():
- """Create an argparse.ArgumentParser instance with common argument groups.
-
- Returns:
- A tuple of (parser, in_group, out_group) corresponding to the parser
- instance, and the input and output argument groups for it, respectively.
- """
- parser = argparse.ArgumentParser(description=__doc__)
-
- input_opts = parser.add_argument_group('Input options')
- output_opts = parser.add_argument_group('Output options')
-
- build_utils.AddDepfileOption(output_opts)
-
- input_opts.add_argument('--android-sdk-jars', required=True,
- help='Path to the android.jar file.')
-
- input_opts.add_argument('--aapt-path', required=True,
- help='Path to the Android aapt tool')
-
- input_opts.add_argument('--aapt2-path',
- help='Path to the Android aapt2 tool. If in different'
- ' directory from --aapt-path.')
-
- input_opts.add_argument('--dependencies-res-zips', required=True,
- help='Resources zip archives from dependents. Required to '
- 'resolve @type/foo references into dependent '
- 'libraries.')
-
- input_opts.add_argument(
- '--r-text-in',
- help='Path to pre-existing R.txt. Its resource IDs override those found '
- 'in the aapt-generated R.txt when generating R.java.')
-
- input_opts.add_argument(
- '--extra-res-packages',
- help='Additional package names to generate R.java files for.')
-
- input_opts.add_argument(
- '--extra-r-text-files',
- help='For each additional package, the R.txt file should contain a '
- 'list of resources to be included in the R.java file in the format '
- 'generated by aapt.')
-
- return (parser, input_opts, output_opts)
-
-
-def HandleCommonOptions(options):
- """Handle common command-line options after parsing.
-
- Args:
- options: the result of parse_args() on the parser returned by
- ResourceArgsParser(). This function updates a few common fields.
- """
- options.android_sdk_jars = build_utils.ParseGnList(options.android_sdk_jars)
-
- options.dependencies_res_zips = (
- build_utils.ParseGnList(options.dependencies_res_zips))
-
- # Don't use [] as default value since some script explicitly pass "".
- if options.extra_res_packages:
- options.extra_res_packages = (
- build_utils.ParseGnList(options.extra_res_packages))
- else:
- options.extra_res_packages = []
-
- if options.extra_r_text_files:
- options.extra_r_text_files = (
- build_utils.ParseGnList(options.extra_r_text_files))
- else:
- options.extra_r_text_files = []
-
- if not options.aapt2_path:
- options.aapt2_path = options.aapt_path + '2'
diff --git a/build/android/pylib/constants/host_paths_unittest.py b/build/android/pylib/constants/host_paths_unittest.py
deleted file mode 100755
index 658ed08bd9..0000000000
--- a/build/android/pylib/constants/host_paths_unittest.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2018 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.
-
-import logging
-import os
-import unittest
-
-import pylib.constants as constants
-import pylib.constants.host_paths as host_paths
-
-
-# This map corresponds to the binprefix of NDK prebuilt toolchains for various
-# target CPU architectures. Note that 'x86_64' and 'x64' are the same.
-_EXPECTED_NDK_TOOL_SUBDIR_MAP = {
- 'arm': 'toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/' +
- 'arm-linux-androideabi-',
- 'arm64':
- 'toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/' +
- 'aarch64-linux-android-',
- 'x86': 'toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-',
- 'x86_64':
- 'toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-',
- 'x64':
- 'toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-',
- 'mips':
- 'toolchains/mipsel-linux-android-4.9/prebuilt/linux-x86_64/bin/' +
- 'mipsel-linux-android-'
-}
-
-
-class HostPathsTest(unittest.TestCase):
- def setUp(self):
- logging.getLogger().setLevel(logging.ERROR)
-
- def test_GetAaptPath(self):
- _EXPECTED_AAPT_PATH = os.path.join(constants.ANDROID_SDK_TOOLS, 'aapt')
- self.assertEqual(host_paths.GetAaptPath(), _EXPECTED_AAPT_PATH)
- self.assertEqual(host_paths.GetAaptPath(), _EXPECTED_AAPT_PATH)
-
- def test_ToolPath(self):
- for cpu_arch, binprefix in _EXPECTED_NDK_TOOL_SUBDIR_MAP.iteritems():
- expected_binprefix = os.path.join(constants.ANDROID_NDK_ROOT, binprefix)
- expected_path = expected_binprefix + 'foo'
- self.assertEqual(host_paths.ToolPath('foo', cpu_arch), expected_path)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/build/android/pylib/content_settings.py b/build/android/pylib/content_settings.py
deleted file mode 100644
index 3bf11bc490..0000000000
--- a/build/android/pylib/content_settings.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# 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.
-
-
-class ContentSettings(dict):
-
- """A dict interface to interact with device content settings.
-
- System properties are key/value pairs as exposed by adb shell content.
- """
-
- def __init__(self, table, device):
- super(ContentSettings, self).__init__()
- self._table = table
- self._device = device
-
- @staticmethod
- def _GetTypeBinding(value):
- if isinstance(value, bool):
- return 'b'
- if isinstance(value, float):
- return 'f'
- if isinstance(value, int):
- return 'i'
- if isinstance(value, long):
- return 'l'
- if isinstance(value, str):
- return 's'
- raise ValueError('Unsupported type %s' % type(value))
-
- def iteritems(self):
- # Example row:
- # 'Row: 0 _id=13, name=logging_id2, value=-1fccbaa546705b05'
- for row in self._device.RunShellCommand(
- 'content query --uri content://%s' % self._table, as_root=True):
- fields = row.split(', ')
- key = None
- value = None
- for field in fields:
- k, _, v = field.partition('=')
- if k == 'name':
- key = v
- elif k == 'value':
- value = v
- if not key:
- continue
- if not value:
- value = ''
- yield key, value
-
- def __getitem__(self, key):
- return self._device.RunShellCommand(
- 'content query --uri content://%s --where "name=\'%s\'" '
- '--projection value' % (self._table, key), as_root=True).strip()
-
- def __setitem__(self, key, value):
- if key in self:
- self._device.RunShellCommand(
- 'content update --uri content://%s '
- '--bind value:%s:%s --where "name=\'%s\'"' % (
- self._table,
- self._GetTypeBinding(value), value, key),
- as_root=True)
- else:
- self._device.RunShellCommand(
- 'content insert --uri content://%s '
- '--bind name:%s:%s --bind value:%s:%s' % (
- self._table,
- self._GetTypeBinding(key), key,
- self._GetTypeBinding(value), value),
- as_root=True)
-
- def __delitem__(self, key):
- self._device.RunShellCommand(
- 'content delete --uri content://%s '
- '--bind name:%s:%s' % (
- self._table,
- self._GetTypeBinding(key), key),
- as_root=True)
diff --git a/build/android/pylib/device_settings.py b/build/android/pylib/device_settings.py
deleted file mode 100644
index ab4ad1b900..0000000000
--- a/build/android/pylib/device_settings.py
+++ /dev/null
@@ -1,199 +0,0 @@
-# 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.
-
-import logging
-
-from pylib import content_settings
-
-_LOCK_SCREEN_SETTINGS_PATH = '/data/system/locksettings.db'
-_ALTERNATE_LOCK_SCREEN_SETTINGS_PATH = (
- '/data/data/com.android.providers.settings/databases/settings.db')
-PASSWORD_QUALITY_UNSPECIFIED = '0'
-_COMPATIBLE_BUILD_TYPES = ['userdebug', 'eng']
-
-
-def ConfigureContentSettings(device, desired_settings):
- """Configures device content setings from a list.
-
- Many settings are documented at:
- http://developer.android.com/reference/android/provider/Settings.Global.html
- http://developer.android.com/reference/android/provider/Settings.Secure.html
- http://developer.android.com/reference/android/provider/Settings.System.html
-
- Many others are undocumented.
-
- Args:
- device: A DeviceUtils instance for the device to configure.
- desired_settings: A list of (table, [(key: value), ...]) for all
- settings to configure.
- """
- for table, key_value in desired_settings:
- settings = content_settings.ContentSettings(table, device)
- for key, value in key_value:
- settings[key] = value
- logging.info('\n%s %s', table, (80 - len(table)) * '-')
- for key, value in sorted(settings.iteritems()):
- logging.info('\t%s: %s', key, value)
-
-
-def SetLockScreenSettings(device):
- """Sets lock screen settings on the device.
-
- On certain device/Android configurations we need to disable the lock screen in
- a different database. Additionally, the password type must be set to
- DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED.
- Lock screen settings are stored in sqlite on the device in:
- /data/system/locksettings.db
-
- IMPORTANT: The first column is used as a primary key so that all rows with the
- same value for that column are removed from the table prior to inserting the
- new values.
-
- Args:
- device: A DeviceUtils instance for the device to configure.
-
- Raises:
- Exception if the setting was not properly set.
- """
- if device.build_type not in _COMPATIBLE_BUILD_TYPES:
- logging.warning('Unable to disable lockscreen on %s builds.',
- device.build_type)
- return
-
- def get_lock_settings(table):
- return [(table, 'lockscreen.disabled', '1'),
- (table, 'lockscreen.password_type', PASSWORD_QUALITY_UNSPECIFIED),
- (table, 'lockscreen.password_type_alternate',
- PASSWORD_QUALITY_UNSPECIFIED)]
-
- if device.FileExists(_LOCK_SCREEN_SETTINGS_PATH):
- db = _LOCK_SCREEN_SETTINGS_PATH
- locksettings = get_lock_settings('locksettings')
- columns = ['name', 'user', 'value']
- generate_values = lambda k, v: [k, '0', v]
- elif device.FileExists(_ALTERNATE_LOCK_SCREEN_SETTINGS_PATH):
- db = _ALTERNATE_LOCK_SCREEN_SETTINGS_PATH
- locksettings = get_lock_settings('secure') + get_lock_settings('system')
- columns = ['name', 'value']
- generate_values = lambda k, v: [k, v]
- else:
- logging.warning('Unable to find database file to set lock screen settings.')
- return
-
- for table, key, value in locksettings:
- # Set the lockscreen setting for default user '0'
- values = generate_values(key, value)
-
- cmd = """begin transaction;
-delete from '%(table)s' where %(primary_key)s='%(primary_value)s';
-insert into '%(table)s' (%(columns)s) values (%(values)s);
-commit transaction;""" % {
- 'table': table,
- 'primary_key': columns[0],
- 'primary_value': values[0],
- 'columns': ', '.join(columns),
- 'values': ', '.join(["'%s'" % value for value in values])
- }
- output_msg = device.RunShellCommand('sqlite3 %s "%s"' % (db, cmd),
- as_root=True)
- if output_msg:
- logging.info(' '.join(output_msg))
-
-
-ENABLE_LOCATION_SETTINGS = [
- # Note that setting these in this order is required in order for all of
- # them to take and stick through a reboot.
- ('com.google.settings/partner', [
- ('use_location_for_services', 1),
- ]),
- ('settings/secure', [
- # Ensure Geolocation is enabled and allowed for tests.
- ('location_providers_allowed', 'gps,network'),
- ]),
- ('com.google.settings/partner', [
- ('network_location_opt_in', 1),
- ])
-]
-
-DISABLE_LOCATION_SETTINGS = [
- ('com.google.settings/partner', [
- ('use_location_for_services', 0),
- ]),
- ('settings/secure', [
- # Ensure Geolocation is disabled.
- ('location_providers_allowed', ''),
- ]),
-]
-
-ENABLE_MOCK_LOCATION_SETTINGS = [
- ('settings/secure', [
- ('mock_location', 1),
- ]),
-]
-
-DISABLE_MOCK_LOCATION_SETTINGS = [
- ('settings/secure', [
- ('mock_location', 0),
- ]),
-]
-
-DETERMINISTIC_DEVICE_SETTINGS = [
- ('settings/global', [
- ('assisted_gps_enabled', 0),
-
- # Disable "auto time" and "auto time zone" to avoid network-provided time
- # to overwrite the device's datetime and timezone synchronized from host
- # when running tests later. See b/6569849.
- ('auto_time', 0),
- ('auto_time_zone', 0),
-
- ('development_settings_enabled', 1),
-
- # Flag for allowing ActivityManagerService to send ACTION_APP_ERROR intents
- # on application crashes and ANRs. If this is disabled, the crash/ANR dialog
- # will never display the "Report" button.
- # Type: int ( 0 = disallow, 1 = allow )
- ('send_action_app_error', 0),
-
- ('stay_on_while_plugged_in', 3),
-
- ('verifier_verify_adb_installs', 0),
- ]),
- ('settings/secure', [
- ('allowed_geolocation_origins',
- 'http://www.google.co.uk http://www.google.com'),
-
- # Ensure that we never get random dialogs like "Unfortunately the process
- # android.process.acore has stopped", which steal the focus, and make our
- # automation fail (because the dialog steals the focus then mistakenly
- # receives the injected user input events).
- ('anr_show_background', 0),
-
- ('lockscreen.disabled', 1),
-
- ('screensaver_enabled', 0),
-
- ('skip_first_use_hints', 1),
- ]),
- ('settings/system', [
- # Don't want devices to accidentally rotate the screen as that could
- # affect performance measurements.
- ('accelerometer_rotation', 0),
-
- ('lockscreen.disabled', 1),
-
- # Turn down brightness and disable auto-adjust so that devices run cooler.
- ('screen_brightness', 5),
- ('screen_brightness_mode', 0),
-
- ('user_rotation', 0),
- ]),
-]
-
-NETWORK_DISABLED_SETTINGS = [
- ('settings/global', [
- ('airplane_mode_on', 1),
- ('wifi_on', 0),
- ]),
-]
diff --git a/build/android/pylib/pexpect.py b/build/android/pylib/pexpect.py
deleted file mode 100644
index cf59fb0f6d..0000000000
--- a/build/android/pylib/pexpect.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 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.
-from __future__ import absolute_import
-
-import os
-import sys
-
-_CHROME_SRC = os.path.join(
- os.path.abspath(os.path.dirname(__file__)), '..', '..', '..')
-
-_PEXPECT_PATH = os.path.join(_CHROME_SRC, 'third_party', 'pexpect')
-if _PEXPECT_PATH not in sys.path:
- sys.path.append(_PEXPECT_PATH)
-
-# pexpect is not available on all platforms. We allow this file to be imported
-# on platforms without pexpect and only fail when pexpect is actually used.
-try:
- from pexpect import * # pylint: disable=W0401,W0614
-except ImportError:
- pass
diff --git a/build/android/pylib/restart_adbd.sh b/build/android/pylib/restart_adbd.sh
deleted file mode 100755
index 393b2ebac0..0000000000
--- a/build/android/pylib/restart_adbd.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/system/bin/sh
-
-# 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.
-
-# Android shell script to restart adbd on the device. This has to be run
-# atomically as a shell script because stopping adbd prevents further commands
-# from running (even if called in the same adb shell).
-
-trap '' HUP
-trap '' TERM
-trap '' PIPE
-
-function restart() {
- stop adbd
- start adbd
-}
-
-restart &
diff --git a/build/android/pylib/valgrind_tools.py b/build/android/pylib/valgrind_tools.py
deleted file mode 100644
index 3dc2488b26..0000000000
--- a/build/android/pylib/valgrind_tools.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# Copyright (c) 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.
-
-# pylint: disable=R0201
-
-import glob
-import logging
-import os.path
-import subprocess
-import sys
-
-from devil.android import device_errors
-from devil.android.valgrind_tools import base_tool
-from pylib.constants import DIR_SOURCE_ROOT
-
-
-def SetChromeTimeoutScale(device, scale):
- """Sets the timeout scale in /data/local/tmp/chrome_timeout_scale to scale."""
- path = '/data/local/tmp/chrome_timeout_scale'
- if not scale or scale == 1.0:
- # Delete if scale is None/0.0/1.0 since the default timeout scale is 1.0
- device.RemovePath(path, force=True, as_root=True)
- else:
- device.WriteFile(path, '%f' % scale, as_root=True)
-
-
-
-class AddressSanitizerTool(base_tool.BaseTool):
- """AddressSanitizer tool."""
-
- WRAPPER_NAME = '/system/bin/asanwrapper'
- # Disable memcmp overlap check.There are blobs (gl drivers)
- # on some android devices that use memcmp on overlapping regions,
- # nothing we can do about that.
- EXTRA_OPTIONS = 'strict_memcmp=0,use_sigaltstack=1'
-
- def __init__(self, device):
- super(AddressSanitizerTool, self).__init__()
- self._device = device
-
- @classmethod
- def CopyFiles(cls, device):
- """Copies ASan tools to the device."""
- libs = glob.glob(os.path.join(DIR_SOURCE_ROOT,
- 'third_party/llvm-build/Release+Asserts/',
- 'lib/clang/*/lib/linux/',
- 'libclang_rt.asan-arm-android.so'))
- assert len(libs) == 1
- subprocess.call(
- [os.path.join(
- DIR_SOURCE_ROOT,
- 'tools/android/asan/third_party/asan_device_setup.sh'),
- '--device', str(device),
- '--lib', libs[0],
- '--extra-options', AddressSanitizerTool.EXTRA_OPTIONS])
- device.WaitUntilFullyBooted()
-
- def GetTestWrapper(self):
- return AddressSanitizerTool.WRAPPER_NAME
-
- def GetUtilWrapper(self):
- """Returns the wrapper for utilities, such as forwarder.
-
- AddressSanitizer wrapper must be added to all instrumented binaries,
- including forwarder and the like. This can be removed if such binaries
- were built without instrumentation. """
- return self.GetTestWrapper()
-
- def SetupEnvironment(self):
- try:
- self._device.EnableRoot()
- except device_errors.CommandFailedError as e:
- # Try to set the timeout scale anyway.
- # TODO(jbudorick) Handle this exception appropriately after interface
- # conversions are finished.
- logging.error(str(e))
- SetChromeTimeoutScale(self._device, self.GetTimeoutScale())
-
- def CleanUpEnvironment(self):
- SetChromeTimeoutScale(self._device, None)
-
- def GetTimeoutScale(self):
- # Very slow startup.
- return 20.0
-
-
-TOOL_REGISTRY = {
- 'asan': AddressSanitizerTool,
-}
-
-
-def CreateTool(tool_name, device):
- """Creates a tool with the specified tool name.
-
- Args:
- tool_name: Name of the tool to create.
- device: A DeviceUtils instance.
- Returns:
- A tool for the specified tool_name.
- """
- if not tool_name:
- return base_tool.BaseTool()
-
- ctor = TOOL_REGISTRY.get(tool_name)
- if ctor:
- return ctor(device)
- else:
- print 'Unknown tool %s, available tools: %s' % (
- tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))
- sys.exit(1)
-
-def PushFilesForTool(tool_name, device):
- """Pushes the files required for |tool_name| to |device|.
-
- Args:
- tool_name: Name of the tool to create.
- device: A DeviceUtils instance.
- """
- if not tool_name:
- return
-
- clazz = TOOL_REGISTRY.get(tool_name)
- if clazz:
- clazz.CopyFiles(device)
- else:
- print 'Unknown tool %s, available tools: %s' % (
- tool_name, ', '.join(sorted(TOOL_REGISTRY.keys())))
- sys.exit(1)
-
diff --git a/build/apply_locales.py b/build/apply_locales.py
deleted file mode 100755
index 6af7280fad..0000000000
--- a/build/apply_locales.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2009 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.
-
-# TODO: remove this script when GYP has for loops
-
-import sys
-import optparse
-
-def main(argv):
-
- parser = optparse.OptionParser()
- usage = 'usage: %s [options ...] format_string locale_list'
- parser.set_usage(usage.replace('%s', '%prog'))
- parser.add_option('-d', dest='dash_to_underscore', action="store_true",
- default=False,
- help='map "en-US" to "en" and "-" to "_" in locales')
-
- (options, arglist) = parser.parse_args(argv)
-
- if len(arglist) < 3:
- print 'ERROR: need string and list of locales'
- return 1
-
- str_template = arglist[1]
- locales = arglist[2:]
-
- results = []
- for locale in locales:
- # For Cocoa to find the locale at runtime, it needs to use '_' instead
- # of '-' (http://crbug.com/20441). Also, 'en-US' should be represented
- # simply as 'en' (http://crbug.com/19165, http://crbug.com/25578).
- if options.dash_to_underscore:
- if locale == 'en-US':
- locale = 'en'
- locale = locale.replace('-', '_')
- results.append(str_template.replace('ZZLOCALE', locale))
-
- # Quote each element so filename spaces don't mess up GYP's attempt to parse
- # it into a list.
- print ' '.join(["'%s'" % x for x in results])
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/build/build_config.h b/build/build_config.h
index 0a00240887..d669ea750e 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -24,21 +24,25 @@
// within an Android checkout.
// - ANDROID is defined via -D when building code for either Android targets or
// hosts. Use __ANDROID__ and __ANDROID_HOST__ instead.
-// - OS_ANDROID is a define used to build Chrome for Android within the NDK and
-// to build Android targets.
+// - OS_ANDROID is a Chrome-specific define used to build Chrome for Android
+// within the NDK.
// Android targets and hosts don't use tcmalloc.
#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
#define NO_TCMALLOC
#endif // defined(__ANDROID__) || defined(__ANDROID_HOST__)
+// Use the Chrome OS version of the code for both Android targets and Chrome OS builds.
+#if !defined(__ANDROID_HOST__)
+#define OS_CHROMEOS 1
+#endif // !defined(__ANDROID_HOST__)
+
#if defined(__ANDROID__) // Android targets
-#define OS_ANDROID 1
+#define __linux__ 1
#elif !defined(__ANDROID_HOST__) // Chrome OS
-#define OS_CHROMEOS 1
// TODO: Remove these once the GLib MessageLoopForUI isn't being used:
// https://crbug.com/361635
#define USE_GLIB 1
@@ -58,6 +62,7 @@
#else
#define OS_NACL_SFI
#endif
+// Don't set OS_ANDROID; it's only used when building Chrome for Android.
#elif defined(__APPLE__)
// only include TargetConditions after testing ANDROID as some android builds
// on mac don't have this header available and it's not needed unless the target
diff --git a/build/check_gn_headers.py b/build/check_gn_headers.py
deleted file mode 100755
index f6ae8f5cac..0000000000
--- a/build/check_gn_headers.py
+++ /dev/null
@@ -1,304 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 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.
-
-"""Find header files missing in GN.
-
-This script gets all the header files from ninja_deps, which is from the true
-dependency generated by the compiler, and report if they don't exist in GN.
-"""
-
-import argparse
-import json
-import os
-import re
-import shutil
-import subprocess
-import sys
-import tempfile
-from multiprocessing import Process, Queue
-
-SRC_DIR = os.path.abspath(
- os.path.join(os.path.abspath(os.path.dirname(__file__)), os.path.pardir))
-DEPOT_TOOLS_DIR = os.path.join(SRC_DIR, 'third_party', 'depot_tools')
-
-
-def GetHeadersFromNinja(out_dir, skip_obj, q):
- """Return all the header files from ninja_deps"""
-
- def NinjaSource():
- cmd = [os.path.join(DEPOT_TOOLS_DIR, 'ninja'), '-C', out_dir, '-t', 'deps']
- # A negative bufsize means to use the system default, which usually
- # means fully buffered.
- popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=-1)
- for line in iter(popen.stdout.readline, ''):
- yield line.rstrip()
-
- popen.stdout.close()
- return_code = popen.wait()
- if return_code:
- raise subprocess.CalledProcessError(return_code, cmd)
-
- ans, err = set(), None
- try:
- ans = ParseNinjaDepsOutput(NinjaSource(), out_dir, skip_obj)
- except Exception as e:
- err = str(e)
- q.put((ans, err))
-
-
-def ParseNinjaDepsOutput(ninja_out, out_dir, skip_obj):
- """Parse ninja output and get the header files"""
- all_headers = {}
-
- # Ninja always uses "/", even on Windows.
- prefix = '../../'
-
- is_valid = False
- obj_file = ''
- for line in ninja_out:
- if line.startswith(' '):
- if not is_valid:
- continue
- if line.endswith('.h') or line.endswith('.hh'):
- f = line.strip()
- if f.startswith(prefix):
- f = f[6:] # Remove the '../../' prefix
- # build/ only contains build-specific files like build_config.h
- # and buildflag.h, and system header files, so they should be
- # skipped.
- if f.startswith(out_dir) or f.startswith('out'):
- continue
- if not f.startswith('build'):
- all_headers.setdefault(f, [])
- if not skip_obj:
- all_headers[f].append(obj_file)
- else:
- is_valid = line.endswith('(VALID)')
- obj_file = line.split(':')[0]
-
- return all_headers
-
-
-def GetHeadersFromGN(out_dir, q):
- """Return all the header files from GN"""
-
- tmp = None
- ans, err = set(), None
- try:
- # Argument |dir| is needed to make sure it's on the same drive on Windows.
- # dir='' means dir='.', but doesn't introduce an unneeded prefix.
- tmp = tempfile.mkdtemp(dir='')
- shutil.copy2(os.path.join(out_dir, 'args.gn'),
- os.path.join(tmp, 'args.gn'))
- # Do "gn gen" in a temp dir to prevent dirtying |out_dir|.
- gn_exe = 'gn.bat' if sys.platform == 'win32' else 'gn'
- subprocess.check_call([
- os.path.join(DEPOT_TOOLS_DIR, gn_exe), 'gen', tmp, '--ide=json', '-q'])
- gn_json = json.load(open(os.path.join(tmp, 'project.json')))
- ans = ParseGNProjectJSON(gn_json, out_dir, tmp)
- except Exception as e:
- err = str(e)
- finally:
- if tmp:
- shutil.rmtree(tmp)
- q.put((ans, err))
-
-
-def ParseGNProjectJSON(gn, out_dir, tmp_out):
- """Parse GN output and get the header files"""
- all_headers = set()
-
- for _target, properties in gn['targets'].iteritems():
- sources = properties.get('sources', [])
- public = properties.get('public', [])
- # Exclude '"public": "*"'.
- if type(public) is list:
- sources += public
- for f in sources:
- if f.endswith('.h') or f.endswith('.hh'):
- if f.startswith('//'):
- f = f[2:] # Strip the '//' prefix.
- if f.startswith(tmp_out):
- f = out_dir + f[len(tmp_out):]
- all_headers.add(f)
-
- return all_headers
-
-
-def GetDepsPrefixes(q):
- """Return all the folders controlled by DEPS file"""
- prefixes, err = set(), None
- try:
- gclient_exe = 'gclient.bat' if sys.platform == 'win32' else 'gclient'
- gclient_out = subprocess.check_output([
- os.path.join(DEPOT_TOOLS_DIR, gclient_exe),
- 'recurse', '--no-progress', '-j1',
- 'python', '-c', 'import os;print os.environ["GCLIENT_DEP_PATH"]'],
- universal_newlines=True)
- for i in gclient_out.split('\n'):
- if i.startswith('src/'):
- i = i[4:]
- prefixes.add(i)
- except Exception as e:
- err = str(e)
- q.put((prefixes, err))
-
-
-def IsBuildClean(out_dir):
- cmd = [os.path.join(DEPOT_TOOLS_DIR, 'ninja'), '-C', out_dir, '-n']
- try:
- out = subprocess.check_output(cmd)
- return 'no work to do.' in out
- except Exception as e:
- print e
- return False
-
-def ParseWhiteList(whitelist):
- out = set()
- for line in whitelist.split('\n'):
- line = re.sub(r'#.*', '', line).strip()
- if line:
- out.add(line)
- return out
-
-
-def FilterOutDepsedRepo(files, deps):
- return {f for f in files if not any(f.startswith(d) for d in deps)}
-
-
-def GetNonExistingFiles(lst):
- out = set()
- for f in lst:
- if not os.path.isfile(f):
- out.add(f)
- return out
-
-
-def main():
-
- def DumpJson(data):
- if args.json:
- with open(args.json, 'w') as f:
- json.dump(data, f)
-
- def PrintError(msg):
- DumpJson([])
- parser.error(msg)
-
- parser = argparse.ArgumentParser(description='''
- NOTE: Use ninja to build all targets in OUT_DIR before running
- this script.''')
- parser.add_argument('--out-dir', metavar='OUT_DIR', default='out/Release',
- help='output directory of the build')
- parser.add_argument('--json',
- help='JSON output filename for missing headers')
- parser.add_argument('--whitelist', help='file containing whitelist')
- parser.add_argument('--skip-dirty-check', action='store_true',
- help='skip checking whether the build is dirty')
- parser.add_argument('--verbose', action='store_true',
- help='print more diagnostic info')
-
- args, _extras = parser.parse_known_args()
-
- if not os.path.isdir(args.out_dir):
- parser.error('OUT_DIR "%s" does not exist.' % args.out_dir)
-
- if not args.skip_dirty_check and not IsBuildClean(args.out_dir):
- dirty_msg = 'OUT_DIR looks dirty. You need to build all there.'
- if args.json:
- # Assume running on the bots. Silently skip this step.
- # This is possible because "analyze" step can be wrong due to
- # underspecified header files. See crbug.com/725877
- print dirty_msg
- DumpJson([])
- return 0
- else:
- # Assume running interactively.
- parser.error(dirty_msg)
-
- d_q = Queue()
- d_p = Process(target=GetHeadersFromNinja, args=(args.out_dir, True, d_q,))
- d_p.start()
-
- gn_q = Queue()
- gn_p = Process(target=GetHeadersFromGN, args=(args.out_dir, gn_q,))
- gn_p.start()
-
- deps_q = Queue()
- deps_p = Process(target=GetDepsPrefixes, args=(deps_q,))
- deps_p.start()
-
- d, d_err = d_q.get()
- gn, gn_err = gn_q.get()
- missing = set(d.keys()) - gn
- nonexisting = GetNonExistingFiles(gn)
-
- deps, deps_err = deps_q.get()
- missing = FilterOutDepsedRepo(missing, deps)
- nonexisting = FilterOutDepsedRepo(nonexisting, deps)
-
- d_p.join()
- gn_p.join()
- deps_p.join()
-
- if d_err:
- PrintError(d_err)
- if gn_err:
- PrintError(gn_err)
- if deps_err:
- PrintError(deps_err)
- if len(GetNonExistingFiles(d)) > 0:
- print 'Non-existing files in ninja deps:', GetNonExistingFiles(d)
- PrintError('Found non-existing files in ninja deps. You should ' +
- 'build all in OUT_DIR.')
- if len(d) == 0:
- PrintError('OUT_DIR looks empty. You should build all there.')
- if any((('/gen/' in i) for i in nonexisting)):
- PrintError('OUT_DIR looks wrong. You should build all there.')
-
- if args.whitelist:
- whitelist = ParseWhiteList(open(args.whitelist).read())
- missing -= whitelist
- nonexisting -= whitelist
-
- missing = sorted(missing)
- nonexisting = sorted(nonexisting)
-
- DumpJson(sorted(missing + nonexisting))
-
- if len(missing) == 0 and len(nonexisting) == 0:
- return 0
-
- if len(missing) > 0:
- print '\nThe following files should be included in gn files:'
- for i in missing:
- print i
-
- if len(nonexisting) > 0:
- print '\nThe following non-existing files should be removed from gn files:'
- for i in nonexisting:
- print i
-
- if args.verbose:
- # Only get detailed obj dependency here since it is slower.
- GetHeadersFromNinja(args.out_dir, False, d_q)
- d, d_err = d_q.get()
- print '\nDetailed dependency info:'
- for f in missing:
- print f
- for cc in d[f]:
- print ' ', cc
-
- print '\nMissing headers sorted by number of affected object files:'
- count = {k: len(v) for (k, v) in d.iteritems()}
- for f in sorted(count, key=count.get, reverse=True):
- if f in missing:
- print count[f], f
-
- return 1
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/check_gn_headers_unittest.py b/build/check_gn_headers_unittest.py
deleted file mode 100755
index 20c3b13897..0000000000
--- a/build/check_gn_headers_unittest.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 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.
-
-import logging
-import json
-import unittest
-import check_gn_headers
-
-
-ninja_input = r'''
-obj/a.o: #deps 1, deps mtime 123 (VALID)
- ../../a.cc
- ../../dir/path/b.h
- ../../c.hh
-
-obj/b.o: #deps 1, deps mtime 123 (STALE)
- ../../b.cc
- ../../dir2/path/b.h
- ../../c2.hh
-
-obj/c.o: #deps 1, deps mtime 123 (VALID)
- ../../c.cc
- ../../build/a.h
- gen/b.h
- ../../out/Release/gen/no.h
- ../../dir3/path/b.h
- ../../c3.hh
-'''
-
-
-gn_input = json.loads(r'''
-{
- "others": [],
- "targets": {
- "//:All": {
- },
- "//:base": {
- "public": [ "//base/p.h" ],
- "sources": [ "//base/a.cc", "//base/a.h", "//base/b.hh" ],
- "visibility": [ "*" ]
- },
- "//:star_public": {
- "public": "*",
- "sources": [ "//base/c.h", "//tmp/gen/a.h" ],
- "visibility": [ "*" ]
- }
- }
-}
-''')
-
-
-whitelist = r'''
- white-front.c
-a/b/c/white-end.c # comment
- dir/white-both.c #more comment
-
-# empty line above
-a/b/c
-'''
-
-
-class CheckGnHeadersTest(unittest.TestCase):
- def testNinja(self):
- headers = check_gn_headers.ParseNinjaDepsOutput(
- ninja_input.split('\n'), 'out/Release', False)
- expected = {
- 'dir/path/b.h': ['obj/a.o'],
- 'c.hh': ['obj/a.o'],
- 'dir3/path/b.h': ['obj/c.o'],
- 'c3.hh': ['obj/c.o'],
- }
- self.assertEquals(headers, expected)
-
- def testGn(self):
- headers = check_gn_headers.ParseGNProjectJSON(gn_input,
- 'out/Release', 'tmp')
- expected = set([
- 'base/a.h',
- 'base/b.hh',
- 'base/c.h',
- 'base/p.h',
- 'out/Release/gen/a.h',
- ])
- self.assertEquals(headers, expected)
-
- def testWhitelist(self):
- output = check_gn_headers.ParseWhiteList(whitelist)
- expected = set([
- 'white-front.c',
- 'a/b/c/white-end.c',
- 'dir/white-both.c',
- 'a/b/c',
- ])
- self.assertEquals(output, expected)
-
-
-if __name__ == '__main__':
- logging.getLogger().setLevel(logging.DEBUG)
- unittest.main(verbosity=2)
diff --git a/build/check_return_value.py b/build/check_return_value.py
deleted file mode 100755
index c659d1e967..0000000000
--- a/build/check_return_value.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""This program wraps an arbitrary command and prints "1" if the command ran
-successfully."""
-
-import os
-import subprocess
-import sys
-
-devnull = open(os.devnull, 'wb')
-if not subprocess.call(sys.argv[1:], stdout=devnull, stderr=devnull):
- print 1
-else:
- print 0
diff --git a/build/clobber.py b/build/clobber.py
deleted file mode 100755
index 18791c28f1..0000000000
--- a/build/clobber.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 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.
-
-"""This script provides methods for clobbering build directories."""
-
-import argparse
-import os
-import shutil
-import subprocess
-import sys
-
-
-def extract_gn_build_commands(build_ninja_file):
- """Extracts from a build.ninja the commands to run GN.
-
- The commands to run GN are the gn rule and build.ninja build step at the
- top of the build.ninja file. We want to keep these when deleting GN builds
- since we want to preserve the command-line flags to GN.
-
- On error, returns the empty string."""
- result = ""
- with open(build_ninja_file, 'r') as f:
- # Read until the third blank line. The first thing GN writes to the file
- # is "ninja_required_version = x.y.z", then the "rule gn" and the third
- # is the section for "build build.ninja", separated by blank lines.
- num_blank_lines = 0
- while num_blank_lines < 3:
- line = f.readline()
- if len(line) == 0:
- return '' # Unexpected EOF.
- result += line
- if line[0] == '\n':
- num_blank_lines = num_blank_lines + 1
- return result
-
-
-def delete_dir(build_dir):
- if os.path.islink(build_dir):
- return
- # For unknown reasons (anti-virus?) rmtree of Chromium build directories
- # often fails on Windows.
- if sys.platform.startswith('win'):
- subprocess.check_call(['rmdir', '/s', '/q', build_dir], shell=True)
- else:
- shutil.rmtree(build_dir)
-
-
-def delete_build_dir(build_dir):
- # GN writes a build.ninja.d file. Note that not all GN builds have args.gn.
- build_ninja_d_file = os.path.join(build_dir, 'build.ninja.d')
- if not os.path.exists(build_ninja_d_file):
- delete_dir(build_dir)
- return
-
- # GN builds aren't automatically regenerated when you sync. To avoid
- # messing with the GN workflow, erase everything but the args file, and
- # write a dummy build.ninja file that will automatically rerun GN the next
- # time Ninja is run.
- build_ninja_file = os.path.join(build_dir, 'build.ninja')
- build_commands = extract_gn_build_commands(build_ninja_file)
-
- try:
- gn_args_file = os.path.join(build_dir, 'args.gn')
- with open(gn_args_file, 'r') as f:
- args_contents = f.read()
- except IOError:
- args_contents = ''
-
- e = None
- try:
- # delete_dir and os.mkdir() may fail, such as when chrome.exe is running,
- # and we still want to restore args.gn/build.ninja/build.ninja.d, so catch
- # the exception and rethrow it later.
- delete_dir(build_dir)
- os.mkdir(build_dir)
- except Exception as e:
- pass
-
- # Put back the args file (if any).
- if args_contents != '':
- with open(gn_args_file, 'w') as f:
- f.write(args_contents)
-
- # Write the build.ninja file sufficiently to regenerate itself.
- with open(os.path.join(build_dir, 'build.ninja'), 'w') as f:
- if build_commands != '':
- f.write(build_commands)
- else:
- # Couldn't parse the build.ninja file, write a default thing.
- f.write('''rule gn
-command = gn -q gen //out/%s/
-description = Regenerating ninja files
-
-build build.ninja: gn
-generator = 1
-depfile = build.ninja.d
-''' % (os.path.split(build_dir)[1]))
-
- # Write a .d file for the build which references a nonexistant file. This
- # will make Ninja always mark the build as dirty.
- with open(build_ninja_d_file, 'w') as f:
- f.write('build.ninja: nonexistant_file.gn\n')
-
- if e:
- # Rethrow the exception we caught earlier.
- raise e
-
-def clobber(out_dir):
- """Clobber contents of build directory.
-
- Don't delete the directory itself: some checkouts have the build directory
- mounted."""
- for f in os.listdir(out_dir):
- path = os.path.join(out_dir, f)
- if os.path.isfile(path):
- os.unlink(path)
- elif os.path.isdir(path):
- delete_build_dir(path)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('out_dir', help='The output directory to clobber')
- args = parser.parse_args()
- clobber(args.out_dir)
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/cp.py b/build/cp.py
deleted file mode 100755
index 0f32536b62..0000000000
--- a/build/cp.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 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.
-
-"""Copy a file.
-
-This module works much like the cp posix command - it takes 2 arguments:
-(src, dst) and copies the file with path |src| to |dst|.
-"""
-
-import os
-import shutil
-import sys
-
-
-def Main(src, dst):
- # Use copy instead of copyfile to ensure the executable bit is copied.
- return shutil.copy(src, os.path.normpath(dst))
-
-
-if __name__ == '__main__':
- sys.exit(Main(sys.argv[1], sys.argv[2]))
diff --git a/build/detect_host_arch.py b/build/detect_host_arch.py
deleted file mode 100755
index 0e491bc8ba..0000000000
--- a/build/detect_host_arch.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""Outputs host CPU architecture in format recognized by gyp."""
-
-import platform
-import re
-import sys
-
-
-def HostArch():
- """Returns the host architecture with a predictable string."""
- host_arch = platform.machine()
-
- # Convert machine type to format recognized by gyp.
- if re.match(r'i.86', host_arch) or host_arch == 'i86pc':
- host_arch = 'ia32'
- elif host_arch in ['x86_64', 'amd64']:
- host_arch = 'x64'
- elif host_arch.startswith('arm'):
- host_arch = 'arm'
- elif host_arch.startswith('aarch64'):
- host_arch = 'arm64'
- elif host_arch.startswith('mips'):
- host_arch = 'mips'
- elif host_arch.startswith('ppc'):
- host_arch = 'ppc'
- elif host_arch.startswith('s390'):
- host_arch = 's390'
-
-
- # platform.machine is based on running kernel. It's possible to use 64-bit
- # kernel with 32-bit userland, e.g. to give linker slightly more memory.
- # Distinguish between different userland bitness by querying
- # the python binary.
- if host_arch == 'x64' and platform.architecture()[0] == '32bit':
- host_arch = 'ia32'
- if host_arch == 'arm64' and platform.architecture()[0] == '32bit':
- host_arch = 'arm'
-
- return host_arch
-
-def DoMain(_):
- """Hook to be called from gyp without starting a separate python
- interpreter."""
- return HostArch()
-
-if __name__ == '__main__':
- print DoMain([])
diff --git a/build/dir_exists.py b/build/dir_exists.py
deleted file mode 100755
index 70d367ec26..0000000000
--- a/build/dir_exists.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 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.
-"""Writes True if the argument is a directory."""
-
-import os.path
-import sys
-
-def main():
- sys.stdout.write(_is_dir(sys.argv[1]))
- return 0
-
-def _is_dir(dir_name):
- return str(os.path.isdir(dir_name))
-
-def DoMain(args):
- """Hook to be called from gyp without starting a separate python
- interpreter."""
- return _is_dir(args[0])
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/download_translation_unit_tool.py b/build/download_translation_unit_tool.py
deleted file mode 100755
index b60d33a19f..0000000000
--- a/build/download_translation_unit_tool.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 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.
-
-"""Script to download Clang translation_unit tool from google storage."""
-
-import find_depot_tools
-import json
-import os
-import shutil
-import subprocess
-import sys
-import tarfile
-
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir))
-
-
-DEPOT_PATH = find_depot_tools.add_depot_tools_to_path()
-GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py')
-
-LLVM_BUILD_PATH = os.path.join(CHROME_SRC, 'third_party', 'llvm-build',
- 'Release+Asserts')
-CLANG_UPDATE_PY = os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts',
- 'update.py')
-
-CLANG_BUCKET = 'gs://chromium-browser-clang'
-
-
-def main():
- clang_revision = subprocess.check_output([sys.executable, CLANG_UPDATE_PY,
- '--print-revision']).rstrip()
- targz_name = 'translation_unit-%s.tgz' % clang_revision
-
- if sys.platform == 'win32' or sys.platform == 'cygwin':
- cds_full_url = CLANG_BUCKET + '/Win/' + targz_name
- elif sys.platform == 'darwin':
- cds_full_url = CLANG_BUCKET + '/Mac/' + targz_name
- else:
- assert sys.platform.startswith('linux')
- cds_full_url = CLANG_BUCKET + '/Linux_x64/' + targz_name
-
- os.chdir(LLVM_BUILD_PATH)
-
- subprocess.check_call([sys.executable, GSUTIL_PATH,
- 'cp', cds_full_url, targz_name])
- tarfile.open(name=targz_name, mode='r:gz').extractall(path=LLVM_BUILD_PATH)
-
- os.remove(targz_name)
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/env_dump.py b/build/env_dump.py
deleted file mode 100755
index 3f8217398c..0000000000
--- a/build/env_dump.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2013 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.
-
-# This script can either source a file and dump the enironment changes done by
-# it, or just simply dump the current environment as JSON into a file.
-
-import json
-import optparse
-import os
-import pipes
-import subprocess
-import sys
-
-
-def main():
- parser = optparse.OptionParser()
- parser.add_option('-f', '--output-json',
- help='File to dump the environment as JSON into.')
- parser.add_option(
- '-d', '--dump-mode', action='store_true',
- help='Dump the environment to sys.stdout and exit immediately.')
-
- parser.disable_interspersed_args()
- options, args = parser.parse_args()
- if options.dump_mode:
- if args or options.output_json:
- parser.error('Cannot specify args or --output-json with --dump-mode.')
- json.dump(dict(os.environ), sys.stdout)
- else:
- if not options.output_json:
- parser.error('Requires --output-json option.')
-
- envsetup_cmd = ' '.join(map(pipes.quote, args))
- full_cmd = [
- 'bash', '-c',
- '. %s > /dev/null; %s -d' % (envsetup_cmd, os.path.abspath(__file__))
- ]
- try:
- output = subprocess.check_output(full_cmd)
- except Exception as e:
- sys.exit('Error running %s and dumping environment.' % envsetup_cmd)
-
- env_diff = {}
- new_env = json.loads(output)
- for k, val in new_env.items():
- if k == '_' or (k in os.environ and os.environ[k] == val):
- continue
- env_diff[k] = val
- with open(options.output_json, 'w') as f:
- json.dump(env_diff, f)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/extract_from_cab.py b/build/extract_from_cab.py
deleted file mode 100755
index 080370ca9a..0000000000
--- a/build/extract_from_cab.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 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.
-
-"""Extracts a single file from a CAB archive."""
-
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-
-def run_quiet(*args):
- """Run 'expand' suppressing noisy output. Returns returncode from process."""
- popen = subprocess.Popen(args, stdout=subprocess.PIPE)
- out, _ = popen.communicate()
- if popen.returncode:
- # expand emits errors to stdout, so if we fail, then print that out.
- print out
- return popen.returncode
-
-def main():
- if len(sys.argv) != 4:
- print 'Usage: extract_from_cab.py cab_path archived_file output_dir'
- return 1
-
- [cab_path, archived_file, output_dir] = sys.argv[1:]
-
- # Expand.exe does its work in a fixed-named temporary directory created within
- # the given output directory. This is a problem for concurrent extractions, so
- # create a unique temp dir within the desired output directory to work around
- # this limitation.
- temp_dir = tempfile.mkdtemp(dir=output_dir)
-
- try:
- # Invoke the Windows expand utility to extract the file.
- level = run_quiet('expand', cab_path, '-F:' + archived_file, temp_dir)
- if level == 0:
- # Move the output file into place, preserving expand.exe's behavior of
- # paving over any preexisting file.
- output_file = os.path.join(output_dir, archived_file)
- try:
- os.remove(output_file)
- except OSError:
- pass
- os.rename(os.path.join(temp_dir, archived_file), output_file)
- finally:
- shutil.rmtree(temp_dir, True)
-
- if level != 0:
- return level
-
- # The expand utility preserves the modification date and time of the archived
- # file. Touch the extracted file. This helps build systems that compare the
- # modification times of input and output files to determine whether to do an
- # action.
- os.utime(os.path.join(output_dir, archived_file), None)
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/find_depot_tools.py b/build/find_depot_tools.py
deleted file mode 100755
index 5c496e7c79..0000000000
--- a/build/find_depot_tools.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 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.
-"""Small utility function to find depot_tools and add it to the python path.
-
-Will throw an ImportError exception if depot_tools can't be found since it
-imports breakpad.
-
-This can also be used as a standalone script to print out the depot_tools
-directory location.
-"""
-
-import os
-import sys
-
-
-# Path to //src
-SRC = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
-
-
-def IsRealDepotTools(path):
- expanded_path = os.path.expanduser(path)
- return os.path.isfile(os.path.join(expanded_path, 'gclient.py'))
-
-
-def add_depot_tools_to_path():
- """Search for depot_tools and add it to sys.path."""
- # First, check if we have a DEPS'd in "depot_tools".
- deps_depot_tools = os.path.join(SRC, 'third_party', 'depot_tools')
- if IsRealDepotTools(deps_depot_tools):
- # Put the pinned version at the start of the sys.path, in case there
- # are other non-pinned versions already on the sys.path.
- sys.path.insert(0, deps_depot_tools)
- return deps_depot_tools
-
- # Then look if depot_tools is already in PYTHONPATH.
- for i in sys.path:
- if i.rstrip(os.sep).endswith('depot_tools') and IsRealDepotTools(i):
- return i
- # Then look if depot_tools is in PATH, common case.
- for i in os.environ['PATH'].split(os.pathsep):
- if IsRealDepotTools(i):
- sys.path.append(i.rstrip(os.sep))
- return i
- # Rare case, it's not even in PATH, look upward up to root.
- root_dir = os.path.dirname(os.path.abspath(__file__))
- previous_dir = os.path.abspath(__file__)
- while root_dir and root_dir != previous_dir:
- i = os.path.join(root_dir, 'depot_tools')
- if IsRealDepotTools(i):
- sys.path.append(i)
- return i
- previous_dir = root_dir
- root_dir = os.path.dirname(root_dir)
- print >> sys.stderr, 'Failed to find depot_tools'
- return None
-
-DEPOT_TOOLS_PATH = add_depot_tools_to_path()
-
-# pylint: disable=W0611
-import breakpad
-
-
-def main():
- if DEPOT_TOOLS_PATH is None:
- return 1
- print DEPOT_TOOLS_PATH
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/find_isolated_tests.py b/build/find_isolated_tests.py
deleted file mode 100755
index c5b3ab77a9..0000000000
--- a/build/find_isolated_tests.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""Scans build output directory for .isolated files, calculates their SHA1
-hashes, stores final list in JSON document and then removes *.isolated files
-found (to ensure no stale *.isolated stay around on the next build).
-
-Used to figure out what tests were build in isolated mode to trigger these
-tests to run on swarming.
-
-For more info see:
-https://sites.google.com/a/chromium.org/dev/developers/testing/isolated-testing
-"""
-
-import glob
-import hashlib
-import json
-import optparse
-import os
-import re
-import sys
-
-
-def hash_file(filepath):
- """Calculates the hash of a file without reading it all in memory at once."""
- digest = hashlib.sha1()
- with open(filepath, 'rb') as f:
- while True:
- chunk = f.read(1024*1024)
- if not chunk:
- break
- digest.update(chunk)
- return digest.hexdigest()
-
-
-def main():
- parser = optparse.OptionParser(
- usage='%prog --build-dir <path> --output-json <path>',
- description=sys.modules[__name__].__doc__)
- parser.add_option(
- '--build-dir',
- help='Path to a directory to search for *.isolated files.')
- parser.add_option(
- '--output-json',
- help='File to dump JSON results into.')
-
- options, _ = parser.parse_args()
- if not options.build_dir:
- parser.error('--build-dir option is required')
- if not options.output_json:
- parser.error('--output-json option is required')
-
- result = {}
-
- # Get the file hash values and output the pair.
- pattern = os.path.join(options.build_dir, '*.isolated')
- for filepath in sorted(glob.glob(pattern)):
- test_name = os.path.splitext(os.path.basename(filepath))[0]
- if re.match(r'^.+?\.\d$', test_name):
- # It's a split .isolated file, e.g. foo.0.isolated. Ignore these.
- continue
-
- # TODO(csharp): Remove deletion once the isolate tracked dependencies are
- # inputs for the isolated files.
- sha1_hash = hash_file(filepath)
- os.remove(filepath)
- result[test_name] = sha1_hash
-
- with open(options.output_json, 'wb') as f:
- json.dump(result, f)
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/fix_gn_headers.py b/build/fix_gn_headers.py
deleted file mode 100755
index 01ff764e06..0000000000
--- a/build/fix_gn_headers.py
+++ /dev/null
@@ -1,218 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 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.
-
-"""Fix header files missing in GN.
-
-This script takes the missing header files from check_gn_headers.py, and
-try to fix them by adding them to the GN files.
-Manual cleaning up is likely required afterwards.
-"""
-
-import argparse
-import os
-import re
-import subprocess
-import sys
-
-
-def GitGrep(pattern):
- p = subprocess.Popen(
- ['git', 'grep', '-En', pattern, '--', '*.gn', '*.gni'],
- stdout=subprocess.PIPE)
- out, _ = p.communicate()
- return out, p.returncode
-
-
-def ValidMatches(basename, cc, grep_lines):
- """Filter out 'git grep' matches with header files already."""
- matches = []
- for line in grep_lines:
- gnfile, linenr, contents = line.split(':')
- linenr = int(linenr)
- new = re.sub(cc, basename, contents)
- lines = open(gnfile).read().splitlines()
- assert contents in lines[linenr - 1]
- # Skip if it's already there. It could be before or after the match.
- if lines[linenr] == new:
- continue
- if lines[linenr - 2] == new:
- continue
- print ' ', gnfile, linenr, new
- matches.append((gnfile, linenr, new))
- return matches
-
-
-def AddHeadersNextToCC(headers, skip_ambiguous=True):
- """Add header files next to the corresponding .cc files in GN files.
-
- When skip_ambiguous is True, skip if multiple .cc files are found.
- Returns unhandled headers.
-
- Manual cleaning up is likely required, especially if not skip_ambiguous.
- """
- edits = {}
- unhandled = []
- for filename in headers:
- filename = filename.strip()
- if not (filename.endswith('.h') or filename.endswith('.hh')):
- continue
- basename = os.path.basename(filename)
- print filename
- cc = r'\b' + os.path.splitext(basename)[0] + r'\.(cc|cpp|mm)\b'
- out, returncode = GitGrep('(/|")' + cc + '"')
- if returncode != 0 or not out:
- unhandled.append(filename)
- continue
-
- matches = ValidMatches(basename, cc, out.splitlines())
-
- if len(matches) == 0:
- continue
- if len(matches) > 1:
- print '\n[WARNING] Ambiguous matching for', filename
- for i in enumerate(matches, 1):
- print '%d: %s' % (i[0], i[1])
- print
- if skip_ambiguous:
- continue
-
- picked = raw_input('Pick the matches ("2,3" for multiple): ')
- try:
- matches = [matches[int(i) - 1] for i in picked.split(',')]
- except (ValueError, IndexError):
- continue
-
- for match in matches:
- gnfile, linenr, new = match
- print ' ', gnfile, linenr, new
- edits.setdefault(gnfile, {})[linenr] = new
-
- for gnfile in edits:
- lines = open(gnfile).read().splitlines()
- for l in sorted(edits[gnfile].keys(), reverse=True):
- lines.insert(l, edits[gnfile][l])
- open(gnfile, 'w').write('\n'.join(lines) + '\n')
-
- return unhandled
-
-
-def AddHeadersToSources(headers, skip_ambiguous=True):
- """Add header files to the sources list in the first GN file.
-
- The target GN file is the first one up the parent directories.
- This usually does the wrong thing for _test files if the test and the main
- target are in the same .gn file.
- When skip_ambiguous is True, skip if multiple sources arrays are found.
-
- "git cl format" afterwards is required. Manually cleaning up duplicated items
- is likely required.
- """
- for filename in headers:
- filename = filename.strip()
- print filename
- dirname = os.path.dirname(filename)
- while not os.path.exists(os.path.join(dirname, 'BUILD.gn')):
- dirname = os.path.dirname(dirname)
- rel = filename[len(dirname) + 1:]
- gnfile = os.path.join(dirname, 'BUILD.gn')
-
- lines = open(gnfile).read().splitlines()
- matched = [i for i, l in enumerate(lines) if ' sources = [' in l]
- if skip_ambiguous and len(matched) > 1:
- print '[WARNING] Multiple sources in', gnfile
- continue
-
- if len(matched) < 1:
- continue
- print ' ', gnfile, rel
- index = matched[0]
- lines.insert(index + 1, '"%s",' % rel)
- open(gnfile, 'w').write('\n'.join(lines) + '\n')
-
-
-def RemoveHeader(headers, skip_ambiguous=True):
- """Remove non-existing headers in GN files.
-
- When skip_ambiguous is True, skip if multiple matches are found.
- """
- edits = {}
- unhandled = []
- for filename in headers:
- filename = filename.strip()
- if not (filename.endswith('.h') or filename.endswith('.hh')):
- continue
- basename = os.path.basename(filename)
- print filename
- out, returncode = GitGrep('(/|")' + basename + '"')
- if returncode != 0 or not out:
- unhandled.append(filename)
- print ' Not found'
- continue
-
- grep_lines = out.splitlines()
- matches = []
- for line in grep_lines:
- gnfile, linenr, contents = line.split(':')
- print ' ', gnfile, linenr, contents
- linenr = int(linenr)
- lines = open(gnfile).read().splitlines()
- assert contents in lines[linenr - 1]
- matches.append((gnfile, linenr, contents))
-
- if len(matches) == 0:
- continue
- if len(matches) > 1:
- print '\n[WARNING] Ambiguous matching for', filename
- for i in enumerate(matches, 1):
- print '%d: %s' % (i[0], i[1])
- print
- if skip_ambiguous:
- continue
-
- picked = raw_input('Pick the matches ("2,3" for multiple): ')
- try:
- matches = [matches[int(i) - 1] for i in picked.split(',')]
- except (ValueError, IndexError):
- continue
-
- for match in matches:
- gnfile, linenr, contents = match
- print ' ', gnfile, linenr, contents
- edits.setdefault(gnfile, set()).add(linenr)
-
- for gnfile in edits:
- lines = open(gnfile).read().splitlines()
- for l in sorted(edits[gnfile], reverse=True):
- lines.pop(l - 1)
- open(gnfile, 'w').write('\n'.join(lines) + '\n')
-
- return unhandled
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('input_file', help="missing or non-existing headers, "
- "output of check_gn_headers.py")
- parser.add_argument('--prefix',
- help="only handle path name with this prefix")
- parser.add_argument('--remove', action='store_true',
- help="treat input_file as non-existing headers")
-
- args, _extras = parser.parse_known_args()
-
- headers = open(args.input_file).readlines()
-
- if args.prefix:
- headers = [i for i in headers if i.startswith(args.prefix)]
-
- if args.remove:
- RemoveHeader(headers, False)
- else:
- unhandled = AddHeadersNextToCC(headers)
- AddHeadersToSources(unhandled)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/get_landmines.py b/build/get_landmines.py
deleted file mode 100755
index 8a655e3032..0000000000
--- a/build/get_landmines.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2013 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.
-
-"""
-This file emits the list of reasons why a particular build needs to be clobbered
-(or a list of 'landmines').
-"""
-
-import sys
-
-import landmine_utils
-
-
-host_os = landmine_utils.host_os
-
-
-def print_landmines():
- """
- ALL LANDMINES ARE EMITTED FROM HERE.
- """
- # DO NOT add landmines as part of a regular CL. Landmines are a last-effort
- # bandaid fix if a CL that got landed has a build dependency bug and all bots
- # need to be cleaned up. If you're writing a new CL that causes build
- # dependency problems, fix the dependency problems instead of adding a
- # landmine.
- #
- # Before adding or changing a landmine consider the consequences of doing so.
- # Doing so will wipe out every output directory on every Chrome developer's
- # machine. This can be particularly problematic on Windows where the directory
- # deletion may well fail (locked files, command prompt in the directory,
- # etc.), and generated .sln and .vcxproj files will be deleted.
- #
- # This output directory deletion will be repeated when going back and forth
- # across the change that added the landmine, adding to the cost. There are
- # usually less troublesome alternatives.
-
- if host_os() == 'win':
- print 'Compile on cc_unittests fails due to symbols removed in r185063.'
- if host_os() == 'linux':
- print 'Builders switching from make to ninja will clobber on this.'
- if host_os() == 'mac':
- print 'Switching from bundle to unbundled dylib (issue 14743002).'
- if host_os() in ('win', 'mac'):
- print ('Improper dependency for create_nmf.py broke in r240802, '
- 'fixed in r240860.')
- if host_os() == 'win':
- print 'Switch to VS2015 Update 3, 14393 SDK'
- print 'Need to clobber everything due to an IDL change in r154579 (blink)'
- print 'Need to clobber everything due to gen file moves in r175513 (Blink)'
- print 'Clobber to get rid of obselete test plugin after r248358'
- print 'Clobber to rebuild GN files for V8'
- print 'Clobber to get rid of stale generated mojom.h files'
- print 'Need to clobber everything due to build_nexe change in nacl r13424'
- print '[chromium-dev] PSA: clobber build needed for IDR_INSPECTOR_* compil...'
- print 'blink_resources.grd changed: crbug.com/400860'
- print 'ninja dependency cycle: crbug.com/408192'
- print 'Clobber to fix missing NaCl gyp dependencies (crbug.com/427427).'
- print 'Another clobber for missing NaCl gyp deps (crbug.com/427427).'
- print 'Clobber to fix GN not picking up increased ID range (crbug.com/444902)'
- print 'Remove NaCl toolchains from the output dir (crbug.com/456902)'
- if host_os() == 'win':
- print 'Clobber to delete stale generated files (crbug.com/510086)'
- if host_os() == 'mac':
- print 'Clobber to get rid of evil libsqlite3.dylib (crbug.com/526208)'
- if host_os() == 'mac':
- print 'Clobber to remove libsystem.dylib. See crbug.com/620075'
- if host_os() == 'mac':
- print 'Clobber to get past mojo gen build error (crbug.com/679607)'
- if host_os() == 'win':
- print 'Clobber Windows to fix strange PCH-not-rebuilt errors.'
- print 'CLobber all to fix GN breakage (crbug.com/736215)'
- print 'The Great Blink mv for source files (crbug.com/768828)'
-
-def main():
- print_landmines()
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/get_syzygy_binaries.py b/build/get_syzygy_binaries.py
deleted file mode 100755
index 09b1199708..0000000000
--- a/build/get_syzygy_binaries.py
+++ /dev/null
@@ -1,529 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-"""A utility script for downloading versioned Syzygy binaries."""
-
-import hashlib
-import errno
-import json
-import logging
-import optparse
-import os
-import re
-import shutil
-import stat
-import sys
-import subprocess
-import tempfile
-import time
-import zipfile
-
-
-_LOGGER = logging.getLogger(os.path.basename(__file__))
-
-# The relative path where official builds are archived in their GS bucket.
-_SYZYGY_ARCHIVE_PATH = ('/builds/official/%(revision)s')
-
-# A JSON file containing the state of the download directory. If this file and
-# directory state do not agree, then the binaries will be downloaded and
-# installed again.
-_STATE = '.state'
-
-# This matches an integer (an SVN revision number) or a SHA1 value (a GIT hash).
-# The archive exclusively uses lowercase GIT hashes.
-_REVISION_RE = re.compile('^(?:\d+|[a-f0-9]{40})$')
-
-# This matches an MD5 hash.
-_MD5_RE = re.compile('^[a-f0-9]{32}$')
-
-# List of reources to be downloaded and installed. These are tuples with the
-# following format:
-# (basename, logging name, relative installation path, extraction filter)
-_RESOURCES = [
- ('benchmark.zip', 'benchmark', '', None),
- ('binaries.zip', 'binaries', 'exe', None),
- ('symbols.zip', 'symbols', 'exe',
- lambda x: x.filename.endswith('.dll.pdb'))]
-
-
-# Name of the MS DIA dll that we need to copy to the binaries directory.
-_DIA_DLL_NAME = "msdia140.dll"
-
-
-def _LoadState(output_dir):
- """Loads the contents of the state file for a given |output_dir|, returning
- None if it doesn't exist.
- """
- path = os.path.join(output_dir, _STATE)
- if not os.path.exists(path):
- _LOGGER.debug('No state file found.')
- return None
- with open(path, 'rb') as f:
- _LOGGER.debug('Reading state file: %s', path)
- try:
- return json.load(f)
- except ValueError:
- _LOGGER.debug('Invalid state file.')
- return None
-
-
-def _SaveState(output_dir, state, dry_run=False):
- """Saves the |state| dictionary to the given |output_dir| as a JSON file."""
- path = os.path.join(output_dir, _STATE)
- _LOGGER.debug('Writing state file: %s', path)
- if dry_run:
- return
- with open(path, 'wb') as f:
- f.write(json.dumps(state, sort_keys=True, indent=2))
-
-
-def _Md5(path):
- """Returns the MD5 hash of the file at |path|, which must exist."""
- return hashlib.md5(open(path, 'rb').read()).hexdigest()
-
-
-def _StateIsValid(state):
- """Returns true if the given state structure is valid."""
- if not isinstance(state, dict):
- _LOGGER.debug('State must be a dict.')
- return False
- r = state.get('revision', None)
- if not isinstance(r, basestring) or not _REVISION_RE.match(r):
- _LOGGER.debug('State contains an invalid revision.')
- return False
- c = state.get('contents', None)
- if not isinstance(c, dict):
- _LOGGER.debug('State must contain a contents dict.')
- return False
- for (relpath, md5) in c.iteritems():
- if not isinstance(relpath, basestring) or len(relpath) == 0:
- _LOGGER.debug('State contents dict contains an invalid path.')
- return False
- if not isinstance(md5, basestring) or not _MD5_RE.match(md5):
- _LOGGER.debug('State contents dict contains an invalid MD5 digest.')
- return False
- return True
-
-
-def _BuildActualState(stored, revision, output_dir):
- """Builds the actual state using the provided |stored| state as a template.
- Only examines files listed in the stored state, causing the script to ignore
- files that have been added to the directories locally. |stored| must be a
- valid state dictionary.
- """
- contents = {}
- state = { 'revision': revision, 'contents': contents }
- for relpath, md5 in stored['contents'].iteritems():
- abspath = os.path.abspath(os.path.join(output_dir, relpath))
- if os.path.isfile(abspath):
- m = _Md5(abspath)
- contents[relpath] = m
-
- return state
-
-
-def _StatesAreConsistent(stored, actual):
- """Validates whether two state dictionaries are consistent. Both must be valid
- state dictionaries. Additional entries in |actual| are ignored.
- """
- if stored['revision'] != actual['revision']:
- _LOGGER.debug('Mismatched revision number.')
- return False
- cont_stored = stored['contents']
- cont_actual = actual['contents']
- for relpath, md5 in cont_stored.iteritems():
- if relpath not in cont_actual:
- _LOGGER.debug('Missing content: %s', relpath)
- return False
- if md5 != cont_actual[relpath]:
- _LOGGER.debug('Modified content: %s', relpath)
- return False
- return True
-
-
-def _GetCurrentState(revision, output_dir):
- """Loads the current state and checks to see if it is consistent. Returns
- a tuple (state, bool). The returned state will always be valid, even if an
- invalid state is present on disk.
- """
- stored = _LoadState(output_dir)
- if not _StateIsValid(stored):
- _LOGGER.debug('State is invalid.')
- # Return a valid but empty state.
- return ({'revision': '0', 'contents': {}}, False)
- actual = _BuildActualState(stored, revision, output_dir)
- # If the script has been modified consider the state invalid.
- path = os.path.join(output_dir, _STATE)
- if os.path.getmtime(__file__) > os.path.getmtime(path):
- return (stored, False)
- # Otherwise, explicitly validate the state.
- if not _StatesAreConsistent(stored, actual):
- return (stored, False)
- return (stored, True)
-
-
-def _DirIsEmpty(path):
- """Returns true if the given directory is empty, false otherwise."""
- for root, dirs, files in os.walk(path):
- return not dirs and not files
-
-
-def _RmTreeHandleReadOnly(func, path, exc):
- """An error handling function for use with shutil.rmtree. This will
- detect failures to remove read-only files, and will change their properties
- prior to removing them. This is necessary on Windows as os.remove will return
- an access error for read-only files, and git repos contain read-only
- pack/index files.
- """
- excvalue = exc[1]
- if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
- _LOGGER.debug('Removing read-only path: %s', path)
- os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
- func(path)
- else:
- raise
-
-
-def _RmTree(path):
- """A wrapper of shutil.rmtree that handles read-only files."""
- shutil.rmtree(path, ignore_errors=False, onerror=_RmTreeHandleReadOnly)
-
-
-def _CleanState(output_dir, state, dry_run=False):
- """Cleans up files/directories in |output_dir| that are referenced by
- the given |state|. Raises an error if there are local changes. Returns a
- dictionary of files that were deleted.
- """
- _LOGGER.debug('Deleting files from previous installation.')
- deleted = {}
-
- # Generate a list of files to delete, relative to |output_dir|.
- contents = state['contents']
- files = sorted(contents.keys())
-
- # Try to delete the files. Keep track of directories to delete as well.
- dirs = {}
- for relpath in files:
- fullpath = os.path.join(output_dir, relpath)
- fulldir = os.path.dirname(fullpath)
- dirs[fulldir] = True
- if os.path.exists(fullpath):
- # If somehow the file has become a directory complain about it.
- if os.path.isdir(fullpath):
- raise Exception('Directory exists where file expected: %s' % fullpath)
-
- # Double check that the file doesn't have local changes. If it does
- # then refuse to delete it.
- if relpath in contents:
- stored_md5 = contents[relpath]
- actual_md5 = _Md5(fullpath)
- if actual_md5 != stored_md5:
- raise Exception('File has local changes: %s' % fullpath)
-
- # The file is unchanged so it can safely be deleted.
- _LOGGER.debug('Deleting file "%s".', fullpath)
- deleted[relpath] = True
- if not dry_run:
- os.unlink(fullpath)
-
- # Sort directories from longest name to shortest. This lets us remove empty
- # directories from the most nested paths first.
- dirs = sorted(dirs.keys(), key=lambda x: len(x), reverse=True)
- for p in dirs:
- if os.path.exists(p) and _DirIsEmpty(p):
- _LOGGER.debug('Deleting empty directory "%s".', p)
- if not dry_run:
- _RmTree(p)
-
- return deleted
-
-
-def _FindGsUtil():
- """Looks for depot_tools and returns the absolute path to gsutil.py."""
- for path in os.environ['PATH'].split(os.pathsep):
- path = os.path.abspath(path)
- git_cl = os.path.join(path, 'git_cl.py')
- gs_util = os.path.join(path, 'gsutil.py')
- if os.path.exists(git_cl) and os.path.exists(gs_util):
- return gs_util
- return None
-
-
-def _GsUtil(*cmd):
- """Runs the given command in gsutil with exponential backoff and retries."""
- gs_util = _FindGsUtil()
- cmd = [sys.executable, gs_util] + list(cmd)
-
- retries = 3
- timeout = 4 # Seconds.
- while True:
- _LOGGER.debug('Running %s', cmd)
- prog = subprocess.Popen(cmd, shell=False)
- prog.communicate()
-
- # Stop retrying on success.
- if prog.returncode == 0:
- return
-
- # Raise a permanent failure if retries have been exhausted.
- if retries == 0:
- raise RuntimeError('Command "%s" returned %d.' % (cmd, prog.returncode))
-
- _LOGGER.debug('Sleeping %d seconds and trying again.', timeout)
- time.sleep(timeout)
- retries -= 1
- timeout *= 2
-
-
-def _Download(resource):
- """Downloads the given GS resource to a temporary file, returning its path."""
- tmp = tempfile.mkstemp(suffix='syzygy_archive')
- os.close(tmp[0])
- tmp_file = tmp[1]
- url = 'gs://syzygy-archive' + resource
- if sys.platform == 'cygwin':
- # Change temporary path to Windows path for gsutil
- def winpath(path):
- return subprocess.check_output(['cygpath', '-w', path]).strip()
- tmp_file = winpath(tmp_file)
- _GsUtil('cp', url, tmp_file)
- return tmp[1]
-
-
-def _MaybeCopyDIABinaries(options, contents):
- """Try to copy the DIA DLL to the binaries exe directory."""
- toolchain_data_file = os.path.join(os.path.dirname(__file__),
- 'win_toolchain.json')
- if not os.path.exists(toolchain_data_file):
- _LOGGER.debug('Toolchain JSON data file doesn\'t exist, skipping.')
- return
- with open(toolchain_data_file) as temp_f:
- toolchain_data = json.load(temp_f)
- if not os.path.isdir(toolchain_data['path']):
- _LOGGER.error('The toolchain JSON file is invalid.')
- return
- dia_sdk_binaries_dir = os.path.join(toolchain_data['path'], 'DIA SDK', 'bin')
- dia_dll = os.path.join(dia_sdk_binaries_dir, _DIA_DLL_NAME)
- if not os.path.exists(dia_dll):
- _LOGGER.debug('%s is missing, skipping.')
- return
- dia_dll_dest = os.path.join(options.output_dir, 'exe', _DIA_DLL_NAME)
- _LOGGER.debug('Copying %s to %s.' % (dia_dll, dia_dll_dest))
- if not options.dry_run:
- shutil.copy(dia_dll, dia_dll_dest)
- contents[os.path.relpath(dia_dll_dest, options.output_dir)] = (
- _Md5(dia_dll_dest))
-
-
-def _InstallBinaries(options, deleted={}):
- """Installs Syzygy binaries. This assumes that the output directory has
- already been cleaned, as it will refuse to overwrite existing files."""
- contents = {}
- state = { 'revision': options.revision, 'contents': contents }
- archive_path = _SYZYGY_ARCHIVE_PATH % { 'revision': options.revision }
- if options.resources:
- resources = [(resource, resource, '', None)
- for resource in options.resources]
- else:
- resources = _RESOURCES
- for (base, name, subdir, filt) in resources:
- # Create the output directory if it doesn't exist.
- fulldir = os.path.join(options.output_dir, subdir)
- if os.path.isfile(fulldir):
- raise Exception('File exists where a directory needs to be created: %s' %
- fulldir)
- if not os.path.exists(fulldir):
- _LOGGER.debug('Creating directory: %s', fulldir)
- if not options.dry_run:
- os.makedirs(fulldir)
-
- # Download and read the archive.
- resource = archive_path + '/' + base
- _LOGGER.debug('Retrieving %s archive at "%s".', name, resource)
- path = _Download(resource)
-
- _LOGGER.debug('Unzipping %s archive.', name)
- with open(path, 'rb') as data:
- archive = zipfile.ZipFile(data)
- for entry in archive.infolist():
- if not filt or filt(entry):
- fullpath = os.path.normpath(os.path.join(fulldir, entry.filename))
- relpath = os.path.relpath(fullpath, options.output_dir)
- if os.path.exists(fullpath):
- # If in a dry-run take into account the fact that the file *would*
- # have been deleted.
- if options.dry_run and relpath in deleted:
- pass
- else:
- raise Exception('Path already exists: %s' % fullpath)
-
- # Extract the file and update the state dictionary.
- _LOGGER.debug('Extracting "%s".', fullpath)
- if not options.dry_run:
- archive.extract(entry.filename, fulldir)
- md5 = _Md5(fullpath)
- contents[relpath] = md5
- if sys.platform == 'cygwin':
- os.chmod(fullpath, os.stat(fullpath).st_mode | stat.S_IXUSR)
-
- _LOGGER.debug('Removing temporary file "%s".', path)
- os.remove(path)
-
- if options.copy_dia_binaries:
- # Try to copy the DIA binaries to the binaries directory.
- _MaybeCopyDIABinaries(options, contents)
-
- return state
-
-
-def _ParseCommandLine():
- """Parses the command-line and returns an options structure."""
- option_parser = optparse.OptionParser()
- option_parser.add_option('--dry-run', action='store_true', default=False,
- help='If true then will simply list actions that would be performed.')
- option_parser.add_option('--force', action='store_true', default=False,
- help='Force an installation even if the binaries are up to date.')
- option_parser.add_option('--no-cleanup', action='store_true', default=False,
- help='Allow installation on non-Windows platforms, and skip the forced '
- 'cleanup step.')
- option_parser.add_option('--output-dir', type='string',
- help='The path where the binaries will be replaced. Existing binaries '
- 'will only be overwritten if not up to date.')
- option_parser.add_option('--overwrite', action='store_true', default=False,
- help='If specified then the installation will happily delete and rewrite '
- 'the entire output directory, blasting any local changes.')
- option_parser.add_option('--revision', type='string',
- help='The SVN revision or GIT hash associated with the required version.')
- option_parser.add_option('--revision-file', type='string',
- help='A text file containing an SVN revision or GIT hash.')
- option_parser.add_option('--resource', type='string', action='append',
- dest='resources', help='A resource to be downloaded.')
- option_parser.add_option('--verbose', dest='log_level', action='store_const',
- default=logging.INFO, const=logging.DEBUG,
- help='Enables verbose logging.')
- option_parser.add_option('--quiet', dest='log_level', action='store_const',
- default=logging.INFO, const=logging.ERROR,
- help='Disables all output except for errors.')
- option_parser.add_option('--copy-dia-binaries', action='store_true',
- default=False, help='If true then the DIA dll will get copied into the '
- 'binaries directory if it\'s available.')
- options, args = option_parser.parse_args()
- if args:
- option_parser.error('Unexpected arguments: %s' % args)
- if not options.output_dir:
- option_parser.error('Must specify --output-dir.')
- if not options.revision and not options.revision_file:
- option_parser.error('Must specify one of --revision or --revision-file.')
- if options.revision and options.revision_file:
- option_parser.error('Must not specify both --revision and --revision-file.')
-
- # Configure logging.
- logging.basicConfig(level=options.log_level)
-
- # If a revision file has been specified then read it.
- if options.revision_file:
- options.revision = open(options.revision_file, 'rb').read().strip()
- _LOGGER.debug('Parsed revision "%s" from file "%s".',
- options.revision, options.revision_file)
-
- # Ensure that the specified SVN revision or GIT hash is valid.
- if not _REVISION_RE.match(options.revision):
- option_parser.error('Must specify a valid SVN or GIT revision.')
-
- # This just makes output prettier to read.
- options.output_dir = os.path.normpath(options.output_dir)
-
- return options
-
-
-def _RemoveOrphanedFiles(options):
- """This is run on non-Windows systems to remove orphaned files that may have
- been downloaded by a previous version of this script.
- """
- # Reconfigure logging to output info messages. This will allow inspection of
- # cleanup status on non-Windows buildbots.
- _LOGGER.setLevel(logging.INFO)
-
- output_dir = os.path.abspath(options.output_dir)
-
- # We only want to clean up the folder in 'src/third_party/syzygy', and we
- # expect to be called with that as an output directory. This is an attempt to
- # not start deleting random things if the script is run from an alternate
- # location, or not called from the gclient hooks.
- expected_syzygy_dir = os.path.abspath(os.path.join(
- os.path.dirname(__file__), '..', 'third_party', 'syzygy'))
- expected_output_dir = os.path.join(expected_syzygy_dir, 'binaries')
- if expected_output_dir != output_dir:
- _LOGGER.info('Unexpected output directory, skipping cleanup.')
- return
-
- if not os.path.isdir(expected_syzygy_dir):
- _LOGGER.info('Output directory does not exist, skipping cleanup.')
- return
-
- def OnError(function, path, excinfo):
- """Logs error encountered by shutil.rmtree."""
- _LOGGER.error('Error when running %s(%s)', function, path, exc_info=excinfo)
-
- _LOGGER.info('Removing orphaned files from %s', expected_syzygy_dir)
- if not options.dry_run:
- shutil.rmtree(expected_syzygy_dir, True, OnError)
-
-
-def main():
- options = _ParseCommandLine()
-
- if options.dry_run:
- _LOGGER.debug('Performing a dry-run.')
-
- # We only care about Windows platforms, as the Syzygy binaries aren't used
- # elsewhere. However, there was a short period of time where this script
- # wasn't gated on OS types, and those OSes downloaded and installed binaries.
- # This will cleanup orphaned files on those operating systems.
- if sys.platform not in ('win32', 'cygwin'):
- if options.no_cleanup:
- _LOGGER.debug('Skipping usual cleanup for non-Windows platforms.')
- else:
- return _RemoveOrphanedFiles(options)
-
- # Load the current installation state, and validate it against the
- # requested installation.
- state, is_consistent = _GetCurrentState(options.revision, options.output_dir)
-
- # Decide whether or not an install is necessary.
- if options.force:
- _LOGGER.debug('Forcing reinstall of binaries.')
- elif is_consistent:
- # Avoid doing any work if the contents of the directory are consistent.
- _LOGGER.debug('State unchanged, no reinstall necessary.')
- return
-
- # Under normal logging this is the only only message that will be reported.
- _LOGGER.info('Installing revision %s Syzygy binaries.',
- options.revision[0:12])
-
- # Clean up the old state to begin with.
- deleted = []
- if options.overwrite:
- if os.path.exists(options.output_dir):
- # If overwrite was specified then take a heavy-handed approach.
- _LOGGER.debug('Deleting entire installation directory.')
- if not options.dry_run:
- _RmTree(options.output_dir)
- else:
- # Otherwise only delete things that the previous installation put in place,
- # and take care to preserve any local changes.
- deleted = _CleanState(options.output_dir, state, options.dry_run)
-
- # Install the new binaries. In a dry-run this will actually download the
- # archives, but it won't write anything to disk.
- state = _InstallBinaries(options, deleted)
-
- # Build and save the state for the directory.
- _SaveState(options.output_dir, state, options.dry_run)
-
-
-if __name__ == '__main__':
- main()
diff --git a/build/gn_helpers_unittest.py b/build/gn_helpers_unittest.py
deleted file mode 100644
index cc6018a172..0000000000
--- a/build/gn_helpers_unittest.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# Copyright 2016 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.
-
-import gn_helpers
-import unittest
-
-class UnitTest(unittest.TestCase):
- def test_ToGNString(self):
- self.assertEqual(
- gn_helpers.ToGNString([1, 'two', [ '"thr$\\', True, False, [] ]]),
- '[ 1, "two", [ "\\"thr\\$\\\\", true, false, [ ] ] ]')
-
- def test_UnescapeGNString(self):
- # Backslash followed by a \, $, or " means the folling character without
- # the special meaning. Backslash followed by everything else is a literal.
- self.assertEqual(
- gn_helpers.UnescapeGNString('\\as\\$\\\\asd\\"'),
- '\\as$\\asd"')
-
- def test_FromGNString(self):
- self.assertEqual(
- gn_helpers.FromGNString('[1, -20, true, false,["as\\"", []]]'),
- [ 1, -20, True, False, [ 'as"', [] ] ])
-
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('123 456')
- parser.Parse()
-
- def test_ParseBool(self):
- parser = gn_helpers.GNValueParser('true')
- self.assertEqual(parser.Parse(), True)
-
- parser = gn_helpers.GNValueParser('false')
- self.assertEqual(parser.Parse(), False)
-
- def test_ParseNumber(self):
- parser = gn_helpers.GNValueParser('123')
- self.assertEqual(parser.ParseNumber(), 123)
-
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('')
- parser.ParseNumber()
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('a123')
- parser.ParseNumber()
-
- def test_ParseString(self):
- parser = gn_helpers.GNValueParser('"asdf"')
- self.assertEqual(parser.ParseString(), 'asdf')
-
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('') # Empty.
- parser.ParseString()
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('asdf') # Unquoted.
- parser.ParseString()
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('"trailing') # Unterminated.
- parser.ParseString()
-
- def test_ParseList(self):
- parser = gn_helpers.GNValueParser('[1,]') # Optional end comma OK.
- self.assertEqual(parser.ParseList(), [ 1 ])
-
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('') # Empty.
- parser.ParseList()
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('asdf') # No [].
- parser.ParseList()
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('[1, 2') # Unterminated
- parser.ParseList()
- with self.assertRaises(gn_helpers.GNException):
- parser = gn_helpers.GNValueParser('[1 2]') # No separating comma.
- parser.ParseList()
-
- def test_FromGNArgs(self):
- # Booleans and numbers should work; whitespace is allowed works.
- self.assertEqual(gn_helpers.FromGNArgs('foo = true\nbar = 1\n'),
- {'foo': True, 'bar': 1})
-
- # Whitespace is not required; strings should also work.
- self.assertEqual(gn_helpers.FromGNArgs('foo="bar baz"'),
- {'foo': 'bar baz'})
-
- # Lists should work.
- self.assertEqual(gn_helpers.FromGNArgs('foo=[1, 2, 3]'),
- {'foo': [1, 2, 3]})
-
- # Empty strings should return an empty dict.
- self.assertEqual(gn_helpers.FromGNArgs(''), {})
- self.assertEqual(gn_helpers.FromGNArgs(' \n '), {})
-
- # Non-identifiers should raise an exception.
- with self.assertRaises(gn_helpers.GNException):
- gn_helpers.FromGNArgs('123 = true')
-
- # References to other variables should raise an exception.
- with self.assertRaises(gn_helpers.GNException):
- gn_helpers.FromGNArgs('foo = bar')
-
- # References to functions should raise an exception.
- with self.assertRaises(gn_helpers.GNException):
- gn_helpers.FromGNArgs('foo = exec_script("//build/baz.py")')
-
- # Underscores in identifiers should work.
- self.assertEqual(gn_helpers.FromGNArgs('_foo = true'),
- {'_foo': True})
- self.assertEqual(gn_helpers.FromGNArgs('foo_bar = true'),
- {'foo_bar': True})
- self.assertEqual(gn_helpers.FromGNArgs('foo_=true'),
- {'foo_': True})
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/build/gn_run_binary.py b/build/gn_run_binary.py
deleted file mode 100644
index d7f7165e18..0000000000
--- a/build/gn_run_binary.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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.
-
-"""Helper script for GN to run an arbitrary binary. See compiled_action.gni.
-
-Run with:
- python gn_run_binary.py <binary_name> [args ...]
-"""
-
-import subprocess
-import sys
-
-# This script is designed to run binaries produced by the current build. We
-# always prefix it with "./" to avoid picking up system versions that might
-# also be on the path.
-path = './' + sys.argv[1]
-
-# The rest of the arguments are passed directly to the executable.
-args = [path] + sys.argv[2:]
-
-ret = subprocess.call(args)
-if ret != 0:
- if ret <= -100:
- # Windows error codes such as 0xC0000005 and 0xC0000409 are much easier to
- # recognize and differentiate in hex. In order to print them as unsigned
- # hex we need to add 4 Gig to them.
- print '%s failed with exit code 0x%08X' % (sys.argv[1], ret + (1 << 32))
- else:
- print '%s failed with exit code %d' % (sys.argv[1], ret)
-sys.exit(ret)
diff --git a/build/gyp_chromium.py b/build/gyp_chromium.py
deleted file mode 100644
index ab2e470dce..0000000000
--- a/build/gyp_chromium.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (c) 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.
-
-"""This script is now only used by the closure_compilation builders."""
-
-import argparse
-import glob
-import gyp_environment
-import os
-import shlex
-import sys
-
-script_dir = os.path.dirname(os.path.realpath(__file__))
-chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
-
-sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
-import gyp
-
-
-def ProcessGypDefinesItems(items):
- """Converts a list of strings to a list of key-value pairs."""
- result = []
- for item in items:
- tokens = item.split('=', 1)
- # Some GYP variables have hyphens, which we don't support.
- if len(tokens) == 2:
- result += [(tokens[0], tokens[1])]
- else:
- # No value supplied, treat it as a boolean and set it. Note that we
- # use the string '1' here so we have a consistent definition whether
- # you do 'foo=1' or 'foo'.
- result += [(tokens[0], '1')]
- return result
-
-
-def GetSupplementalFiles():
- return []
-
-
-def GetGypVars(_):
- """Returns a dictionary of all GYP vars."""
- # GYP defines from the environment.
- env_items = ProcessGypDefinesItems(
- shlex.split(os.environ.get('GYP_DEFINES', '')))
-
- # GYP defines from the command line.
- parser = argparse.ArgumentParser()
- parser.add_argument('-D', dest='defines', action='append', default=[])
- cmdline_input_items = parser.parse_known_args()[0].defines
- cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
-
- return dict(env_items + cmdline_items)
-
-
-def main():
- gyp_environment.SetEnvironment()
-
- print 'Updating projects from gyp files...'
- sys.stdout.flush()
- sys.exit(gyp.main(sys.argv[1:] + [
- '--check',
- '--no-circular-check',
- '-I', os.path.join(script_dir, 'common.gypi'),
- '-D', 'gyp_output_dir=out']))
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/gyp_environment.py b/build/gyp_environment.py
deleted file mode 100644
index 51b9136f24..0000000000
--- a/build/gyp_environment.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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.
-
-"""
-Sets up various automatic gyp environment variables. These are used by
-gyp_chromium and landmines.py which run at different stages of runhooks. To
-make sure settings are consistent between them, all setup should happen here.
-"""
-
-import gyp_helper
-import os
-import sys
-import vs_toolchain
-
-def SetEnvironment():
- """Sets defaults for GYP_* variables."""
- gyp_helper.apply_chromium_gyp_env()
-
- # Default to ninja on linux and windows, but only if no generator has
- # explicitly been set.
- # Also default to ninja on mac, but only when not building chrome/ios.
- # . -f / --format has precedence over the env var, no need to check for it
- # . set the env var only if it hasn't been set yet
- # . chromium.gyp_env has been applied to os.environ at this point already
- if sys.platform.startswith(('linux', 'win', 'freebsd', 'darwin')) and \
- not os.environ.get('GYP_GENERATORS'):
- os.environ['GYP_GENERATORS'] = 'ninja'
-
- vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
diff --git a/build/gyp_helper.py b/build/gyp_helper.py
deleted file mode 100644
index c840f2d6dc..0000000000
--- a/build/gyp_helper.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (c) 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.
-
-# This file helps gyp_chromium and landmines correctly set up the gyp
-# environment from chromium.gyp_env on disk
-
-import os
-
-SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
-CHROME_SRC = os.path.dirname(SCRIPT_DIR)
-
-
-def apply_gyp_environment_from_file(file_path):
- """Reads in a *.gyp_env file and applies the valid keys to os.environ."""
- if not os.path.exists(file_path):
- return
- with open(file_path, 'rU') as f:
- file_contents = f.read()
- try:
- file_data = eval(file_contents, {'__builtins__': None}, None)
- except SyntaxError, e:
- e.filename = os.path.abspath(file_path)
- raise
- supported_vars = (
- 'CC',
- 'CC_wrapper',
- 'CC.host_wrapper',
- 'CHROMIUM_GYP_FILE',
- 'CHROMIUM_GYP_SYNTAX_CHECK',
- 'CXX',
- 'CXX_wrapper',
- 'CXX.host_wrapper',
- 'GYP_DEFINES',
- 'GYP_GENERATOR_FLAGS',
- 'GYP_CROSSCOMPILE',
- 'GYP_GENERATOR_OUTPUT',
- 'GYP_GENERATORS',
- 'GYP_INCLUDE_FIRST',
- 'GYP_INCLUDE_LAST',
- 'GYP_MSVS_VERSION',
- )
- for var in supported_vars:
- file_val = file_data.get(var)
- if file_val:
- if var in os.environ:
- behavior = 'replaces'
- if var == 'GYP_DEFINES':
- result = file_val + ' ' + os.environ[var]
- behavior = 'merges with, and individual components override,'
- else:
- result = os.environ[var]
- print 'INFO: Environment value for "%s" %s value in %s' % (
- var, behavior, os.path.abspath(file_path)
- )
- string_padding = max(len(var), len(file_path), len('result'))
- print ' %s: %s' % (var.rjust(string_padding), os.environ[var])
- print ' %s: %s' % (file_path.rjust(string_padding), file_val)
- os.environ[var] = result
- else:
- os.environ[var] = file_val
-
-
-def apply_chromium_gyp_env():
- if 'SKIP_CHROMIUM_GYP_ENV' not in os.environ:
- # Update the environment based on chromium.gyp_env
- path = os.path.join(os.path.dirname(CHROME_SRC), 'chromium.gyp_env')
- apply_gyp_environment_from_file(path)
diff --git a/build/gypi_to_gn.py b/build/gypi_to_gn.py
deleted file mode 100644
index 2a3a72ac0f..0000000000
--- a/build/gypi_to_gn.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# 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.
-
-"""Converts a given gypi file to a python scope and writes the result to stdout.
-
-USING THIS SCRIPT IN CHROMIUM
-
-Forking Python to run this script in the middle of GN is slow, especially on
-Windows, and it makes both the GYP and GN files harder to follow. You can't
-use "git grep" to find files in the GN build any more, and tracking everything
-in GYP down requires a level of indirection. Any calls will have to be removed
-and cleaned up once the GYP-to-GN transition is complete.
-
-As a result, we only use this script when the list of files is large and
-frequently-changing. In these cases, having one canonical list outweights the
-downsides.
-
-As of this writing, the GN build is basically complete. It's likely that all
-large and frequently changing targets where this is appropriate use this
-mechanism already. And since we hope to turn down the GYP build soon, the time
-horizon is also relatively short. As a result, it is likely that no additional
-uses of this script should every be added to the build. During this later part
-of the transition period, we should be focusing more and more on the absolute
-readability of the GN build.
-
-
-HOW TO USE
-
-It is assumed that the file contains a toplevel dictionary, and this script
-will return that dictionary as a GN "scope" (see example below). This script
-does not know anything about GYP and it will not expand variables or execute
-conditions.
-
-It will strip conditions blocks.
-
-A variables block at the top level will be flattened so that the variables
-appear in the root dictionary. This way they can be returned to the GN code.
-
-Say your_file.gypi looked like this:
- {
- 'sources': [ 'a.cc', 'b.cc' ],
- 'defines': [ 'ENABLE_DOOM_MELON' ],
- }
-
-You would call it like this:
- gypi_values = exec_script("//build/gypi_to_gn.py",
- [ rebase_path("your_file.gypi") ],
- "scope",
- [ "your_file.gypi" ])
-
-Notes:
- - The rebase_path call converts the gypi file from being relative to the
- current build file to being system absolute for calling the script, which
- will have a different current directory than this file.
-
- - The "scope" parameter tells GN to interpret the result as a series of GN
- variable assignments.
-
- - The last file argument to exec_script tells GN that the given file is a
- dependency of the build so Ninja can automatically re-run GN if the file
- changes.
-
-Read the values into a target like this:
- component("mycomponent") {
- sources = gypi_values.sources
- defines = gypi_values.defines
- }
-
-Sometimes your .gypi file will include paths relative to a different
-directory than the current .gn file. In this case, you can rebase them to
-be relative to the current directory.
- sources = rebase_path(gypi_values.sources, ".",
- "//path/gypi/input/values/are/relative/to")
-
-This script will tolerate a 'variables' in the toplevel dictionary or not. If
-the toplevel dictionary just contains one item called 'variables', it will be
-collapsed away and the result will be the contents of that dictinoary. Some
-.gypi files are written with or without this, depending on how they expect to
-be embedded into a .gyp file.
-
-This script also has the ability to replace certain substrings in the input.
-Generally this is used to emulate GYP variable expansion. If you passed the
-argument "--replace=<(foo)=bar" then all instances of "<(foo)" in strings in
-the input will be replaced with "bar":
-
- gypi_values = exec_script("//build/gypi_to_gn.py",
- [ rebase_path("your_file.gypi"),
- "--replace=<(foo)=bar"],
- "scope",
- [ "your_file.gypi" ])
-
-"""
-
-import gn_helpers
-from optparse import OptionParser
-import sys
-
-def LoadPythonDictionary(path):
- file_string = open(path).read()
- try:
- file_data = eval(file_string, {'__builtins__': None}, None)
- except SyntaxError, e:
- e.filename = path
- raise
- except Exception, e:
- raise Exception("Unexpected error while reading %s: %s" % (path, str(e)))
-
- assert isinstance(file_data, dict), "%s does not eval to a dictionary" % path
-
- # Flatten any variables to the top level.
- if 'variables' in file_data:
- file_data.update(file_data['variables'])
- del file_data['variables']
-
- # Strip all elements that this script can't process.
- elements_to_strip = [
- 'conditions',
- 'target_conditions',
- 'target_defaults',
- 'targets',
- 'includes',
- 'actions',
- ]
- for element in elements_to_strip:
- if element in file_data:
- del file_data[element]
-
- return file_data
-
-
-def ReplaceSubstrings(values, search_for, replace_with):
- """Recursively replaces substrings in a value.
-
- Replaces all substrings of the "search_for" with "repace_with" for all
- strings occurring in "values". This is done by recursively iterating into
- lists as well as the keys and values of dictionaries."""
- if isinstance(values, str):
- return values.replace(search_for, replace_with)
-
- if isinstance(values, list):
- return [ReplaceSubstrings(v, search_for, replace_with) for v in values]
-
- if isinstance(values, dict):
- # For dictionaries, do the search for both the key and values.
- result = {}
- for key, value in values.items():
- new_key = ReplaceSubstrings(key, search_for, replace_with)
- new_value = ReplaceSubstrings(value, search_for, replace_with)
- result[new_key] = new_value
- return result
-
- # Assume everything else is unchanged.
- return values
-
-def main():
- parser = OptionParser()
- parser.add_option("-r", "--replace", action="append",
- help="Replaces substrings. If passed a=b, replaces all substrs a with b.")
- (options, args) = parser.parse_args()
-
- if len(args) != 1:
- raise Exception("Need one argument which is the .gypi file to read.")
-
- data = LoadPythonDictionary(args[0])
- if options.replace:
- # Do replacements for all specified patterns.
- for replace in options.replace:
- split = replace.split('=')
- # Allow "foo=" to replace with nothing.
- if len(split) == 1:
- split.append('')
- assert len(split) == 2, "Replacement must be of the form 'key=value'."
- data = ReplaceSubstrings(data, split[0], split[1])
-
- # Sometimes .gypi files use the GYP syntax with percents at the end of the
- # variable name (to indicate not to overwrite a previously-defined value):
- # 'foo%': 'bar',
- # Convert these to regular variables.
- for key in data:
- if len(key) > 1 and key[len(key) - 1] == '%':
- data[key[:-1]] = data[key]
- del data[key]
-
- print gn_helpers.ToGNString(data)
-
-if __name__ == '__main__':
- try:
- main()
- except Exception, e:
- print str(e)
- sys.exit(1)
diff --git a/build/landmine_utils.py b/build/landmine_utils.py
deleted file mode 100644
index a3f21ff1b8..0000000000
--- a/build/landmine_utils.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2013 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.
-
-
-import sys
-
-
-def IsWindows():
- return sys.platform in ['win32', 'cygwin']
-
-
-def IsLinux():
- return sys.platform.startswith(('linux', 'freebsd', 'netbsd', 'openbsd'))
-
-
-def IsMac():
- return sys.platform == 'darwin'
-
-
-def host_os():
- """
- Returns a string representing the host_os of the current system.
- Possible values: 'win', 'mac', 'linux', 'unknown'.
- """
- if IsWindows():
- return 'win'
- elif IsLinux():
- return 'linux'
- elif IsMac():
- return 'mac'
- else:
- return 'unknown'
diff --git a/build/landmines.py b/build/landmines.py
deleted file mode 100755
index d0f429809a..0000000000
--- a/build/landmines.py
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 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.
-
-"""
-This script runs every build as the first hook (See DEPS). If it detects that
-the build should be clobbered, it will delete the contents of the build
-directory.
-
-A landmine is tripped when a builder checks out a different revision, and the
-diff between the new landmines and the old ones is non-null. At this point, the
-build is clobbered.
-
-Before adding or changing a landmine consider the consequences of doing so.
-Doing so will wipe out every output directory on every Chrome developer's
-machine. This can be particularly problematic on Windows where the directory
-deletion may well fail (locked files, command prompt in the directory, etc.),
-and generated .sln and .vcxproj files will be deleted.
-
-This output directory deletion will be repated when going back and forth across
-the change that added the landmine, adding to the cost. There are usually less
-troublesome alternatives.
-"""
-
-import difflib
-import errno
-import logging
-import optparse
-import os
-import sys
-import subprocess
-import time
-
-import clobber
-import landmine_utils
-
-
-def get_build_dir(src_dir):
- """
- Returns output directory absolute path dependent on build and targets.
- Examples:
- r'c:\b\build\slave\win\build\src\out'
- '/mnt/data/b/build/slave/linux/build/src/out'
- '/b/build/slave/ios_rel_device/build/src/out'
-
- Keep this function in sync with tools/build/scripts/slave/compile.py
- """
- if 'CHROMIUM_OUT_DIR' in os.environ:
- output_dir = os.environ.get('CHROMIUM_OUT_DIR').strip()
- if not output_dir:
- raise Error('CHROMIUM_OUT_DIR environment variable is set but blank!')
- else:
- output_dir = 'out'
- return os.path.abspath(os.path.join(src_dir, output_dir))
-
-
-def clobber_if_necessary(new_landmines, src_dir):
- """Does the work of setting, planting, and triggering landmines."""
- out_dir = get_build_dir(src_dir)
- landmines_path = os.path.normpath(os.path.join(src_dir, '.landmines'))
- try:
- os.makedirs(out_dir)
- except OSError as e:
- if e.errno == errno.EEXIST:
- pass
-
- if os.path.exists(landmines_path):
- with open(landmines_path, 'r') as f:
- old_landmines = f.readlines()
- if old_landmines != new_landmines:
- old_date = time.ctime(os.stat(landmines_path).st_ctime)
- diff = difflib.unified_diff(old_landmines, new_landmines,
- fromfile='old_landmines', tofile='new_landmines',
- fromfiledate=old_date, tofiledate=time.ctime(), n=0)
- sys.stdout.write('Clobbering due to:\n')
- sys.stdout.writelines(diff)
- sys.stdout.flush()
-
- clobber.clobber(out_dir)
-
- # Save current set of landmines for next time.
- with open(landmines_path, 'w') as f:
- f.writelines(new_landmines)
-
-
-def process_options():
- """Returns an options object containing the configuration for this script."""
- parser = optparse.OptionParser()
- parser.add_option(
- '-s', '--landmine-scripts', action='append',
- help='Path to the script which emits landmines to stdout. The target '
- 'is passed to this script via option -t. Note that an extra '
- 'script can be specified via an env var EXTRA_LANDMINES_SCRIPT.')
- parser.add_option('-d', '--src-dir',
- help='Path of the source root dir. Overrides the default location of the '
- 'source root dir when calculating the build directory.')
- parser.add_option('-v', '--verbose', action='store_true',
- default=('LANDMINES_VERBOSE' in os.environ),
- help=('Emit some extra debugging information (default off). This option '
- 'is also enabled by the presence of a LANDMINES_VERBOSE environment '
- 'variable.'))
-
- options, args = parser.parse_args()
-
- if args:
- parser.error('Unknown arguments %s' % args)
-
- logging.basicConfig(
- level=logging.DEBUG if options.verbose else logging.ERROR)
-
- if options.src_dir:
- if not os.path.isdir(options.src_dir):
- parser.error('Cannot find source root dir at %s' % options.src_dir)
- logging.debug('Overriding source root dir. Using: %s', options.src_dir)
- else:
- options.src_dir = \
- os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-
- if not options.landmine_scripts:
- options.landmine_scripts = [os.path.join(options.src_dir, 'build',
- 'get_landmines.py')]
-
- extra_script = os.environ.get('EXTRA_LANDMINES_SCRIPT')
- if extra_script:
- options.landmine_scripts += [extra_script]
-
- return options
-
-
-def main():
- options = process_options()
-
- landmines = []
- for s in options.landmine_scripts:
- proc = subprocess.Popen([sys.executable, s], stdout=subprocess.PIPE)
- output, _ = proc.communicate()
- landmines.extend([('%s\n' % l.strip()) for l in output.splitlines()])
- clobber_if_necessary(landmines, options.src_dir)
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/precompile.h b/build/precompile.h
deleted file mode 100644
index c699562c0c..0000000000
--- a/build/precompile.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 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.
-
-// This file is used as a precompiled header for both C and C++ files. So
-// any C++ headers must go in the __cplusplus block below.
-
-#if defined(BUILD_PRECOMPILE_H_)
-#error You shouldn't include the precompiled header file more than once.
-#endif
-
-#define BUILD_PRECOMPILE_H_
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <math.h>
-#include <memory.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#if defined(__cplusplus)
-
-#include <algorithm>
-#include <bitset>
-#include <cmath>
-#include <cstddef>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fstream>
-#include <functional>
-#include <iomanip>
-#include <iosfwd>
-#include <iterator>
-#include <limits>
-#include <list>
-#include <map>
-#include <numeric>
-#include <ostream>
-#include <queue>
-#include <set>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#endif // __cplusplus
diff --git a/build/print_python_deps.py b/build/print_python_deps.py
deleted file mode 100755
index 2459a28e6b..0000000000
--- a/build/print_python_deps.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/env vpython
-# Copyright 2016 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.
-
-"""Prints all non-system dependencies for the given module.
-
-The primary use-case for this script is to genererate the list of python modules
-required for .isolate files.
-"""
-
-import argparse
-import imp
-import os
-import pipes
-import sys
-
-# Don't use any helper modules, or else they will end up in the results.
-
-
-_SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
-
-
-def _ComputePythonDependencies():
- """Gets the paths of imported non-system python modules.
-
- A path is assumed to be a "system" import if it is outside of chromium's
- src/. The paths will be relative to the current directory.
- """
- module_paths = (m.__file__ for m in sys.modules.values()
- if m and hasattr(m, '__file__'))
-
- src_paths = set()
- for path in module_paths:
- if path == __file__:
- continue
- path = os.path.abspath(path)
- if not path.startswith(_SRC_ROOT):
- continue
-
- if (path.endswith('.pyc')
- or (path.endswith('c') and not os.path.splitext(path)[1])):
- path = path[:-1]
- src_paths.add(path)
-
- return src_paths
-
-
-def _NormalizeCommandLine(options):
- """Returns a string that when run from SRC_ROOT replicates the command."""
- args = ['build/print_python_deps.py']
- root = os.path.relpath(options.root, _SRC_ROOT)
- if root != '.':
- args.extend(('--root', root))
- if options.output:
- args.extend(('--output', os.path.relpath(options.output, _SRC_ROOT)))
- for whitelist in sorted(options.whitelists):
- args.extend(('--whitelist', os.path.relpath(whitelist, _SRC_ROOT)))
- args.append(os.path.relpath(options.module, _SRC_ROOT))
- return ' '.join(pipes.quote(x) for x in args)
-
-
-def _FindPythonInDirectory(directory):
- """Returns an iterable of all non-test python files in the given directory."""
- files = []
- for root, _dirnames, filenames in os.walk(directory):
- for filename in filenames:
- if filename.endswith('.py') and not filename.endswith('_test.py'):
- yield os.path.join(root, filename)
-
-
-def main():
- parser = argparse.ArgumentParser(
- description='Prints all non-system dependencies for the given module.')
- parser.add_argument('module',
- help='The python module to analyze.')
- parser.add_argument('--root', default='.',
- help='Directory to make paths relative to.')
- parser.add_argument('--output',
- help='Write output to a file rather than stdout.')
- parser.add_argument('--no-header', action='store_true',
- help='Do not write the "# Generated by" header.')
- parser.add_argument('--gn-paths', action='store_true',
- help='Write paths as //foo/bar/baz.py')
- parser.add_argument('--whitelist', default=[], action='append',
- dest='whitelists',
- help='Recursively include all non-test python files '
- 'within this directory. May be specified multiple times.')
- options = parser.parse_args()
- # Replace the path entry for print_python_deps.py with the one for the given
- # module.
- sys.path[0] = os.path.dirname(options.module)
- imp.load_source('NAME', options.module)
-
- paths_set = _ComputePythonDependencies()
- for path in options.whitelists:
- paths_set.update(os.path.abspath(p) for p in _FindPythonInDirectory(path))
-
- paths = [os.path.relpath(p, options.root) for p in paths_set]
-
- normalized_cmdline = _NormalizeCommandLine(options)
- out = open(options.output, 'w') if options.output else sys.stdout
- with out:
- if not options.no_header:
- out.write('# Generated by running:\n')
- out.write('# %s\n' % normalized_cmdline)
- prefix = '//' if options.gn_paths else ''
- for path in sorted(paths):
- out.write(prefix + path + '\n')
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/protoc_java.py b/build/protoc_java.py
deleted file mode 100755
index 2addb8210f..0000000000
--- a/build/protoc_java.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 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.
-
-"""Generate java source files from protobuf files.
-
-This is a helper file for the genproto_java action in protoc_java.gypi.
-
-It performs the following steps:
-1. Deletes all old sources (ensures deleted classes are not part of new jars).
-2. Creates source directory.
-3. Generates Java files using protoc (output into either --java-out-dir or
- --srcjar).
-4. Creates a new stamp file.
-"""
-
-import os
-import optparse
-import shutil
-import subprocess
-import sys
-
-sys.path.append(os.path.join(os.path.dirname(__file__), "android", "gyp"))
-from util import build_utils
-
-def main(argv):
- parser = optparse.OptionParser()
- build_utils.AddDepfileOption(parser)
- parser.add_option("--protoc", help="Path to protoc binary.")
- parser.add_option("--proto-path", help="Path to proto directory.")
- parser.add_option("--java-out-dir",
- help="Path to output directory for java files.")
- parser.add_option("--srcjar", help="Path to output srcjar.")
- parser.add_option("--stamp", help="File to touch on success.")
- parser.add_option("--nano",
- help="Use to generate nano protos.", action='store_true')
- options, args = parser.parse_args(argv)
-
- build_utils.CheckOptions(options, parser, ['protoc', 'proto_path'])
- if not options.java_out_dir and not options.srcjar:
- print 'One of --java-out-dir or --srcjar must be specified.'
- return 1
-
- with build_utils.TempDir() as temp_dir:
- if options.nano:
- # Specify arguments to the generator.
- generator_args = ['optional_field_style=reftypes',
- 'store_unknown_fields=true']
- out_arg = '--javanano_out=' + ','.join(generator_args) + ':' + temp_dir
- else:
- out_arg = '--java_out=' + temp_dir
-
- # Check if all proto files (which are listed in the args) are opting to
- # use the lite runtime, otherwise we'd have to include the much heavier
- # regular proto runtime in Chrome.
- # TODO(jkrcal): Replace this check by '--java_lite_out=' for the out_arg
- # above once this works on the master branch of the protobuf library,
- # expected in version 4.0 (see https://crbug.com/800281).
- for proto_file in args:
- if not 'LITE_RUNTIME' in open(proto_file).read():
- raise Exception(
- 'Chrome only supports lite protos. Please add "optimize_for = '
- 'LITE_RUNTIME" to your proto file to enable the lite runtime.')
- # Generate Java files using protoc.
- build_utils.CheckOutput(
- [options.protoc, '--proto_path', options.proto_path, out_arg]
- + args)
-
- if options.java_out_dir:
- build_utils.DeleteDirectory(options.java_out_dir)
- shutil.copytree(temp_dir, options.java_out_dir)
- else:
- build_utils.ZipDir(options.srcjar, temp_dir)
-
- if options.depfile:
- assert options.srcjar
- deps = args + [options.protoc]
- build_utils.WriteDepfile(options.depfile, options.srcjar, deps)
-
- if options.stamp:
- build_utils.Touch(options.stamp)
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))
diff --git a/build/redirect_stdout.py b/build/redirect_stdout.py
deleted file mode 100644
index 72d0732af1..0000000000
--- a/build/redirect_stdout.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2016 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.
-
-import subprocess
-import sys
-
-# This script executes a command and redirects the stdout to a file. This is
-# equivalent to |command... > output_file|.
-#
-# Usage: python redirect_stdout.py output_file command...
-
-if __name__ == '__main__':
- if len(sys.argv) < 2:
- print >> sys.stderr, "Usage: %s output_file command..." % (sys.argv[0])
- sys.exit(1)
-
- with open(sys.argv[1], 'w') as fp:
- sys.exit(subprocess.check_call(sys.argv[2:], stdout=fp))
diff --git a/build/rm.py b/build/rm.py
deleted file mode 100755
index 5ca642d46e..0000000000
--- a/build/rm.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2016 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.
-
-"""Delete a file.
-
-This module works much like the rm posix command.
-"""
-
-import argparse
-import os
-import sys
-
-
-def Main():
- parser = argparse.ArgumentParser()
- parser.add_argument('files', nargs='+')
- parser.add_argument('-f', '--force', action='store_true',
- help="don't err on missing")
- parser.add_argument('--stamp', required=True, help='touch this file')
- args = parser.parse_args()
- for f in args.files:
- try:
- os.remove(f)
- except OSError:
- if not args.force:
- print >>sys.stderr, "'%s' does not exist" % f
- return 1
-
- with open(args.stamp, 'w'):
- os.utime(args.stamp, None)
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(Main())
diff --git a/build/run_swarming_xcode_install.py b/build/run_swarming_xcode_install.py
deleted file mode 100755
index a731c1bd6b..0000000000
--- a/build/run_swarming_xcode_install.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 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.
-
-"""
-This script runs swarming_xcode_install on the bots. It should be run when we
-need to upgrade all the swarming testers. It:
- 1) Packages two python files into an isolate.
- 2) Runs the isolate on swarming machines that satisfy certain dimensions.
-
-Example usage:
- $ ./build/run_swarming_xcode_install.py --luci_path ~/work/luci-py \
- --swarming-server touch-swarming.appspot.com \
- --isolate-server touch-isolate.appspot.com
-"""
-
-import argparse
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-
-
-def main():
- parser = argparse.ArgumentParser(
- description='Run swarming_xcode_install on the bots.')
- parser.add_argument('--luci_path', required=True, type=os.path.abspath)
- parser.add_argument('--swarming-server', required=True, type=str)
- parser.add_argument('--isolate-server', required=True, type=str)
- parser.add_argument('--batches', type=int, default=25,
- help="Run xcode install in batches of size |batches|.")
- parser.add_argument('--dimension', nargs=2, action='append')
- args = parser.parse_args()
-
- args.dimension = args.dimension or []
-
- script_dir = os.path.dirname(os.path.abspath(__file__))
- tmp_dir = tempfile.mkdtemp(prefix='swarming_xcode')
- try:
- print 'Making isolate.'
- shutil.copyfile(os.path.join(script_dir, 'swarming_xcode_install.py'),
- os.path.join(tmp_dir, 'swarming_xcode_install.py'))
- shutil.copyfile(os.path.join(script_dir, 'mac_toolchain.py'),
- os.path.join(tmp_dir, 'mac_toolchain.py'))
-
- luci_client = os.path.join(args.luci_path, 'client')
- cmd = [
- sys.executable, os.path.join(luci_client, 'isolateserver.py'), 'archive',
- '-I', args.isolate_server, tmp_dir,
- ]
- isolate_hash = subprocess.check_output(cmd).split()[0]
-
- print 'Running swarming_xcode_install.'
- # TODO(crbug.com/765361): The dimensions below should be updated once
- # swarming for iOS is fleshed out, likely removing xcode_version 9 and
- # adding different dimensions.
- luci_tools = os.path.join(luci_client, 'tools')
- dimensions = [['pool', 'Chrome'], ['xcode_version', '9.0']] + args.dimension
- dim_args = []
- for d in dimensions:
- dim_args += ['--dimension'] + d
- cmd = [
- sys.executable, os.path.join(luci_tools, 'run_on_bots.py'),
- '--swarming', args.swarming_server, '--isolate-server',
- args.isolate_server, '--priority', '20', '--batches', str(args.batches),
- '--tags', 'name:run_swarming_xcode_install',
- ] + dim_args + ['--name', 'run_swarming_xcode_install', '--', isolate_hash,
- 'python', 'swarming_xcode_install.py',
- ]
- subprocess.check_call(cmd)
- print 'All tasks completed.'
-
- finally:
- shutil.rmtree(tmp_dir)
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/swarming_xcode_install.py b/build/swarming_xcode_install.py
deleted file mode 100755
index 7764aa55c7..0000000000
--- a/build/swarming_xcode_install.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 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.
-
-"""
-Script used to install Xcode on the swarming bots.
-"""
-
-import os
-import shutil
-import subprocess
-import sys
-import tarfile
-import tempfile
-
-import mac_toolchain
-
-VERSION = '9A235'
-URL = 'gs://chrome-mac-sdk/ios-toolchain-9A235-1.tgz'
-REMOVE_DIR = '/Applications/Xcode9.0-Beta4.app/'
-OUTPUT_DIR = '/Applications/Xcode9.0.app/'
-
-def main():
- # Check if it's already installed.
- if os.path.exists(OUTPUT_DIR):
- env = os.environ.copy()
- env['DEVELOPER_DIR'] = OUTPUT_DIR
- cmd = ['xcodebuild', '-version']
- found_version = \
- subprocess.Popen(cmd, env=env, stdout=subprocess.PIPE).communicate()[0]
- if VERSION in found_version:
- print "Xcode %s already installed" % VERSION
- sys.exit(0)
-
- # Confirm old dir is there first.
- if not os.path.exists(REMOVE_DIR):
- print "Failing early since %s isn't there." % REMOVE_DIR
- sys.exit(1)
-
- # Download Xcode.
- with tempfile.NamedTemporaryFile() as temp:
- env = os.environ.copy()
- env['PATH'] += ":/b/depot_tools"
- subprocess.check_call(['gsutil.py', 'cp', URL, temp.name], env=env)
- if os.path.exists(OUTPUT_DIR):
- shutil.rmtree(OUTPUT_DIR)
- if not os.path.exists(OUTPUT_DIR):
- os.makedirs(OUTPUT_DIR)
- tarfile.open(mode='r:gz', name=temp.name).extractall(path=OUTPUT_DIR)
-
- # Accept license, call runFirstLaunch.
- mac_toolchain.FinalizeUnpack(OUTPUT_DIR, 'ios')
-
- # Set new Xcode as default.
- subprocess.check_call(['sudo', '/usr/bin/xcode-select', '-s', OUTPUT_DIR])
-
- if os.path.exists(REMOVE_DIR):
- shutil.rmtree(REMOVE_DIR)
-
-
-if __name__ == '__main__':
- sys.exit(main())
-
diff --git a/build/symlink.py b/build/symlink.py
deleted file mode 100755
index 5a261dcad9..0000000000
--- a/build/symlink.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2013 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.
-
-"""Make a symlink and optionally touch a file (to handle dependencies).
-
-Usage:
- symlink.py [options] sources... target
-
-A sym link to source is created at target. If multiple sources are specfied,
-then target is assumed to be a directory, and will contain all the links to
-the sources (basenames identical to their source).
-"""
-
-import errno
-import optparse
-import os.path
-import shutil
-import sys
-
-
-def Main(argv):
- parser = optparse.OptionParser()
- parser.add_option('-f', '--force', action='store_true')
- parser.add_option('--touch')
-
- options, args = parser.parse_args(argv[1:])
- if len(args) < 2:
- parser.error('at least two arguments required.')
-
- target = args[-1]
- sources = args[:-1]
- for s in sources:
- t = os.path.join(target, os.path.basename(s))
- if len(sources) == 1 and not os.path.isdir(target):
- t = target
- t = os.path.expanduser(t)
- if os.path.realpath(t) == s:
- continue
- try:
- os.symlink(s, t)
- except OSError, e:
- if e.errno == errno.EEXIST and options.force:
- if os.path.isdir(t):
- shutil.rmtree(t, ignore_errors=True)
- else:
- os.remove(t)
- os.symlink(s, t)
- else:
- raise
-
-
- if options.touch:
- with open(options.touch, 'w') as f:
- pass
-
-
-if __name__ == '__main__':
- sys.exit(Main(sys.argv))
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
deleted file mode 100755
index 83847f4566..0000000000
--- a/build/vs_toolchain.py
+++ /dev/null
@@ -1,471 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import glob
-import json
-import os
-import pipes
-import platform
-import re
-import shutil
-import stat
-import subprocess
-import sys
-from gn_helpers import ToGNString
-
-
-script_dir = os.path.dirname(os.path.realpath(__file__))
-chrome_src = os.path.abspath(os.path.join(script_dir, os.pardir))
-SRC_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-sys.path.insert(0, os.path.join(chrome_src, 'tools', 'gyp', 'pylib'))
-json_data_file = os.path.join(script_dir, 'win_toolchain.json')
-
-
-# Use MSVS2017 as the default toolchain.
-CURRENT_DEFAULT_TOOLCHAIN_VERSION = '2017'
-
-
-def SetEnvironmentAndGetRuntimeDllDirs():
- """Sets up os.environ to use the depot_tools VS toolchain with gyp, and
- returns the location of the VS runtime DLLs so they can be copied into
- the output directory after gyp generation.
-
- Return value is [x64path, x86path] or None
- """
- vs_runtime_dll_dirs = None
- depot_tools_win_toolchain = \
- bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
- # When running on a non-Windows host, only do this if the SDK has explicitly
- # been downloaded before (in which case json_data_file will exist).
- if ((sys.platform in ('win32', 'cygwin') or os.path.exists(json_data_file))
- and depot_tools_win_toolchain):
- if ShouldUpdateToolchain():
- update_result = Update()
- if update_result != 0:
- raise Exception('Failed to update, error code %d.' % update_result)
- with open(json_data_file, 'r') as tempf:
- toolchain_data = json.load(tempf)
-
- toolchain = toolchain_data['path']
- version = toolchain_data['version']
- win_sdk = toolchain_data.get('win_sdk')
- if not win_sdk:
- win_sdk = toolchain_data['win8sdk']
- wdk = toolchain_data['wdk']
- # TODO(scottmg): The order unfortunately matters in these. They should be
- # split into separate keys for x86 and x64. (See CopyDlls call below).
- # http://crbug.com/345992
- vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
-
- os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
- os.environ['GYP_MSVS_VERSION'] = version
-
- os.environ['WINDOWSSDKDIR'] = win_sdk
- os.environ['WDK_DIR'] = wdk
- # Include the VS runtime in the PATH in case it's not machine-installed.
- runtime_path = os.path.pathsep.join(vs_runtime_dll_dirs)
- os.environ['PATH'] = runtime_path + os.path.pathsep + os.environ['PATH']
- elif sys.platform == 'win32' and not depot_tools_win_toolchain:
- if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ:
- os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath()
- if not 'GYP_MSVS_VERSION' in os.environ:
- os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
-
- # When using an installed toolchain these files aren't needed in the output
- # directory in order to run binaries locally, but they are needed in order
- # to create isolates or the mini_installer. Copying them to the output
- # directory ensures that they are available when needed.
- bitness = platform.architecture()[0]
- # When running 64-bit python the x64 DLLs will be in System32
- x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
- x64_path = os.path.join(os.path.expandvars('%windir%'), x64_path)
- vs_runtime_dll_dirs = [x64_path, os.path.expandvars('%windir%/SysWOW64')]
-
- return vs_runtime_dll_dirs
-
-
-def _RegistryGetValueUsingWinReg(key, value):
- """Use the _winreg module to obtain the value of a registry key.
-
- Args:
- key: The registry key.
- value: The particular registry value to read.
- Return:
- contents of the registry key's value, or None on failure. Throws
- ImportError if _winreg is unavailable.
- """
- import _winreg
- try:
- root, subkey = key.split('\\', 1)
- assert root == 'HKLM' # Only need HKLM for now.
- with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
- return _winreg.QueryValueEx(hkey, value)[0]
- except WindowsError:
- return None
-
-
-def _RegistryGetValue(key, value):
- try:
- return _RegistryGetValueUsingWinReg(key, value)
- except ImportError:
- raise Exception('The python library _winreg not found.')
-
-
-def GetVisualStudioVersion():
- """Return GYP_MSVS_VERSION of Visual Studio.
- """
- return os.environ.get('GYP_MSVS_VERSION', CURRENT_DEFAULT_TOOLCHAIN_VERSION)
-
-
-def DetectVisualStudioPath():
- """Return path to the GYP_MSVS_VERSION of Visual Studio.
- """
-
- # Note that this code is used from
- # build/toolchain/win/setup_toolchain.py as well.
- version_as_year = GetVisualStudioVersion()
- year_to_version = {
- '2017': '15.0',
- }
- if version_as_year not in year_to_version:
- raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)'
- ' not supported. Supported versions are: %s') % (
- version_as_year, ', '.join(year_to_version.keys())))
- version = year_to_version[version_as_year]
- if version_as_year == '2017':
- # The VC++ 2017 install location needs to be located using COM instead of
- # the registry. For details see:
- # https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/
- # For now we use a hardcoded default with an environment variable override.
- for path in (
- os.environ.get('vs2017_install'),
- os.path.expandvars('%ProgramFiles(x86)%'
- '/Microsoft Visual Studio/2017/Enterprise'),
- os.path.expandvars('%ProgramFiles(x86)%'
- '/Microsoft Visual Studio/2017/Professional'),
- os.path.expandvars('%ProgramFiles(x86)%'
- '/Microsoft Visual Studio/2017/Community')):
- if path and os.path.exists(path):
- return path
-
- raise Exception(('Visual Studio Version %s (from GYP_MSVS_VERSION)'
- ' not found.') % (version_as_year))
-
-
-def _CopyRuntimeImpl(target, source, verbose=True):
- """Copy |source| to |target| if it doesn't already exist or if it needs to be
- updated (comparing last modified time as an approximate float match as for
- some reason the values tend to differ by ~1e-07 despite being copies of the
- same file... https://crbug.com/603603).
- """
- if (os.path.isdir(os.path.dirname(target)) and
- (not os.path.isfile(target) or
- abs(os.stat(target).st_mtime - os.stat(source).st_mtime) >= 0.01)):
- if verbose:
- print 'Copying %s to %s...' % (source, target)
- if os.path.exists(target):
- # Make the file writable so that we can delete it now, and keep it
- # readable.
- os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
- os.unlink(target)
- shutil.copy2(source, target)
- # Make the file writable so that we can overwrite or delete it later,
- # keep it readable.
- os.chmod(target, stat.S_IWRITE | stat.S_IREAD)
-
-
-def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix):
- """Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
- exist, but the target directory does exist."""
- for file_part in ('msvcp', 'vccorlib', 'vcruntime'):
- dll = dll_pattern % file_part
- target = os.path.join(target_dir, dll)
- source = os.path.join(source_dir, dll)
- _CopyRuntimeImpl(target, source)
- # Copy the UCRT files from the Windows SDK. This location includes the
- # api-ms-win-crt-*.dll files that are not found in the Windows directory.
- # These files are needed for component builds. If WINDOWSSDKDIR is not set
- # use the default SDK path. This will be the case when
- # DEPOT_TOOLS_WIN_TOOLCHAIN=0 and vcvarsall.bat has not been run.
- win_sdk_dir = os.path.normpath(
- os.environ.get('WINDOWSSDKDIR',
- os.path.expandvars('%ProgramFiles(x86)%'
- '\\Windows Kits\\10')))
- ucrt_dll_dirs = os.path.join(win_sdk_dir, 'Redist', 'ucrt', 'DLLs',
- target_cpu)
- ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll'))
- assert len(ucrt_files) > 0
- for ucrt_src_file in ucrt_files:
- file_part = os.path.basename(ucrt_src_file)
- ucrt_dst_file = os.path.join(target_dir, file_part)
- _CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
- _CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
- os.path.join(source_dir, 'ucrtbase' + suffix))
-
-
-def FindVCToolsRoot():
- """In VS2017 the PGO runtime dependencies are located in
- {toolchain_root}/VC/Tools/MSVC/{x.y.z}/bin/Host{target_cpu}/{target_cpu}/, the
- {version_number} part is likely to change in case of a minor update of the
- toolchain so we don't hardcode this value here (except for the major number).
-
- This returns the '{toolchain_root}/VC/Tools/MSVC/{x.y.z}/bin/' path.
-
- This function should only be called when using VS2017.
- """
- assert GetVisualStudioVersion() == '2017'
- SetEnvironmentAndGetRuntimeDllDirs()
- assert ('GYP_MSVS_OVERRIDE_PATH' in os.environ)
- vc_tools_msvc_root = os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
- 'VC', 'Tools', 'MSVC')
- for directory in os.listdir(vc_tools_msvc_root):
- if not os.path.isdir(os.path.join(vc_tools_msvc_root, directory)):
- continue
- if re.match('14\.\d+\.\d+', directory):
- return os.path.join(vc_tools_msvc_root, directory, 'bin')
- raise Exception('Unable to find the VC tools directory.')
-
-
-def _CopyPGORuntime(target_dir, target_cpu):
- """Copy the runtime dependencies required during a PGO build.
- """
- env_version = GetVisualStudioVersion()
- # These dependencies will be in a different location depending on the version
- # of the toolchain.
- if env_version == '2017':
- pgo_runtime_root = FindVCToolsRoot()
- assert pgo_runtime_root
- # There's no version of pgosweep.exe in HostX64/x86, so we use the copy
- # from HostX86/x86.
- pgo_x86_runtime_dir = os.path.join(pgo_runtime_root, 'HostX86', 'x86')
- pgo_x64_runtime_dir = os.path.join(pgo_runtime_root, 'HostX64', 'x64')
- else:
- raise Exception('Unexpected toolchain version: %s.' % env_version)
-
- # We need to copy 2 runtime dependencies used during the profiling step:
- # - pgort140.dll: runtime library required to run the instrumented image.
- # - pgosweep.exe: executable used to collect the profiling data
- pgo_runtimes = ['pgort140.dll', 'pgosweep.exe']
- for runtime in pgo_runtimes:
- if target_cpu == 'x86':
- source = os.path.join(pgo_x86_runtime_dir, runtime)
- elif target_cpu == 'x64':
- source = os.path.join(pgo_x64_runtime_dir, runtime)
- else:
- raise NotImplementedError("Unexpected target_cpu value: " + target_cpu)
- if not os.path.exists(source):
- raise Exception('Unable to find %s.' % source)
- _CopyRuntimeImpl(os.path.join(target_dir, runtime), source)
-
-
-def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
- """Copy the VS runtime DLLs, only if the target doesn't exist, but the target
- directory does exist. Handles VS 2015 and VS 2017."""
- suffix = "d.dll" if debug else ".dll"
- # VS 2017 uses the same CRT DLLs as VS 2015.
- _CopyUCRTRuntime(target_dir, source_dir, target_cpu, '%s140' + suffix,
- suffix)
-
-
-def CopyDlls(target_dir, configuration, target_cpu):
- """Copy the VS runtime DLLs into the requested directory as needed.
-
- configuration is one of 'Debug' or 'Release'.
- target_cpu is one of 'x86' or 'x64'.
-
- The debug configuration gets both the debug and release DLLs; the
- release config only the latter.
- """
- vs_runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
- if not vs_runtime_dll_dirs:
- return
-
- x64_runtime, x86_runtime = vs_runtime_dll_dirs
- runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime
- _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False)
- if configuration == 'Debug':
- _CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True)
- else:
- _CopyPGORuntime(target_dir, target_cpu)
-
- _CopyDebugger(target_dir, target_cpu)
-
-
-def _CopyDebugger(target_dir, target_cpu):
- """Copy dbghelp.dll and dbgcore.dll into the requested directory as needed.
-
- target_cpu is one of 'x86' or 'x64'.
-
- dbghelp.dll is used when Chrome needs to symbolize stacks. Copying this file
- from the SDK directory avoids using the system copy of dbghelp.dll which then
- ensures compatibility with recent debug information formats, such as VS
- 2017 /debug:fastlink PDBs.
-
- dbgcore.dll is needed when using some functions from dbghelp.dll (like
- MinidumpWriteDump).
- """
- win_sdk_dir = SetEnvironmentAndGetSDKDir()
- if not win_sdk_dir:
- return
-
- # List of debug files that should be copied, the first element of the tuple is
- # the name of the file and the second indicates if it's optional.
- debug_files = [('dbghelp.dll', False), ('dbgcore.dll', True)]
- for debug_file, is_optional in debug_files:
- full_path = os.path.join(win_sdk_dir, 'Debuggers', target_cpu, debug_file)
- if not os.path.exists(full_path):
- if is_optional:
- continue
- else:
- # TODO(crbug.com/773476): remove version requirement.
- raise Exception('%s not found in "%s"\r\nYou must install the '
- '"Debugging Tools for Windows" feature from the Windows'
- ' 10 SDK. You must use v10.0.17134.0. of the SDK'
- % (debug_file, full_path))
- target_path = os.path.join(target_dir, debug_file)
- _CopyRuntimeImpl(target_path, full_path)
-
-
-def _GetDesiredVsToolchainHashes():
- """Load a list of SHA1s corresponding to the toolchains that we want installed
- to build with."""
- env_version = GetVisualStudioVersion()
- if env_version == '2017':
- # VS 2017 Update 7.1 (15.7.1) with 10.0.17134.12 SDK, rebuilt with
- # dbghelp.dll fix.
- toolchain_hash = '3bc0ec615cf20ee342f3bc29bc991b5ad66d8d2c'
- # Third parties that do not have access to the canonical toolchain can map
- # canonical toolchain version to their own toolchain versions.
- toolchain_hash_mapping_key = 'GYP_MSVS_HASH_%s' % toolchain_hash
- return [os.environ.get(toolchain_hash_mapping_key, toolchain_hash)]
- raise Exception('Unsupported VS version %s' % env_version)
-
-
-def ShouldUpdateToolchain():
- """Check if the toolchain should be upgraded."""
- if not os.path.exists(json_data_file):
- return True
- with open(json_data_file, 'r') as tempf:
- toolchain_data = json.load(tempf)
- version = toolchain_data['version']
- env_version = GetVisualStudioVersion()
- # If there's a mismatch between the version set in the environment and the one
- # in the json file then the toolchain should be updated.
- return version != env_version
-
-
-def Update(force=False):
- """Requests an update of the toolchain to the specific hashes we have at
- this revision. The update outputs a .json of the various configuration
- information required to pass to gyp which we use in |GetToolchainDir()|.
- """
- if force != False and force != '--force':
- print >>sys.stderr, 'Unknown parameter "%s"' % force
- return 1
- if force == '--force' or os.path.exists(json_data_file):
- force = True
-
- depot_tools_win_toolchain = \
- bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
- if ((sys.platform in ('win32', 'cygwin') or force) and
- depot_tools_win_toolchain):
- import find_depot_tools
- depot_tools_path = find_depot_tools.add_depot_tools_to_path()
-
- # On Linux, the file system is usually case-sensitive while the Windows
- # SDK only works on case-insensitive file systems. If it doesn't already
- # exist, set up a ciopfs fuse mount to put the SDK in a case-insensitive
- # part of the file system.
- toolchain_dir = os.path.join(depot_tools_path, 'win_toolchain', 'vs_files')
- # For testing this block, unmount existing mounts with
- # fusermount -u third_party/depot_tools/win_toolchain/vs_files
- if sys.platform.startswith('linux') and not os.path.ismount(toolchain_dir):
- import distutils.spawn
- ciopfs = distutils.spawn.find_executable('ciopfs')
- if not ciopfs:
- # ciopfs not found in PATH; try the one downloaded from the DEPS hook.
- ciopfs = os.path.join(script_dir, 'ciopfs')
- if not os.path.isdir(toolchain_dir):
- os.mkdir(toolchain_dir)
- if not os.path.isdir(toolchain_dir + '.ciopfs'):
- os.mkdir(toolchain_dir + '.ciopfs')
- # Without use_ino, clang's #pragma once and Wnonportable-include-path
- # both don't work right, see https://llvm.org/PR34931
- # use_ino doesn't slow down builds, so it seems there's no drawback to
- # just using it always.
- subprocess.check_call([
- ciopfs, '-o', 'use_ino', toolchain_dir + '.ciopfs', toolchain_dir])
-
- # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
- # in the correct directory.
- os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
- get_toolchain_args = [
- sys.executable,
- os.path.join(depot_tools_path,
- 'win_toolchain',
- 'get_toolchain_if_necessary.py'),
- '--output-json', json_data_file,
- ] + _GetDesiredVsToolchainHashes()
- if force:
- get_toolchain_args.append('--force')
- subprocess.check_call(get_toolchain_args)
-
- return 0
-
-
-def NormalizePath(path):
- while path.endswith("\\"):
- path = path[:-1]
- return path
-
-
-def SetEnvironmentAndGetSDKDir():
- """Gets location information about the current sdk (must have been
- previously updated by 'update'). This is used for the GN build."""
- SetEnvironmentAndGetRuntimeDllDirs()
-
- # If WINDOWSSDKDIR is not set, search the default SDK path and set it.
- if not 'WINDOWSSDKDIR' in os.environ:
- default_sdk_path = os.path.expandvars('%ProgramFiles(x86)%'
- '\\Windows Kits\\10')
- if os.path.isdir(default_sdk_path):
- os.environ['WINDOWSSDKDIR'] = default_sdk_path
-
- return NormalizePath(os.environ['WINDOWSSDKDIR'])
-
-
-def GetToolchainDir():
- """Gets location information about the current toolchain (must have been
- previously updated by 'update'). This is used for the GN build."""
- runtime_dll_dirs = SetEnvironmentAndGetRuntimeDllDirs()
- win_sdk_dir = SetEnvironmentAndGetSDKDir()
-
- print '''vs_path = %s
-sdk_path = %s
-vs_version = %s
-wdk_dir = %s
-runtime_dirs = %s
-''' % (
- ToGNString(NormalizePath(os.environ['GYP_MSVS_OVERRIDE_PATH'])),
- ToGNString(win_sdk_dir),
- ToGNString(GetVisualStudioVersion()),
- ToGNString(NormalizePath(os.environ.get('WDK_DIR', ''))),
- ToGNString(os.path.pathsep.join(runtime_dll_dirs or ['None'])))
-
-
-def main():
- commands = {
- 'update': Update,
- 'get_toolchain_dir': GetToolchainDir,
- 'copy_dlls': CopyDlls,
- }
- if len(sys.argv) < 2 or sys.argv[1] not in commands:
- print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
- return 1
- return commands[sys.argv[1]](*sys.argv[2:])
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/write_build_date_header.py b/build/write_build_date_header.py
deleted file mode 100755
index 6fe514fd78..0000000000
--- a/build/write_build_date_header.py
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2016 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.
-"""Writes a file that contains a define that approximates the build date.
-
-build_type impacts the timestamp generated:
-- default: the build date is set to the most recent first Sunday of a month at
- 5:00am. The reason is that it is a time where invalidating the build cache
- shouldn't have major reprecussions (due to lower load).
-- official: the build date is set to the current date at 5:00am, or the day
- before if the current time is before 5:00am.
-Either way, it is guaranteed to be in the past and always in UTC.
-
-It is also possible to explicitly set a build date to be used.
-"""
-
-import argparse
-import calendar
-import datetime
-import doctest
-import os
-import sys
-
-
-def GetFirstSundayOfMonth(year, month):
- """Returns the first sunday of the given month of the given year.
-
- >>> GetFirstSundayOfMonth(2016, 2)
- 7
- >>> GetFirstSundayOfMonth(2016, 3)
- 6
- >>> GetFirstSundayOfMonth(2000, 1)
- 2
- """
- weeks = calendar.Calendar().monthdays2calendar(year, month)
- # Return the first day in the first week that is a Sunday.
- return [date_day[0] for date_day in weeks[0] if date_day[1] == 6][0]
-
-
-def GetBuildDate(build_type, utc_now):
- """Gets the approximate build date given the specific build type.
-
- >>> GetBuildDate('default', datetime.datetime(2016, 2, 6, 1, 2, 3))
- 'Jan 03 2016 01:02:03'
- >>> GetBuildDate('default', datetime.datetime(2016, 2, 7, 5))
- 'Feb 07 2016 05:00:00'
- >>> GetBuildDate('default', datetime.datetime(2016, 2, 8, 5))
- 'Feb 07 2016 05:00:00'
- """
- day = utc_now.day
- month = utc_now.month
- year = utc_now.year
- if build_type != 'official':
- first_sunday = GetFirstSundayOfMonth(year, month)
- # If our build is after the first Sunday, we've already refreshed our build
- # cache on a quiet day, so just use that day.
- # Otherwise, take the first Sunday of the previous month.
- if day >= first_sunday:
- day = first_sunday
- else:
- month -= 1
- if month == 0:
- month = 12
- year -= 1
- day = GetFirstSundayOfMonth(year, month)
- now = datetime.datetime(
- year, month, day, utc_now.hour, utc_now.minute, utc_now.second)
- return '{:%b %d %Y %H:%M:%S}'.format(now)
-
-
-def main():
- if doctest.testmod()[0]:
- return 1
- argument_parser = argparse.ArgumentParser(
- description=sys.modules[__name__].__doc__,
- formatter_class=argparse.RawDescriptionHelpFormatter)
- argument_parser.add_argument('output_file', help='The file to write to')
- argument_parser.add_argument(
- 'build_type', help='The type of build', choices=('official', 'default'))
- argument_parser.add_argument(
- 'build_date_override', nargs='?',
- help='Optional override for the build date. Format must be '
- '\'Mmm DD YYYY HH:MM:SS\'')
- args = argument_parser.parse_args()
-
- if args.build_date_override:
- # Format is expected to be "Mmm DD YYYY HH:MM:SS".
- build_date = args.build_date_override
- else:
- now = datetime.datetime.utcnow()
- if now.hour < 5:
- # The time is locked at 5:00 am in UTC to cause the build cache
- # invalidation to not happen exactly at midnight. Use the same calculation
- # as the day before.
- # See //base/build_time.cc.
- now = now - datetime.timedelta(days=1)
- now = datetime.datetime(now.year, now.month, now.day, 5, 0, 0)
- build_date = GetBuildDate(args.build_type, now)
-
- output = ('// Generated by //build/write_build_date_header.py\n'
- '#ifndef BUILD_DATE\n'
- '#define BUILD_DATE "{}"\n'
- '#endif // BUILD_DATE\n'.format(build_date))
-
- current_contents = ''
- if os.path.isfile(args.output_file):
- with open(args.output_file, 'r') as current_file:
- current_contents = current_file.read()
-
- if current_contents != output:
- with open(args.output_file, 'w') as output_file:
- output_file.write(output)
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/build/write_buildflag_header.py b/build/write_buildflag_header.py
deleted file mode 100755
index d46cfc89a9..0000000000
--- a/build/write_buildflag_header.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2015 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.
-
-# This writes headers for build flags. See buildflag_header.gni for usage of
-# this system as a whole.
-#
-# The parameters are passed in a response file so we don't have to worry
-# about command line lengths. The name of the response file is passed on the
-# command line.
-#
-# The format of the response file is:
-# [--flags <list of one or more flag values>]
-
-import optparse
-import os
-import shlex
-import sys
-
-
-class Options:
- def __init__(self, output, rulename, header_guard, flags):
- self.output = output
- self.rulename = rulename
- self.header_guard = header_guard
- self.flags = flags
-
-
-def GetOptions():
- parser = optparse.OptionParser()
- parser.add_option('--output', help="Output header name inside --gen-dir.")
- parser.add_option('--rulename',
- help="Helpful name of build rule for including in the " +
- "comment at the top of the file.")
- parser.add_option('--gen-dir',
- help="Path to root of generated file directory tree.")
- parser.add_option('--definitions',
- help="Name of the response file containing the flags.")
- cmdline_options, cmdline_flags = parser.parse_args()
-
- # Compute header guard by replacing some chars with _ and upper-casing.
- header_guard = cmdline_options.output.upper()
- header_guard = \
- header_guard.replace('/', '_').replace('\\', '_').replace('.', '_')
- header_guard += '_'
-
- # The actual output file is inside the gen dir.
- output = os.path.join(cmdline_options.gen_dir, cmdline_options.output)
-
- # Definition file in GYP is newline separated, in GN they are shell formatted.
- # shlex can parse both of these.
- with open(cmdline_options.definitions, 'r') as def_file:
- defs = shlex.split(def_file.read())
- flags_index = defs.index('--flags')
-
- # Everything after --flags are flags. true/false are remapped to 1/0,
- # everything else is passed through.
- flags = []
- for flag in defs[flags_index + 1 :]:
- equals_index = flag.index('=')
- key = flag[:equals_index]
- value = flag[equals_index + 1:]
-
- # Canonicalize and validate the value.
- if value == 'true':
- value = '1'
- elif value == 'false':
- value = '0'
- flags.append((key, str(value)))
-
- return Options(output=output,
- rulename=cmdline_options.rulename,
- header_guard=header_guard,
- flags=flags)
-
-
-def WriteHeader(options):
- with open(options.output, 'w') as output_file:
- output_file.write("// Generated by build/write_buildflag_header.py\n")
- if options.rulename:
- output_file.write('// From "' + options.rulename + '"\n')
-
- output_file.write('\n#ifndef %s\n' % options.header_guard)
- output_file.write('#define %s\n\n' % options.header_guard)
- output_file.write('#include "build/buildflag.h"\n\n')
-
- for pair in options.flags:
- output_file.write('#define BUILDFLAG_INTERNAL_%s() (%s)\n' % pair)
-
- output_file.write('\n#endif // %s\n' % options.header_guard)
-
-
-options = GetOptions()
-WriteHeader(options)
diff --git a/components/json_schema/README b/components/json_schema/README
deleted file mode 100644
index c7453db06d..0000000000
--- a/components/json_schema/README
+++ /dev/null
@@ -1,6 +0,0 @@
-The //components/json_schema component provides:
-
-a) JSON schema constants, which can be used to inspect schema objects.
-
-b) The JSONSchemaValidator class, which can be used to parse and validate JSON
-schemas, and to validate JSON objects against the parsed schema.
diff --git a/components/json_schema/json_schema_validator_unittest.cc b/components/json_schema/json_schema_validator_unittest.cc
deleted file mode 100644
index b1559536d5..0000000000
--- a/components/json_schema/json_schema_validator_unittest.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2013 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 <stddef.h>
-
-#include "base/values.h"
-#include "components/json_schema/json_schema_validator.h"
-#include "components/json_schema/json_schema_validator_unittest_base.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class JSONSchemaValidatorCPPTest : public JSONSchemaValidatorTestBase {
- public:
- JSONSchemaValidatorCPPTest() {}
-
- protected:
- void ExpectValid(const std::string& test_source,
- base::Value* instance,
- base::DictionaryValue* schema,
- base::ListValue* types) override {
- JSONSchemaValidator validator(schema, types);
- if (validator.Validate(instance))
- return;
-
- for (size_t i = 0; i < validator.errors().size(); ++i) {
- ADD_FAILURE() << test_source << ": "
- << validator.errors()[i].path << ": "
- << validator.errors()[i].message;
- }
- }
-
- void ExpectNotValid(const std::string& test_source,
- base::Value* instance,
- base::DictionaryValue* schema,
- base::ListValue* types,
- const std::string& expected_error_path,
- const std::string& expected_error_message) override {
- JSONSchemaValidator validator(schema, types);
- if (validator.Validate(instance)) {
- ADD_FAILURE() << test_source;
- return;
- }
-
- ASSERT_EQ(1u, validator.errors().size()) << test_source;
- EXPECT_EQ(expected_error_path, validator.errors()[0].path) << test_source;
- EXPECT_EQ(expected_error_message, validator.errors()[0].message)
- << test_source;
- }
-};
-
-TEST_F(JSONSchemaValidatorCPPTest, Test) {
- RunTests();
-}
-
-TEST(JSONSchemaValidator, IsValidSchema) {
- std::string error;
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema("", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema("\0", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema("string", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema("\"string\"", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema("[]", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema("{}", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{ \"type\": 123 }", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{ \"type\": \"invalid\" }", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"object\","
- " \"properties\": []" // Invalid properties type.
- "}", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"string\","
- " \"maxLength\": -1" // Must be >= 0.
- "}", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"string\","
- " \"enum\": [ {} ]" // "enum" dict values must contain "name".
- "}", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"string\","
- " \"enum\": [ { \"name\": {} } ]" // "enum" name must be a simple value.
- "}", &error));
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"array\","
- " \"items\": [ 123 ]," // "items" must contain a schema or schemas.
- "}", &error));
- EXPECT_TRUE(JSONSchemaValidator::IsValidSchema(
- "{ \"type\": \"object\" }", &error)) << error;
- EXPECT_TRUE(JSONSchemaValidator::IsValidSchema(
- "{ \"type\": [\"object\", \"array\"] }", &error)) << error;
- EXPECT_TRUE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": [\"object\", \"array\"],"
- " \"properties\": {"
- " \"string-property\": {"
- " \"type\": \"string\","
- " \"minLength\": 1,"
- " \"maxLength\": 100,"
- " \"title\": \"The String Policy\","
- " \"description\": \"This policy controls the String widget.\""
- " },"
- " \"integer-property\": {"
- " \"type\": \"number\","
- " \"minimum\": 1000.0,"
- " \"maximum\": 9999.0"
- " },"
- " \"enum-property\": {"
- " \"type\": \"integer\","
- " \"enum\": [0, 1, {\"name\": 10}, 100]"
- " },"
- " \"items-property\": {"
- " \"type\": \"array\","
- " \"items\": {"
- " \"type\": \"string\""
- " }"
- " },"
- " \"items-list-property\": {"
- " \"type\": \"array\","
- " \"items\": ["
- " { \"type\": \"string\" },"
- " { \"type\": \"integer\" }"
- " ]"
- " }"
- " },"
- " \"additionalProperties\": {"
- " \"type\": \"any\""
- " }"
- "}", &error)) << error;
- EXPECT_TRUE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"object\","
- " \"patternProperties\": {"
- " \".\": { \"type\": \"any\" },"
- " \"foo\": { \"type\": \"any\" },"
- " \"^foo$\": { \"type\": \"any\" },"
- " \"foo+\": { \"type\": \"any\" },"
- " \"foo?\": { \"type\": \"any\" },"
- " \"fo{2,4}\": { \"type\": \"any\" },"
- " \"(left)|(right)\": { \"type\": \"any\" }"
- " }"
- "}", &error)) << error;
- EXPECT_TRUE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"object\","
- " \"unknown attribute\": \"that should just be ignored\""
- "}",
- JSONSchemaValidator::OPTIONS_IGNORE_UNKNOWN_ATTRIBUTES,
- &error)) << error;
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(
- "{"
- " \"type\": \"object\","
- " \"unknown attribute\": \"that will cause a failure\""
- "}", 0, &error)) << error;
-
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(R"(
- {
- "type": "object",
- "properties": {"foo": {"type": "number"}},
- "required": 123
- })",
- 0, &error))
- << error;
-
- EXPECT_FALSE(JSONSchemaValidator::IsValidSchema(R"(
- {
- "type": "object",
- "properties": {"foo": {"type": "number"}},
- "required": [ 123 ]
- })",
- 0, &error))
- << error;
-}
diff --git a/components/json_schema/json_schema_validator_unittest_base.cc b/components/json_schema/json_schema_validator_unittest_base.cc
deleted file mode 100644
index ce220dc479..0000000000
--- a/components/json_schema/json_schema_validator_unittest_base.cc
+++ /dev/null
@@ -1,710 +0,0 @@
-// Copyright 2013 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 "components/json_schema/json_schema_validator_unittest_base.h"
-
-#include <cfloat>
-#include <cmath>
-#include <limits>
-#include <memory>
-
-#include "base/base_paths.h"
-#include "base/files/file_util.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "components/json_schema/json_schema_constants.h"
-#include "components/json_schema/json_schema_validator.h"
-
-namespace schema = json_schema_constants;
-
-namespace {
-
-#define TEST_SOURCE base::StringPrintf("%s:%i", __FILE__, __LINE__)
-
-base::Value* LoadValue(const std::string& filename) {
- base::FilePath path;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
- path = path.AppendASCII("components")
- .AppendASCII("test")
- .AppendASCII("data")
- .AppendASCII("json_schema")
- .AppendASCII(filename);
- EXPECT_TRUE(base::PathExists(path));
-
- std::string error_message;
- JSONFileValueDeserializer deserializer(path);
- base::Value* result =
- deserializer.Deserialize(nullptr, &error_message).release();
- if (!result)
- ADD_FAILURE() << "Could not parse JSON: " << error_message;
- return result;
-}
-
-base::Value* LoadValue(const std::string& filename, base::Value::Type type) {
- std::unique_ptr<base::Value> result(LoadValue(filename));
- if (!result)
- return nullptr;
- if (result->type() != type) {
- ADD_FAILURE() << "Expected type " << type << ", got: " << result->type();
- return nullptr;
- }
- return result.release();
-}
-
-base::ListValue* LoadList(const std::string& filename) {
- return static_cast<base::ListValue*>(
- LoadValue(filename, base::Value::Type::LIST));
-}
-
-base::DictionaryValue* LoadDictionary(const std::string& filename) {
- return static_cast<base::DictionaryValue*>(
- LoadValue(filename, base::Value::Type::DICTIONARY));
-}
-
-} // namespace
-
-
-JSONSchemaValidatorTestBase::JSONSchemaValidatorTestBase() {
-}
-
-void JSONSchemaValidatorTestBase::RunTests() {
- TestComplex();
- TestStringPattern();
- TestEnum();
- TestChoices();
- TestExtends();
- TestObject();
- TestTypeReference();
- TestArrayTuple();
- TestArrayNonTuple();
- TestString();
- TestNumber();
- TestTypeClassifier();
- TestTypes();
-}
-
-void JSONSchemaValidatorTestBase::TestComplex() {
- std::unique_ptr<base::DictionaryValue> schema(
- LoadDictionary("complex_schema.json"));
- std::unique_ptr<base::ListValue> instance(LoadList("complex_instance.json"));
-
- ASSERT_TRUE(schema.get());
- ASSERT_TRUE(instance.get());
-
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Remove(instance->GetSize() - 1, nullptr);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Append(std::make_unique<base::DictionaryValue>());
- ExpectNotValid(
- TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kNumber, schema::kObject));
- instance->Remove(instance->GetSize() - 1, nullptr);
-
- base::DictionaryValue* item = nullptr;
- ASSERT_TRUE(instance->GetDictionary(0, &item));
- item->SetString("url", "xxxxxxxxxxx");
-
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0.url",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kStringMaxLength, "10"));
-}
-
-void JSONSchemaValidatorTestBase::TestStringPattern() {
- std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
- schema->SetString(schema::kType, schema::kString);
- schema->SetString(schema::kPattern, "foo+");
-
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("foo")).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("foooooo")).get(),
- schema.get(), nullptr);
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("bar")).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kStringPattern, "foo+"));
-}
-
-void JSONSchemaValidatorTestBase::TestEnum() {
- std::unique_ptr<base::DictionaryValue> schema(
- LoadDictionary("enum_schema.json"));
-
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("foo")).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(false)).get(),
- schema.get(), nullptr);
-
- ExpectNotValid(
- TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value("42")).get(),
- schema.get(), nullptr, std::string(), JSONSchemaValidator::kInvalidEnum);
- ExpectNotValid(TEST_SOURCE, std::make_unique<base::Value>().get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::kInvalidEnum);
-}
-
-void JSONSchemaValidatorTestBase::TestChoices() {
- std::unique_ptr<base::DictionaryValue> schema(
- LoadDictionary("choices_schema.json"));
-
- ExpectValid(TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(),
- nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr);
-
- std::unique_ptr<base::DictionaryValue> instance(new base::DictionaryValue());
- instance->SetString("foo", "bar");
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("foo")).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::kInvalidChoice);
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::ListValue()).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::kInvalidChoice);
-
- instance->SetInteger("foo", 42);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
- std::string(), JSONSchemaValidator::kInvalidChoice);
-}
-
-void JSONSchemaValidatorTestBase::TestExtends() {
- // TODO(aa): JS only
-}
-
-void JSONSchemaValidatorTestBase::TestObject() {
- std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
- schema->SetString(schema::kType, schema::kObject);
- schema->SetString("properties.foo.type", schema::kString);
- schema->SetString("properties.bar.type", schema::kInteger);
-
- std::unique_ptr<base::DictionaryValue> instance(new base::DictionaryValue());
- instance->SetString("foo", "foo");
- instance->SetInteger("bar", 42);
-
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- instance->SetBoolean("extra", true);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extra",
- JSONSchemaValidator::kUnexpectedProperty);
- instance->Remove("extra", nullptr);
-
- instance->Remove("bar", nullptr);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
- JSONSchemaValidator::kObjectPropertyIsRequired);
-
- instance->SetString("bar", "42");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kInteger,
- schema::kString));
- instance->SetInteger("bar", 42);
-
- // Test "patternProperties".
- instance->SetInteger("extra", 42);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extra",
- JSONSchemaValidator::kUnexpectedProperty);
- schema->SetString("patternProperties.extra+.type",
- schema::kInteger);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Remove("extra", nullptr);
- instance->SetInteger("extraaa", 42);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Remove("extraaa", nullptr);
- instance->SetInteger("extr", 42);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extr",
- JSONSchemaValidator::kUnexpectedProperty);
- instance->Remove("extr", nullptr);
- schema->Remove(schema::kPatternProperties, nullptr);
-
- // Test "patternProperties" and "properties" schemas are both checked if
- // applicable.
- schema->SetString("patternProperties.fo+.type", schema::kInteger);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "foo",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kInteger,
- schema::kString));
- instance->SetInteger("foo", 123);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "foo",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kString,
- schema::kInteger));
- instance->SetString("foo", "foo");
- schema->Remove(schema::kPatternProperties, nullptr);
-
- // Test additional properties.
- base::DictionaryValue* additional_properties = schema->SetDictionary(
- schema::kAdditionalProperties, std::make_unique<base::DictionaryValue>());
- additional_properties->SetString(schema::kType, schema::kAny);
-
- instance->SetBoolean("extra", true);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- instance->SetString("extra", "foo");
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- additional_properties->SetString(schema::kType, schema::kBoolean);
- instance->SetBoolean("extra", true);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- instance->SetString("extra", "foo");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "extra",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kBoolean,
- schema::kString));
- instance->Remove("extra", nullptr);
-
- base::DictionaryValue* properties = nullptr;
- base::DictionaryValue* bar_property = nullptr;
- ASSERT_TRUE(schema->GetDictionary(schema::kProperties, &properties));
- ASSERT_TRUE(properties->GetDictionary("bar", &bar_property));
-
- bar_property->SetBoolean(schema::kOptional, true);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Remove("bar", nullptr);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Set("bar", std::make_unique<base::Value>());
- ExpectNotValid(
- TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
- JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
- schema::kInteger, schema::kNull));
- instance->SetString("bar", "42");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "bar",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kInteger,
- schema::kString));
-
- // Verify that JSON parser handles dot in "patternProperties" well.
- schema.reset(LoadDictionary("pattern_properties_dot.json"));
- ASSERT_TRUE(schema->GetDictionary(schema::kPatternProperties, &properties));
- ASSERT_TRUE(properties->HasKey("^.$"));
-
- instance.reset(new base::DictionaryValue());
- instance->SetString("a", "whatever");
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->SetString("foo", "bar");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "foo",
- JSONSchemaValidator::kUnexpectedProperty);
-}
-
-void JSONSchemaValidatorTestBase::TestTypeReference() {
- std::unique_ptr<base::ListValue> types(LoadList("reference_types.json"));
- ASSERT_TRUE(types.get());
-
- std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
- schema->SetString(schema::kType, schema::kObject);
- schema->SetString("properties.foo.type", schema::kString);
- schema->SetString("properties.bar.$ref", "Max10Int");
- schema->SetString("properties.baz.$ref", "MinLengthString");
-
- std::unique_ptr<base::DictionaryValue> schema_inline(
- new base::DictionaryValue());
- schema_inline->SetString(schema::kType, schema::kObject);
- schema_inline->SetString("properties.foo.type", schema::kString);
- schema_inline->SetString("properties.bar.id", "NegativeInt");
- schema_inline->SetString("properties.bar.type", schema::kInteger);
- schema_inline->SetInteger("properties.bar.maximum", 0);
- schema_inline->SetString("properties.baz.$ref", "NegativeInt");
-
- std::unique_ptr<base::DictionaryValue> instance(new base::DictionaryValue());
- instance->SetString("foo", "foo");
- instance->SetInteger("bar", 4);
- instance->SetString("baz", "ab");
-
- std::unique_ptr<base::DictionaryValue> instance_inline(
- new base::DictionaryValue());
- instance_inline->SetString("foo", "foo");
- instance_inline->SetInteger("bar", -4);
- instance_inline->SetInteger("baz", -2);
-
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), types.get());
- ExpectValid(TEST_SOURCE, instance_inline.get(), schema_inline.get(), nullptr);
-
- // Validation failure, but successful schema reference.
- instance->SetString("baz", "a");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), types.get(),
- "baz", JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kStringMinLength, "2"));
-
- instance_inline->SetInteger("bar", 20);
- ExpectNotValid(TEST_SOURCE, instance_inline.get(), schema_inline.get(),
- nullptr, "bar",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kNumberMaximum, "0"));
-
- // Remove MinLengthString type.
- types->Remove(types->GetSize() - 1, nullptr);
- instance->SetString("baz", "ab");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), types.get(),
- "bar", JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kUnknownTypeReference,
- "Max10Int"));
-
- // Remove internal type "NegativeInt".
- schema_inline->Remove("properties.bar", nullptr);
- instance_inline->Remove("bar", nullptr);
- ExpectNotValid(
- TEST_SOURCE, instance_inline.get(), schema_inline.get(), nullptr, "baz",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kUnknownTypeReference, "NegativeInt"));
-}
-
-void JSONSchemaValidatorTestBase::TestArrayTuple() {
- std::unique_ptr<base::DictionaryValue> schema(
- LoadDictionary("array_tuple_schema.json"));
- ASSERT_TRUE(schema.get());
-
- std::unique_ptr<base::ListValue> instance(new base::ListValue());
- instance->AppendString("42");
- instance->AppendInteger(42);
-
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- instance->AppendString("anything");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
- std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kArrayMaxItems, "2"));
-
- instance->Remove(1, nullptr);
- instance->Remove(1, nullptr);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
- JSONSchemaValidator::kArrayItemRequired);
-
- instance->Set(0, std::make_unique<base::Value>(42));
- instance->AppendInteger(42);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kString,
- schema::kInteger));
-
- base::DictionaryValue* additional_properties = schema->SetDictionary(
- schema::kAdditionalProperties, std::make_unique<base::DictionaryValue>());
- additional_properties->SetString(schema::kType, schema::kAny);
- instance->Set(0, std::make_unique<base::Value>("42"));
- instance->AppendString("anything");
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Set(2, std::make_unique<base::ListValue>());
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- additional_properties->SetString(schema::kType, schema::kBoolean);
- ExpectNotValid(
- TEST_SOURCE, instance.get(), schema.get(), nullptr, "2",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kBoolean, schema::kArray));
- instance->Set(2, std::make_unique<base::Value>(false));
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- base::ListValue* items_schema = nullptr;
- base::DictionaryValue* item0_schema = nullptr;
- ASSERT_TRUE(schema->GetList(schema::kItems, &items_schema));
- ASSERT_TRUE(items_schema->GetDictionary(0, &item0_schema));
- item0_schema->SetBoolean(schema::kOptional, true);
- instance->Remove(2, nullptr);
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- // TODO(aa): I think this is inconsistent with the handling of NULL+optional
- // for objects.
- instance->Set(0, std::make_unique<base::Value>());
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->Set(0, std::make_unique<base::Value>(42));
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "0",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kString,
- schema::kInteger));
-}
-
-void JSONSchemaValidatorTestBase::TestArrayNonTuple() {
- std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
- schema->SetString(schema::kType, schema::kArray);
- schema->SetString("items.type", schema::kString);
- schema->SetInteger(schema::kMinItems, 2);
- schema->SetInteger(schema::kMaxItems, 3);
-
- std::unique_ptr<base::ListValue> instance(new base::ListValue());
- instance->AppendString("x");
- instance->AppendString("x");
-
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
- instance->AppendString("x");
- ExpectValid(TEST_SOURCE, instance.get(), schema.get(), nullptr);
-
- instance->AppendString("x");
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
- std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kArrayMaxItems, "3"));
- instance->Remove(1, nullptr);
- instance->Remove(1, nullptr);
- instance->Remove(1, nullptr);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr,
- std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kArrayMinItems, "2"));
-
- instance->Remove(1, nullptr);
- instance->AppendInteger(42);
- ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), nullptr, "1",
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kString,
- schema::kInteger));
-}
-
-void JSONSchemaValidatorTestBase::TestString() {
- std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
- schema->SetString(schema::kType, schema::kString);
- schema->SetInteger(schema::kMinLength, 1);
- schema->SetInteger(schema::kMaxLength, 10);
-
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("x")).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("xxxxxxxxxx")).get(),
- schema.get(), nullptr);
-
- ExpectNotValid(
- TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(std::string())).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kStringMinLength, "1"));
- ExpectNotValid(
- TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("xxxxxxxxxxx")).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kStringMaxLength, "10"));
-}
-
-void JSONSchemaValidatorTestBase::TestNumber() {
- std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
- schema->SetString(schema::kType, schema::kNumber);
- schema->SetInteger(schema::kMinimum, 1);
- schema->SetInteger(schema::kMaximum, 100);
- schema->SetInteger("maxDecimal", 2);
-
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(1)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(50)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(100)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(88.88)).get(),
- schema.get(), nullptr);
-
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(0.5)).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kNumberMinimum, "1"));
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(100.1)).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kNumberMaximum, "100"));
-}
-
-void JSONSchemaValidatorTestBase::TestTypeClassifier() {
- EXPECT_EQ(std::string(schema::kBoolean),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(true)).get()));
- EXPECT_EQ(std::string(schema::kBoolean),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(false)).get()));
-
- // It doesn't matter whether the C++ type is 'integer' or 'real'. If the
- // number is integral and within the representable range of integers in
- // double, it's classified as 'integer'.
- EXPECT_EQ(std::string(schema::kInteger),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(42)).get()));
- EXPECT_EQ(std::string(schema::kInteger),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(0)).get()));
- EXPECT_EQ(std::string(schema::kInteger),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(42)).get()));
- EXPECT_EQ(
- std::string(schema::kInteger),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(pow(2.0, DBL_MANT_DIG)))
- .get()));
- EXPECT_EQ(
- std::string(schema::kInteger),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(pow(-2.0, DBL_MANT_DIG)))
- .get()));
-
- // "number" is only used for non-integral numbers, or numbers beyond what
- // double can accurately represent.
- EXPECT_EQ(std::string(schema::kNumber),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value(88.8)).get()));
- EXPECT_EQ(std::string(schema::kNumber),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(
- new base::Value(pow(2.0, DBL_MANT_DIG) * 2))
- .get()));
- EXPECT_EQ(std::string(schema::kNumber),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(
- new base::Value(pow(-2.0, DBL_MANT_DIG) * 2))
- .get()));
-
- EXPECT_EQ(std::string(schema::kString),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::Value("foo")).get()));
- EXPECT_EQ(std::string(schema::kArray),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::ListValue()).get()));
- EXPECT_EQ(
- std::string(schema::kObject),
- JSONSchemaValidator::GetJSONSchemaType(
- std::unique_ptr<base::Value>(new base::DictionaryValue()).get()));
- EXPECT_EQ(std::string(schema::kNull),
- JSONSchemaValidator::GetJSONSchemaType(
- std::make_unique<base::Value>().get()));
-}
-
-void JSONSchemaValidatorTestBase::TestTypes() {
- std::unique_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
-
- // valid
- schema->SetString(schema::kType, schema::kObject);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::DictionaryValue()).get(),
- schema.get(), nullptr);
-
- schema->SetString(schema::kType, schema::kArray);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::ListValue()).get(),
- schema.get(), nullptr);
-
- schema->SetString(schema::kType, schema::kString);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value("foobar")).get(),
- schema.get(), nullptr);
-
- schema->SetString(schema::kType, schema::kNumber);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(88.8)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(0)).get(),
- schema.get(), nullptr);
-
- schema->SetString(schema::kType, schema::kInteger);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(0)).get(),
- schema.get(), nullptr);
- ExpectValid(
- TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(pow(2.0, DBL_MANT_DIG)))
- .get(),
- schema.get(), nullptr);
- ExpectValid(
- TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(pow(-2.0, DBL_MANT_DIG)))
- .get(),
- schema.get(), nullptr);
-
- schema->SetString(schema::kType, schema::kBoolean);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(false)).get(),
- schema.get(), nullptr);
- ExpectValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(true)).get(),
- schema.get(), nullptr);
-
- schema->SetString(schema::kType, schema::kNull);
- ExpectValid(TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(),
- nullptr);
-
- // not valid
- schema->SetString(schema::kType, schema::kObject);
- ExpectNotValid(
- TEST_SOURCE, std::unique_ptr<base::Value>(new base::ListValue()).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
- schema::kObject, schema::kArray));
-
- schema->SetString(schema::kType, schema::kObject);
- ExpectNotValid(
- TEST_SOURCE, std::make_unique<base::Value>().get(), schema.get(), nullptr,
- std::string(),
- JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
- schema::kObject, schema::kNull));
-
- schema->SetString(schema::kType, schema::kArray);
- ExpectNotValid(
- TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kArray, schema::kInteger));
-
- schema->SetString(schema::kType, schema::kString);
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(42)).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kString,
- schema::kInteger));
-
- schema->SetString(schema::kType, schema::kNumber);
- ExpectNotValid(
- TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value("42")).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kNumber, schema::kString));
-
- schema->SetString(schema::kType, schema::kInteger);
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(88.8)).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::kInvalidTypeIntegerNumber);
-
- schema->SetString(schema::kType, schema::kBoolean);
- ExpectNotValid(TEST_SOURCE,
- std::unique_ptr<base::Value>(new base::Value(1)).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(
- JSONSchemaValidator::kInvalidType, schema::kBoolean,
- schema::kInteger));
-
- schema->SetString(schema::kType, schema::kNull);
- ExpectNotValid(
- TEST_SOURCE, std::unique_ptr<base::Value>(new base::Value(false)).get(),
- schema.get(), nullptr, std::string(),
- JSONSchemaValidator::FormatErrorMessage(JSONSchemaValidator::kInvalidType,
- schema::kNull, schema::kBoolean));
-}
diff --git a/components/json_schema/json_schema_validator_unittest_base.h b/components/json_schema/json_schema_validator_unittest_base.h
deleted file mode 100644
index ff661acb32..0000000000
--- a/components/json_schema/json_schema_validator_unittest_base.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_JSON_SCHEMA_JSON_SCHEMA_VALIDATOR_UNITTEST_BASE_H_
-#define COMPONENTS_JSON_SCHEMA_JSON_SCHEMA_VALIDATOR_UNITTEST_BASE_H_
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-class DictionaryValue;
-class ListValue;
-class Value;
-}
-
-// Base class for unit tests for JSONSchemaValidator. There is currently only
-// one implementation, JSONSchemaValidatorCPPTest.
-//
-// TODO(aa): Refactor extensions/test/data/json_schema_test.js into
-// JSONSchemaValidatorJSTest that inherits from this.
-class JSONSchemaValidatorTestBase : public testing::Test {
- public:
- JSONSchemaValidatorTestBase();
-
- void RunTests();
-
- protected:
- virtual void ExpectValid(const std::string& test_source,
- base::Value* instance,
- base::DictionaryValue* schema,
- base::ListValue* types) = 0;
-
- virtual void ExpectNotValid(const std::string& test_source,
- base::Value* instance,
- base::DictionaryValue* schema,
- base::ListValue* types,
- const std::string& expected_error_path,
- const std::string& expected_error_message) = 0;
-
- private:
- void TestComplex();
- void TestStringPattern();
- void TestEnum();
- void TestChoices();
- void TestExtends();
- void TestObject();
- void TestTypeReference();
- void TestArrayTuple();
- void TestArrayNonTuple();
- void TestString();
- void TestNumber();
- void TestTypeClassifier();
- void TestTypes();
-};
-
-#endif // COMPONENTS_JSON_SCHEMA_JSON_SCHEMA_VALIDATOR_UNITTEST_BASE_H_
diff --git a/components/policy/core/common/async_policy_loader.cc b/components/policy/core/common/async_policy_loader.cc
deleted file mode 100644
index b0edee2ea7..0000000000
--- a/components/policy/core/common/async_policy_loader.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/async_policy_loader.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/sequenced_task_runner.h"
-#include "components/policy/core/common/policy_bundle.h"
-
-using base::Time;
-using base::TimeDelta;
-
-namespace policy {
-
-namespace {
-
-// Amount of time to wait for the files on disk to settle before trying to load
-// them. This alleviates the problem of reading partially written files and
-// makes it possible to batch quasi-simultaneous changes.
-constexpr TimeDelta kSettleInterval = TimeDelta::FromSeconds(5);
-
-// The time interval for rechecking policy. This is the fallback in case the
-// implementation never detects changes.
-constexpr TimeDelta kReloadInterval = TimeDelta::FromMinutes(15);
-
-} // namespace
-
-AsyncPolicyLoader::AsyncPolicyLoader(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : task_runner_(task_runner) {}
-
-AsyncPolicyLoader::~AsyncPolicyLoader() {}
-
-Time AsyncPolicyLoader::LastModificationTime() {
- return Time();
-}
-
-void AsyncPolicyLoader::Reload(bool force) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
-
- TimeDelta delay;
- Time now = Time::Now();
- // Check if there was a recent modification to the underlying files.
- if (!force && !IsSafeToReload(now, &delay)) {
- ScheduleNextReload(delay);
- return;
- }
-
- std::unique_ptr<PolicyBundle> bundle(Load());
-
- // Check if there was a modification while reading.
- if (!force && !IsSafeToReload(now, &delay)) {
- ScheduleNextReload(delay);
- return;
- }
-
- // Filter out mismatching policies.
- schema_map_->FilterBundle(bundle.get());
-
- update_callback_.Run(std::move(bundle));
- ScheduleNextReload(kReloadInterval);
-}
-
-std::unique_ptr<PolicyBundle> AsyncPolicyLoader::InitialLoad(
- const scoped_refptr<SchemaMap>& schema_map) {
- // This is the first load, early during startup. Use this to record the
- // initial |last_modification_time_|, so that potential changes made before
- // installing the watches can be detected.
- last_modification_time_ = LastModificationTime();
- schema_map_ = schema_map;
- std::unique_ptr<PolicyBundle> bundle(Load());
- // Filter out mismatching policies.
- schema_map_->FilterBundle(bundle.get());
- return bundle;
-}
-
-void AsyncPolicyLoader::Init(const UpdateCallback& update_callback) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- DCHECK(update_callback_.is_null());
- DCHECK(!update_callback.is_null());
- update_callback_ = update_callback;
-
- InitOnBackgroundThread();
-
- // There might have been changes to the underlying files since the initial
- // load and before the watchers have been created.
- if (LastModificationTime() != last_modification_time_)
- Reload(false);
-
- // Start periodic refreshes.
- ScheduleNextReload(kReloadInterval);
-}
-
-void AsyncPolicyLoader::RefreshPolicies(scoped_refptr<SchemaMap> schema_map) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- schema_map_ = schema_map;
- Reload(true);
-}
-
-void AsyncPolicyLoader::ScheduleNextReload(TimeDelta delay) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- weak_factory_.InvalidateWeakPtrs();
- task_runner_->PostDelayedTask(FROM_HERE,
- base::Bind(&AsyncPolicyLoader::Reload,
- weak_factory_.GetWeakPtr(),
- false /* force */),
- delay);
-}
-
-bool AsyncPolicyLoader::IsSafeToReload(const Time& now, TimeDelta* delay) {
- Time last_modification = LastModificationTime();
- if (last_modification.is_null())
- return true;
-
- // If there was a change since the last recorded modification, wait some more.
- if (last_modification != last_modification_time_) {
- last_modification_time_ = last_modification;
- last_modification_clock_ = now;
- *delay = kSettleInterval;
- return false;
- }
-
- // Check whether the settle interval has elapsed.
- const TimeDelta age = now - last_modification_clock_;
- if (age < kSettleInterval) {
- *delay = kSettleInterval - age;
- return false;
- }
-
- return true;
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/async_policy_loader.h b/components/policy/core/common/async_policy_loader.h
deleted file mode 100644
index 04ea60b998..0000000000
--- a/components/policy/core/common/async_policy_loader.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_LOADER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_LOADER_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/time/time.h"
-#include "components/policy/core/common/schema_map.h"
-#include "components/policy/policy_export.h"
-
-namespace base {
-class SequencedTaskRunner;
-}
-
-namespace policy {
-
-class PolicyBundle;
-
-// Base implementation for platform-specific policy loaders. Together with the
-// AsyncPolicyProvider, this base implementation takes care of the initial load,
-// periodic reloads, watching file changes, refreshing policies and object
-// lifetime.
-//
-// All methods are invoked on the background |task_runner_|, including the
-// destructor. The only exceptions are the constructor (which may be called on
-// any thread), InitialLoad() which is called on the thread that owns the
-// provider and the calls of Load() and LastModificationTime() during the
-// initial load.
-// Also, during tests the destructor may be called on the main thread.
-class POLICY_EXPORT AsyncPolicyLoader {
- public:
- explicit AsyncPolicyLoader(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner);
- virtual ~AsyncPolicyLoader();
-
- // Gets a SequencedTaskRunner backed by the background thread.
- base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); }
-
- // Returns the currently configured policies. Load() is always invoked on
- // the background thread, except for the initial Load() at startup which is
- // invoked from the thread that owns the provider.
- virtual std::unique_ptr<PolicyBundle> Load() = 0;
-
- // Allows implementations to finalize their initialization on the background
- // thread (e.g. setup file watchers).
- virtual void InitOnBackgroundThread() = 0;
-
- // Implementations should return the time of the last modification detected,
- // or base::Time() if it doesn't apply, which is the default.
- virtual base::Time LastModificationTime();
-
- // Used by the AsyncPolicyProvider to do the initial Load(). The first load
- // is also used to initialize |last_modification_time_| and
- // |schema_map_|.
- std::unique_ptr<PolicyBundle> InitialLoad(
- const scoped_refptr<SchemaMap>& schemas);
-
- // Implementations should invoke Reload() when a change is detected. This
- // must be invoked from the background thread and will trigger a Load(),
- // and pass the returned bundle to the provider.
- // The load is immediate when |force| is true. Otherwise, the loader
- // reschedules the reload until the LastModificationTime() is a couple of
- // seconds in the past. This mitigates the problem of reading files that are
- // currently being written to, and whose contents are incomplete.
- // A reload is posted periodically, if it hasn't been triggered recently. This
- // makes sure the policies are reloaded if the update events aren't triggered.
- void Reload(bool force);
-
- const scoped_refptr<SchemaMap>& schema_map() const { return schema_map_; }
-
- private:
- // Allow AsyncPolicyProvider to call Init().
- friend class AsyncPolicyProvider;
-
- typedef base::Callback<void(std::unique_ptr<PolicyBundle>)> UpdateCallback;
-
- // Used by the AsyncPolicyProvider to install the |update_callback_|.
- // Invoked on the background thread.
- void Init(const UpdateCallback& update_callback);
-
- // Used by the AsyncPolicyProvider to reload with an updated SchemaMap.
- void RefreshPolicies(scoped_refptr<SchemaMap> schema_map);
-
- // Cancels any pending periodic reload and posts one |delay| time units from
- // now.
- void ScheduleNextReload(base::TimeDelta delay);
-
- // Checks if the underlying files haven't changed recently, by checking the
- // LastModificationTime(). |delay| is updated with a suggested time to wait
- // before retrying when this returns false.
- bool IsSafeToReload(const base::Time& now, base::TimeDelta* delay);
-
- // Task runner for running background jobs.
- const scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- // Callback for updates, passed in Init().
- UpdateCallback update_callback_;
-
- // Records last known modification timestamp.
- base::Time last_modification_time_;
-
- // The wall clock time at which the last modification timestamp was
- // recorded. It's better to not assume the file notification time and the
- // wall clock times come from the same source, just in case there is some
- // non-local filesystem involved.
- base::Time last_modification_clock_;
-
- // The current policy schemas that this provider should load.
- scoped_refptr<SchemaMap> schema_map_;
-
- // Used to get WeakPtrs for the periodic reload task.
- base::WeakPtrFactory<AsyncPolicyLoader> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(AsyncPolicyLoader);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_LOADER_H_
diff --git a/components/policy/core/common/async_policy_provider.cc b/components/policy/core/common/async_policy_provider.cc
deleted file mode 100644
index 9fe4153204..0000000000
--- a/components/policy/core/common/async_policy_provider.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/async_policy_provider.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "components/policy/core/common/async_policy_loader.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/schema_registry.h"
-
-namespace policy {
-
-AsyncPolicyProvider::AsyncPolicyProvider(
- SchemaRegistry* registry,
- std::unique_ptr<AsyncPolicyLoader> loader)
- : loader_(std::move(loader)), weak_factory_(this) {
- // Make an immediate synchronous load on startup.
- OnLoaderReloaded(loader_->InitialLoad(registry->schema_map()));
-}
-
-AsyncPolicyProvider::~AsyncPolicyProvider() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-}
-
-void AsyncPolicyProvider::Init(SchemaRegistry* registry) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- ConfigurationPolicyProvider::Init(registry);
-
- if (!loader_)
- return;
-
- AsyncPolicyLoader::UpdateCallback callback =
- base::Bind(&AsyncPolicyProvider::LoaderUpdateCallback,
- base::ThreadTaskRunnerHandle::Get(),
- weak_factory_.GetWeakPtr());
- bool post = loader_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&AsyncPolicyLoader::Init,
- base::Unretained(loader_.get()),
- callback));
- DCHECK(post) << "AsyncPolicyProvider::Init() called with threads not running";
-}
-
-void AsyncPolicyProvider::Shutdown() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Note on the lifetime of |loader_|:
- // The |loader_| lives on the background thread, and is deleted from here.
- // This means that posting tasks on the |loader_| to the background thread
- // from the AsyncPolicyProvider is always safe, since a potential DeleteSoon()
- // is only posted from here. The |loader_| posts back to the
- // AsyncPolicyProvider through the |update_callback_|, which has a WeakPtr to
- // |this|.
- // If threads are spinning, delete the loader on the thread it lives on. If
- // there are no threads, kill it immediately.
- AsyncPolicyLoader* loader_to_delete = loader_.release();
- if (!loader_to_delete->task_runner()->DeleteSoon(FROM_HERE, loader_to_delete))
- delete loader_to_delete;
- ConfigurationPolicyProvider::Shutdown();
-}
-
-void AsyncPolicyProvider::RefreshPolicies() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- // Subtle: RefreshPolicies() has a contract that requires the next policy
- // update notification (triggered from UpdatePolicy()) to reflect any changes
- // made before this call. So if a caller has modified the policy settings and
- // invoked RefreshPolicies(), then by the next notification these policies
- // should already be provided.
- // However, it's also possible that an asynchronous Reload() is in progress
- // and just posted OnLoaderReloaded(). Therefore a task is posted to the
- // background thread before posting the next Reload, to prevent a potential
- // concurrent Reload() from triggering a notification too early. If another
- // refresh task has been posted, it is invalidated now.
- if (!loader_)
- return;
- refresh_callback_.Reset(
- base::Bind(&AsyncPolicyProvider::ReloadAfterRefreshSync,
- weak_factory_.GetWeakPtr()));
- loader_->task_runner()->PostTaskAndReply(FROM_HERE, base::DoNothing(),
- refresh_callback_.callback());
-}
-
-void AsyncPolicyProvider::ReloadAfterRefreshSync() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // This task can only enter if it was posted from RefreshPolicies(), and it
- // hasn't been cancelled meanwhile by another call to RefreshPolicies().
- DCHECK(!refresh_callback_.IsCancelled());
- // There can't be another refresh callback pending now, since its creation
- // in RefreshPolicies() would have cancelled the current execution. So it's
- // safe to cancel the |refresh_callback_| now, so that OnLoaderReloaded()
- // sees that there is no refresh pending.
- refresh_callback_.Cancel();
-
- if (!loader_)
- return;
-
- loader_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&AsyncPolicyLoader::RefreshPolicies,
- base::Unretained(loader_.get()),
- schema_map()));
-}
-
-void AsyncPolicyProvider::OnLoaderReloaded(
- std::unique_ptr<PolicyBundle> bundle) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Only propagate policy updates if there are no pending refreshes, and if
- // Shutdown() hasn't been called yet.
- if (refresh_callback_.IsCancelled() && loader_)
- UpdatePolicy(std::move(bundle));
-}
-
-// static
-void AsyncPolicyProvider::LoaderUpdateCallback(
- scoped_refptr<base::SingleThreadTaskRunner> runner,
- base::WeakPtr<AsyncPolicyProvider> weak_this,
- std::unique_ptr<PolicyBundle> bundle) {
- runner->PostTask(FROM_HERE,
- base::BindOnce(&AsyncPolicyProvider::OnLoaderReloaded,
- weak_this, std::move(bundle)));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/async_policy_provider.h b/components/policy/core/common/async_policy_provider.h
deleted file mode 100644
index 3ef4c4b0bf..0000000000
--- a/components/policy/core/common/async_policy_provider.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_PROVIDER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_PROVIDER_H_
-
-#include <memory>
-
-#include "base/cancelable_callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "components/policy/core/common/configuration_policy_provider.h"
-#include "components/policy/policy_export.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace policy {
-
-class AsyncPolicyLoader;
-class PolicyBundle;
-class SchemaRegistry;
-
-// A policy provider that loads its policies asynchronously on a background
-// thread. Platform-specific providers are created by passing an implementation
-// of AsyncPolicyLoader to a new AsyncPolicyProvider.
-class POLICY_EXPORT AsyncPolicyProvider : public ConfigurationPolicyProvider {
- public:
- // The AsyncPolicyProvider does a synchronous load in its constructor, and
- // therefore it needs the |registry| at construction time. The same |registry|
- // should be passed later to Init().
- AsyncPolicyProvider(SchemaRegistry* registry,
- std::unique_ptr<AsyncPolicyLoader> loader);
- ~AsyncPolicyProvider() override;
-
- // ConfigurationPolicyProvider implementation.
- void Init(SchemaRegistry* registry) override;
- void Shutdown() override;
- void RefreshPolicies() override;
-
- private:
- // Helper for RefreshPolicies().
- void ReloadAfterRefreshSync();
-
- // Invoked with the latest bundle loaded by the |loader_|.
- void OnLoaderReloaded(std::unique_ptr<PolicyBundle> bundle);
-
- // Callback passed to the loader that it uses to pass back the current policy
- // bundle to the provider. This is invoked on the background thread and
- // forwards to OnLoaderReloaded() on the runner that owns the provider,
- // if |weak_this| is still valid.
- static void LoaderUpdateCallback(
- scoped_refptr<base::SingleThreadTaskRunner> runner,
- base::WeakPtr<AsyncPolicyProvider> weak_this,
- std::unique_ptr<PolicyBundle> bundle);
-
- // The |loader_| that does the platform-specific policy loading. It lives
- // on the background thread but is owned by |this|.
- std::unique_ptr<AsyncPolicyLoader> loader_;
-
- // Callback used to synchronize RefreshPolicies() calls with the background
- // thread. See the implementation for the details.
- base::CancelableClosure refresh_callback_;
-
- SEQUENCE_CHECKER(sequence_checker_);
-
- // Used to get a WeakPtr to |this| for the update callback given to the
- // loader.
- base::WeakPtrFactory<AsyncPolicyProvider> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(AsyncPolicyProvider);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_ASYNC_POLICY_PROVIDER_H_
diff --git a/components/policy/core/common/async_policy_provider_unittest.cc b/components/policy/core/common/async_policy_provider_unittest.cc
deleted file mode 100644
index 61286c6633..0000000000
--- a/components/policy/core/common/async_policy_provider_unittest.cc
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/async_policy_provider.h"
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
-#include "base/values.h"
-#include "components/policy/core/common/async_policy_loader.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/mock_configuration_policy_provider.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/core/common/schema_registry.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::Mock;
-using testing::Return;
-using testing::Sequence;
-
-namespace policy {
-
-namespace {
-
-// Helper to write a policy in |bundle| with less code.
-void SetPolicy(PolicyBundle* bundle,
- const std::string& name,
- const std::string& value) {
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>(value),
- nullptr);
-}
-
-class MockPolicyLoader : public AsyncPolicyLoader {
- public:
- explicit MockPolicyLoader(
- scoped_refptr<base::SequencedTaskRunner> task_runner);
- ~MockPolicyLoader() override;
-
- // Load() returns a std::unique_ptr<PolicyBundle> but it can't be mocked
- // because std::unique_ptr is moveable but not copyable. This override
- // forwards the call to MockLoad() which returns a PolicyBundle*, and returns
- // a copy wrapped in a std::unique_ptr.
- std::unique_ptr<PolicyBundle> Load() override;
-
- MOCK_METHOD0(MockLoad, const PolicyBundle*());
- MOCK_METHOD0(InitOnBackgroundThread, void());
- MOCK_METHOD0(LastModificationTime, base::Time());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockPolicyLoader);
-};
-
-MockPolicyLoader::MockPolicyLoader(
- scoped_refptr<base::SequencedTaskRunner> task_runner)
- : AsyncPolicyLoader(task_runner) {}
-
-MockPolicyLoader::~MockPolicyLoader() {}
-
-std::unique_ptr<PolicyBundle> MockPolicyLoader::Load() {
- std::unique_ptr<PolicyBundle> bundle;
- const PolicyBundle* loaded = MockLoad();
- if (loaded) {
- bundle.reset(new PolicyBundle());
- bundle->CopyFrom(*loaded);
- }
- return bundle;
-}
-
-} // namespace
-
-class AsyncPolicyProviderTest : public testing::Test {
- protected:
- AsyncPolicyProviderTest();
- ~AsyncPolicyProviderTest() override;
-
- void SetUp() override;
- void TearDown() override;
-
- base::MessageLoop loop_;
- SchemaRegistry schema_registry_;
- PolicyBundle initial_bundle_;
- MockPolicyLoader* loader_;
- std::unique_ptr<AsyncPolicyProvider> provider_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AsyncPolicyProviderTest);
-};
-
-AsyncPolicyProviderTest::AsyncPolicyProviderTest() {}
-
-AsyncPolicyProviderTest::~AsyncPolicyProviderTest() {}
-
-void AsyncPolicyProviderTest::SetUp() {
- SetPolicy(&initial_bundle_, "policy", "initial");
- loader_ = new MockPolicyLoader(loop_.task_runner());
- EXPECT_CALL(*loader_, LastModificationTime())
- .WillRepeatedly(Return(base::Time()));
- EXPECT_CALL(*loader_, InitOnBackgroundThread()).Times(1);
- EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&initial_bundle_));
-
- provider_.reset(new AsyncPolicyProvider(
- &schema_registry_, std::unique_ptr<AsyncPolicyLoader>(loader_)));
- provider_->Init(&schema_registry_);
- // Verify that the initial load is done synchronously:
- EXPECT_TRUE(provider_->policies().Equals(initial_bundle_));
-
- base::RunLoop().RunUntilIdle();
- Mock::VerifyAndClearExpectations(loader_);
-
- EXPECT_CALL(*loader_, LastModificationTime())
- .WillRepeatedly(Return(base::Time()));
-}
-
-void AsyncPolicyProviderTest::TearDown() {
- if (provider_) {
- provider_->Shutdown();
- provider_.reset();
- }
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(AsyncPolicyProviderTest, RefreshPolicies) {
- PolicyBundle refreshed_bundle;
- SetPolicy(&refreshed_bundle, "policy", "refreshed");
- EXPECT_CALL(*loader_, MockLoad()).WillOnce(Return(&refreshed_bundle));
-
- MockConfigurationPolicyObserver observer;
- provider_->AddObserver(&observer);
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
- provider_->RefreshPolicies();
- base::RunLoop().RunUntilIdle();
- // The refreshed policies are now provided.
- EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
- provider_->RemoveObserver(&observer);
-}
-
-TEST_F(AsyncPolicyProviderTest, RefreshPoliciesTwice) {
- PolicyBundle refreshed_bundle;
- SetPolicy(&refreshed_bundle, "policy", "refreshed");
- EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&refreshed_bundle));
-
- MockConfigurationPolicyObserver observer;
- provider_->AddObserver(&observer);
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
- provider_->RefreshPolicies();
- // Doesn't refresh before going through the background thread.
- Mock::VerifyAndClearExpectations(&observer);
-
- // Doesn't refresh if another RefreshPolicies request is made.
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
- provider_->RefreshPolicies();
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
- base::RunLoop().RunUntilIdle();
- // The refreshed policies are now provided.
- EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
- Mock::VerifyAndClearExpectations(&observer);
- provider_->RemoveObserver(&observer);
-}
-
-TEST_F(AsyncPolicyProviderTest, RefreshPoliciesDuringReload) {
- PolicyBundle reloaded_bundle;
- SetPolicy(&reloaded_bundle, "policy", "reloaded");
- PolicyBundle refreshed_bundle;
- SetPolicy(&refreshed_bundle, "policy", "refreshed");
-
- Sequence load_sequence;
- // Reload.
- EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence)
- .WillOnce(Return(&reloaded_bundle));
- // RefreshPolicies.
- EXPECT_CALL(*loader_, MockLoad()).InSequence(load_sequence)
- .WillOnce(Return(&refreshed_bundle));
-
- MockConfigurationPolicyObserver observer;
- provider_->AddObserver(&observer);
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
-
- // A Reload is triggered before RefreshPolicies, and it shouldn't trigger
- // notifications.
- loader_->Reload(true);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Doesn't refresh before going through the background thread.
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
- provider_->RefreshPolicies();
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
- base::RunLoop().RunUntilIdle();
- // The refreshed policies are now provided, and the |reloaded_bundle| was
- // dropped.
- EXPECT_TRUE(provider_->policies().Equals(refreshed_bundle));
- Mock::VerifyAndClearExpectations(&observer);
- provider_->RemoveObserver(&observer);
-}
-
-TEST_F(AsyncPolicyProviderTest, Shutdown) {
- EXPECT_CALL(*loader_, MockLoad()).WillRepeatedly(Return(&initial_bundle_));
-
- MockConfigurationPolicyObserver observer;
- provider_->AddObserver(&observer);
-
- // Though there is a pending Reload, the provider and the loader can be
- // deleted at any time.
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
- loader_->Reload(true);
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(0);
- provider_->Shutdown();
- base::RunLoop().RunUntilIdle();
- Mock::VerifyAndClearExpectations(&observer);
-
- provider_->RemoveObserver(&observer);
- provider_.reset();
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/config_dir_policy_loader.cc b/components/policy/core/common/config_dir_policy_loader.cc
deleted file mode 100644
index 8edf58623d..0000000000
--- a/components/policy/core/common/config_dir_policy_loader.cc
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/config_dir_policy_loader.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <set>
-#include <string>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_util.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/json/json_reader.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/stl_util.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_load_status.h"
-#include "components/policy/core/common/policy_types.h"
-
-namespace policy {
-
-namespace {
-
-// Subdirectories that contain the mandatory and recommended policies.
-constexpr base::FilePath::CharType kMandatoryConfigDir[] =
- FILE_PATH_LITERAL("managed");
-constexpr base::FilePath::CharType kRecommendedConfigDir[] =
- FILE_PATH_LITERAL("recommended");
-
-PolicyLoadStatus JsonErrorToPolicyLoadStatus(int status) {
- switch (status) {
- case JSONFileValueDeserializer::JSON_ACCESS_DENIED:
- case JSONFileValueDeserializer::JSON_CANNOT_READ_FILE:
- case JSONFileValueDeserializer::JSON_FILE_LOCKED:
- return POLICY_LOAD_STATUS_READ_ERROR;
- case JSONFileValueDeserializer::JSON_NO_SUCH_FILE:
- return POLICY_LOAD_STATUS_MISSING;
- case base::JSONReader::JSON_INVALID_ESCAPE:
- case base::JSONReader::JSON_SYNTAX_ERROR:
- case base::JSONReader::JSON_UNEXPECTED_TOKEN:
- case base::JSONReader::JSON_TRAILING_COMMA:
- case base::JSONReader::JSON_TOO_MUCH_NESTING:
- case base::JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT:
- case base::JSONReader::JSON_UNSUPPORTED_ENCODING:
- case base::JSONReader::JSON_UNQUOTED_DICTIONARY_KEY:
- return POLICY_LOAD_STATUS_PARSE_ERROR;
- case base::JSONReader::JSON_NO_ERROR:
- NOTREACHED();
- return POLICY_LOAD_STATUS_STARTED;
- }
- NOTREACHED() << "Invalid status " << status;
- return POLICY_LOAD_STATUS_PARSE_ERROR;
-}
-
-} // namespace
-
-ConfigDirPolicyLoader::ConfigDirPolicyLoader(
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- const base::FilePath& config_dir,
- PolicyScope scope)
- : AsyncPolicyLoader(task_runner),
- task_runner_(task_runner),
- config_dir_(config_dir),
- scope_(scope) {}
-
-ConfigDirPolicyLoader::~ConfigDirPolicyLoader() {}
-
-void ConfigDirPolicyLoader::InitOnBackgroundThread() {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- base::FilePathWatcher::Callback callback =
- base::Bind(&ConfigDirPolicyLoader::OnFileUpdated, base::Unretained(this));
- mandatory_watcher_.Watch(config_dir_.Append(kMandatoryConfigDir), false,
- callback);
- recommended_watcher_.Watch(config_dir_.Append(kRecommendedConfigDir), false,
- callback);
-}
-
-std::unique_ptr<PolicyBundle> ConfigDirPolicyLoader::Load() {
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
- LoadFromPath(config_dir_.Append(kMandatoryConfigDir),
- POLICY_LEVEL_MANDATORY,
- bundle.get());
- LoadFromPath(config_dir_.Append(kRecommendedConfigDir),
- POLICY_LEVEL_RECOMMENDED,
- bundle.get());
- return bundle;
-}
-
-base::Time ConfigDirPolicyLoader::LastModificationTime() {
- static constexpr const base::FilePath::CharType* kConfigDirSuffixes[] = {
- kMandatoryConfigDir, kRecommendedConfigDir,
- };
-
- base::Time last_modification = base::Time();
- base::File::Info info;
-
- for (size_t i = 0; i < arraysize(kConfigDirSuffixes); ++i) {
- base::FilePath path(config_dir_.Append(kConfigDirSuffixes[i]));
-
- // Skip if the file doesn't exist, or it isn't a directory.
- if (!base::GetFileInfo(path, &info) || !info.is_directory)
- continue;
-
- // Enumerate the files and find the most recent modification timestamp.
- base::FileEnumerator file_enumerator(path, false,
- base::FileEnumerator::FILES);
- for (base::FilePath config_file = file_enumerator.Next();
- !config_file.empty();
- config_file = file_enumerator.Next()) {
- if (base::GetFileInfo(config_file, &info) && !info.is_directory)
- last_modification = std::max(last_modification, info.last_modified);
- }
- }
-
- return last_modification;
-}
-
-void ConfigDirPolicyLoader::LoadFromPath(const base::FilePath& path,
- PolicyLevel level,
- PolicyBundle* bundle) {
- // Enumerate the files and sort them lexicographically.
- std::set<base::FilePath> files;
- base::FileEnumerator file_enumerator(path, false,
- base::FileEnumerator::FILES);
- for (base::FilePath config_file_path = file_enumerator.Next();
- !config_file_path.empty(); config_file_path = file_enumerator.Next())
- files.insert(config_file_path);
-
- PolicyLoadStatusUmaReporter status;
- if (files.empty()) {
- status.Add(POLICY_LOAD_STATUS_NO_POLICY);
- return;
- }
-
- // Start with an empty dictionary and merge the files' contents.
- // The files are processed in reverse order because |MergeFrom| gives priority
- // to existing keys, but the ConfigDirPolicyProvider gives priority to the
- // last file in lexicographic order.
- for (std::set<base::FilePath>::reverse_iterator config_file_iter =
- files.rbegin(); config_file_iter != files.rend();
- ++config_file_iter) {
- JSONFileValueDeserializer deserializer(*config_file_iter,
- base::JSON_ALLOW_TRAILING_COMMAS);
- int error_code = 0;
- std::string error_msg;
- std::unique_ptr<base::Value> value =
- deserializer.Deserialize(&error_code, &error_msg);
- if (!value) {
- LOG(WARNING) << "Failed to read configuration file "
- << config_file_iter->value() << ": " << error_msg;
- status.Add(JsonErrorToPolicyLoadStatus(error_code));
- continue;
- }
- base::DictionaryValue* dictionary_value = nullptr;
- if (!value->GetAsDictionary(&dictionary_value)) {
- LOG(WARNING) << "Expected JSON dictionary in configuration file "
- << config_file_iter->value();
- status.Add(POLICY_LOAD_STATUS_PARSE_ERROR);
- continue;
- }
-
- // Detach the "3rdparty" node.
- std::unique_ptr<base::Value> third_party;
- if (dictionary_value->Remove("3rdparty", &third_party))
- Merge3rdPartyPolicy(third_party.get(), level, bundle);
-
- // Add chrome policy.
- PolicyMap policy_map;
- policy_map.LoadFrom(dictionary_value, level, scope_,
- POLICY_SOURCE_PLATFORM);
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .MergeFrom(policy_map);
- }
-}
-
-void ConfigDirPolicyLoader::Merge3rdPartyPolicy(
- const base::Value* policies,
- PolicyLevel level,
- PolicyBundle* bundle) {
- // The first-level entries in |policies| are PolicyDomains. The second-level
- // entries are component IDs, and the third-level entries are the policies
- // for that domain/component namespace.
-
- const base::DictionaryValue* domains_dictionary;
- if (!policies->GetAsDictionary(&domains_dictionary)) {
- LOG(WARNING) << "3rdparty value is not a dictionary!";
- return;
- }
-
- // Helper to lookup a domain given its string name.
- std::map<std::string, PolicyDomain> supported_domains;
- supported_domains["extensions"] = POLICY_DOMAIN_EXTENSIONS;
-
- for (base::DictionaryValue::Iterator domains_it(*domains_dictionary);
- !domains_it.IsAtEnd(); domains_it.Advance()) {
- if (!base::ContainsKey(supported_domains, domains_it.key())) {
- LOG(WARNING) << "Unsupported 3rd party policy domain: "
- << domains_it.key();
- continue;
- }
-
- const base::DictionaryValue* components_dictionary;
- if (!domains_it.value().GetAsDictionary(&components_dictionary)) {
- LOG(WARNING) << "3rdparty/" << domains_it.key()
- << " value is not a dictionary!";
- continue;
- }
-
- PolicyDomain domain = supported_domains[domains_it.key()];
- for (base::DictionaryValue::Iterator components_it(*components_dictionary);
- !components_it.IsAtEnd(); components_it.Advance()) {
- const base::DictionaryValue* policy_dictionary;
- if (!components_it.value().GetAsDictionary(&policy_dictionary)) {
- LOG(WARNING) << "3rdparty/" << domains_it.key() << "/"
- << components_it.key() << " value is not a dictionary!";
- continue;
- }
-
- PolicyMap policy;
- policy.LoadFrom(policy_dictionary, level, scope_, POLICY_SOURCE_PLATFORM);
- bundle->Get(PolicyNamespace(domain, components_it.key()))
- .MergeFrom(policy);
- }
- }
-}
-
-void ConfigDirPolicyLoader::OnFileUpdated(const base::FilePath& path,
- bool error) {
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
- if (!error)
- Reload(false);
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/config_dir_policy_loader.h b/components/policy/core/common/config_dir_policy_loader.h
deleted file mode 100644
index 8956353e73..0000000000
--- a/components/policy/core/common/config_dir_policy_loader.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_CONFIG_DIR_POLICY_LOADER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_CONFIG_DIR_POLICY_LOADER_H_
-
-#include "base/files/file_path.h"
-#include "base/files/file_path_watcher.h"
-#include "base/macros.h"
-#include "base/sequenced_task_runner.h"
-#include "components/policy/core/common/async_policy_loader.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/policy_export.h"
-
-namespace base {
-class Value;
-}
-
-namespace policy {
-
-// A policy loader implementation backed by a set of files in a given
-// directory. The files should contain JSON-formatted policy settings. They are
-// merged together and the result is returned in a PolicyBundle.
-// The files are consulted in lexicographic file name order, so the
-// last value read takes precedence in case of policy key collisions.
-class POLICY_EXPORT ConfigDirPolicyLoader : public AsyncPolicyLoader {
- public:
- ConfigDirPolicyLoader(scoped_refptr<base::SequencedTaskRunner> task_runner,
- const base::FilePath& config_dir,
- PolicyScope scope);
- ~ConfigDirPolicyLoader() override;
-
- // AsyncPolicyLoader implementation.
- void InitOnBackgroundThread() override;
- std::unique_ptr<PolicyBundle> Load() override;
- base::Time LastModificationTime() override;
-
- private:
- // Loads the policy files at |path| into the |bundle|, with the given |level|.
- void LoadFromPath(const base::FilePath& path,
- PolicyLevel level,
- PolicyBundle* bundle);
-
- // Merges the 3rd party |policies| into the |bundle|, with the given |level|.
- void Merge3rdPartyPolicy(const base::Value* policies,
- PolicyLevel level,
- PolicyBundle* bundle);
-
- // Callback for the FilePathWatchers.
- void OnFileUpdated(const base::FilePath& path, bool error);
-
- // Task runner for running background jobs.
- const scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- // The directory containing the policy files.
- const base::FilePath config_dir_;
-
- // Policies loaded by this provider will have this scope.
- const PolicyScope scope_;
-
- // Watchers for events on the mandatory and recommended subdirectories of
- // |config_dir_|.
- base::FilePathWatcher mandatory_watcher_;
- base::FilePathWatcher recommended_watcher_;
-
- DISALLOW_COPY_AND_ASSIGN(ConfigDirPolicyLoader);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_CONFIG_DIR_POLICY_LOADER_H_
diff --git a/components/policy/core/common/config_dir_policy_loader_unittest.cc b/components/policy/core/common/config_dir_policy_loader_unittest.cc
deleted file mode 100644
index b17add7974..0000000000
--- a/components/policy/core/common/config_dir_policy_loader_unittest.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/config_dir_policy_loader.h"
-#include <memory>
-
-#include <utility>
-
-#include "base/compiler_specific.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/json/json_string_value_serializer.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/values.h"
-#include "components/policy/core/common/async_policy_provider.h"
-#include "components/policy/core/common/configuration_policy_provider_test.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_types.h"
-
-namespace policy {
-
-namespace {
-
-// Subdirectory of the config dir that contains mandatory policies.
-const base::FilePath::CharType kMandatoryPath[] = FILE_PATH_LITERAL("managed");
-
-class TestHarness : public PolicyProviderTestHarness {
- public:
- TestHarness();
- ~TestHarness() override;
-
- void SetUp() override;
-
- ConfigurationPolicyProvider* CreateProvider(
- SchemaRegistry* registry,
- scoped_refptr<base::SequencedTaskRunner> task_runner) override;
-
- void InstallEmptyPolicy() override;
- void InstallStringPolicy(const std::string& policy_name,
- const std::string& policy_value) override;
- void InstallIntegerPolicy(const std::string& policy_name,
- int policy_value) override;
- void InstallBooleanPolicy(const std::string& policy_name,
- bool policy_value) override;
- void InstallStringListPolicy(const std::string& policy_name,
- const base::ListValue* policy_value) override;
- void InstallDictionaryPolicy(
- const std::string& policy_name,
- const base::DictionaryValue* policy_value) override;
- void Install3rdPartyPolicy(const base::DictionaryValue* policies) override;
-
- const base::FilePath& test_dir() { return test_dir_.GetPath(); }
-
- // JSON-encode a dictionary and write it to a file.
- void WriteConfigFile(const base::DictionaryValue& dict,
- const std::string& file_name);
-
- // Returns a unique name for a policy file. Each subsequent call returns a new
- // name that comes lexicographically after the previous one.
- std::string NextConfigFileName();
-
- static PolicyProviderTestHarness* Create();
-
- private:
- base::ScopedTempDir test_dir_;
- int next_policy_file_index_;
-
- DISALLOW_COPY_AND_ASSIGN(TestHarness);
-};
-
-TestHarness::TestHarness()
- : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_PLATFORM),
- next_policy_file_index_(100) {}
-
-TestHarness::~TestHarness() {}
-
-void TestHarness::SetUp() {
- ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
-}
-
-ConfigurationPolicyProvider* TestHarness::CreateProvider(
- SchemaRegistry* registry,
- scoped_refptr<base::SequencedTaskRunner> task_runner) {
- std::unique_ptr<AsyncPolicyLoader> loader(
- new ConfigDirPolicyLoader(task_runner, test_dir(), POLICY_SCOPE_MACHINE));
- return new AsyncPolicyProvider(registry, std::move(loader));
-}
-
-void TestHarness::InstallEmptyPolicy() {
- base::DictionaryValue dict;
- WriteConfigFile(dict, NextConfigFileName());
-}
-
-void TestHarness::InstallStringPolicy(const std::string& policy_name,
- const std::string& policy_value) {
- base::DictionaryValue dict;
- dict.SetString(policy_name, policy_value);
- WriteConfigFile(dict, NextConfigFileName());
-}
-
-void TestHarness::InstallIntegerPolicy(const std::string& policy_name,
- int policy_value) {
- base::DictionaryValue dict;
- dict.SetInteger(policy_name, policy_value);
- WriteConfigFile(dict, NextConfigFileName());
-}
-
-void TestHarness::InstallBooleanPolicy(const std::string& policy_name,
- bool policy_value) {
- base::DictionaryValue dict;
- dict.SetBoolean(policy_name, policy_value);
- WriteConfigFile(dict, NextConfigFileName());
-}
-
-void TestHarness::InstallStringListPolicy(const std::string& policy_name,
- const base::ListValue* policy_value) {
- base::DictionaryValue dict;
- dict.Set(policy_name, std::make_unique<base::Value>(policy_value->Clone()));
- WriteConfigFile(dict, NextConfigFileName());
-}
-
-void TestHarness::InstallDictionaryPolicy(
- const std::string& policy_name,
- const base::DictionaryValue* policy_value) {
- base::DictionaryValue dict;
- dict.Set(policy_name, std::make_unique<base::Value>(policy_value->Clone()));
- WriteConfigFile(dict, NextConfigFileName());
-}
-
-void TestHarness::Install3rdPartyPolicy(const base::DictionaryValue* policies) {
- base::DictionaryValue dict;
- dict.SetKey("3rdparty", policies->Clone());
- WriteConfigFile(dict, NextConfigFileName());
-}
-
-void TestHarness::WriteConfigFile(const base::DictionaryValue& dict,
- const std::string& file_name) {
- std::string data;
- JSONStringValueSerializer serializer(&data);
- serializer.Serialize(dict);
- const base::FilePath mandatory_dir(test_dir().Append(kMandatoryPath));
- ASSERT_TRUE(base::CreateDirectory(mandatory_dir));
- const base::FilePath file_path(mandatory_dir.AppendASCII(file_name));
- ASSERT_EQ((int) data.size(),
- base::WriteFile(file_path, data.c_str(), data.size()));
-}
-
-std::string TestHarness::NextConfigFileName() {
- EXPECT_LE(next_policy_file_index_, 999);
- return std::string("policy") + base::IntToString(next_policy_file_index_++);
-}
-
-// static
-PolicyProviderTestHarness* TestHarness::Create() {
- return new TestHarness();
-}
-
-} // namespace
-
-// Instantiate abstract test case for basic policy reading tests.
-INSTANTIATE_TEST_CASE_P(
- ConfigDirPolicyLoaderTest,
- ConfigurationPolicyProviderTest,
- testing::Values(TestHarness::Create));
-
-// Instantiate abstract test case for 3rd party policy reading tests.
-INSTANTIATE_TEST_CASE_P(
- ConfigDir3rdPartyPolicyLoaderTest,
- Configuration3rdPartyPolicyProviderTest,
- testing::Values(TestHarness::Create));
-
-// Some tests that exercise special functionality in ConfigDirPolicyLoader.
-class ConfigDirPolicyLoaderTest : public PolicyTestBase {
- protected:
- void SetUp() override {
- PolicyTestBase::SetUp();
- harness_.SetUp();
- }
-
- TestHarness harness_;
-};
-
-// The preferences dictionary is expected to be empty when there are no files to
-// load.
-TEST_F(ConfigDirPolicyLoaderTest, ReadPrefsEmpty) {
- ConfigDirPolicyLoader loader(
- scoped_task_environment_.GetMainThreadTaskRunner(), harness_.test_dir(),
- POLICY_SCOPE_MACHINE);
- std::unique_ptr<PolicyBundle> bundle(loader.Load());
- ASSERT_TRUE(bundle.get());
- const PolicyBundle kEmptyBundle;
- EXPECT_TRUE(bundle->Equals(kEmptyBundle));
-}
-
-// Reading from a non-existent directory should result in an empty preferences
-// dictionary.
-TEST_F(ConfigDirPolicyLoaderTest, ReadPrefsNonExistentDirectory) {
- base::FilePath non_existent_dir(
- harness_.test_dir().Append(FILE_PATH_LITERAL("not_there")));
- ConfigDirPolicyLoader loader(
- scoped_task_environment_.GetMainThreadTaskRunner(), non_existent_dir,
- POLICY_SCOPE_MACHINE);
- std::unique_ptr<PolicyBundle> bundle(loader.Load());
- ASSERT_TRUE(bundle.get());
- const PolicyBundle kEmptyBundle;
- EXPECT_TRUE(bundle->Equals(kEmptyBundle));
-}
-
-// Test merging values from different files.
-TEST_F(ConfigDirPolicyLoaderTest, ReadPrefsMergePrefs) {
- // Write a bunch of data files in order to increase the chance to detect the
- // provider not respecting lexicographic ordering when reading them. Since the
- // filesystem may return files in arbitrary order, there is no way to be sure,
- // but this is better than nothing.
- base::DictionaryValue test_dict_bar;
- test_dict_bar.SetString("HomepageLocation", "http://bar.com");
- for (unsigned int i = 1; i <= 4; ++i)
- harness_.WriteConfigFile(test_dict_bar, base::UintToString(i));
- base::DictionaryValue test_dict_foo;
- test_dict_foo.SetString("HomepageLocation", "http://foo.com");
- harness_.WriteConfigFile(test_dict_foo, "9");
- for (unsigned int i = 5; i <= 8; ++i)
- harness_.WriteConfigFile(test_dict_bar, base::UintToString(i));
-
- ConfigDirPolicyLoader loader(
- scoped_task_environment_.GetMainThreadTaskRunner(), harness_.test_dir(),
- POLICY_SCOPE_USER);
- std::unique_ptr<PolicyBundle> bundle(loader.Load());
- ASSERT_TRUE(bundle.get());
- PolicyBundle expected_bundle;
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .LoadFrom(&test_dict_foo, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_PLATFORM);
- EXPECT_TRUE(bundle->Equals(expected_bundle));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/configuration_policy_provider.cc b/components/policy/core/common/configuration_policy_provider.cc
deleted file mode 100644
index a886bd4bca..0000000000
--- a/components/policy/core/common/configuration_policy_provider.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/configuration_policy_provider.h"
-
-#include "base/callback.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/policy_map.h"
-
-namespace policy {
-
-ConfigurationPolicyProvider::Observer::~Observer() {}
-
-ConfigurationPolicyProvider::ConfigurationPolicyProvider()
- : initialized_(false), schema_registry_(nullptr) {}
-
-ConfigurationPolicyProvider::~ConfigurationPolicyProvider() {
- DCHECK(!initialized_);
-}
-
-void ConfigurationPolicyProvider::Init(SchemaRegistry* registry) {
- schema_registry_ = registry;
- schema_registry_->AddObserver(this);
- initialized_ = true;
-}
-
-void ConfigurationPolicyProvider::Shutdown() {
- initialized_ = false;
- if (schema_registry_) {
- // Unit tests don't initialize the BrowserPolicyConnector but call
- // shutdown; handle that.
- schema_registry_->RemoveObserver(this);
- schema_registry_ = nullptr;
- }
-}
-
-bool ConfigurationPolicyProvider::IsInitializationComplete(
- PolicyDomain domain) const {
- return true;
-}
-
-void ConfigurationPolicyProvider::UpdatePolicy(
- std::unique_ptr<PolicyBundle> bundle) {
- if (bundle)
- policy_bundle_.Swap(bundle.get());
- else
- policy_bundle_.Clear();
- for (auto& observer : observer_list_)
- observer.OnUpdatePolicy(this);
-}
-
-SchemaRegistry* ConfigurationPolicyProvider::schema_registry() const {
- return schema_registry_;
-}
-
-const scoped_refptr<SchemaMap>&
-ConfigurationPolicyProvider::schema_map() const {
- return schema_registry_->schema_map();
-}
-
-void ConfigurationPolicyProvider::AddObserver(Observer* observer) {
- observer_list_.AddObserver(observer);
-}
-
-void ConfigurationPolicyProvider::RemoveObserver(Observer* observer) {
- observer_list_.RemoveObserver(observer);
-}
-
-void ConfigurationPolicyProvider::OnSchemaRegistryUpdated(
- bool has_new_schemas) {}
-
-void ConfigurationPolicyProvider::OnSchemaRegistryReady() {}
-
-} // namespace policy
diff --git a/components/policy/core/common/configuration_policy_provider.h b/components/policy/core/common/configuration_policy_provider.h
deleted file mode 100644
index a813c0c091..0000000000
--- a/components/policy/core/common/configuration_policy_provider.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/observer_list.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/core/common/schema_registry.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// A mostly-abstract super class for platform-specific policy providers.
-// Platform-specific policy providers (Windows Group Policy, gconf,
-// etc.) should implement a subclass of this class.
-class POLICY_EXPORT ConfigurationPolicyProvider
- : public SchemaRegistry::Observer {
- public:
- class POLICY_EXPORT Observer {
- public:
- virtual ~Observer();
- virtual void OnUpdatePolicy(ConfigurationPolicyProvider* provider) = 0;
- };
-
- ConfigurationPolicyProvider();
-
- // Policy providers can be deleted quite late during shutdown of the browser,
- // and it's not guaranteed that the message loops will still be running when
- // this is invoked. Override Shutdown() instead for cleanup code that needs
- // to post to the FILE thread, for example.
- ~ConfigurationPolicyProvider() override;
-
- // Invoked as soon as the main message loops are spinning. Policy providers
- // are created early during startup to provide the initial policies; the
- // Init() call allows them to perform initialization tasks that require
- // running message loops.
- // The policy provider will load policy for the components registered in
- // the |schema_registry| whose domain is supported by this provider.
- virtual void Init(SchemaRegistry* registry);
-
- // Must be invoked before deleting the provider. Implementations can override
- // this method to do appropriate cleanup while threads are still running, and
- // must also invoke ConfigurationPolicyProvider::Shutdown().
- // The provider should keep providing the current policies after Shutdown()
- // is invoked, it only has to stop updating.
- virtual void Shutdown();
-
- // Returns the current PolicyBundle.
- const PolicyBundle& policies() const { return policy_bundle_; }
-
- // Check whether this provider has completed initialization for the given
- // policy |domain|. This is used to detect whether initialization is done in
- // case implementations need to do asynchronous operations for initialization.
- virtual bool IsInitializationComplete(PolicyDomain domain) const;
-
- // Asks the provider to refresh its policies. All the updates caused by this
- // call will be visible on the next call of OnUpdatePolicy on the observers,
- // which are guaranteed to happen even if the refresh fails.
- // It is possible that Shutdown() is called first though, and
- // OnUpdatePolicy won't be called if that happens.
- virtual void RefreshPolicies() = 0;
-
- // Observers must detach themselves before the provider is deleted.
- virtual void AddObserver(Observer* observer);
- virtual void RemoveObserver(Observer* observer);
-
- // SchemaRegistry::Observer:
- void OnSchemaRegistryUpdated(bool has_new_schemas) override;
- void OnSchemaRegistryReady() override;
-
- protected:
- // Subclasses must invoke this to update the policies currently served by
- // this provider. UpdatePolicy() takes ownership of |policies|.
- // The observers are notified after the policies are updated.
- void UpdatePolicy(std::unique_ptr<PolicyBundle> bundle);
-
- SchemaRegistry* schema_registry() const;
-
- const scoped_refptr<SchemaMap>& schema_map() const;
-
- private:
- // The policies currently configured at this provider.
- PolicyBundle policy_bundle_;
-
- // Used to validate proper Init() and Shutdown() nesting. This flag is set by
- // Init() and cleared by Shutdown() and needs to be false in the destructor.
- bool initialized_;
-
- SchemaRegistry* schema_registry_;
-
- base::ObserverList<Observer, true> observer_list_;
-
- DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProvider);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_H_
diff --git a/components/policy/core/common/configuration_policy_provider_test.cc b/components/policy/core/common/configuration_policy_provider_test.cc
deleted file mode 100644
index 4f9beea29c..0000000000
--- a/components/policy/core/common/configuration_policy_provider_test.cc
+++ /dev/null
@@ -1,420 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/configuration_policy_provider_test.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
-#include "base/values.h"
-#include "components/policy/core/common/configuration_policy_provider.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/mock_configuration_policy_provider.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/core/common/policy_types.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using ::testing::Mock;
-using ::testing::_;
-
-namespace policy {
-
-const char kTestChromeSchema[] =
- "{"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"StringPolicy\": { \"type\": \"string\" },"
- " \"BooleanPolicy\": { \"type\": \"boolean\" },"
- " \"IntegerPolicy\": { \"type\": \"integer\" },"
- " \"StringListPolicy\": {"
- " \"type\": \"array\","
- " \"items\": { \"type\": \"string\" }"
- " },"
- " \"DictionaryPolicy\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"bool\": { \"type\": \"boolean\" },"
- " \"double\": { \"type\": \"number\" },"
- " \"int\": { \"type\": \"integer\" },"
- " \"string\": { \"type\": \"string\" },"
- " \"array\": {"
- " \"type\": \"array\","
- " \"items\": { \"type\": \"string\" }"
- " },"
- " \"dictionary\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"sub\": { \"type\": \"string\" },"
- " \"sublist\": {"
- " \"type\": \"array\","
- " \"items\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"aaa\": { \"type\": \"integer\" },"
- " \"bbb\": { \"type\": \"integer\" },"
- " \"ccc\": { \"type\": \"string\" },"
- " \"ddd\": { \"type\": \"string\" }"
- " }"
- " }"
- " }"
- " }"
- " },"
- " \"list\": {"
- " \"type\": \"array\","
- " \"items\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"subdictindex\": { \"type\": \"integer\" },"
- " \"subdict\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"bool\": { \"type\": \"boolean\" },"
- " \"double\": { \"type\": \"number\" },"
- " \"int\": { \"type\": \"integer\" },"
- " \"string\": { \"type\": \"string\" }"
- " }"
- " }"
- " }"
- " }"
- " },"
- " \"dict\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"bool\": { \"type\": \"boolean\" },"
- " \"double\": { \"type\": \"number\" },"
- " \"int\": { \"type\": \"integer\" },"
- " \"string\": { \"type\": \"string\" },"
- " \"list\": {"
- " \"type\": \"array\","
- " \"items\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"subdictindex\": { \"type\": \"integer\" },"
- " \"subdict\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"bool\": { \"type\": \"boolean\" },"
- " \"double\": { \"type\": \"number\" },"
- " \"int\": { \"type\": \"integer\" },"
- " \"string\": { \"type\": \"string\" }"
- " }"
- " }"
- " }"
- " }"
- " }"
- " }"
- " }"
- " }"
- " }"
- " }"
- "}";
-
-namespace test_keys {
-
-const char kKeyString[] = "StringPolicy";
-const char kKeyBoolean[] = "BooleanPolicy";
-const char kKeyInteger[] = "IntegerPolicy";
-const char kKeyStringList[] = "StringListPolicy";
-const char kKeyDictionary[] = "DictionaryPolicy";
-
-} // namespace test_keys
-
-PolicyTestBase::PolicyTestBase() {}
-
-PolicyTestBase::~PolicyTestBase() {}
-
-void PolicyTestBase::SetUp() {
- const PolicyNamespace ns(POLICY_DOMAIN_CHROME, "");
- ASSERT_TRUE(RegisterSchema(ns, kTestChromeSchema));
-}
-
-void PolicyTestBase::TearDown() {
- scoped_task_environment_.RunUntilIdle();
-}
-
-bool PolicyTestBase::RegisterSchema(const PolicyNamespace& ns,
- const std::string& schema_string) {
- std::string error;
- Schema schema = Schema::Parse(schema_string, &error);
- if (schema.valid()) {
- schema_registry_.RegisterComponent(ns, schema);
- return true;
- }
- ADD_FAILURE() << error;
- return false;
-}
-
-PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level,
- PolicyScope scope,
- PolicySource source)
- : level_(level), scope_(scope), source_(source) {}
-
-PolicyProviderTestHarness::~PolicyProviderTestHarness() {}
-
-PolicyLevel PolicyProviderTestHarness::policy_level() const {
- return level_;
-}
-
-PolicyScope PolicyProviderTestHarness::policy_scope() const {
- return scope_;
-}
-
-PolicySource PolicyProviderTestHarness::policy_source() const {
- return source_;
-}
-
-void PolicyProviderTestHarness::Install3rdPartyPolicy(
- const base::DictionaryValue* policies) {
- FAIL();
-}
-
-ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {}
-
-ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {}
-
-void ConfigurationPolicyProviderTest::SetUp() {
- PolicyTestBase::SetUp();
-
- test_harness_.reset((*GetParam())());
- ASSERT_NO_FATAL_FAILURE(test_harness_->SetUp());
-
- const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
- Schema chrome_schema = *schema_registry_.schema_map()->GetSchema(chrome_ns);
- Schema extension_schema =
- chrome_schema.GetKnownProperty(test_keys::kKeyDictionary);
- ASSERT_TRUE(extension_schema.valid());
- schema_registry_.RegisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
- extension_schema);
- schema_registry_.RegisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
- extension_schema);
- schema_registry_.RegisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- "cccccccccccccccccccccccccccccccc"),
- extension_schema);
-
- provider_.reset(test_harness_->CreateProvider(
- &schema_registry_,
- base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()})));
- provider_->Init(&schema_registry_);
- // Some providers do a reload on init. Make sure any notifications generated
- // are fired now.
- scoped_task_environment_.RunUntilIdle();
-
- const PolicyBundle kEmptyBundle;
- EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle));
-}
-
-void ConfigurationPolicyProviderTest::TearDown() {
- // Give providers the chance to clean up after themselves on the file thread.
- provider_->Shutdown();
- provider_.reset();
-
- PolicyTestBase::TearDown();
-}
-
-void ConfigurationPolicyProviderTest::CheckValue(
- const char* policy_name,
- const base::Value& expected_value,
- base::Closure install_value) {
- // Install the value, reload policy and check the provider for the value.
- install_value.Run();
- provider_->RefreshPolicies();
- scoped_task_environment_.RunUntilIdle();
- PolicyBundle expected_bundle;
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set(policy_name, test_harness_->policy_level(),
- test_harness_->policy_scope(), test_harness_->policy_source(),
- expected_value.CreateDeepCopy(), nullptr);
- EXPECT_TRUE(provider_->policies().Equals(expected_bundle));
- // TODO(joaodasilva): set the policy in the POLICY_DOMAIN_EXTENSIONS too,
- // and extend the |expected_bundle|, once all providers are ready.
-}
-
-TEST_P(ConfigurationPolicyProviderTest, Empty) {
- provider_->RefreshPolicies();
- scoped_task_environment_.RunUntilIdle();
- const PolicyBundle kEmptyBundle;
- EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle));
-}
-
-TEST_P(ConfigurationPolicyProviderTest, StringValue) {
- const char kTestString[] = "string_value";
- base::Value expected_value(kTestString);
- CheckValue(test_keys::kKeyString,
- expected_value,
- base::Bind(&PolicyProviderTestHarness::InstallStringPolicy,
- base::Unretained(test_harness_.get()),
- test_keys::kKeyString,
- kTestString));
-}
-
-TEST_P(ConfigurationPolicyProviderTest, BooleanValue) {
- base::Value expected_value(true);
- CheckValue(test_keys::kKeyBoolean,
- expected_value,
- base::Bind(&PolicyProviderTestHarness::InstallBooleanPolicy,
- base::Unretained(test_harness_.get()),
- test_keys::kKeyBoolean,
- true));
-}
-
-TEST_P(ConfigurationPolicyProviderTest, IntegerValue) {
- base::Value expected_value(42);
- CheckValue(test_keys::kKeyInteger,
- expected_value,
- base::Bind(&PolicyProviderTestHarness::InstallIntegerPolicy,
- base::Unretained(test_harness_.get()),
- test_keys::kKeyInteger,
- 42));
-}
-
-TEST_P(ConfigurationPolicyProviderTest, StringListValue) {
- base::ListValue expected_value;
- expected_value.AppendString("first");
- expected_value.AppendString("second");
- CheckValue(test_keys::kKeyStringList,
- expected_value,
- base::Bind(&PolicyProviderTestHarness::InstallStringListPolicy,
- base::Unretained(test_harness_.get()),
- test_keys::kKeyStringList,
- &expected_value));
-}
-
-TEST_P(ConfigurationPolicyProviderTest, DictionaryValue) {
- base::DictionaryValue expected_value;
- expected_value.SetBoolean("bool", true);
- expected_value.SetDouble("double", 123.456);
- expected_value.SetInteger("int", 123);
- expected_value.SetString("string", "omg");
-
- auto list = std::make_unique<base::ListValue>();
- list->AppendString("first");
- list->AppendString("second");
- expected_value.Set("array", std::move(list));
-
- auto dict = std::make_unique<base::DictionaryValue>();
- dict->SetString("sub", "value");
- list = std::make_unique<base::ListValue>();
- auto sub = std::make_unique<base::DictionaryValue>();
- sub->SetInteger("aaa", 111);
- sub->SetInteger("bbb", 222);
- list->Append(std::move(sub));
- sub = std::make_unique<base::DictionaryValue>();
- sub->SetString("ccc", "333");
- sub->SetString("ddd", "444");
- list->Append(std::move(sub));
- dict->Set("sublist", std::move(list));
- expected_value.Set("dictionary", std::move(dict));
-
- CheckValue(test_keys::kKeyDictionary,
- expected_value,
- base::Bind(&PolicyProviderTestHarness::InstallDictionaryPolicy,
- base::Unretained(test_harness_.get()),
- test_keys::kKeyDictionary,
- &expected_value));
-}
-
-TEST_P(ConfigurationPolicyProviderTest, RefreshPolicies) {
- PolicyBundle bundle;
- EXPECT_TRUE(provider_->policies().Equals(bundle));
-
- // OnUpdatePolicy is called even when there are no changes.
- MockConfigurationPolicyObserver observer;
- provider_->AddObserver(&observer);
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
- provider_->RefreshPolicies();
- scoped_task_environment_.RunUntilIdle();
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_TRUE(provider_->policies().Equals(bundle));
-
- // OnUpdatePolicy is called when there are changes.
- test_harness_->InstallStringPolicy(test_keys::kKeyString, "value");
- EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1);
- provider_->RefreshPolicies();
- scoped_task_environment_.RunUntilIdle();
- Mock::VerifyAndClearExpectations(&observer);
-
- bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set(test_keys::kKeyString, test_harness_->policy_level(),
- test_harness_->policy_scope(), test_harness_->policy_source(),
- std::make_unique<base::Value>("value"), nullptr);
- EXPECT_TRUE(provider_->policies().Equals(bundle));
- provider_->RemoveObserver(&observer);
-}
-
-Configuration3rdPartyPolicyProviderTest::
- Configuration3rdPartyPolicyProviderTest() {}
-
-Configuration3rdPartyPolicyProviderTest::
- ~Configuration3rdPartyPolicyProviderTest() {}
-
-TEST_P(Configuration3rdPartyPolicyProviderTest, Load3rdParty) {
- base::DictionaryValue policy_dict;
- policy_dict.SetBoolean("bool", true);
- policy_dict.SetDouble("double", 123.456);
- policy_dict.SetInteger("int", 789);
- policy_dict.SetString("string", "string value");
-
- auto list = std::make_unique<base::ListValue>();
- for (int i = 0; i < 2; ++i) {
- auto dict = std::make_unique<base::DictionaryValue>();
- dict->SetInteger("subdictindex", i);
- dict->SetKey("subdict", policy_dict.Clone());
- list->Append(std::move(dict));
- }
- policy_dict.Set("list", std::move(list));
- policy_dict.SetKey("dict", policy_dict.Clone());
-
- // Install these policies as a Chrome policy.
- test_harness_->InstallDictionaryPolicy(test_keys::kKeyDictionary,
- &policy_dict);
- // Install them as 3rd party policies too.
- base::DictionaryValue policy_3rdparty;
- policy_3rdparty.SetPath({"extensions", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
- policy_dict.Clone());
- policy_3rdparty.SetPath({"extensions", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"},
- policy_dict.Clone());
- // Install invalid 3rd party policies that shouldn't be loaded. These also
- // help detecting memory leaks in the code paths that detect invalid input.
- policy_3rdparty.SetPath({"invalid-domain", "component"}, policy_dict.Clone());
- policy_3rdparty.SetString("extensions.cccccccccccccccccccccccccccccccc",
- "invalid-value");
- test_harness_->Install3rdPartyPolicy(&policy_3rdparty);
-
- provider_->RefreshPolicies();
- scoped_task_environment_.RunUntilIdle();
-
- PolicyMap expected_policy;
- expected_policy.Set(test_keys::kKeyDictionary, test_harness_->policy_level(),
- test_harness_->policy_scope(),
- test_harness_->policy_source(),
- policy_dict.CreateDeepCopy(), nullptr);
- PolicyBundle expected_bundle;
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .CopyFrom(expected_policy);
- expected_policy.Clear();
- expected_policy.LoadFrom(&policy_dict,
- test_harness_->policy_level(),
- test_harness_->policy_scope(),
- test_harness_->policy_source());
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
- .CopyFrom(expected_policy);
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
- .CopyFrom(expected_policy);
- EXPECT_TRUE(provider_->policies().Equals(expected_bundle));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/configuration_policy_provider_test.h b/components/policy/core/common/configuration_policy_provider_test.h
deleted file mode 100644
index 0d314b3f4c..0000000000
--- a/components/policy/core/common/configuration_policy_provider_test.h
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_TEST_H_
-#define COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_TEST_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/test/scoped_task_environment.h"
-#include "build/build_config.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/core/common/schema.h"
-#include "components/policy/core/common/schema_registry.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-class DictionaryValue;
-class ListValue;
-class SequencedTaskRunner;
-class Value;
-}
-
-namespace policy {
-
-class ConfigurationPolicyProvider;
-
-namespace test_keys {
-
-extern const char kKeyString[];
-extern const char kKeyBoolean[];
-extern const char kKeyInteger[];
-extern const char kKeyStringList[];
-extern const char kKeyDictionary[];
-
-} // namespace test_keys
-
-class PolicyTestBase : public testing::Test {
- public:
- PolicyTestBase();
- ~PolicyTestBase() override;
-
- // testing::Test:
- void SetUp() override;
- void TearDown() override;
-
- protected:
- bool RegisterSchema(const PolicyNamespace& ns,
- const std::string& schema);
-
- // Needs to be the first member
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- SchemaRegistry schema_registry_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PolicyTestBase);
-};
-
-// An interface for creating a test policy provider and creating a policy
-// provider instance for testing. Used as the parameter to the abstract
-// ConfigurationPolicyProviderTest below.
-class PolicyProviderTestHarness {
- public:
- // |level|, |scope| and |source| are the level, scope and source of the
- // policies returned by the providers from CreateProvider().
- PolicyProviderTestHarness(PolicyLevel level,
- PolicyScope scope,
- PolicySource source);
- virtual ~PolicyProviderTestHarness();
-
- // Actions to run at gtest SetUp() time.
- virtual void SetUp() = 0;
-
- // Create a new policy provider.
- virtual ConfigurationPolicyProvider* CreateProvider(
- SchemaRegistry* registry,
- scoped_refptr<base::SequencedTaskRunner> task_runner) = 0;
-
- // Returns the policy level, scope and source set by the policy provider.
- PolicyLevel policy_level() const;
- PolicyScope policy_scope() const;
- PolicySource policy_source() const;
-
- // Helpers to configure the environment the policy provider reads from.
- virtual void InstallEmptyPolicy() = 0;
- virtual void InstallStringPolicy(const std::string& policy_name,
- const std::string& policy_value) = 0;
- virtual void InstallIntegerPolicy(const std::string& policy_name,
- int policy_value) = 0;
- virtual void InstallBooleanPolicy(const std::string& policy_name,
- bool policy_value) = 0;
- virtual void InstallStringListPolicy(const std::string& policy_name,
- const base::ListValue* policy_value) = 0;
- virtual void InstallDictionaryPolicy(
- const std::string& policy_name,
- const base::DictionaryValue* policy_value) = 0;
-
- // Not every provider supports installing 3rd party policy. Those who do
- // should override this method; the default just makes the test fail.
- virtual void Install3rdPartyPolicy(const base::DictionaryValue* policies);
-
- private:
- PolicyLevel level_;
- PolicyScope scope_;
- PolicySource source_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyProviderTestHarness);
-};
-
-// A factory method for creating a test harness.
-typedef PolicyProviderTestHarness* (*CreatePolicyProviderTestHarness)();
-
-// Abstract policy provider test. This is meant to be instantiated for each
-// policy provider implementation, passing in a suitable harness factory
-// function as the test parameter.
-class ConfigurationPolicyProviderTest
- : public PolicyTestBase,
- public testing::WithParamInterface<CreatePolicyProviderTestHarness> {
- protected:
- ConfigurationPolicyProviderTest();
- virtual ~ConfigurationPolicyProviderTest();
-
- void SetUp() override;
- void TearDown() override;
-
- // Installs a valid policy and checks whether the provider returns the
- // |expected_value|.
- void CheckValue(const char* policy_name,
- const base::Value& expected_value,
- base::Closure install_value);
-
- std::unique_ptr<PolicyProviderTestHarness> test_harness_;
- std::unique_ptr<ConfigurationPolicyProvider> provider_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProviderTest);
-};
-
-// An extension of ConfigurationPolicyProviderTest that also tests loading of
-// 3rd party policy. Policy provider implementations that support loading of
-// 3rd party policy should also instantiate these tests.
-class Configuration3rdPartyPolicyProviderTest
- : public ConfigurationPolicyProviderTest {
- protected:
- Configuration3rdPartyPolicyProviderTest();
- virtual ~Configuration3rdPartyPolicyProviderTest();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Configuration3rdPartyPolicyProviderTest);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_TEST_H_
diff --git a/components/policy/core/common/external_data_fetcher.cc b/components/policy/core/common/external_data_fetcher.cc
deleted file mode 100644
index 1bce30a969..0000000000
--- a/components/policy/core/common/external_data_fetcher.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/external_data_fetcher.h"
-
-#include "base/callback.h"
-#include "components/policy/core/common/external_data_manager.h"
-
-namespace policy {
-
-ExternalDataFetcher::ExternalDataFetcher(
- base::WeakPtr<ExternalDataManager> manager,
- const std::string& policy)
- : manager_(manager),
- policy_(policy) {
-}
-
-ExternalDataFetcher::ExternalDataFetcher(const ExternalDataFetcher& other)
- : manager_(other.manager_),
- policy_(other.policy_) {
-}
-
-ExternalDataFetcher::~ExternalDataFetcher() {
-}
-
-// static
-bool ExternalDataFetcher::Equals(const ExternalDataFetcher* first,
- const ExternalDataFetcher* second) {
- if (!first && !second)
- return true;
- if (!first || !second)
- return false;
- return first->manager_.get() == second->manager_.get() &&
- first->policy_ == second->policy_;
-}
-
-void ExternalDataFetcher::Fetch(const FetchCallback& callback) const {
- if (manager_)
- manager_->Fetch(policy_, callback);
- else
- callback.Run(std::unique_ptr<std::string>());
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/external_data_fetcher.h b/components/policy/core/common/external_data_fetcher.h
deleted file mode 100644
index 0c014e794b..0000000000
--- a/components/policy/core/common/external_data_fetcher.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_EXTERNAL_DATA_FETCHER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_EXTERNAL_DATA_FETCHER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback_forward.h"
-#include "base/memory/weak_ptr.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-class ExternalDataManager;
-
-// A helper that encapsulates the parameters required to retrieve the external
-// data for a policy.
-class POLICY_EXPORT ExternalDataFetcher {
- public:
- typedef base::Callback<void(std::unique_ptr<std::string>)> FetchCallback;
-
- // This instance's Fetch() method will instruct the |manager| to retrieve the
- // external data referenced by the given |policy|.
- ExternalDataFetcher(base::WeakPtr<ExternalDataManager> manager,
- const std::string& policy);
- ExternalDataFetcher(const ExternalDataFetcher& other);
-
- ~ExternalDataFetcher();
-
- static bool Equals(const ExternalDataFetcher* first,
- const ExternalDataFetcher* second);
-
- // Retrieves the external data referenced by |policy_| and invokes |callback|
- // with the result. If |policy_| does not reference any external data, the
- // |callback| is invoked with a NULL pointer. Otherwise, the |callback| is
- // invoked with the referenced data once it has been successfully retrieved.
- // If retrieval is temporarily impossible (e.g. no network connectivity), the
- // |callback| will be invoked when the temporary hindrance is resolved. If
- // retrieval is permanently impossible (e.g. |policy_| references data that
- // does not exist on the server), the |callback| will never be invoked.
- void Fetch(const FetchCallback& callback) const;
-
- private:
- base::WeakPtr<ExternalDataManager> manager_;
- const std::string policy_;
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_EXTERNAL_DATA_FETCHER_H_
diff --git a/components/policy/core/common/external_data_manager.h b/components/policy/core/common/external_data_manager.h
deleted file mode 100644
index 406cf596bb..0000000000
--- a/components/policy/core/common/external_data_manager.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_EXTERNAL_DATA_MANAGER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_EXTERNAL_DATA_MANAGER_H_
-
-#include <string>
-
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// Downloads, verifies, caches and retrieves external data referenced by
-// policies.
-// An implementation of this abstract interface should be provided for each
-// policy source (cloud policy, platform policy) that supports external data
-// references.
-class POLICY_EXPORT ExternalDataManager {
- public:
- // Retrieves the external data referenced by |policy| and invokes |callback|
- // with the result. If |policy| does not reference any external data, the
- // |callback| is invoked with a NULL pointer. Otherwise, the |callback| is
- // invoked with the referenced data once it has been successfully retrieved.
- // If retrieval is temporarily impossible (e.g. no network connectivity), the
- // |callback| will be invoked when the temporary hindrance is resolved. If
- // retrieval is permanently impossible (e.g. |policy| references data that
- // does not exist on the server), the |callback| will never be invoked.
- virtual void Fetch(const std::string& policy,
- const ExternalDataFetcher::FetchCallback& callback) = 0;
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_EXTERNAL_DATA_MANAGER_H_
diff --git a/components/policy/core/common/fake_async_policy_loader.cc b/components/policy/core/common/fake_async_policy_loader.cc
deleted file mode 100644
index efa9f7b6b3..0000000000
--- a/components/policy/core/common/fake_async_policy_loader.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 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 "components/policy/core/common/fake_async_policy_loader.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/sequenced_task_runner.h"
-
-namespace policy {
-
-FakeAsyncPolicyLoader::FakeAsyncPolicyLoader(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : AsyncPolicyLoader(task_runner) {
-}
-
-std::unique_ptr<PolicyBundle> FakeAsyncPolicyLoader::Load() {
- std::unique_ptr<PolicyBundle> result(new PolicyBundle());
- result->CopyFrom(policy_bundle_);
- return result;
-}
-
-void FakeAsyncPolicyLoader::InitOnBackgroundThread() {
- // Nothing to do.
-}
-
-void FakeAsyncPolicyLoader::SetPolicies(const PolicyBundle& policy_bundle) {
- policy_bundle_.CopyFrom(policy_bundle);
-}
-
-void FakeAsyncPolicyLoader::PostReloadOnBackgroundThread(bool force) {
- task_runner()->PostTask(FROM_HERE, base::Bind(&AsyncPolicyLoader::Reload,
- base::Unretained(this), force));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/fake_async_policy_loader.h b/components/policy/core/common/fake_async_policy_loader.h
deleted file mode 100644
index e1583741fe..0000000000
--- a/components/policy/core/common/fake_async_policy_loader.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_FAKE_ASYNC_POLICY_LOADER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_FAKE_ASYNC_POLICY_LOADER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "components/policy/core/common/async_policy_loader.h"
-#include "components/policy/core/common/policy_bundle.h"
-
-namespace base {
-class SequencedTaskRunner;
-} // namespace base
-
-namespace policy {
-
-// Fake AsyncPolicyLoader for testing with test-controlled policies.
-//
-// Typical test code would populate the policy contents via calls to
-// ClearPolicies and AddPolicies and then notify the rest of the policy
-// subsystem of the changes by calling PostReloadOnBackgroundThread.
-class FakeAsyncPolicyLoader : public AsyncPolicyLoader {
- public:
- explicit FakeAsyncPolicyLoader(
- const scoped_refptr<base::SequencedTaskRunner>& task_runner);
-
- // Implementation of virtual methods from AsyncPolicyLoader base class.
- std::unique_ptr<PolicyBundle> Load() override;
- void InitOnBackgroundThread() override;
-
- // Provides content for the simulated / faked policies.
- void SetPolicies(const PolicyBundle& policy_bundle);
-
- // Notifies the rest of the policy subsystem that policy contents have
- // changed. This simulates / fakes a notification that normally would be
- // triggered by a FilePathWatcher or (registry)ObjectWatcher in a real loader.
- //
- // See AsyncPolicyLoader::Reload method for description of the |force|
- // parameter.
- void PostReloadOnBackgroundThread(bool force);
-
- private:
- PolicyBundle policy_bundle_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeAsyncPolicyLoader);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_FAKE_ASYNC_POLICY_LOADER_H_
diff --git a/components/policy/core/common/generate_policy_source_unittest.cc b/components/policy/core/common/generate_policy_source_unittest.cc
deleted file mode 100644
index 78d5cadbd0..0000000000
--- a/components/policy/core/common/generate_policy_source_unittest.cc
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2013 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 <cstring>
-#include <memory>
-#include <string>
-
-#include "base/values.h"
-#include "build/build_config.h"
-#include "components/policy/core/common/policy_details.h"
-#include "components/policy/core/common/schema.h"
-#include "components/policy/policy_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// This unittest tests the code generated by
-// chrome/tools/build/generate_policy_source.py.
-
-namespace policy {
-
-namespace {
-
-#if defined(OS_CHROMEOS)
-// Checks if two schemas are the same or not. Note that this function doesn't
-// consider restrictions on integers and strings nor pattern properties.
-bool IsSameSchema(Schema a, Schema b) {
- if (a.valid() != b.valid())
- return false;
- if (!a.valid())
- return true;
- if (a.type() != b.type())
- return false;
- if (a.type() == base::Value::Type::LIST)
- return IsSameSchema(a.GetItems(), b.GetItems());
- if (a.type() != base::Value::Type::DICTIONARY)
- return true;
- Schema::Iterator a_it = a.GetPropertiesIterator();
- Schema::Iterator b_it = b.GetPropertiesIterator();
- while (!a_it.IsAtEnd()) {
- if (b_it.IsAtEnd())
- return false;
- if (strcmp(a_it.key(), b_it.key()) != 0)
- return false;
- if (!IsSameSchema(a_it.schema(), b_it.schema()))
- return false;
- a_it.Advance();
- b_it.Advance();
- }
- if (!b_it.IsAtEnd())
- return false;
- return IsSameSchema(a.GetAdditionalProperties(), b.GetAdditionalProperties());
-}
-#endif
-
-} // namespace
-
-TEST(GeneratePolicySource, ChromeSchemaData) {
- Schema schema = Schema::Wrap(GetChromeSchemaData());
- ASSERT_TRUE(schema.valid());
- EXPECT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- Schema subschema = schema.GetAdditionalProperties();
- EXPECT_FALSE(subschema.valid());
-
- subschema = schema.GetProperty("no such policy exists");
- EXPECT_FALSE(subschema.valid());
-
- subschema = schema.GetProperty(key::kSearchSuggestEnabled);
- ASSERT_TRUE(subschema.valid());
- EXPECT_EQ(base::Value::Type::BOOLEAN, subschema.type());
-
- subschema = schema.GetProperty(key::kDefaultCookiesSetting);
- ASSERT_TRUE(subschema.valid());
- EXPECT_EQ(base::Value::Type::INTEGER, subschema.type());
-
- subschema = schema.GetProperty(key::kProxyMode);
- ASSERT_TRUE(subschema.valid());
- EXPECT_EQ(base::Value::Type::STRING, subschema.type());
-
- subschema = schema.GetProperty(key::kURLBlacklist);
- ASSERT_TRUE(subschema.valid());
- EXPECT_EQ(base::Value::Type::LIST, subschema.type());
- ASSERT_TRUE(subschema.GetItems().valid());
- EXPECT_EQ(base::Value::Type::STRING, subschema.GetItems().type());
-
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
- subschema = schema.GetProperty(key::kExtensionSettings);
- ASSERT_TRUE(subschema.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, subschema.type());
- EXPECT_FALSE(subschema.GetAdditionalProperties().valid());
- EXPECT_FALSE(subschema.GetProperty("no such extension id exists").valid());
- EXPECT_TRUE(subschema.GetPatternProperties("*").empty());
- EXPECT_TRUE(subschema.GetPatternProperties("no such extension id").empty());
- EXPECT_TRUE(subschema.GetPatternProperties("^[a-p]{32}$").empty());
- EXPECT_TRUE(subschema.GetPatternProperties(
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").empty());
- EXPECT_TRUE(subschema.GetPatternProperties(
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").empty());
- SchemaList schema_list =
- subschema.GetPatternProperties("abcdefghijklmnopabcdefghijklmnop");
- ASSERT_EQ(1u, schema_list.size());
- subschema = schema_list[0];
- ASSERT_TRUE(subschema.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, subschema.type());
- subschema = subschema.GetProperty("installation_mode");
- ASSERT_TRUE(subschema.valid());
- ASSERT_EQ(base::Value::Type::STRING, subschema.type());
-
- subschema = schema.GetProperty(key::kExtensionSettings).GetProperty("*");
- ASSERT_TRUE(subschema.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, subschema.type());
- subschema = subschema.GetProperty("installation_mode");
- ASSERT_TRUE(subschema.valid());
- ASSERT_EQ(base::Value::Type::STRING, subschema.type());
-#endif
-
- subschema = schema.GetProperty(key::kProxySettings);
- ASSERT_TRUE(subschema.valid());
- EXPECT_EQ(base::Value::Type::DICTIONARY, subschema.type());
- EXPECT_FALSE(subschema.GetAdditionalProperties().valid());
- EXPECT_FALSE(subschema.GetProperty("no such proxy key exists").valid());
- ASSERT_TRUE(subschema.GetProperty(key::kProxyMode).valid());
- ASSERT_TRUE(subschema.GetProperty(key::kProxyServer).valid());
- ASSERT_TRUE(subschema.GetProperty(key::kProxyServerMode).valid());
- ASSERT_TRUE(subschema.GetProperty(key::kProxyPacUrl).valid());
- ASSERT_TRUE(subschema.GetProperty(key::kProxyBypassList).valid());
-
- // Verify that all the Chrome policies are there.
- for (Schema::Iterator it = schema.GetPropertiesIterator();
- !it.IsAtEnd(); it.Advance()) {
- EXPECT_TRUE(it.key());
- EXPECT_FALSE(std::string(it.key()).empty());
- EXPECT_TRUE(GetChromePolicyDetails(it.key()));
- }
-
- // The properties are iterated in order.
- const char* kExpectedProperties[] = {
- key::kProxyBypassList, key::kProxyMode, key::kProxyPacUrl,
- key::kProxyServer, key::kProxyServerMode, nullptr,
- };
- const char** next = kExpectedProperties;
- for (Schema::Iterator it(subschema.GetPropertiesIterator());
- !it.IsAtEnd(); it.Advance(), ++next) {
- ASSERT_TRUE(*next != nullptr);
- EXPECT_STREQ(*next, it.key());
- ASSERT_TRUE(it.schema().valid());
- EXPECT_EQ(base::Value::Type::STRING, it.schema().type());
- }
- EXPECT_TRUE(*next == nullptr);
-
-#if defined(OS_CHROMEOS)
- subschema = schema.GetKnownProperty(key::kPowerManagementIdleSettings);
- ASSERT_TRUE(subschema.valid());
-
- EXPECT_TRUE(IsSameSchema(subschema.GetKnownProperty("AC"),
- subschema.GetKnownProperty("Battery")));
-
- subschema = schema.GetKnownProperty(key::kDeviceLoginScreenPowerManagement);
- ASSERT_TRUE(subschema.valid());
-
- EXPECT_TRUE(IsSameSchema(subschema.GetKnownProperty("AC"),
- subschema.GetKnownProperty("Battery")));
-#endif
-}
-
-TEST(GeneratePolicySource, PolicyDetails) {
- EXPECT_FALSE(GetChromePolicyDetails(""));
- EXPECT_FALSE(GetChromePolicyDetails("no such policy"));
- EXPECT_FALSE(GetChromePolicyDetails("SearchSuggestEnable"));
- EXPECT_FALSE(GetChromePolicyDetails("searchSuggestEnabled"));
- EXPECT_FALSE(GetChromePolicyDetails("SSearchSuggestEnabled"));
-
- const PolicyDetails* details =
- GetChromePolicyDetails(key::kSearchSuggestEnabled);
- ASSERT_TRUE(details);
- EXPECT_FALSE(details->is_deprecated);
- EXPECT_FALSE(details->is_device_policy);
- EXPECT_EQ(6, details->id);
- EXPECT_EQ(0u, details->max_external_data_size);
-
-#if !defined(OS_IOS)
- details = GetChromePolicyDetails(key::kJavascriptEnabled);
- ASSERT_TRUE(details);
- EXPECT_TRUE(details->is_deprecated);
- EXPECT_FALSE(details->is_device_policy);
- EXPECT_EQ(9, details->id);
- EXPECT_EQ(0u, details->max_external_data_size);
-#endif
-
-#if defined(OS_CHROMEOS)
- details = GetChromePolicyDetails(key::kDevicePolicyRefreshRate);
- ASSERT_TRUE(details);
- EXPECT_FALSE(details->is_deprecated);
- EXPECT_TRUE(details->is_device_policy);
- EXPECT_EQ(90, details->id);
- EXPECT_EQ(0u, details->max_external_data_size);
-#endif
-
- // TODO(bartfab): add a test that verifies a max_external_data_size larger
- // than 0, once a type 'external' policy is added.
-}
-
-#if defined(OS_CHROMEOS)
-TEST(GeneratePolicySource, SetEnterpriseDefaults) {
- PolicyMap policy_map;
-
- // If policy not configured yet, set the enterprise default.
- SetEnterpriseUsersDefaults(&policy_map);
-
- const base::Value* multiprof_behavior =
- policy_map.GetValue(key::kChromeOsMultiProfileUserBehavior);
- base::Value expected("primary-only");
- EXPECT_TRUE(expected.Equals(multiprof_behavior));
-
- // If policy already configured, it's not changed to enterprise defaults.
- policy_map.Set(key::kChromeOsMultiProfileUserBehavior, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>("test_value"), nullptr);
- SetEnterpriseUsersDefaults(&policy_map);
- multiprof_behavior =
- policy_map.GetValue(key::kChromeOsMultiProfileUserBehavior);
- expected = base::Value("test_value");
- EXPECT_TRUE(expected.Equals(multiprof_behavior));
-}
-#endif
-
-} // namespace policy
diff --git a/components/policy/core/common/mock_configuration_policy_provider.cc b/components/policy/core/common/mock_configuration_policy_provider.cc
deleted file mode 100644
index ae8458a226..0000000000
--- a/components/policy/core/common/mock_configuration_policy_provider.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/mock_configuration_policy_provider.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/message_loop/message_loop_current.h"
-#include "base/run_loop.h"
-#include "components/policy/core/common/policy_bundle.h"
-
-using testing::Invoke;
-
-namespace policy {
-
-MockConfigurationPolicyProvider::MockConfigurationPolicyProvider() {}
-
-MockConfigurationPolicyProvider::~MockConfigurationPolicyProvider() {}
-
-void MockConfigurationPolicyProvider::UpdateChromePolicy(
- const PolicyMap& policy) {
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .CopyFrom(policy);
- UpdatePolicy(std::move(bundle));
- if (base::MessageLoopCurrent::IsSet())
- base::RunLoop().RunUntilIdle();
-}
-
-void MockConfigurationPolicyProvider::SetAutoRefresh() {
- EXPECT_CALL(*this, RefreshPolicies()).WillRepeatedly(
- Invoke(this, &MockConfigurationPolicyProvider::RefreshWithSamePolicies));
-}
-
-void MockConfigurationPolicyProvider::RefreshWithSamePolicies() {
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle);
- bundle->CopyFrom(policies());
- UpdatePolicy(std::move(bundle));
-}
-
-MockConfigurationPolicyObserver::MockConfigurationPolicyObserver() {}
-
-MockConfigurationPolicyObserver::~MockConfigurationPolicyObserver() {}
-
-} // namespace policy
diff --git a/components/policy/core/common/mock_configuration_policy_provider.h b/components/policy/core/common/mock_configuration_policy_provider.h
deleted file mode 100644
index 84f664c71d..0000000000
--- a/components/policy/core/common/mock_configuration_policy_provider.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_MOCK_CONFIGURATION_POLICY_PROVIDER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_MOCK_CONFIGURATION_POLICY_PROVIDER_H_
-
-#include "base/macros.h"
-#include "components/policy/core/common/configuration_policy_provider.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/schema_registry.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace policy {
-
-// Mock ConfigurationPolicyProvider implementation that supplies canned
-// values for polices.
-// TODO(joaodasilva, mnissler): introduce an implementation that non-policy
-// code can use that doesn't require the usual boilerplate.
-// http://crbug.com/242087
-class MockConfigurationPolicyProvider : public ConfigurationPolicyProvider {
- public:
- MockConfigurationPolicyProvider();
- ~MockConfigurationPolicyProvider() override;
-
- MOCK_CONST_METHOD1(IsInitializationComplete, bool(PolicyDomain domain));
- MOCK_METHOD0(RefreshPolicies, void());
-
- // Make public for tests.
- using ConfigurationPolicyProvider::UpdatePolicy;
-
- // Utility method that invokes UpdatePolicy() with a PolicyBundle that maps
- // the Chrome namespace to a copy of |policy|.
- void UpdateChromePolicy(const PolicyMap& policy);
-
- // Convenience method so that tests don't need to create a registry to create
- // this mock.
- using ConfigurationPolicyProvider::Init;
- void Init() {
- ConfigurationPolicyProvider::Init(&registry_);
- }
-
- // Convenience method that installs an expectation on RefreshPolicies that
- // just notifies the observers and serves the same policies.
- void SetAutoRefresh();
-
- private:
- void RefreshWithSamePolicies();
-
- SchemaRegistry registry_;
-
- DISALLOW_COPY_AND_ASSIGN(MockConfigurationPolicyProvider);
-};
-
-class MockConfigurationPolicyObserver
- : public ConfigurationPolicyProvider::Observer {
- public:
- MockConfigurationPolicyObserver();
- ~MockConfigurationPolicyObserver() override;
-
- MOCK_METHOD1(OnUpdatePolicy, void(ConfigurationPolicyProvider*));
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_MOCK_CONFIGURATION_POLICY_PROVIDER_H_
diff --git a/components/policy/core/common/mock_policy_service.cc b/components/policy/core/common/mock_policy_service.cc
deleted file mode 100644
index 6e3e0c1cbf..0000000000
--- a/components/policy/core/common/mock_policy_service.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/mock_policy_service.h"
-
-namespace policy {
-
-MockPolicyServiceObserver::MockPolicyServiceObserver() {
-}
-
-MockPolicyServiceObserver::~MockPolicyServiceObserver() {
-}
-
-MockPolicyService::MockPolicyService() {
-}
-
-MockPolicyService::~MockPolicyService() {
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/mock_policy_service.h b/components/policy/core/common/mock_policy_service.h
deleted file mode 100644
index 3352860b28..0000000000
--- a/components/policy/core/common/mock_policy_service.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_MOCK_POLICY_SERVICE_H_
-#define COMPONENTS_POLICY_CORE_COMMON_MOCK_POLICY_SERVICE_H_
-
-#include "components/policy/core/common/policy_service.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace policy {
-
-class MockPolicyServiceObserver : public PolicyService::Observer {
- public:
- MockPolicyServiceObserver();
- ~MockPolicyServiceObserver() override;
-
- MOCK_METHOD3(OnPolicyUpdated, void(const PolicyNamespace&,
- const PolicyMap& previous,
- const PolicyMap& current));
- MOCK_METHOD1(OnPolicyServiceInitialized, void(PolicyDomain));
-};
-
-class MockPolicyService : public PolicyService {
- public:
- MockPolicyService();
- ~MockPolicyService() override;
-
- MOCK_METHOD2(AddObserver, void(PolicyDomain, Observer*));
- MOCK_METHOD2(RemoveObserver, void(PolicyDomain, Observer*));
-
- MOCK_CONST_METHOD1(GetPolicies, const PolicyMap&(const PolicyNamespace&));
- MOCK_CONST_METHOD1(IsInitializationComplete, bool(PolicyDomain domain));
- MOCK_METHOD1(RefreshPolicies, void(const base::Closure&));
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_MOCK_POLICY_SERVICE_H_
diff --git a/components/policy/core/common/plist_writer.cc b/components/policy/core/common/plist_writer.cc
deleted file mode 100644
index 68c1db5494..0000000000
--- a/components/policy/core/common/plist_writer.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2018 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 "components/policy/core/common/plist_writer.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "build/build_config.h"
-#include "third_party/libxml/chromium/libxml_utils.h"
-
-namespace policy {
-
-namespace {
-
-// Called recursively to build the Plist xml. When completed,
-// |plist_writer| will contain the Plist. Return true on success and false on
-// failure.
-bool BuildPlistString(const base::Value& node, XmlWriter& plist_writer) {
- switch (node.type()) {
- case base::Value::Type::BOOLEAN: {
- bool value = node.GetBool();
- plist_writer.StartElement(value ? "true" : "false");
- plist_writer.EndElement();
- return true;
- }
-
- case base::Value::Type::INTEGER: {
- int value = node.GetInt();
- plist_writer.WriteElement("integer", base::IntToString(value));
- return true;
- }
-
- case base::Value::Type::STRING: {
- std::string value = node.GetString();
- plist_writer.WriteElement("string", value);
- return true;
- }
-
- case base::Value::Type::LIST: {
- plist_writer.StartElement("array");
-
- for (const auto& value : node.GetList()) {
- if (!BuildPlistString(value, plist_writer))
- return false;
- }
-
- plist_writer.EndElement();
- return true;
- }
-
- case base::Value::Type::DICTIONARY: {
- plist_writer.StartElement("dict");
-
- const base::DictionaryValue* dict = nullptr;
- bool result = node.GetAsDictionary(&dict);
- DCHECK(result);
- for (base::DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd();
- itr.Advance()) {
- plist_writer.WriteElement("key", itr.key());
-
- if (!BuildPlistString(itr.value(), plist_writer))
- result = false;
- }
-
- plist_writer.EndElement();
- return result;
- }
-
- default:
- NOTREACHED();
- return false;
- }
-}
-
-} // namespace
-
-bool PlistWrite(const base::Value& node, std::string* plist) {
- // Where we write Plist data as we generate it.
- XmlWriter plist_writer;
- plist_writer.StartWriting();
- plist_writer.StartIndenting();
- plist_writer.StartElement("plist");
- bool result = BuildPlistString(node, plist_writer);
- plist_writer.EndElement();
- plist_writer.StopWriting();
-
- *plist = plist_writer.GetWrittenString();
- return result;
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/plist_writer.h b/components/policy/core/common/plist_writer.h
deleted file mode 100644
index 0ad82235f7..0000000000
--- a/components/policy/core/common/plist_writer.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2018 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_PLIST_WRITER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_PLIST_WRITER_H_
-
-#include <stddef.h>
-#include <string>
-#include "base/values.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// Given a root node, generates a Plist string and puts it into |plist|.
-// The output string is overwritten and not appended.
-// Return true on success and false on failure.
-// TODO(rodmartin): Should we generate plist if it would be invalid plist
-// (e.g., |node| is not a DictionaryValue/ListValue or if there are inf/-inf
-// float values)?
-POLICY_EXPORT bool PlistWrite(const base::Value& node, std::string* plist);
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_Plist_WRITER_H_ \ No newline at end of file
diff --git a/components/policy/core/common/plist_writer_unittest.cc b/components/policy/core/common/plist_writer_unittest.cc
deleted file mode 100644
index 0d89d0aa83..0000000000
--- a/components/policy/core/common/plist_writer_unittest.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2018 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 "components/policy/core/common/plist_writer.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/strings/strcat.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-const char kPlistHeaderXML[] = "<?xml version=\"1.0\"?>";
-const char kPlistHeaderVersion[] = "<plist>";
-const char kPlistFooter[] = "</plist>\n";
-
-#define PLIST_NEWLINE "\n"
-
-} // namespace
-
-class PlistWriterTest : public testing::Test {
- public:
- PlistWriterTest();
- ~PlistWriterTest() override;
-
- void SetUp() override;
-
- std::string header_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PlistWriterTest);
-};
-
-PlistWriterTest::PlistWriterTest() {}
-
-PlistWriterTest::~PlistWriterTest() {}
-
-void PlistWriterTest::SetUp() {
- header_ = base::StrCat(
- {kPlistHeaderXML, PLIST_NEWLINE, kPlistHeaderVersion, PLIST_NEWLINE});
-}
-
-TEST_F(PlistWriterTest, BasicTypes) {
- std::string output_plist;
-
- // Test empty dict.
- EXPECT_TRUE(PlistWrite(base::DictionaryValue(), &output_plist));
- EXPECT_EQ(base::StrCat({header_, " <dict/>", PLIST_NEWLINE, kPlistFooter}),
- output_plist);
-
- // Test empty list.
- EXPECT_TRUE(PlistWrite(base::ListValue(), &output_plist));
- EXPECT_EQ(base::StrCat({header_, " <array/>", PLIST_NEWLINE, kPlistFooter}),
- output_plist);
-
- // Test integer values.
- EXPECT_TRUE(PlistWrite(base::Value(42), &output_plist));
- EXPECT_EQ(base::StrCat({header_, " <integer>42</integer>", PLIST_NEWLINE,
- kPlistFooter}),
- output_plist);
-
- // Test boolean values.
- EXPECT_TRUE(PlistWrite(base::Value(true), &output_plist));
- EXPECT_EQ(base::StrCat({header_, " <true/>", PLIST_NEWLINE, kPlistFooter}),
- output_plist);
-
- // Test string values.
- EXPECT_TRUE(PlistWrite(base::Value("foo"), &output_plist));
- EXPECT_EQ(base::StrCat({header_, " <string>foo</string>", PLIST_NEWLINE,
- kPlistFooter}),
- output_plist);
-}
-
-TEST_F(PlistWriterTest, NestedTypes) {
- std::string output_plist;
-
- // Writer unittests like empty list/dict nesting,
- // list list nesting, etc.
- base::DictionaryValue root_dict;
- std::unique_ptr<base::ListValue> list(new base::ListValue());
- std::unique_ptr<base::DictionaryValue> inner_dict(
- new base::DictionaryValue());
- inner_dict->SetInteger("inner int", 10);
- list->Append(std::move(inner_dict));
- list->Append(std::make_unique<base::ListValue>());
- list->AppendBoolean(false);
- root_dict.Set("list", std::move(list));
-
- EXPECT_TRUE(PlistWrite(root_dict, &output_plist));
- EXPECT_EQ(base::StrCat({header_, " <dict>",
- PLIST_NEWLINE, " <key>list</key>",
- PLIST_NEWLINE, " <array>",
- PLIST_NEWLINE, " <dict>",
- PLIST_NEWLINE, " <key>inner int</key>",
- PLIST_NEWLINE, " <integer>10</integer>",
- PLIST_NEWLINE, " </dict>",
- PLIST_NEWLINE, " <array/>",
- PLIST_NEWLINE, " <false/>",
- PLIST_NEWLINE, " </array>",
- PLIST_NEWLINE, " </dict>",
- PLIST_NEWLINE, kPlistFooter}),
- output_plist);
-}
-
-TEST_F(PlistWriterTest, KeysWithPeriods) {
- std::string output_plist;
-
- base::DictionaryValue period_dict;
- period_dict.SetKey("a.b", base::Value(3));
- period_dict.SetKey("c", base::Value(2));
- std::unique_ptr<base::DictionaryValue> period_dict2(
- new base::DictionaryValue());
- period_dict2->SetKey("g.h.i.j", base::Value(1));
- period_dict.SetWithoutPathExpansion("d.e.f", std::move(period_dict2));
- EXPECT_TRUE(PlistWrite(period_dict, &output_plist));
- EXPECT_EQ(base::StrCat({header_, " <dict>",
- PLIST_NEWLINE, " <key>a.b</key>",
- PLIST_NEWLINE, " <integer>3</integer>",
- PLIST_NEWLINE, " <key>c</key>",
- PLIST_NEWLINE, " <integer>2</integer>",
- PLIST_NEWLINE, " <key>d.e.f</key>",
- PLIST_NEWLINE, " <dict>",
- PLIST_NEWLINE, " <key>g.h.i.j</key>",
- PLIST_NEWLINE, " <integer>1</integer>",
- PLIST_NEWLINE, " </dict>",
- PLIST_NEWLINE, " </dict>",
- PLIST_NEWLINE, kPlistFooter}),
- output_plist);
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_bundle.cc b/components/policy/core/common/policy_bundle.cc
deleted file mode 100644
index 3d9d1584a2..0000000000
--- a/components/policy/core/common/policy_bundle.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_bundle.h"
-
-#include "base/logging.h"
-
-namespace policy {
-
-PolicyBundle::PolicyBundle() {}
-
-PolicyBundle::~PolicyBundle() {
- Clear();
-}
-
-PolicyMap& PolicyBundle::Get(const PolicyNamespace& ns) {
- DCHECK(ns.domain != POLICY_DOMAIN_CHROME || ns.component_id.empty());
- std::unique_ptr<PolicyMap>& policy = policy_bundle_[ns];
- if (!policy)
- policy = std::make_unique<PolicyMap>();
- return *policy;
-}
-
-const PolicyMap& PolicyBundle::Get(const PolicyNamespace& ns) const {
- DCHECK(ns.domain != POLICY_DOMAIN_CHROME || ns.component_id.empty());
- const_iterator it = policy_bundle_.find(ns);
- return it == end() ? kEmpty_ : *it->second;
-}
-
-void PolicyBundle::Swap(PolicyBundle* other) {
- policy_bundle_.swap(other->policy_bundle_);
-}
-
-void PolicyBundle::CopyFrom(const PolicyBundle& other) {
- Clear();
- for (auto it = other.begin(); it != other.end(); ++it) {
- policy_bundle_[it->first] = it->second->DeepCopy();
- }
-}
-
-void PolicyBundle::MergeFrom(const PolicyBundle& other) {
- // Iterate over both |this| and |other| in order; skip what's extra in |this|,
- // add what's missing, and merge the namespaces in common.
- MapType::iterator it_this = policy_bundle_.begin();
- MapType::iterator end_this = policy_bundle_.end();
- const_iterator it_other = other.begin();
- const_iterator end_other = other.end();
-
- while (it_this != end_this && it_other != end_other) {
- if (it_this->first == it_other->first) {
- // Same namespace: merge existing PolicyMaps.
- it_this->second->MergeFrom(*it_other->second);
- ++it_this;
- ++it_other;
- } else if (it_this->first < it_other->first) {
- // |this| has a PolicyMap that |other| doesn't; skip it.
- ++it_this;
- } else if (it_other->first < it_this->first) {
- // |other| has a PolicyMap that |this| doesn't; copy it.
- policy_bundle_[it_other->first] = it_other->second->DeepCopy();
- ++it_other;
- } else {
- NOTREACHED();
- }
- }
-
- // Add extra PolicyMaps at the end.
- while (it_other != end_other) {
- policy_bundle_[it_other->first] = it_other->second->DeepCopy();
- ++it_other;
- }
-}
-
-bool PolicyBundle::Equals(const PolicyBundle& other) const {
- // Equals() has the peculiarity that an entry with an empty PolicyMap equals
- // an non-existent entry. This handles usage of non-const Get() that doesn't
- // insert any policies.
- const_iterator it_this = begin();
- const_iterator it_other = other.begin();
-
- while (true) {
- // Skip empty PolicyMaps.
- while (it_this != end() && it_this->second->empty())
- ++it_this;
- while (it_other != other.end() && it_other->second->empty())
- ++it_other;
- if (it_this == end() || it_other == other.end())
- break;
- if (it_this->first != it_other->first ||
- !it_this->second->Equals(*it_other->second)) {
- return false;
- }
- ++it_this;
- ++it_other;
- }
- return it_this == end() && it_other == other.end();
-}
-
-void PolicyBundle::Clear() {
- policy_bundle_.clear();
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_bundle.h b/components/policy/core/common/policy_bundle.h
deleted file mode 100644
index 8a395323ff..0000000000
--- a/components/policy/core/common/policy_bundle.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_BUNDLE_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_BUNDLE_H_
-
-#include <map>
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// Maps policy namespaces to PolicyMaps.
-class POLICY_EXPORT PolicyBundle {
- public:
- using MapType = std::map<PolicyNamespace, std::unique_ptr<PolicyMap>>;
- using iterator = MapType::iterator;
- using const_iterator = MapType::const_iterator;
-
- PolicyBundle();
- virtual ~PolicyBundle();
-
- // Returns the PolicyMap for namespace |ns|. Creates a new map if necessary.
- PolicyMap& Get(const PolicyNamespace& ns);
- const PolicyMap& Get(const PolicyNamespace& ns) const;
-
- // Swaps the internal representation of |this| with |other|.
- void Swap(PolicyBundle* other);
-
- // |this| becomes a copy of |other|. Any existing PolicyMaps are dropped.
- void CopyFrom(const PolicyBundle& other);
-
- // Merges the PolicyMaps of |this| with those of |other| for each namespace
- // in common. Also adds copies of the (namespace, PolicyMap) pairs in |other|
- // that don't have an entry in |this|.
- // Each policy in each PolicyMap is replaced only if the policy from |other|
- // has a higher priority.
- // See PolicyMap::MergeFrom for details on merging individual PolicyMaps.
- void MergeFrom(const PolicyBundle& other);
-
- // Returns true if |other| has the same keys and value as |this|.
- bool Equals(const PolicyBundle& other) const;
-
- // Returns iterators to the beginning and end of the underlying container.
- iterator begin() { return policy_bundle_.begin(); }
- iterator end() { return policy_bundle_.end(); }
-
- // These can be used to iterate over and read the PolicyMaps, but not to
- // modify them.
- const_iterator begin() const { return policy_bundle_.begin(); }
- const_iterator end() const { return policy_bundle_.end(); }
-
- // Erases all the existing pairs.
- void Clear();
-
- private:
- MapType policy_bundle_;
-
- // An empty PolicyMap that is returned by const Get() for namespaces that
- // do not exist in |policy_bundle_|.
- const PolicyMap kEmpty_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyBundle);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_BUNDLE_H_
diff --git a/components/policy/core/common/policy_bundle_unittest.cc b/components/policy/core/common/policy_bundle_unittest.cc
deleted file mode 100644
index 7ac3bd13e5..0000000000
--- a/components/policy/core/common/policy_bundle_unittest.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_bundle.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/values.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-const char kPolicyClashing0[] = "policy-clashing-0";
-const char kPolicyClashing1[] = "policy-clashing-1";
-const char kPolicy0[] = "policy-0";
-const char kPolicy1[] = "policy-1";
-const char kPolicy2[] = "policy-2";
-const char kExtension0[] = "extension-0";
-const char kExtension1[] = "extension-1";
-const char kExtension2[] = "extension-2";
-const char kExtension3[] = "extension-3";
-
-// Adds test policies to |policy|.
-void AddTestPolicies(PolicyMap* policy) {
- policy->Set("mandatory-user", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(123), nullptr);
- policy->Set("mandatory-machine", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("omg"),
- nullptr);
- policy->Set("recommended-user", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true),
- nullptr);
- std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
- dict->SetBoolean("false", false);
- dict->SetInteger("int", 456);
- dict->SetString("str", "bbq");
- policy->Set("recommended-machine", POLICY_LEVEL_RECOMMENDED,
- POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, std::move(dict),
- nullptr);
-}
-
-// Adds test policies to |policy| based on the parameters:
-// - kPolicyClashing0 mapped to |value|, user mandatory
-// - kPolicyClashing1 mapped to |value|, with |level| and |scope|
-// - |name| mapped to |value|, user mandatory
-void AddTestPoliciesWithParams(PolicyMap *policy,
- const char* name,
- int value,
- PolicyLevel level,
- PolicyScope scope) {
- policy->Set(kPolicyClashing0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(value),
- nullptr);
- policy->Set(kPolicyClashing1, level, scope, POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>(value), nullptr);
- policy->Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(value),
- nullptr);
-}
-
-// Returns true if |bundle| is empty.
-bool IsEmpty(const PolicyBundle& bundle) {
- return bundle.begin() == bundle.end();
-}
-
-} // namespace
-
-TEST(PolicyBundleTest, Get) {
- PolicyBundle bundle;
- EXPECT_TRUE(IsEmpty(bundle));
-
- AddTestPolicies(&bundle.Get(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
- EXPECT_FALSE(IsEmpty(bundle));
-
- PolicyMap policy;
- AddTestPolicies(&policy);
- EXPECT_TRUE(bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string())).Equals(policy));
-
- PolicyBundle::const_iterator it = bundle.begin();
- ASSERT_TRUE(it != bundle.end());
- EXPECT_EQ(POLICY_DOMAIN_CHROME, it->first.domain);
- EXPECT_EQ("", it->first.component_id);
- ASSERT_TRUE(it->second);
- EXPECT_TRUE(it->second->Equals(policy));
- ++it;
- EXPECT_TRUE(it == bundle.end());
- EXPECT_TRUE(bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension0)).empty());
-
- EXPECT_FALSE(IsEmpty(bundle));
- bundle.Clear();
- EXPECT_TRUE(IsEmpty(bundle));
-}
-
-TEST(PolicyBundleTest, SwapAndCopy) {
- PolicyBundle bundle0;
- PolicyBundle bundle1;
-
- AddTestPolicies(&bundle0.Get(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
- AddTestPolicies(&bundle0.Get(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0)));
- EXPECT_FALSE(IsEmpty(bundle0));
- EXPECT_TRUE(IsEmpty(bundle1));
-
- PolicyMap policy;
- AddTestPolicies(&policy);
- EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string())).Equals(policy));
- EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension0)).Equals(policy));
-
- bundle0.Swap(&bundle1);
- EXPECT_TRUE(IsEmpty(bundle0));
- EXPECT_FALSE(IsEmpty(bundle1));
-
- EXPECT_TRUE(bundle1.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string())).Equals(policy));
- EXPECT_TRUE(bundle1.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension0)).Equals(policy));
-
- bundle0.CopyFrom(bundle1);
- EXPECT_FALSE(IsEmpty(bundle0));
- EXPECT_FALSE(IsEmpty(bundle1));
- EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string())).Equals(policy));
- EXPECT_TRUE(bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension0)).Equals(policy));
-}
-
-TEST(PolicyBundleTest, MergeFrom) {
- // Each bundleN has kExtensionN. Each bundle also has policy for
- // chrome and kExtension3.
- // |bundle0| has the highest priority, |bundle2| the lowest.
- PolicyBundle bundle0;
- PolicyBundle bundle1;
- PolicyBundle bundle2;
-
- PolicyMap policy0;
- AddTestPoliciesWithParams(
- &policy0, kPolicy0, 0u, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER);
- bundle0.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .CopyFrom(policy0);
- bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0))
- .CopyFrom(policy0);
- bundle0.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension3))
- .CopyFrom(policy0);
-
- PolicyMap policy1;
- AddTestPoliciesWithParams(
- &policy1, kPolicy1, 1u, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
- bundle1.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .CopyFrom(policy1);
- bundle1.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1))
- .CopyFrom(policy1);
- bundle1.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension3))
- .CopyFrom(policy1);
-
- PolicyMap policy2;
- AddTestPoliciesWithParams(
- &policy2, kPolicy2, 2u, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
- bundle2.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .CopyFrom(policy2);
- bundle2.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension2))
- .CopyFrom(policy2);
- bundle2.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension3))
- .CopyFrom(policy2);
-
- // Merge in order of decreasing priority.
- PolicyBundle merged;
- merged.MergeFrom(bundle0);
- merged.MergeFrom(bundle1);
- merged.MergeFrom(bundle2);
- PolicyBundle empty_bundle;
- merged.MergeFrom(empty_bundle);
-
- // chrome and kExtension3 policies are merged:
- // - kPolicyClashing0 comes from bundle0, which has the highest priority;
- // - kPolicyClashing1 comes from bundle1, which has the highest level/scope
- // combination;
- // - kPolicyN are merged from each bundle.
- PolicyMap expected;
- expected.Set(kPolicyClashing0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
- expected.Set(kPolicyClashing1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
- expected.Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
- expected.Set(kPolicy1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
- expected.Set(kPolicy2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(2), nullptr);
- EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string())).Equals(expected));
- EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension3)).Equals(expected));
- // extension0 comes only from bundle0.
- EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension0)).Equals(policy0));
- // extension1 comes only from bundle1.
- EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension1)).Equals(policy1));
- // extension2 comes only from bundle2.
- EXPECT_TRUE(merged.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
- kExtension2)).Equals(policy2));
-}
-
-TEST(PolicyBundleTest, Equals) {
- PolicyBundle bundle;
- AddTestPolicies(&bundle.Get(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
- AddTestPolicies(&bundle.Get(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0)));
-
- PolicyBundle other;
- EXPECT_FALSE(bundle.Equals(other));
- other.CopyFrom(bundle);
- EXPECT_TRUE(bundle.Equals(other));
-
- AddTestPolicies(&bundle.Get(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1)));
- EXPECT_FALSE(bundle.Equals(other));
- other.CopyFrom(bundle);
- EXPECT_TRUE(bundle.Equals(other));
- AddTestPolicies(&other.Get(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension2)));
- EXPECT_FALSE(bundle.Equals(other));
-
- other.CopyFrom(bundle);
- bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(123), nullptr);
- EXPECT_FALSE(bundle.Equals(other));
- other.CopyFrom(bundle);
- EXPECT_TRUE(bundle.Equals(other));
- bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(123), nullptr);
- EXPECT_FALSE(bundle.Equals(other));
-
- // Test non-const Get().
- bundle.Clear();
- other.Clear();
- PolicyMap& policy_map =
- bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
- EXPECT_TRUE(bundle.Equals(other));
- policy_map.Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(123),
- nullptr);
- EXPECT_FALSE(bundle.Equals(other));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_details.h b/components/policy/core/common/policy_details.h
deleted file mode 100644
index 66e26d0e1a..0000000000
--- a/components/policy/core/common/policy_details.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_DETAILS_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_DETAILS_H_
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/callback_forward.h"
-#include "components/policy/policy_export.h"
-#include "components/policy/risk_tag.h"
-
-namespace policy {
-
-// Contains read-only metadata about a Chrome policy.
-struct POLICY_EXPORT PolicyDetails {
- // True if this policy has been deprecated.
- bool is_deprecated;
-
- // True if this policy is a Chrome OS device policy.
- bool is_device_policy;
-
- // The id of the protobuf field that contains this policy,
- // in the cloud policy protobuf.
- int id;
-
- // If this policy references external data then this is the maximum size
- // allowed for that data.
- // Otherwise this field is 0 and doesn't have any meaning.
- size_t max_external_data_size;
-
- // Contains tags that describe impact on a user's privacy or security.
- RiskTag risk_tags[kMaxRiskTagCount];
-};
-
-// A typedef for functions that match the signature of
-// GetChromePolicyDetails(). This can be used to inject that
-// function into objects, so that it can be easily mocked for
-// tests.
-typedef base::Callback<const PolicyDetails*(const std::string&)>
- GetChromePolicyDetailsCallback;
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_DETAILS_H_
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc
deleted file mode 100644
index 50750bbd62..0000000000
--- a/components/policy/core/common/policy_map.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_map.h"
-
-#include <algorithm>
-
-#include "base/callback.h"
-#include "base/stl_util.h"
-
-namespace policy {
-
-PolicyMap::Entry::Entry() = default;
-
-PolicyMap::Entry::~Entry() = default;
-
-PolicyMap::Entry::Entry(Entry&&) noexcept = default;
-PolicyMap::Entry& PolicyMap::Entry::operator=(Entry&&) noexcept = default;
-
-PolicyMap::Entry PolicyMap::Entry::DeepCopy() const {
- Entry copy;
- copy.level = level;
- copy.scope = scope;
- copy.source = source;
- if (value)
- copy.value = value->CreateDeepCopy();
- copy.error = error;
- if (external_data_fetcher) {
- copy.external_data_fetcher.reset(
- new ExternalDataFetcher(*external_data_fetcher));
- }
- return copy;
-}
-
-bool PolicyMap::Entry::has_higher_priority_than(
- const PolicyMap::Entry& other) const {
- if (level != other.level)
- return level > other.level;
-
- if (scope != other.scope)
- return scope > other.scope;
-
- return source > other.source;
-}
-
-bool PolicyMap::Entry::Equals(const PolicyMap::Entry& other) const {
- return level == other.level && scope == other.scope &&
- source == other.source && // Necessary for PolicyUIHandler observers.
- // They have to update when sources change.
- error == other.error &&
- ((!value && !other.value) ||
- (value && other.value && *value == *other.value)) &&
- ExternalDataFetcher::Equals(external_data_fetcher.get(),
- other.external_data_fetcher.get());
-}
-
-PolicyMap::PolicyMap() {}
-
-PolicyMap::~PolicyMap() {
- Clear();
-}
-
-const PolicyMap::Entry* PolicyMap::Get(const std::string& policy) const {
- PolicyMapType::const_iterator entry = map_.find(policy);
- return entry == map_.end() ? nullptr : &entry->second;
-}
-
-PolicyMap::Entry* PolicyMap::GetMutable(const std::string& policy) {
- PolicyMapType::iterator entry = map_.find(policy);
- return entry == map_.end() ? nullptr : &entry->second;
-}
-
-const base::Value* PolicyMap::GetValue(const std::string& policy) const {
- PolicyMapType::const_iterator entry = map_.find(policy);
- return entry == map_.end() ? nullptr : entry->second.value.get();
-}
-
-base::Value* PolicyMap::GetMutableValue(const std::string& policy) {
- PolicyMapType::iterator entry = map_.find(policy);
- return entry == map_.end() ? nullptr : entry->second.value.get();
-}
-
-void PolicyMap::Set(
- const std::string& policy,
- PolicyLevel level,
- PolicyScope scope,
- PolicySource source,
- std::unique_ptr<base::Value> value,
- std::unique_ptr<ExternalDataFetcher> external_data_fetcher) {
- Entry entry;
- entry.level = level;
- entry.scope = scope;
- entry.source = source;
- entry.value = std::move(value);
- entry.external_data_fetcher = std::move(external_data_fetcher);
- Set(policy, std::move(entry));
-}
-
-void PolicyMap::Set(const std::string& policy, Entry entry) {
- map_[policy] = std::move(entry);
-}
-
-void PolicyMap::SetError(const std::string& policy, const std::string& error) {
- map_[policy].error = error;
-}
-
-void PolicyMap::SetSourceForAll(PolicySource source) {
- for (auto& it : map_) {
- it.second.source = source;
- }
-}
-
-void PolicyMap::Erase(const std::string& policy) {
- map_.erase(policy);
-}
-
-void PolicyMap::EraseMatching(
- const base::Callback<bool(const const_iterator)>& filter) {
- FilterErase(filter, true);
-}
-
-void PolicyMap::EraseNonmatching(
- const base::Callback<bool(const const_iterator)>& filter) {
- FilterErase(filter, false);
-}
-
-void PolicyMap::Swap(PolicyMap* other) {
- map_.swap(other->map_);
-}
-
-void PolicyMap::CopyFrom(const PolicyMap& other) {
- Clear();
- for (const auto& it : other)
- Set(it.first, it.second.DeepCopy());
-}
-
-std::unique_ptr<PolicyMap> PolicyMap::DeepCopy() const {
- std::unique_ptr<PolicyMap> copy(new PolicyMap());
- copy->CopyFrom(*this);
- return copy;
-}
-
-void PolicyMap::MergeFrom(const PolicyMap& other) {
- for (const auto& it : other) {
- const Entry* entry = Get(it.first);
- if (!entry || it.second.has_higher_priority_than(*entry))
- Set(it.first, it.second.DeepCopy());
- }
-}
-
-void PolicyMap::LoadFrom(const base::DictionaryValue* policies,
- PolicyLevel level,
- PolicyScope scope,
- PolicySource source) {
- for (base::DictionaryValue::Iterator it(*policies); !it.IsAtEnd();
- it.Advance()) {
- Set(it.key(), level, scope, source, it.value().CreateDeepCopy(), nullptr);
- }
-}
-
-void PolicyMap::GetDifferingKeys(const PolicyMap& other,
- std::set<std::string>* differing_keys) const {
- // Walk over the maps in lockstep, adding everything that is different.
- const_iterator iter_this(begin());
- const_iterator iter_other(other.begin());
- while (iter_this != end() && iter_other != other.end()) {
- const int diff = iter_this->first.compare(iter_other->first);
- if (diff == 0) {
- if (!iter_this->second.Equals(iter_other->second))
- differing_keys->insert(iter_this->first);
- ++iter_this;
- ++iter_other;
- } else if (diff < 0) {
- differing_keys->insert(iter_this->first);
- ++iter_this;
- } else {
- differing_keys->insert(iter_other->first);
- ++iter_other;
- }
- }
-
- // Add the remaining entries.
- for (; iter_this != end(); ++iter_this)
- differing_keys->insert(iter_this->first);
- for (; iter_other != other.end(); ++iter_other)
- differing_keys->insert(iter_other->first);
-}
-
-bool PolicyMap::Equals(const PolicyMap& other) const {
- return other.size() == size() &&
- std::equal(begin(), end(), other.begin(), MapEntryEquals);
-}
-
-bool PolicyMap::empty() const {
- return map_.empty();
-}
-
-size_t PolicyMap::size() const {
- return map_.size();
-}
-
-PolicyMap::const_iterator PolicyMap::begin() const {
- return map_.begin();
-}
-
-PolicyMap::const_iterator PolicyMap::end() const {
- return map_.end();
-}
-
-void PolicyMap::Clear() {
- map_.clear();
-}
-
-// static
-bool PolicyMap::MapEntryEquals(const PolicyMap::PolicyMapType::value_type& a,
- const PolicyMap::PolicyMapType::value_type& b) {
- return a.first == b.first && a.second.Equals(b.second);
-}
-
-void PolicyMap::FilterErase(
- const base::Callback<bool(const const_iterator)>& filter,
- bool deletion_value) {
- PolicyMapType::iterator iter(map_.begin());
- while (iter != map_.end()) {
- if (filter.Run(iter) == deletion_value) {
- map_.erase(iter++);
- } else {
- ++iter;
- }
- }
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_map.h b/components/policy/core/common/policy_map.h
deleted file mode 100644
index 0f0ef09634..0000000000
--- a/components/policy/core/common/policy_map.h
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_MAP_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_MAP_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/values.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// A mapping of policy names to policy values for a given policy namespace.
-class POLICY_EXPORT PolicyMap {
- public:
- // Each policy maps to an Entry which keeps the policy value as well as other
- // relevant data about the policy.
- struct POLICY_EXPORT Entry {
- PolicyLevel level = POLICY_LEVEL_RECOMMENDED;
- PolicyScope scope = POLICY_SCOPE_USER;
- std::unique_ptr<base::Value> value;
- std::string error;
- std::unique_ptr<ExternalDataFetcher> external_data_fetcher;
-
- // For debugging and displaying only. Set by provider delivering the policy.
- PolicySource source = POLICY_SOURCE_ENTERPRISE_DEFAULT;
-
- Entry();
- ~Entry();
-
- Entry(Entry&&) noexcept;
- Entry& operator=(Entry&&) noexcept;
-
- // Returns a copy of |this|.
- Entry DeepCopy() const;
-
- // Returns true if |this| has higher priority than |other|. The priority of
- // the fields are |level| > |scope| > |source|.
- bool has_higher_priority_than(const Entry& other) const;
-
- // Returns true if |this| equals |other|.
- bool Equals(const Entry& other) const;
- };
-
- typedef std::map<std::string, Entry> PolicyMapType;
- typedef PolicyMapType::const_iterator const_iterator;
-
- PolicyMap();
- virtual ~PolicyMap();
-
- // Returns a weak reference to the entry currently stored for key |policy|,
- // or NULL if not found. Ownership is retained by the PolicyMap.
- const Entry* Get(const std::string& policy) const;
- Entry* GetMutable(const std::string& policy);
-
- // Returns a weak reference to the value currently stored for key
- // |policy|, or NULL if not found. Ownership is retained by the PolicyMap.
- // This is equivalent to Get(policy)->value, when it doesn't return NULL.
- const base::Value* GetValue(const std::string& policy) const;
- base::Value* GetMutableValue(const std::string& policy);
-
- // Overwrites any existing information stored in the map for the key |policy|.
- // Resets the error for that policy to the empty string.
- void Set(const std::string& policy,
- PolicyLevel level,
- PolicyScope scope,
- PolicySource source,
- std::unique_ptr<base::Value> value,
- std::unique_ptr<ExternalDataFetcher> external_data_fetcher);
-
- void Set(const std::string& policy, Entry entry);
-
- // Adds an |error| to the map for the key |policy| that should be shown to the
- // user alongside the value in the policy UI. This is equivalent to calling
- // |GetMutableValue(policy)->error = error|, so should only be called for
- // policies that are already stored in this map.
- void SetError(const std::string& policy, const std::string& error);
-
- // For all policies, overwrite the PolicySource with |source|.
- void SetSourceForAll(PolicySource source);
-
- // Erase the given |policy|, if it exists in this map.
- void Erase(const std::string& policy);
-
- // Erase all entries for which |filter| returns true.
- void EraseMatching(const base::Callback<bool(const const_iterator)>& filter);
-
- // Erase all entries for which |filter| returns false.
- void EraseNonmatching(
- const base::Callback<bool(const const_iterator)>& filter);
-
- // Swaps the internal representation of |this| with |other|.
- void Swap(PolicyMap* other);
-
- // |this| becomes a copy of |other|. Any existing policies are dropped.
- void CopyFrom(const PolicyMap& other);
-
- // Returns a copy of |this|.
- std::unique_ptr<PolicyMap> DeepCopy() const;
-
- // Merges policies from |other| into |this|. Existing policies are only
- // overridden by those in |other| if they have a higher priority, as defined
- // by Entry::has_higher_priority_than(). If a policy is contained in both
- // maps with the same priority, the current value in |this| is preserved.
- void MergeFrom(const PolicyMap& other);
-
- // Loads the values in |policies| into this PolicyMap. All policies loaded
- // will have |level|, |scope| and |source| in their entries. Existing entries
- // are replaced.
- void LoadFrom(const base::DictionaryValue* policies,
- PolicyLevel level,
- PolicyScope scope,
- PolicySource source);
-
- // Compares this value map against |other| and stores all key names that have
- // different values or reference different external data in |differing_keys|.
- // This includes keys that are present only in one of the maps.
- // |differing_keys| is not cleared before the keys are added.
- void GetDifferingKeys(const PolicyMap& other,
- std::set<std::string>* differing_keys) const;
-
- bool Equals(const PolicyMap& other) const;
- bool empty() const;
- size_t size() const;
-
- const_iterator begin() const;
- const_iterator end() const;
- void Clear();
-
- private:
- // Helper function for Equals().
- static bool MapEntryEquals(const PolicyMapType::value_type& a,
- const PolicyMapType::value_type& b);
-
- // Erase all entries for which |filter| returns |deletion_value|.
- void FilterErase(const base::Callback<bool(const const_iterator)>& filter,
- bool deletion_value);
-
- PolicyMapType map_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyMap);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_MAP_H_
diff --git a/components/policy/core/common/policy_map_unittest.cc b/components/policy/core/common/policy_map_unittest.cc
deleted file mode 100644
index 691bd21762..0000000000
--- a/components/policy/core/common/policy_map_unittest.cc
+++ /dev/null
@@ -1,354 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_map.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/memory/weak_ptr.h"
-#include "components/policy/core/common/external_data_manager.h"
-#include "components/policy/core/common/policy_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-// Dummy policy names.
-const char kTestPolicyName1[] = "policy.test.1";
-const char kTestPolicyName2[] = "policy.test.2";
-const char kTestPolicyName3[] = "policy.test.3";
-const char kTestPolicyName4[] = "policy.test.4";
-const char kTestPolicyName5[] = "policy.test.5";
-const char kTestPolicyName6[] = "policy.test.6";
-const char kTestPolicyName7[] = "policy.test.7";
-const char kTestPolicyName8[] = "policy.test.8";
-
-// Dummy error message.
-const char kTestError[] = "Test error message";
-
-// Utility functions for the tests.
-void SetPolicy(PolicyMap* map,
- const char* name,
- std::unique_ptr<base::Value> value) {
- map->Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
- std::move(value), nullptr);
-}
-
-void SetPolicy(PolicyMap* map,
- const char* name,
- std::unique_ptr<ExternalDataFetcher> external_data_fetcher) {
- map->Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
- nullptr, std::move(external_data_fetcher));
-}
-
-} // namespace
-
-class PolicyMapTest : public testing::Test {
- protected:
- std::unique_ptr<ExternalDataFetcher> CreateExternalDataFetcher(
- const std::string& policy) const;
-};
-
-std::unique_ptr<ExternalDataFetcher> PolicyMapTest::CreateExternalDataFetcher(
- const std::string& policy) const {
- return std::make_unique<ExternalDataFetcher>(
- base::WeakPtr<ExternalDataManager>(), policy);
-}
-
-TEST_F(PolicyMapTest, SetAndGet) {
- PolicyMap map;
- SetPolicy(&map, kTestPolicyName1, std::make_unique<base::Value>("aaa"));
- base::Value expected("aaa");
- EXPECT_TRUE(expected.Equals(map.GetValue(kTestPolicyName1)));
- SetPolicy(&map, kTestPolicyName1, std::make_unique<base::Value>("bbb"));
- base::Value expected_b("bbb");
- EXPECT_TRUE(expected_b.Equals(map.GetValue(kTestPolicyName1)));
- SetPolicy(&map, kTestPolicyName1, CreateExternalDataFetcher("dummy"));
- map.SetError(kTestPolicyName1, kTestError);
- EXPECT_FALSE(map.GetValue(kTestPolicyName1));
- const PolicyMap::Entry* entry = map.Get(kTestPolicyName1);
- ASSERT_TRUE(entry != nullptr);
- EXPECT_EQ(POLICY_LEVEL_MANDATORY, entry->level);
- EXPECT_EQ(POLICY_SCOPE_USER, entry->scope);
- EXPECT_EQ(POLICY_SOURCE_CLOUD, entry->source);
- EXPECT_EQ(kTestError, entry->error);
- EXPECT_TRUE(
- ExternalDataFetcher::Equals(entry->external_data_fetcher.get(),
- CreateExternalDataFetcher("dummy").get()));
- map.Set(kTestPolicyName1, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_ENTERPRISE_DEFAULT, nullptr, nullptr);
- EXPECT_FALSE(map.GetValue(kTestPolicyName1));
- entry = map.Get(kTestPolicyName1);
- ASSERT_TRUE(entry != nullptr);
- EXPECT_EQ(POLICY_LEVEL_RECOMMENDED, entry->level);
- EXPECT_EQ(POLICY_SCOPE_MACHINE, entry->scope);
- EXPECT_EQ(POLICY_SOURCE_ENTERPRISE_DEFAULT, entry->source);
- EXPECT_EQ("", entry->error);
- EXPECT_FALSE(entry->external_data_fetcher);
-}
-
-TEST_F(PolicyMapTest, Equals) {
- PolicyMap a;
- SetPolicy(&a, kTestPolicyName1, std::make_unique<base::Value>("aaa"));
- PolicyMap a2;
- SetPolicy(&a2, kTestPolicyName1, std::make_unique<base::Value>("aaa"));
- PolicyMap b;
- SetPolicy(&b, kTestPolicyName1, std::make_unique<base::Value>("bbb"));
- PolicyMap c;
- SetPolicy(&c, kTestPolicyName1, std::make_unique<base::Value>("aaa"));
- SetPolicy(&c, kTestPolicyName2, std::make_unique<base::Value>(true));
- PolicyMap d;
- SetPolicy(&d, kTestPolicyName1, CreateExternalDataFetcher("ddd"));
- PolicyMap d2;
- SetPolicy(&d2, kTestPolicyName1, CreateExternalDataFetcher("ddd"));
- PolicyMap e;
- SetPolicy(&e, kTestPolicyName1, CreateExternalDataFetcher("eee"));
- EXPECT_FALSE(a.Equals(b));
- EXPECT_FALSE(a.Equals(c));
- EXPECT_FALSE(a.Equals(d));
- EXPECT_FALSE(a.Equals(e));
- EXPECT_FALSE(b.Equals(a));
- EXPECT_FALSE(b.Equals(c));
- EXPECT_FALSE(b.Equals(d));
- EXPECT_FALSE(b.Equals(e));
- EXPECT_FALSE(c.Equals(a));
- EXPECT_FALSE(c.Equals(b));
- EXPECT_FALSE(c.Equals(d));
- EXPECT_FALSE(c.Equals(e));
- EXPECT_FALSE(d.Equals(a));
- EXPECT_FALSE(d.Equals(b));
- EXPECT_FALSE(d.Equals(c));
- EXPECT_FALSE(d.Equals(e));
- EXPECT_FALSE(e.Equals(a));
- EXPECT_FALSE(e.Equals(b));
- EXPECT_FALSE(e.Equals(c));
- EXPECT_FALSE(e.Equals(d));
- EXPECT_TRUE(a.Equals(a2));
- EXPECT_TRUE(a2.Equals(a));
- EXPECT_TRUE(d.Equals(d2));
- EXPECT_TRUE(d2.Equals(d));
- PolicyMap empty1;
- PolicyMap empty2;
- EXPECT_TRUE(empty1.Equals(empty2));
- EXPECT_TRUE(empty2.Equals(empty1));
- EXPECT_FALSE(empty1.Equals(a));
- EXPECT_FALSE(a.Equals(empty1));
-}
-
-TEST_F(PolicyMapTest, Swap) {
- PolicyMap a;
- SetPolicy(&a, kTestPolicyName1, std::make_unique<base::Value>("aaa"));
- SetPolicy(&a, kTestPolicyName2, CreateExternalDataFetcher("dummy"));
- PolicyMap b;
- SetPolicy(&b, kTestPolicyName1, std::make_unique<base::Value>("bbb"));
- SetPolicy(&b, kTestPolicyName3, std::make_unique<base::Value>(true));
-
- a.Swap(&b);
- base::Value expected("bbb");
- EXPECT_TRUE(expected.Equals(a.GetValue(kTestPolicyName1)));
- base::Value expected_bool(true);
- EXPECT_TRUE(expected_bool.Equals(a.GetValue(kTestPolicyName3)));
- EXPECT_FALSE(a.GetValue(kTestPolicyName2));
- EXPECT_FALSE(a.Get(kTestPolicyName2));
- base::Value expected_a("aaa");
- EXPECT_TRUE(expected_a.Equals(b.GetValue(kTestPolicyName1)));
- EXPECT_FALSE(b.GetValue(kTestPolicyName3));
- EXPECT_FALSE(a.GetValue(kTestPolicyName2));
- const PolicyMap::Entry* entry = b.Get(kTestPolicyName2);
- ASSERT_TRUE(entry);
- EXPECT_TRUE(
- ExternalDataFetcher::Equals(CreateExternalDataFetcher("dummy").get(),
- entry->external_data_fetcher.get()));
-
- b.Clear();
- a.Swap(&b);
- PolicyMap empty;
- EXPECT_TRUE(a.Equals(empty));
- EXPECT_FALSE(b.Equals(empty));
-}
-
-TEST_F(PolicyMapTest, MergeFrom) {
- PolicyMap a;
- a.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com"),
- nullptr);
- a.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
- a.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_ENTERPRISE_DEFAULT, nullptr,
- CreateExternalDataFetcher("a"));
- a.Set(kTestPolicyName4, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false), nullptr);
- a.Set(kTestPolicyName5, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com/q={x}"),
- nullptr);
- a.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT, std::make_unique<base::Value>(false),
- nullptr);
-
- PolicyMap b;
- b.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("chromium.org"),
- nullptr);
- b.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false), nullptr);
- b.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_ENTERPRISE_DEFAULT, nullptr,
- CreateExternalDataFetcher("b"));
- b.Set(kTestPolicyName4, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_PUBLIC_SESSION_OVERRIDE,
- std::make_unique<base::Value>(true), nullptr);
- b.Set(kTestPolicyName5, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>(std::string()),
- nullptr);
- b.Set(kTestPolicyName6, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
- b.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ACTIVE_DIRECTORY, std::make_unique<base::Value>(true),
- nullptr);
-
- a.MergeFrom(b);
-
- PolicyMap c;
- // POLICY_SCOPE_MACHINE over POLICY_SCOPE_USER.
- c.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("chromium.org"),
- nullptr);
- // |a| has precedence over |b|.
- c.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
- c.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_ENTERPRISE_DEFAULT, nullptr,
- CreateExternalDataFetcher("a"));
- // POLICY_SCOPE_MACHINE over POLICY_SCOPE_USER for POLICY_LEVEL_RECOMMENDED.
- c.Set(kTestPolicyName4, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_PUBLIC_SESSION_OVERRIDE,
- std::make_unique<base::Value>(true), nullptr);
- // POLICY_LEVEL_MANDATORY over POLICY_LEVEL_RECOMMENDED.
- c.Set(kTestPolicyName5, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>(std::string()),
- nullptr);
- // Merge new ones.
- c.Set(kTestPolicyName6, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
- // POLICY_SOURCE_ACTIVE_DIRECTORY over POLICY_SOURCE_ENTERPRISE_DEFAULT.
- c.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ACTIVE_DIRECTORY, std::make_unique<base::Value>(true),
- nullptr);
-
- EXPECT_TRUE(a.Equals(c));
-}
-
-TEST_F(PolicyMapTest, GetDifferingKeys) {
- PolicyMap a;
- a.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com"),
- nullptr);
- a.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, nullptr, CreateExternalDataFetcher("dummy"));
- a.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
- a.Set(kTestPolicyName4, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, nullptr, CreateExternalDataFetcher("a"));
- a.Set(kTestPolicyName5, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false), nullptr);
- a.Set(kTestPolicyName6, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com/q={x}"),
- nullptr);
- a.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
-
- PolicyMap b;
- b.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com"),
- nullptr);
- b.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, nullptr, CreateExternalDataFetcher("dummy"));
- b.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false), nullptr);
- b.Set(kTestPolicyName4, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, nullptr, CreateExternalDataFetcher("b"));
- b.Set(kTestPolicyName5, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false), nullptr);
- b.Set(kTestPolicyName6, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com/q={x}"),
- nullptr);
- b.Set(kTestPolicyName8, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
-
- std::set<std::string> diff;
- std::set<std::string> diff2;
- a.GetDifferingKeys(b, &diff);
- b.GetDifferingKeys(a, &diff2);
- // Order shouldn't matter.
- EXPECT_EQ(diff, diff2);
- // No change.
- EXPECT_TRUE(diff.find(kTestPolicyName1) == diff.end());
- EXPECT_TRUE(diff.find(kTestPolicyName2) == diff.end());
- // Different values.
- EXPECT_TRUE(diff.find(kTestPolicyName3) != diff.end());
- // Different external data references.
- EXPECT_TRUE(diff.find(kTestPolicyName4) != diff.end());
- // Different levels.
- EXPECT_TRUE(diff.find(kTestPolicyName5) != diff.end());
- // Different scopes.
- EXPECT_TRUE(diff.find(kTestPolicyName6) != diff.end());
- // Not in |a|.
- EXPECT_TRUE(diff.find(kTestPolicyName8) != diff.end());
- // Not in |b|.
- EXPECT_TRUE(diff.find(kTestPolicyName7) != diff.end());
- // No surprises.
- EXPECT_EQ(6u, diff.size());
-}
-
-TEST_F(PolicyMapTest, LoadFromSetsLevelScopeAndSource) {
- base::DictionaryValue policies;
- policies.SetString("TestPolicy1", "google.com");
- policies.SetBoolean("TestPolicy2", true);
- policies.SetInteger("TestPolicy3", -12321);
-
- PolicyMap loaded;
- loaded.LoadFrom(&policies,
- POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER,
- POLICY_SOURCE_PLATFORM);
-
- PolicyMap expected;
- expected.Set("TestPolicy1", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_PLATFORM,
- std::make_unique<base::Value>("google.com"), nullptr);
- expected.Set("TestPolicy2", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>(true),
- nullptr);
- expected.Set("TestPolicy3", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>(-12321),
- nullptr);
- EXPECT_TRUE(loaded.Equals(expected));
-}
-
-bool IsMandatory(const PolicyMap::PolicyMapType::const_iterator iter) {
- return iter->second.level == POLICY_LEVEL_MANDATORY;
-}
-
-TEST_F(PolicyMapTest, EraseNonmatching) {
- PolicyMap a;
- a.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com"),
- nullptr);
- a.Set(kTestPolicyName2, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
-
- a.EraseNonmatching(base::Bind(&IsMandatory));
-
- PolicyMap b;
- b.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("google.com"),
- nullptr);
- EXPECT_TRUE(a.Equals(b));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_namespace.cc b/components/policy/core/common/policy_namespace.cc
deleted file mode 100644
index 33a9992835..0000000000
--- a/components/policy/core/common/policy_namespace.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_namespace.h"
-
-#include <tuple>
-
-namespace policy {
-
-PolicyNamespace::PolicyNamespace() {}
-
-PolicyNamespace::PolicyNamespace(PolicyDomain domain,
- const std::string& component_id)
- : domain(domain),
- component_id(component_id) {}
-
-PolicyNamespace::PolicyNamespace(const PolicyNamespace& other)
- : domain(other.domain),
- component_id(other.component_id) {}
-
-PolicyNamespace::~PolicyNamespace() {}
-
-PolicyNamespace& PolicyNamespace::operator=(const PolicyNamespace& other) {
- domain = other.domain;
- component_id = other.component_id;
- return *this;
-}
-
-bool PolicyNamespace::operator<(const PolicyNamespace& other) const {
- return std::tie(domain, component_id) <
- std::tie(other.domain, other.component_id);
-}
-
-bool PolicyNamespace::operator==(const PolicyNamespace& other) const {
- return domain == other.domain && component_id == other.component_id;
-}
-
-bool PolicyNamespace::operator!=(const PolicyNamespace& other) const {
- return !(*this == other);
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_namespace.h b/components/policy/core/common/policy_namespace.h
deleted file mode 100644
index 780fa22f95..0000000000
--- a/components/policy/core/common/policy_namespace.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_NAMESPACE_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_NAMESPACE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// Policies are namespaced by a (PolicyDomain, ID) pair. The meaning of the ID
-// string depends on the domain; for example, if the PolicyDomain is
-// "extensions" then the ID identifies the extension that the policies control.
-enum PolicyDomain {
- // The component ID for chrome policies is always the empty string.
- POLICY_DOMAIN_CHROME,
-
- // The component ID for the extension policies is equal to the extension ID.
- POLICY_DOMAIN_EXTENSIONS,
-
- // The namespace that corresponds to the policies for extensions running
- // under Chrome OS signin profile. The component ID is equal to the extension
- // ID.
- POLICY_DOMAIN_SIGNIN_EXTENSIONS,
-
- // Must be the last entry.
- POLICY_DOMAIN_SIZE,
-};
-
-// Groups a policy domain and a component ID in a single object representing
-// a policy namespace. Objects of this class can be used as keys in std::maps.
-struct POLICY_EXPORT PolicyNamespace {
- PolicyNamespace();
- PolicyNamespace(PolicyDomain domain, const std::string& component_id);
- PolicyNamespace(const PolicyNamespace& other);
- ~PolicyNamespace();
-
- PolicyNamespace& operator=(const PolicyNamespace& other);
- bool operator<(const PolicyNamespace& other) const;
- bool operator==(const PolicyNamespace& other) const;
- bool operator!=(const PolicyNamespace& other) const;
-
- PolicyDomain domain;
- std::string component_id;
-};
-
-typedef std::vector<PolicyNamespace> PolicyNamespaceList;
-
-struct PolicyNamespaceHash {
- size_t operator()(const policy::PolicyNamespace& ns) const {
- return std::hash<std::string>()(ns.component_id) ^
- (UINT64_C(1) << ns.domain);
- }
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_NAMESPACE_H_
diff --git a/components/policy/core/common/policy_pref_names.cc b/components/policy/core/common/policy_pref_names.cc
deleted file mode 100644
index 6daa439509..0000000000
--- a/components/policy/core/common/policy_pref_names.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_pref_names.h"
-
-namespace policy {
-namespace policy_prefs {
-
-// 64-bit serialization of the time last policy usage statistics were collected
-// by UMA_HISTOGRAM_ENUMERATION.
-const char kLastPolicyStatisticsUpdate[] = "policy.last_statistics_update";
-
-// Blocks access to the listed host patterns.
-const char kUrlBlacklist[] = "policy.url_blacklist";
-
-// Allows access to the listed host patterns, as exceptions to the blacklist.
-const char kUrlWhitelist[] = "policy.url_whitelist";
-
-// Integer that specifies the policy refresh rate for user-policy in
-// milliseconds. Not all values are meaningful, so it is clamped to a sane range
-// by the cloud policy subsystem.
-const char kUserPolicyRefreshRate[] = "policy.user_refresh_rate";
-
-// The enrollment token of machine level user cloud policy
-const char kMachineLevelUserCloudPolicyEnrollmentToken[] =
- "policy.machine_level_user_cloud_policy_enrollment_token";
-
-} // namespace policy_prefs
-} // namespace policy
diff --git a/components/policy/core/common/policy_pref_names.h b/components/policy/core/common/policy_pref_names.h
deleted file mode 100644
index 31a82119a8..0000000000
--- a/components/policy/core/common/policy_pref_names.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_PREF_NAMES_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_PREF_NAMES_H_
-
-#include "components/policy/policy_export.h"
-
-namespace policy {
-namespace policy_prefs {
-
-POLICY_EXPORT extern const char kLastPolicyStatisticsUpdate[];
-POLICY_EXPORT extern const char kUrlBlacklist[];
-POLICY_EXPORT extern const char kUrlWhitelist[];
-POLICY_EXPORT extern const char kUserPolicyRefreshRate[];
-POLICY_EXPORT extern const char kMachineLevelUserCloudPolicyEnrollmentToken[];
-} // namespace policy_prefs
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_PREF_NAMES_H_
diff --git a/components/policy/core/common/policy_proto_decoders.cc b/components/policy/core/common/policy_proto_decoders.cc
deleted file mode 100644
index c5c8414fd9..0000000000
--- a/components/policy/core/common/policy_proto_decoders.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2018 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 "components/policy/core/common/policy_proto_decoders.h"
-
-#include <limits>
-#include <memory>
-
-#include "base/json/json_reader.h"
-#include "base/logging.h"
-#include "base/values.h"
-#include "components/policy/core/common/cloud/cloud_external_data_manager.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/policy_constants.h"
-#include "components/policy/proto/cloud_policy.pb.h"
-
-namespace policy {
-
-namespace em = enterprise_management;
-
-namespace {
-
-// Returns true and sets |level| to a PolicyLevel if the policy has been set
-// at that level. Returns false if the policy is not set, or has been set at
-// the level of PolicyOptions::UNSET.
-template <class AnyPolicyProto>
-bool GetPolicyLevel(const AnyPolicyProto& policy_proto, PolicyLevel* level) {
- if (!policy_proto.has_value()) {
- return false;
- }
- if (!policy_proto.has_policy_options()) {
- *level = POLICY_LEVEL_MANDATORY; // Default level.
- return true;
- }
- switch (policy_proto.policy_options().mode()) {
- case em::PolicyOptions::MANDATORY:
- *level = POLICY_LEVEL_MANDATORY;
- return true;
- case em::PolicyOptions::RECOMMENDED:
- *level = POLICY_LEVEL_RECOMMENDED;
- return true;
- case em::PolicyOptions::UNSET:
- return false;
- }
-}
-
-// Convert a BooleanPolicyProto to a bool base::Value.
-std::unique_ptr<base::Value> DecodeBooleanProto(
- const em::BooleanPolicyProto& proto) {
- return std::make_unique<base::Value>(proto.value());
-}
-
-// Convert an IntegerPolicyProto to an int base::Value.
-std::unique_ptr<base::Value> DecodeIntegerProto(
- const em::IntegerPolicyProto& proto,
- std::string* error) {
- google::protobuf::int64 value = proto.value();
-
- if (value < std::numeric_limits<int>::min() ||
- value > std::numeric_limits<int>::max()) {
- LOG(WARNING) << "Integer value " << value << " out of numeric limits";
- *error = "Number out of range - invalid int32";
- return std::make_unique<base::Value>(std::to_string(value));
- }
-
- return std::make_unique<base::Value>(static_cast<int>(value));
-}
-
-// Convert a StringPolicyProto to a string base::Value.
-std::unique_ptr<base::Value> DecodeStringProto(
- const em::StringPolicyProto& proto) {
- return std::make_unique<base::Value>(proto.value());
-}
-
-// Convert a StringListPolicyProto to a List base::Value, where each list value
-// is of Type::STRING.
-std::unique_ptr<base::Value> DecodeStringListProto(
- const em::StringListPolicyProto& proto) {
- auto list_value = std::make_unique<base::ListValue>();
- for (const auto& entry : proto.value().entries())
- list_value->AppendString(entry);
- return std::move(list_value);
-}
-
-// Convert a StringPolicyProto to a base::Value of any type (for example,
-// Type::DICTIONARY or Type::LIST) by parsing it as JSON.
-std::unique_ptr<base::Value> DecodeJsonProto(const em::StringPolicyProto& proto,
- std::string* error) {
- const std::string& json = proto.value();
- std::unique_ptr<base::Value> parsed_value =
- base::JSONReader::ReadAndReturnError(
- json, base::JSON_ALLOW_TRAILING_COMMAS, nullptr, error);
-
- if (!parsed_value) {
- // Can't parse as JSON so return it as a string, and leave it to the handler
- // to validate.
- LOG(WARNING) << "Invalid JSON: " << json;
- return std::make_unique<base::Value>(json);
- }
-
- // Accept any Value type that parsed as JSON, and leave it to the handler to
- // convert and check the concrete type.
- error->clear();
- return parsed_value;
-}
-
-} // namespace
-
-void DecodeProtoFields(
- const em::CloudPolicySettings& policy,
- base::WeakPtr<CloudExternalDataManager> external_data_manager,
- PolicySource source,
- PolicyScope scope,
- PolicyMap* map) {
- PolicyLevel level;
-
- // Access arrays are terminated by a struct that contains only nullptrs.
- for (const BooleanPolicyAccess* access = &kBooleanPolicyAccess[0];
- access->policy_key; access++) {
- if (!(policy.*access->has_proto)())
- continue;
-
- const em::BooleanPolicyProto& proto = (policy.*access->get_proto)();
- if (!GetPolicyLevel(proto, &level))
- continue;
-
- map->Set(access->policy_key, level, scope, source,
- DecodeBooleanProto(proto), nullptr);
- }
-
- for (const IntegerPolicyAccess* access = &kIntegerPolicyAccess[0];
- access->policy_key; access++) {
- if (!(policy.*access->has_proto)())
- continue;
-
- const em::IntegerPolicyProto& proto = (policy.*access->get_proto)();
- if (!GetPolicyLevel(proto, &level))
- continue;
-
- std::string error;
- map->Set(access->policy_key, level, scope, source,
- DecodeIntegerProto(proto, &error), nullptr);
- if (!error.empty())
- map->SetError(access->policy_key, error);
- }
-
- for (const StringPolicyAccess* access = &kStringPolicyAccess[0];
- access->policy_key; access++) {
- if (!(policy.*access->has_proto)())
- continue;
-
- const em::StringPolicyProto& proto = (policy.*access->get_proto)();
- if (!GetPolicyLevel(proto, &level))
- continue;
-
- std::string error;
- std::unique_ptr<base::Value> value =
- (access->type == StringPolicyType::STRING)
- ? DecodeStringProto(proto)
- : DecodeJsonProto(proto, &error);
-
- std::unique_ptr<ExternalDataFetcher> external_data_fetcher =
- (access->type == StringPolicyType::EXTERNAL)
- ? std::make_unique<ExternalDataFetcher>(external_data_manager,
- access->policy_key)
- : nullptr;
-
- map->Set(access->policy_key, level, scope, source, std::move(value),
- std::move(external_data_fetcher));
- if (!error.empty())
- map->SetError(access->policy_key, error);
- }
-
- for (const StringListPolicyAccess* access = &kStringListPolicyAccess[0];
- access->policy_key; access++) {
- if (!(policy.*access->has_proto)())
- continue;
-
- const em::StringListPolicyProto& proto = (policy.*access->get_proto)();
- if (!GetPolicyLevel(proto, &level))
- continue;
-
- map->Set(access->policy_key, level, scope, source,
- DecodeStringListProto(proto), nullptr);
- }
-}
-
-} // namespace policy \ No newline at end of file
diff --git a/components/policy/core/common/policy_proto_decoders.h b/components/policy/core/common/policy_proto_decoders.h
deleted file mode 100644
index 7b95851634..0000000000
--- a/components/policy/core/common/policy_proto_decoders.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_PROTO_DECODERS_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_PROTO_DECODERS_H_
-
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "components/policy/core/common/policy_types.h"
-
-namespace enterprise_management {
-class CloudPolicySettings;
-} // namespace enterprise_management
-
-namespace policy {
-
-class CloudExternalDataManager;
-class PolicyMap;
-
-// Decode all of the fields in |policy| which are recognized (see the metadata
-// in policy_constants.cc) and store them in the given |map|, with the given
-// |source| and |scope|.
-void DecodeProtoFields(
- const enterprise_management::CloudPolicySettings& policy,
- base::WeakPtr<CloudExternalDataManager> external_data_manager,
- PolicySource source,
- PolicyScope scope,
- PolicyMap* map);
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_PROTO_DECODERS_H_
diff --git a/components/policy/core/common/policy_scheduler.cc b/components/policy/core/common/policy_scheduler.cc
deleted file mode 100644
index 4c8d67db50..0000000000
--- a/components/policy/core/common/policy_scheduler.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 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 "components/policy/core/common/policy_scheduler.h"
-
-#include "base/threading/thread_task_runner_handle.h"
-
-namespace policy {
-
-PolicyScheduler::PolicyScheduler(Task task,
- SchedulerCallback callback,
- base::TimeDelta interval)
- : task_(task), callback_(callback), interval_(interval) {
- ScheduleTaskNow();
-}
-
-PolicyScheduler::~PolicyScheduler() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-}
-
-void PolicyScheduler::ScheduleTaskNow() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- ScheduleDelayedTask(base::TimeDelta());
-}
-
-void PolicyScheduler::ScheduleDelayedTask(base::TimeDelta delay) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- if (job_) {
- job_->Cancel();
- }
- job_ = std::make_unique<base::CancelableClosure>(base::Bind(
- &PolicyScheduler::RunScheduledTask, weak_ptr_factory_.GetWeakPtr()));
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE,
- job_->callback(), delay);
-}
-
-void PolicyScheduler::ScheduleNextTask() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- base::TimeDelta interval = overlap_ ? base::TimeDelta() : interval_;
- const base::TimeTicks now(base::TimeTicks::Now());
- // Time uses saturated arithmetics thus no under/overflow possible.
- const base::TimeDelta delay = last_task_ + interval - now;
- // Clamping delay to non-negative values just to be on the safe side.
- ScheduleDelayedTask(std::max(base::TimeDelta(), delay));
-}
-
-void PolicyScheduler::RunScheduledTask() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- if (task_in_progress_) {
- overlap_ = true;
- return;
- }
-
- overlap_ = false;
- task_in_progress_ = true;
- task_.Run(base::BindOnce(&PolicyScheduler::OnTaskDone,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void PolicyScheduler::OnTaskDone(bool success) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- task_in_progress_ = false;
- last_task_ = base::TimeTicks::Now();
- callback_.Run(success);
- ScheduleNextTask();
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_scheduler.h b/components/policy/core/common/policy_scheduler.h
deleted file mode 100644
index b31314e828..0000000000
--- a/components/policy/core/common/policy_scheduler.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEDULER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEDULER_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/cancelable_callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "base/time/time.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// Scheduler for driving repeated asynchronous tasks such as e.g. policy
-// fetches. Subsequent tasks are guaranteed not to overlap. Tasks are posted to
-// the current thread and therefore must not block (suitable e.g. for
-// asynchronous D-Bus calls).
-// Tasks scheduling begins immediately after instantiation of the class. Upon
-// destruction, scheduled but not yet started tasks are cancelled. The result of
-// started but not finished tasks is NOT reported.
-class POLICY_EXPORT PolicyScheduler {
- public:
- // Callback for the task to report success or failure.
- using TaskCallback = base::OnceCallback<void(bool success)>;
-
- // Task to be performed at regular intervals. The task takes a |callback| to
- // return success or failure.
- using Task = base::RepeatingCallback<void(TaskCallback callback)>;
-
- // Callback for PolicyScheduler to report success or failure of the tasks.
- using SchedulerCallback = base::RepeatingCallback<void(bool success)>;
-
- // Defines the |task| to be run every |interval| and the |callback| for the
- // scheduler to report the result. (Intervals are computed as the time
- // difference between the end of the previous and the start of the subsequent
- // task.) Calling the constructor starts the loop and schedules the first task
- // to be run without delay.
- PolicyScheduler(Task task,
- SchedulerCallback callback,
- base::TimeDelta interval);
- ~PolicyScheduler();
-
- // Schedules a task to run immediately. Deletes any previously scheduled but
- // not yet started tasks. In case a task is running currently, the new task is
- // scheduled to run immediately after the end of the currently running task.
- void ScheduleTaskNow();
-
- base::TimeDelta interval() const { return interval_; }
-
- private:
- // Schedules next task to run in |delay|. Deletes any previously scheduled
- // tasks.
- void ScheduleDelayedTask(base::TimeDelta delay);
-
- // Schedules next task to run in |interval_| or immediately in case of
- // overlap. Deletes any previously scheduled tasks.
- void ScheduleNextTask();
-
- // Actually executes the scheduled task.
- void RunScheduledTask();
-
- // Reports back the |result| of the previous task and schedules the next one.
- void OnTaskDone(bool result);
-
- Task task_;
- SchedulerCallback callback_;
- // Tasks are being run every |interval_|.
- const base::TimeDelta interval_;
-
- // Whether a task is in progress.
- bool task_in_progress_ = false;
-
- // Whether there had been an overlap of tasks and thus the next task needs to
- // be scheduled without delay.
- bool overlap_ = false;
-
- // End time of the previous task. Zero in case no task has ended yet.
- base::TimeTicks last_task_;
-
- std::unique_ptr<base::CancelableClosure> job_;
-
- SEQUENCE_CHECKER(sequence_checker_);
-
- // Must be last member.
- base::WeakPtrFactory<PolicyScheduler> weak_ptr_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(PolicyScheduler);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEDULER_H_
diff --git a/components/policy/core/common/policy_scheduler_unittest.cc b/components/policy/core/common/policy_scheduler_unittest.cc
deleted file mode 100644
index 2950f3f112..0000000000
--- a/components/policy/core/common/policy_scheduler_unittest.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2017 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 "components/policy/core/common/policy_scheduler.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-class PolicySchedulerTest : public testing::Test {
- public:
- void DoTask(PolicyScheduler::TaskCallback callback) {
- do_counter_++;
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), true));
- }
-
- void OnTaskDone(bool success) {
- done_counter_++;
-
- // Terminate PolicyScheduler after 5 iterations.
- if (done_counter_ >= 5) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&PolicySchedulerTest::Terminate,
- base::Unretained(this)));
- }
- }
-
- // To simulate a slow task the callback is captured instead of running it.
- void CaptureCallbackForSlowTask(PolicyScheduler::TaskCallback callback) {
- do_counter_++;
- slow_callback_ = std::move(callback);
- }
-
- // Runs the captured callback to simulate the end of the slow task.
- void PostSlowTaskCallback() {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(slow_callback_), true));
- }
-
- void Terminate() { scheduler_.reset(); }
-
- protected:
- int do_counter_ = 0;
- int done_counter_ = 0;
- std::unique_ptr<PolicyScheduler> scheduler_;
-
- PolicyScheduler::TaskCallback slow_callback_;
-
- base::test::ScopedTaskEnvironment scoped_task_environment_;
-};
-
-TEST_F(PolicySchedulerTest, Run) {
- scheduler_ = std::make_unique<PolicyScheduler>(
- base::BindRepeating(&PolicySchedulerTest::DoTask, base::Unretained(this)),
- base::BindRepeating(&PolicySchedulerTest::OnTaskDone,
- base::Unretained(this)),
- base::TimeDelta::Max());
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, done_counter_);
-}
-
-TEST_F(PolicySchedulerTest, Loop) {
- scheduler_ = std::make_unique<PolicyScheduler>(
- base::BindRepeating(&PolicySchedulerTest::DoTask, base::Unretained(this)),
- base::BindRepeating(&PolicySchedulerTest::OnTaskDone,
- base::Unretained(this)),
- base::TimeDelta());
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(5, done_counter_);
-}
-
-TEST_F(PolicySchedulerTest, Reschedule) {
- scheduler_ = std::make_unique<PolicyScheduler>(
- base::BindRepeating(&PolicySchedulerTest::DoTask, base::Unretained(this)),
- base::BindRepeating(&PolicySchedulerTest::OnTaskDone,
- base::Unretained(this)),
- base::TimeDelta::Max());
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, done_counter_);
-
- // Delayed action is not run.
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, done_counter_);
-
- // Rescheduling with 0 delay causes it to run.
- scheduler_->ScheduleTaskNow();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, done_counter_);
-}
-
-TEST_F(PolicySchedulerTest, OverlappingTasks) {
- scheduler_ = std::make_unique<PolicyScheduler>(
- base::BindRepeating(&PolicySchedulerTest::CaptureCallbackForSlowTask,
- base::Unretained(this)),
- base::BindRepeating(&PolicySchedulerTest::OnTaskDone,
- base::Unretained(this)),
- base::TimeDelta::Max());
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, do_counter_);
- EXPECT_EQ(0, done_counter_);
-
- // Second action doesn't start while first is still pending.
- scheduler_->ScheduleTaskNow();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, do_counter_);
- EXPECT_EQ(0, done_counter_);
-
- // After first action has finished, the second is started.
- PostSlowTaskCallback();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, do_counter_);
- EXPECT_EQ(1, done_counter_);
-
- // Let the second action finish.
- PostSlowTaskCallback();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, do_counter_);
- EXPECT_EQ(2, done_counter_);
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_service.cc b/components/policy/core/common/policy_service.cc
deleted file mode 100644
index fe35ca5928..0000000000
--- a/components/policy/core/common/policy_service.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/policy_service.h"
-
-#include "base/values.h"
-
-namespace policy {
-
-PolicyChangeRegistrar::PolicyChangeRegistrar(PolicyService* policy_service,
- const PolicyNamespace& ns)
- : policy_service_(policy_service),
- ns_(ns) {}
-
-PolicyChangeRegistrar::~PolicyChangeRegistrar() {
- if (!callback_map_.empty())
- policy_service_->RemoveObserver(ns_.domain, this);
-}
-
-void PolicyChangeRegistrar::Observe(const std::string& policy_name,
- const UpdateCallback& callback) {
- if (callback_map_.empty())
- policy_service_->AddObserver(ns_.domain, this);
- callback_map_[policy_name] = callback;
-}
-
-void PolicyChangeRegistrar::OnPolicyUpdated(const PolicyNamespace& ns,
- const PolicyMap& previous,
- const PolicyMap& current) {
- if (ns != ns_)
- return;
- for (CallbackMap::iterator it = callback_map_.begin();
- it != callback_map_.end(); ++it) {
- const base::Value* prev = previous.GetValue(it->first);
- const base::Value* cur = current.GetValue(it->first);
-
- // Check if the values pointed to by |prev| and |cur| are different.
- if ((!prev ^ !cur) || (prev && cur && *prev != *cur))
- it->second.Run(prev, cur);
- }
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_service.h b/components/policy/core/common/policy_service.h
deleted file mode 100644
index b9897e18a2..0000000000
--- a/components/policy/core/common/policy_service.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_H_
-
-#include <map>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// The PolicyService merges policies from all available sources, taking into
-// account their priorities. Policy clients can retrieve policy for their domain
-// and register for notifications on policy updates.
-//
-// The PolicyService is available from BrowserProcess as a global singleton.
-// There is also a PolicyService for browser-wide policies available from
-// BrowserProcess as a global singleton.
-class POLICY_EXPORT PolicyService {
- public:
- class POLICY_EXPORT Observer {
- public:
- // Invoked whenever policies for the given |ns| namespace are modified.
- // This is only invoked for changes that happen after AddObserver is called.
- // |previous| contains the values of the policies before the update,
- // and |current| contains the current values.
- virtual void OnPolicyUpdated(const PolicyNamespace& ns,
- const PolicyMap& previous,
- const PolicyMap& current) = 0;
-
- // Invoked at most once for each |domain|, when the PolicyService becomes
- // ready. If IsInitializationComplete() is false, then this will be invoked
- // once all the policy providers have finished loading their policies for
- // |domain|.
- virtual void OnPolicyServiceInitialized(PolicyDomain domain) {}
-
- protected:
- virtual ~Observer() {}
- };
-
- virtual ~PolicyService() {}
-
- // Observes changes to all components of the given |domain|.
- virtual void AddObserver(PolicyDomain domain, Observer* observer) = 0;
-
- virtual void RemoveObserver(PolicyDomain domain, Observer* observer) = 0;
-
- virtual const PolicyMap& GetPolicies(const PolicyNamespace& ns) const = 0;
-
- // The PolicyService loads policy from several sources, and some require
- // asynchronous loads. IsInitializationComplete() returns true once all
- // sources have loaded their policies for the given |domain|.
- // It is safe to read policy from the PolicyService even if
- // IsInitializationComplete() is false; there will be an OnPolicyUpdated()
- // notification once new policies become available.
- //
- // OnPolicyServiceInitialized() is called when IsInitializationComplete()
- // becomes true, which happens at most once for each domain.
- // If IsInitializationComplete() is already true for |domain| when an Observer
- // is registered, then that Observer will not receive an
- // OnPolicyServiceInitialized() notification.
- virtual bool IsInitializationComplete(PolicyDomain domain) const = 0;
-
- // Asks the PolicyService to reload policy from all available policy sources.
- // |callback| is invoked once every source has reloaded its policies, and
- // GetPolicies() is guaranteed to return the updated values at that point.
- virtual void RefreshPolicies(const base::Closure& callback) = 0;
-};
-
-// A registrar that only observes changes to particular policies within the
-// PolicyMap for the given policy namespace.
-class POLICY_EXPORT PolicyChangeRegistrar : public PolicyService::Observer {
- public:
- typedef base::Callback<void(const base::Value*,
- const base::Value*)> UpdateCallback;
-
- // Observes updates to the given (domain, component_id) namespace in the given
- // |policy_service|, and notifies |observer| whenever any of the registered
- // policy keys changes. Both the |policy_service| and the |observer| must
- // outlive |this|.
- PolicyChangeRegistrar(PolicyService* policy_service,
- const PolicyNamespace& ns);
-
- ~PolicyChangeRegistrar() override;
-
- // Will invoke |callback| whenever |policy_name| changes its value, as long
- // as this registrar exists.
- // Only one callback can be registed per policy name; a second call with the
- // same |policy_name| will overwrite the previous callback.
- void Observe(const std::string& policy_name, const UpdateCallback& callback);
-
- // Implementation of PolicyService::Observer:
- void OnPolicyUpdated(const PolicyNamespace& ns,
- const PolicyMap& previous,
- const PolicyMap& current) override;
-
- private:
- typedef std::map<std::string, UpdateCallback> CallbackMap;
-
- PolicyService* policy_service_;
- PolicyNamespace ns_;
- CallbackMap callback_map_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyChangeRegistrar);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_H_
diff --git a/components/policy/core/common/policy_service_impl.cc b/components/policy/core/common/policy_service_impl.cc
deleted file mode 100644
index dd555a1463..0000000000
--- a/components/policy/core/common/policy_service_impl.cc
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/policy_service_impl.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/values.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/policy_constants.h"
-
-namespace policy {
-
-namespace {
-
-const char* kProxyPolicies[] = {
- key::kProxyMode,
- key::kProxyServerMode,
- key::kProxyServer,
- key::kProxyPacUrl,
- key::kProxyBypassList,
-};
-
-// Maps the separate policies for proxy settings into a single Dictionary
-// policy. This allows to keep the logic of merging policies from different
-// sources simple, as all separate proxy policies should be considered as a
-// single whole during merging.
-void RemapProxyPolicies(PolicyMap* policies) {
- // The highest (level, scope) pair for an existing proxy policy is determined
- // first, and then only policies with those exact attributes are merged.
- PolicyMap::Entry current_priority; // Defaults to the lowest priority.
- PolicySource inherited_source = POLICY_SOURCE_ENTERPRISE_DEFAULT;
- std::unique_ptr<base::DictionaryValue> proxy_settings(
- new base::DictionaryValue);
- for (size_t i = 0; i < arraysize(kProxyPolicies); ++i) {
- const PolicyMap::Entry* entry = policies->Get(kProxyPolicies[i]);
- if (entry) {
- if (entry->has_higher_priority_than(current_priority)) {
- proxy_settings->Clear();
- current_priority = entry->DeepCopy();
- if (entry->source > inherited_source) // Higher priority?
- inherited_source = entry->source;
- }
- if (!entry->has_higher_priority_than(current_priority) &&
- !current_priority.has_higher_priority_than(*entry)) {
- proxy_settings->Set(kProxyPolicies[i], entry->value->CreateDeepCopy());
- }
- policies->Erase(kProxyPolicies[i]);
- }
- }
- // Sets the new |proxy_settings| if kProxySettings isn't set yet, or if the
- // new priority is higher.
- const PolicyMap::Entry* existing = policies->Get(key::kProxySettings);
- if (!proxy_settings->empty() &&
- (!existing || current_priority.has_higher_priority_than(*existing))) {
- policies->Set(key::kProxySettings, current_priority.level,
- current_priority.scope, inherited_source,
- std::move(proxy_settings), nullptr);
- }
-}
-
-} // namespace
-
-PolicyServiceImpl::PolicyServiceImpl(Providers providers)
- : update_task_ptr_factory_(this) {
- providers_ = std::move(providers);
- for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain)
- initialization_complete_[domain] = true;
- for (auto* provider : providers_) {
- provider->AddObserver(this);
- for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
- initialization_complete_[domain] &=
- provider->IsInitializationComplete(static_cast<PolicyDomain>(domain));
- }
- }
- // There are no observers yet, but calls to GetPolicies() should already get
- // the processed policy values.
- MergeAndTriggerUpdates();
-}
-
-PolicyServiceImpl::~PolicyServiceImpl() {
- DCHECK(thread_checker_.CalledOnValidThread());
- for (auto* provider : providers_)
- provider->RemoveObserver(this);
-}
-
-void PolicyServiceImpl::AddObserver(PolicyDomain domain,
- PolicyService::Observer* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- std::unique_ptr<Observers>& list = observers_[domain];
- if (!list)
- list = std::make_unique<Observers>();
- list->AddObserver(observer);
-}
-
-void PolicyServiceImpl::RemoveObserver(PolicyDomain domain,
- PolicyService::Observer* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- auto it = observers_.find(domain);
- if (it == observers_.end()) {
- NOTREACHED();
- return;
- }
- it->second->RemoveObserver(observer);
- if (!it->second->might_have_observers()) {
- observers_.erase(it);
- }
-}
-
-const PolicyMap& PolicyServiceImpl::GetPolicies(
- const PolicyNamespace& ns) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- return policy_bundle_.Get(ns);
-}
-
-bool PolicyServiceImpl::IsInitializationComplete(PolicyDomain domain) const {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(domain >= 0 && domain < POLICY_DOMAIN_SIZE);
- return initialization_complete_[domain];
-}
-
-void PolicyServiceImpl::RefreshPolicies(const base::Closure& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (!callback.is_null())
- refresh_callbacks_.push_back(callback);
-
- if (providers_.empty()) {
- // Refresh is immediately complete if there are no providers. See the note
- // on OnUpdatePolicy() about why this is a posted task.
- update_task_ptr_factory_.InvalidateWeakPtrs();
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates,
- update_task_ptr_factory_.GetWeakPtr()));
- } else {
- // Some providers might invoke OnUpdatePolicy synchronously while handling
- // RefreshPolicies. Mark all as pending before refreshing.
- for (auto* provider : providers_)
- refresh_pending_.insert(provider);
- for (auto* provider : providers_)
- provider->RefreshPolicies();
- }
-}
-
-void PolicyServiceImpl::OnUpdatePolicy(ConfigurationPolicyProvider* provider) {
- DCHECK_EQ(1, std::count(providers_.begin(), providers_.end(), provider));
- refresh_pending_.erase(provider);
-
- // Note: a policy change may trigger further policy changes in some providers.
- // For example, disabling SigninAllowed would cause the CloudPolicyManager to
- // drop all its policies, which makes this method enter again for that
- // provider.
- //
- // Therefore this update is posted asynchronously, to prevent reentrancy in
- // MergeAndTriggerUpdates. Also, cancel a pending update if there is any,
- // since both will produce the same PolicyBundle.
- update_task_ptr_factory_.InvalidateWeakPtrs();
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&PolicyServiceImpl::MergeAndTriggerUpdates,
- update_task_ptr_factory_.GetWeakPtr()));
-}
-
-void PolicyServiceImpl::NotifyNamespaceUpdated(
- const PolicyNamespace& ns,
- const PolicyMap& previous,
- const PolicyMap& current) {
- DCHECK(thread_checker_.CalledOnValidThread());
- auto iterator = observers_.find(ns.domain);
- if (iterator != observers_.end()) {
- for (auto& observer : *iterator->second)
- observer.OnPolicyUpdated(ns, previous, current);
- }
-}
-
-void PolicyServiceImpl::MergeAndTriggerUpdates() {
- // Merge from each provider in their order of priority.
- const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
- PolicyBundle bundle;
- for (auto* provider : providers_) {
- PolicyBundle provided_bundle;
- provided_bundle.CopyFrom(provider->policies());
- RemapProxyPolicies(&provided_bundle.Get(chrome_namespace));
- bundle.MergeFrom(provided_bundle);
- }
-
- // Swap first, so that observers that call GetPolicies() see the current
- // values.
- policy_bundle_.Swap(&bundle);
-
- // Only notify observers of namespaces that have been modified.
- const PolicyMap kEmpty;
- PolicyBundle::const_iterator it_new = policy_bundle_.begin();
- PolicyBundle::const_iterator end_new = policy_bundle_.end();
- PolicyBundle::const_iterator it_old = bundle.begin();
- PolicyBundle::const_iterator end_old = bundle.end();
- while (it_new != end_new && it_old != end_old) {
- if (it_new->first < it_old->first) {
- // A new namespace is available.
- NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
- ++it_new;
- } else if (it_old->first < it_new->first) {
- // A previously available namespace is now gone.
- NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
- ++it_old;
- } else {
- if (!it_new->second->Equals(*it_old->second)) {
- // An existing namespace's policies have changed.
- NotifyNamespaceUpdated(it_new->first, *it_old->second, *it_new->second);
- }
- ++it_new;
- ++it_old;
- }
- }
-
- // Send updates for the remaining new namespaces, if any.
- for (; it_new != end_new; ++it_new)
- NotifyNamespaceUpdated(it_new->first, kEmpty, *it_new->second);
-
- // Sends updates for the remaining removed namespaces, if any.
- for (; it_old != end_old; ++it_old)
- NotifyNamespaceUpdated(it_old->first, *it_old->second, kEmpty);
-
- CheckInitializationComplete();
- CheckRefreshComplete();
-}
-
-void PolicyServiceImpl::CheckInitializationComplete() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // Check if all the providers just became initialized for each domain; if so,
- // notify that domain's observers.
- for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain) {
- if (initialization_complete_[domain])
- continue;
-
- PolicyDomain policy_domain = static_cast<PolicyDomain>(domain);
-
- bool all_complete = true;
- for (auto* provider : providers_) {
- if (!provider->IsInitializationComplete(policy_domain)) {
- all_complete = false;
- break;
- }
- }
- if (all_complete) {
- initialization_complete_[domain] = true;
- auto iter = observers_.find(policy_domain);
- if (iter != observers_.end()) {
- for (auto& observer : *iter->second)
- observer.OnPolicyServiceInitialized(policy_domain);
- }
- }
- }
-}
-
-void PolicyServiceImpl::CheckRefreshComplete() {
- // Invoke all the callbacks if a refresh has just fully completed.
- if (refresh_pending_.empty() && !refresh_callbacks_.empty()) {
- std::vector<base::Closure> callbacks;
- callbacks.swap(refresh_callbacks_);
- std::vector<base::Closure>::iterator it;
- for (it = callbacks.begin(); it != callbacks.end(); ++it)
- it->Run();
- }
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_service_impl.h b/components/policy/core/common/policy_service_impl.h
deleted file mode 100644
index 985b27e257..0000000000
--- a/components/policy/core/common/policy_service_impl.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_IMPL_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_IMPL_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/threading/thread_checker.h"
-#include "components/policy/core/common/configuration_policy_provider.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_service.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-class PolicyMap;
-
-class POLICY_EXPORT PolicyServiceImpl
- : public PolicyService,
- public ConfigurationPolicyProvider::Observer {
- public:
- using Providers = std::vector<ConfigurationPolicyProvider*>;
-
- // Creates a new PolicyServiceImpl with the list of
- // ConfigurationPolicyProviders, in order of decreasing priority.
- explicit PolicyServiceImpl(Providers providers);
- ~PolicyServiceImpl() override;
-
- // PolicyService overrides:
- void AddObserver(PolicyDomain domain,
- PolicyService::Observer* observer) override;
- void RemoveObserver(PolicyDomain domain,
- PolicyService::Observer* observer) override;
- const PolicyMap& GetPolicies(const PolicyNamespace& ns) const override;
- bool IsInitializationComplete(PolicyDomain domain) const override;
- void RefreshPolicies(const base::Closure& callback) override;
-
- private:
- using Observers = base::ObserverList<PolicyService::Observer, true>;
-
- // ConfigurationPolicyProvider::Observer overrides:
- void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override;
-
- // Posts a task to notify observers of |ns| that its policies have changed,
- // passing along the |previous| and the |current| policies.
- void NotifyNamespaceUpdated(const PolicyNamespace& ns,
- const PolicyMap& previous,
- const PolicyMap& current);
-
- // Combines the policies from all the providers, and notifies the observers
- // of namespaces whose policies have been modified.
- void MergeAndTriggerUpdates();
-
- // Checks if all providers are initialized, and notifies the observers
- // if the service just became initialized.
- void CheckInitializationComplete();
-
- // Invokes all the refresh callbacks if there are no more refreshes pending.
- void CheckRefreshComplete();
-
- // The providers, in order of decreasing priority.
- Providers providers_;
-
- // Maps each policy namespace to its current policies.
- PolicyBundle policy_bundle_;
-
- // Maps each policy domain to its observer list.
- std::map<PolicyDomain, std::unique_ptr<Observers>> observers_;
-
- // True if all the providers are initialized for the indexed policy domain.
- bool initialization_complete_[POLICY_DOMAIN_SIZE];
-
- // Set of providers that have a pending update that was triggered by a
- // call to RefreshPolicies().
- std::set<ConfigurationPolicyProvider*> refresh_pending_;
-
- // List of callbacks to invoke once all providers refresh after a
- // RefreshPolicies() call.
- std::vector<base::Closure> refresh_callbacks_;
-
- // Used to verify thread-safe usage.
- base::ThreadChecker thread_checker_;
-
- // Used to create tasks to delay new policy updates while we may be already
- // processing previous policy updates.
- base::WeakPtrFactory<PolicyServiceImpl> update_task_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyServiceImpl);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_IMPL_H_
diff --git a/components/policy/core/common/policy_service_impl_unittest.cc b/components/policy/core/common/policy_service_impl_unittest.cc
deleted file mode 100644
index bc84baa9d6..0000000000
--- a/components/policy/core/common/policy_service_impl_unittest.cc
+++ /dev/null
@@ -1,706 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/policy_service_impl.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/values.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/mock_configuration_policy_provider.h"
-#include "components/policy/core/common/mock_policy_service.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/policy_constants.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::AnyNumber;
-using ::testing::Mock;
-using ::testing::Return;
-using ::testing::_;
-
-namespace policy {
-
-namespace {
-
-const char kExtension[] = "extension-id";
-const char kSameLevelPolicy[] = "policy-same-level-and-scope";
-const char kDiffLevelPolicy[] = "chrome-diff-level-and-scope";
-
-// Helper to compare the arguments to an EXPECT_CALL of OnPolicyUpdated() with
-// their expected values.
-MATCHER_P(PolicyEquals, expected, "") {
- return arg.Equals(*expected);
-}
-
-// Helper to compare the arguments to an EXPECT_CALL of OnPolicyValueUpdated()
-// with their expected values.
-MATCHER_P(ValueEquals, expected, "") {
- return *expected == *arg;
-}
-
-// Helper that fills |bundle| with test policies.
-void AddTestPolicies(PolicyBundle* bundle,
- const char* value,
- PolicyLevel level,
- PolicyScope scope) {
- PolicyMap* policy_map =
- &bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
- policy_map->Set(kSameLevelPolicy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>(value), nullptr);
- policy_map->Set(kDiffLevelPolicy, level, scope, POLICY_SOURCE_PLATFORM,
- std::make_unique<base::Value>(value), nullptr);
- policy_map =
- &bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension));
- policy_map->Set(kSameLevelPolicy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>(value), nullptr);
- policy_map->Set(kDiffLevelPolicy, level, scope, POLICY_SOURCE_PLATFORM,
- std::make_unique<base::Value>(value), nullptr);
-}
-
-// Observer class that changes the policy in the passed provider when the
-// callback is invoked.
-class ChangePolicyObserver : public PolicyService::Observer {
- public:
- explicit ChangePolicyObserver(MockConfigurationPolicyProvider* provider)
- : provider_(provider),
- observer_invoked_(false) {}
-
- void OnPolicyUpdated(const PolicyNamespace&,
- const PolicyMap& previous,
- const PolicyMap& current) override {
- PolicyMap new_policy;
- new_policy.Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(14),
- nullptr);
- provider_->UpdateChromePolicy(new_policy);
- observer_invoked_ = true;
- }
-
- bool observer_invoked() const { return observer_invoked_; }
-
- private:
- MockConfigurationPolicyProvider* provider_;
- bool observer_invoked_;
-};
-
-} // namespace
-
-class PolicyServiceTest : public testing::Test {
- public:
- PolicyServiceTest() {}
- void SetUp() override {
- EXPECT_CALL(provider0_, IsInitializationComplete(_))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider1_, IsInitializationComplete(_))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider2_, IsInitializationComplete(_))
- .WillRepeatedly(Return(true));
-
- provider0_.Init();
- provider1_.Init();
- provider2_.Init();
-
- policy0_.Set("pre", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>(13), nullptr);
- provider0_.UpdateChromePolicy(policy0_);
-
- PolicyServiceImpl::Providers providers;
- providers.push_back(&provider0_);
- providers.push_back(&provider1_);
- providers.push_back(&provider2_);
- policy_service_ = std::make_unique<PolicyServiceImpl>(std::move(providers));
- }
-
- void TearDown() override {
- provider0_.Shutdown();
- provider1_.Shutdown();
- provider2_.Shutdown();
- }
-
- MOCK_METHOD2(OnPolicyValueUpdated, void(const base::Value*,
- const base::Value*));
-
- MOCK_METHOD0(OnPolicyRefresh, void());
-
- // Returns true if the policies for namespace |ns| match |expected|.
- bool VerifyPolicies(const PolicyNamespace& ns,
- const PolicyMap& expected) {
- return policy_service_->GetPolicies(ns).Equals(expected);
- }
-
- void RunUntilIdle() {
- base::RunLoop loop;
- loop.RunUntilIdle();
- }
-
- protected:
- base::MessageLoop loop_;
- MockConfigurationPolicyProvider provider0_;
- MockConfigurationPolicyProvider provider1_;
- MockConfigurationPolicyProvider provider2_;
- PolicyMap policy0_;
- PolicyMap policy1_;
- PolicyMap policy2_;
- std::unique_ptr<PolicyServiceImpl> policy_service_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PolicyServiceTest);
-};
-
-TEST_F(PolicyServiceTest, LoadsPoliciesBeforeProvidersRefresh) {
- PolicyMap expected;
- expected.Set("pre", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>(13), nullptr);
- EXPECT_TRUE(VerifyPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), expected));
-}
-
-TEST_F(PolicyServiceTest, NotifyObservers) {
- MockPolicyServiceObserver observer;
- policy_service_->AddObserver(POLICY_DOMAIN_CHROME, &observer);
-
- PolicyMap expectedPrevious;
- expectedPrevious.Set("pre", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>(13), nullptr);
-
- PolicyMap expectedCurrent;
- expectedCurrent.CopyFrom(expectedPrevious);
- expectedCurrent.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(123),
- nullptr);
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(123),
- nullptr);
- EXPECT_CALL(observer, OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string()),
- PolicyEquals(&expectedPrevious),
- PolicyEquals(&expectedCurrent)));
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(&observer);
-
- // No changes.
- EXPECT_CALL(observer, OnPolicyUpdated(_, _, _)).Times(0);
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(VerifyPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), expectedCurrent));
-
- // New policy.
- expectedPrevious.CopyFrom(expectedCurrent);
- expectedCurrent.Set("bbb", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(456),
- nullptr);
- policy0_.Set("bbb", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(456),
- nullptr);
- EXPECT_CALL(observer, OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string()),
- PolicyEquals(&expectedPrevious),
- PolicyEquals(&expectedCurrent)));
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Removed policy.
- expectedPrevious.CopyFrom(expectedCurrent);
- expectedCurrent.Erase("bbb");
- policy0_.Erase("bbb");
- EXPECT_CALL(observer, OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string()),
- PolicyEquals(&expectedPrevious),
- PolicyEquals(&expectedCurrent)));
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Changed policy.
- expectedPrevious.CopyFrom(expectedCurrent);
- expectedCurrent.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(789),
- nullptr);
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(789),
- nullptr);
-
- EXPECT_CALL(observer, OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string()),
- PolicyEquals(&expectedPrevious),
- PolicyEquals(&expectedCurrent)));
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(&observer);
-
- // No changes again.
- EXPECT_CALL(observer, OnPolicyUpdated(_, _, _)).Times(0);
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(VerifyPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), expectedCurrent));
-
- policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, &observer);
-}
-
-TEST_F(PolicyServiceTest, NotifyObserversInMultipleNamespaces) {
- const std::string kExtension0("extension-0");
- const std::string kExtension1("extension-1");
- const std::string kExtension2("extension-2");
- MockPolicyServiceObserver chrome_observer;
- MockPolicyServiceObserver extension_observer;
- policy_service_->AddObserver(POLICY_DOMAIN_CHROME, &chrome_observer);
- policy_service_->AddObserver(POLICY_DOMAIN_EXTENSIONS, &extension_observer);
-
- PolicyMap previous_policy_map;
- previous_policy_map.Set("pre", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>(13), nullptr);
- PolicyMap policy_map;
- policy_map.CopyFrom(previous_policy_map);
- policy_map.Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value"),
- nullptr);
-
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
- // The initial setup includes a policy for chrome that is now changing.
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .CopyFrom(policy_map);
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0))
- .CopyFrom(policy_map);
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1))
- .CopyFrom(policy_map);
-
- const PolicyMap kEmptyPolicyMap;
- EXPECT_CALL(
- chrome_observer,
- OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()),
- PolicyEquals(&previous_policy_map),
- PolicyEquals(&policy_map)));
- EXPECT_CALL(
- extension_observer,
- OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0),
- PolicyEquals(&kEmptyPolicyMap),
- PolicyEquals(&policy_map)));
- EXPECT_CALL(
- extension_observer,
- OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1),
- PolicyEquals(&kEmptyPolicyMap),
- PolicyEquals(&policy_map)));
- provider0_.UpdatePolicy(std::move(bundle));
- RunUntilIdle();
- Mock::VerifyAndClearExpectations(&chrome_observer);
- Mock::VerifyAndClearExpectations(&extension_observer);
-
- // Chrome policy stays the same, kExtension0 is gone, kExtension1 changes,
- // and kExtension2 is new.
- previous_policy_map.CopyFrom(policy_map);
- bundle.reset(new PolicyBundle());
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .CopyFrom(policy_map);
- policy_map.Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>("another value"), nullptr);
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1))
- .CopyFrom(policy_map);
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension2))
- .CopyFrom(policy_map);
-
- EXPECT_CALL(chrome_observer, OnPolicyUpdated(_, _, _)).Times(0);
- EXPECT_CALL(
- extension_observer,
- OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension0),
- PolicyEquals(&previous_policy_map),
- PolicyEquals(&kEmptyPolicyMap)));
- EXPECT_CALL(
- extension_observer,
- OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension1),
- PolicyEquals(&previous_policy_map),
- PolicyEquals(&policy_map)));
- EXPECT_CALL(
- extension_observer,
- OnPolicyUpdated(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension2),
- PolicyEquals(&kEmptyPolicyMap),
- PolicyEquals(&policy_map)));
- provider0_.UpdatePolicy(std::move(bundle));
- RunUntilIdle();
- Mock::VerifyAndClearExpectations(&chrome_observer);
- Mock::VerifyAndClearExpectations(&extension_observer);
-
- policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, &chrome_observer);
- policy_service_->RemoveObserver(POLICY_DOMAIN_EXTENSIONS,
- &extension_observer);
-}
-
-TEST_F(PolicyServiceTest, ObserverChangesPolicy) {
- ChangePolicyObserver observer(&provider0_);
- policy_service_->AddObserver(POLICY_DOMAIN_CHROME, &observer);
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(123),
- nullptr);
- policy0_.Set("bbb", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1234),
- nullptr);
- // Should not crash.
- provider0_.UpdateChromePolicy(policy0_);
- policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, &observer);
- EXPECT_TRUE(observer.observer_invoked());
-}
-
-TEST_F(PolicyServiceTest, Priorities) {
- PolicyMap expected;
- expected.Set("pre", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>(13), nullptr);
- expected.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
- policy1_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
- policy2_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(2), nullptr);
- provider0_.UpdateChromePolicy(policy0_);
- provider1_.UpdateChromePolicy(policy1_);
- provider2_.UpdateChromePolicy(policy2_);
- EXPECT_TRUE(VerifyPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), expected));
-
- expected.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
- policy0_.Erase("aaa");
- provider0_.UpdateChromePolicy(policy0_);
- EXPECT_TRUE(VerifyPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), expected));
-
- expected.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(2), nullptr);
- policy1_.Set("aaa", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
- provider1_.UpdateChromePolicy(policy1_);
- EXPECT_TRUE(VerifyPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()), expected));
-}
-
-TEST_F(PolicyServiceTest, PolicyChangeRegistrar) {
- std::unique_ptr<PolicyChangeRegistrar> registrar(new PolicyChangeRegistrar(
- policy_service_.get(),
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
-
- // Starting to observe existing policies doesn't trigger a notification.
- EXPECT_CALL(*this, OnPolicyValueUpdated(_, _)).Times(0);
- registrar->Observe("pre", base::Bind(
- &PolicyServiceTest::OnPolicyValueUpdated,
- base::Unretained(this)));
- registrar->Observe("aaa", base::Bind(
- &PolicyServiceTest::OnPolicyValueUpdated,
- base::Unretained(this)));
- RunUntilIdle();
- Mock::VerifyAndClearExpectations(this);
-
- // Changing it now triggers a notification.
- base::Value kValue0(0);
- EXPECT_CALL(*this, OnPolicyValueUpdated(NULL, ValueEquals(&kValue0)));
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue0.CreateDeepCopy(), nullptr);
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(this);
-
- // Changing other values doesn't trigger a notification.
- EXPECT_CALL(*this, OnPolicyValueUpdated(_, _)).Times(0);
- policy0_.Set("bbb", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue0.CreateDeepCopy(), nullptr);
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(this);
-
- // Modifying the value triggers a notification.
- base::Value kValue1(1);
- EXPECT_CALL(*this, OnPolicyValueUpdated(ValueEquals(&kValue0),
- ValueEquals(&kValue1)));
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue1.CreateDeepCopy(), nullptr);
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(this);
-
- // Removing the value triggers a notification.
- EXPECT_CALL(*this, OnPolicyValueUpdated(ValueEquals(&kValue1), NULL));
- policy0_.Erase("aaa");
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(this);
-
- // No more notifications after destroying the registrar.
- EXPECT_CALL(*this, OnPolicyValueUpdated(_, _)).Times(0);
- registrar.reset();
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue1.CreateDeepCopy(), nullptr);
- policy0_.Set("pre", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT, kValue1.CreateDeepCopy(),
- nullptr);
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(this);
-}
-
-TEST_F(PolicyServiceTest, RefreshPolicies) {
- EXPECT_CALL(provider0_, RefreshPolicies()).Times(AnyNumber());
- EXPECT_CALL(provider1_, RefreshPolicies()).Times(AnyNumber());
- EXPECT_CALL(provider2_, RefreshPolicies()).Times(AnyNumber());
-
- EXPECT_CALL(*this, OnPolicyRefresh()).Times(0);
- policy_service_->RefreshPolicies(base::Bind(
- &PolicyServiceTest::OnPolicyRefresh,
- base::Unretained(this)));
- // Let any queued observer tasks run.
- RunUntilIdle();
- Mock::VerifyAndClearExpectations(this);
-
- EXPECT_CALL(*this, OnPolicyRefresh()).Times(0);
- base::Value kValue0(0);
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue0.CreateDeepCopy(), nullptr);
- provider0_.UpdateChromePolicy(policy0_);
- Mock::VerifyAndClearExpectations(this);
-
- EXPECT_CALL(*this, OnPolicyRefresh()).Times(0);
- base::Value kValue1(1);
- policy1_.Set("aaa", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue1.CreateDeepCopy(), nullptr);
- provider1_.UpdateChromePolicy(policy1_);
- Mock::VerifyAndClearExpectations(this);
-
- // A provider can refresh more than once after a RefreshPolicies call, but
- // OnPolicyRefresh should be triggered only after all providers are
- // refreshed.
- EXPECT_CALL(*this, OnPolicyRefresh()).Times(0);
- policy1_.Set("bbb", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue1.CreateDeepCopy(), nullptr);
- provider1_.UpdateChromePolicy(policy1_);
- Mock::VerifyAndClearExpectations(this);
-
- // If another RefreshPolicies() call happens while waiting for a previous
- // one to complete, then all providers must refresh again.
- EXPECT_CALL(*this, OnPolicyRefresh()).Times(0);
- policy_service_->RefreshPolicies(base::Bind(
- &PolicyServiceTest::OnPolicyRefresh,
- base::Unretained(this)));
- RunUntilIdle();
- Mock::VerifyAndClearExpectations(this);
-
- EXPECT_CALL(*this, OnPolicyRefresh()).Times(0);
- policy2_.Set("bbb", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue0.CreateDeepCopy(), nullptr);
- provider2_.UpdateChromePolicy(policy2_);
- Mock::VerifyAndClearExpectations(this);
-
- // Providers 0 and 1 must reload again.
- EXPECT_CALL(*this, OnPolicyRefresh()).Times(2);
- base::Value kValue2(2);
- policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, kValue2.CreateDeepCopy(), nullptr);
- provider0_.UpdateChromePolicy(policy0_);
- provider1_.UpdateChromePolicy(policy1_);
- Mock::VerifyAndClearExpectations(this);
-
- const PolicyMap& policies = policy_service_->GetPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
- EXPECT_EQ(kValue2, *policies.GetValue("aaa"));
- EXPECT_EQ(kValue0, *policies.GetValue("bbb"));
-}
-
-TEST_F(PolicyServiceTest, NamespaceMerge) {
- std::unique_ptr<PolicyBundle> bundle0(new PolicyBundle());
- std::unique_ptr<PolicyBundle> bundle1(new PolicyBundle());
- std::unique_ptr<PolicyBundle> bundle2(new PolicyBundle());
-
- AddTestPolicies(bundle0.get(), "bundle0",
- POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER);
- AddTestPolicies(bundle1.get(), "bundle1",
- POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
- AddTestPolicies(bundle2.get(), "bundle2",
- POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
-
- provider0_.UpdatePolicy(std::move(bundle0));
- provider1_.UpdatePolicy(std::move(bundle1));
- provider2_.UpdatePolicy(std::move(bundle2));
- RunUntilIdle();
-
- PolicyMap expected;
- // For policies of the same level and scope, the first provider takes
- // precedence, on every namespace.
- expected.Set(kSameLevelPolicy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_ENTERPRISE_DEFAULT,
- std::make_unique<base::Value>("bundle0"), nullptr);
- // For policies with different levels and scopes, the highest priority
- // level/scope combination takes precedence, on every namespace.
- expected.Set(kDiffLevelPolicy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
- POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>("bundle2"),
- nullptr);
- EXPECT_TRUE(policy_service_->GetPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())).Equals(expected));
- EXPECT_TRUE(policy_service_->GetPolicies(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension)).Equals(expected));
-}
-
-TEST_F(PolicyServiceTest, IsInitializationComplete) {
- // |provider0| has all domains initialized.
- Mock::VerifyAndClearExpectations(&provider1_);
- Mock::VerifyAndClearExpectations(&provider2_);
- EXPECT_CALL(provider1_, IsInitializationComplete(_))
- .WillRepeatedly(Return(false));
- EXPECT_CALL(provider2_, IsInitializationComplete(_))
- .WillRepeatedly(Return(false));
- PolicyServiceImpl::Providers providers;
- providers.push_back(&provider0_);
- providers.push_back(&provider1_);
- providers.push_back(&provider2_);
- policy_service_ = std::make_unique<PolicyServiceImpl>(std::move(providers));
- EXPECT_FALSE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
- EXPECT_FALSE(
- policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
- EXPECT_FALSE(policy_service_->IsInitializationComplete(
- POLICY_DOMAIN_SIGNIN_EXTENSIONS));
-
- // |provider2_| still doesn't have POLICY_DOMAIN_CHROME initialized, so
- // the initialization status of that domain won't change.
- MockPolicyServiceObserver observer;
- policy_service_->AddObserver(POLICY_DOMAIN_CHROME, &observer);
- policy_service_->AddObserver(POLICY_DOMAIN_EXTENSIONS, &observer);
- policy_service_->AddObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer);
- EXPECT_CALL(observer, OnPolicyServiceInitialized(_)).Times(0);
- Mock::VerifyAndClearExpectations(&provider1_);
- EXPECT_CALL(provider1_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider1_, IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS))
- .WillRepeatedly(Return(false));
- EXPECT_CALL(provider1_,
- IsInitializationComplete(POLICY_DOMAIN_SIGNIN_EXTENSIONS))
- .WillRepeatedly(Return(false));
- const PolicyMap kPolicyMap;
- provider1_.UpdateChromePolicy(kPolicyMap);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_FALSE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
- EXPECT_FALSE(
- policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
- EXPECT_FALSE(policy_service_->IsInitializationComplete(
- POLICY_DOMAIN_SIGNIN_EXTENSIONS));
-
- // Same if |provider1_| doesn't have POLICY_DOMAIN_EXTENSIONS initialized.
- EXPECT_CALL(observer, OnPolicyServiceInitialized(_)).Times(0);
- Mock::VerifyAndClearExpectations(&provider2_);
- EXPECT_CALL(provider2_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
- .WillRepeatedly(Return(false));
- EXPECT_CALL(provider2_, IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider2_,
- IsInitializationComplete(POLICY_DOMAIN_SIGNIN_EXTENSIONS))
- .WillRepeatedly(Return(true));
- provider2_.UpdateChromePolicy(kPolicyMap);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_FALSE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
- EXPECT_FALSE(
- policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
- EXPECT_FALSE(policy_service_->IsInitializationComplete(
- POLICY_DOMAIN_SIGNIN_EXTENSIONS));
-
- // Now initialize POLICY_DOMAIN_CHROME on all the providers.
- EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_CHROME));
- Mock::VerifyAndClearExpectations(&provider2_);
- EXPECT_CALL(provider2_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider2_, IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider2_,
- IsInitializationComplete(POLICY_DOMAIN_SIGNIN_EXTENSIONS))
- .WillRepeatedly(Return(true));
- provider2_.UpdateChromePolicy(kPolicyMap);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
- // Other domains are still not initialized.
- EXPECT_FALSE(
- policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
- EXPECT_FALSE(policy_service_->IsInitializationComplete(
- POLICY_DOMAIN_SIGNIN_EXTENSIONS));
-
- // Initialize the remaining domain.
- EXPECT_CALL(observer, OnPolicyServiceInitialized(POLICY_DOMAIN_EXTENSIONS));
- EXPECT_CALL(observer,
- OnPolicyServiceInitialized(POLICY_DOMAIN_SIGNIN_EXTENSIONS));
- Mock::VerifyAndClearExpectations(&provider1_);
- EXPECT_CALL(provider1_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider1_, IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(provider1_,
- IsInitializationComplete(POLICY_DOMAIN_SIGNIN_EXTENSIONS))
- .WillRepeatedly(Return(true));
- provider1_.UpdateChromePolicy(kPolicyMap);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
- EXPECT_TRUE(
- policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
- EXPECT_TRUE(policy_service_->IsInitializationComplete(
- POLICY_DOMAIN_SIGNIN_EXTENSIONS));
-
- // Cleanup.
- policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, &observer);
- policy_service_->RemoveObserver(POLICY_DOMAIN_EXTENSIONS, &observer);
- policy_service_->RemoveObserver(POLICY_DOMAIN_SIGNIN_EXTENSIONS, &observer);
-}
-
-TEST_F(PolicyServiceTest, SeparateProxyPoliciesMerging) {
- const PolicyNamespace chrome_namespace(POLICY_DOMAIN_CHROME, std::string());
- const PolicyNamespace extension_namespace(POLICY_DOMAIN_EXTENSIONS, "xyz");
-
- std::unique_ptr<PolicyBundle> policy_bundle(new PolicyBundle());
- PolicyMap& policy_map = policy_bundle->Get(chrome_namespace);
- // Individual proxy policy values in the Chrome namespace should be collected
- // into a dictionary.
- policy_map.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>(3), nullptr);
-
- // Both these policies should be ignored, since there's a higher priority
- // policy available.
- policy_map.Set(key::kProxyMode, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>("pac_script"), nullptr);
- policy_map.Set(key::kProxyPacUrl, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>("http://example.com/wpad.dat"),
- nullptr);
-
- // Add a value to a non-Chrome namespace.
- policy_bundle->Get(extension_namespace)
- .Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(3), nullptr);
-
- // The resulting Chrome namespace map should have the collected policy.
- PolicyMap expected_chrome;
- std::unique_ptr<base::DictionaryValue> expected_value(
- new base::DictionaryValue);
- expected_value->SetInteger(key::kProxyServerMode, 3);
- expected_chrome.Set(key::kProxySettings, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
- std::move(expected_value), nullptr);
-
- // The resulting Extensions namespace map shouldn't have been modified.
- PolicyMap expected_extension;
- expected_extension.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>(3), nullptr);
-
- provider0_.UpdatePolicy(std::move(policy_bundle));
- RunUntilIdle();
-
- EXPECT_TRUE(VerifyPolicies(chrome_namespace, expected_chrome));
- EXPECT_TRUE(VerifyPolicies(extension_namespace, expected_extension));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_service_stub.cc b/components/policy/core/common/policy_service_stub.cc
deleted file mode 100644
index 025ff86e40..0000000000
--- a/components/policy/core/common/policy_service_stub.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/policy_service_stub.h"
-
-
-namespace policy {
-
-PolicyServiceStub::PolicyServiceStub() {}
-
-PolicyServiceStub::~PolicyServiceStub() {}
-
-void PolicyServiceStub::AddObserver(PolicyDomain domain,
- Observer* observer) {}
-
-void PolicyServiceStub::RemoveObserver(PolicyDomain domain,
- Observer* observer) {}
-
-const PolicyMap& PolicyServiceStub::GetPolicies(
- const PolicyNamespace& ns) const {
- return kEmpty_;
-}
-
-bool PolicyServiceStub::IsInitializationComplete(PolicyDomain domain) const {
- return true;
-}
-
-void PolicyServiceStub::RefreshPolicies(const base::Closure& callback) {
- if (!callback.is_null())
- callback.Run();
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_service_stub.h b/components/policy/core/common/policy_service_stub.h
deleted file mode 100644
index 8759336fe8..0000000000
--- a/components/policy/core/common/policy_service_stub.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_STUB_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_STUB_H_
-
-#include "base/macros.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_service.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// A stub implementation, that is used when ENABLE_CONFIGURATION_POLICY is not
-// set. This allows client code to compile without requiring #ifdefs.
-class POLICY_EXPORT PolicyServiceStub : public PolicyService {
- public:
- PolicyServiceStub();
- ~PolicyServiceStub() override;
-
- void AddObserver(PolicyDomain domain,
- Observer* observer) override;
-
- void RemoveObserver(PolicyDomain domain,
- Observer* observer) override;
-
- const PolicyMap& GetPolicies(
- const PolicyNamespace& ns) const override;
-
- bool IsInitializationComplete(PolicyDomain domain) const override;
-
- void RefreshPolicies(const base::Closure& callback) override;
- private:
- const PolicyMap kEmpty_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyServiceStub);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_SERVICE_STUB_H_
diff --git a/components/policy/core/common/policy_statistics_collector.cc b/components/policy/core/common/policy_statistics_collector.cc
deleted file mode 100644
index de3cd16ce4..0000000000
--- a/components/policy/core/common/policy_statistics_collector.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/policy_statistics_collector.h"
-
-#include <algorithm>
-#include <string>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/task_runner.h"
-#include "components/policy/core/common/policy_pref_names.h"
-#include "components/policy/core/common/policy_service.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-
-namespace policy {
-
-const int PolicyStatisticsCollector::kStatisticsUpdateRate =
- 24 * 60 * 60 * 1000; // 24 hours.
-
-PolicyStatisticsCollector::PolicyStatisticsCollector(
- const GetChromePolicyDetailsCallback& get_details,
- const Schema& chrome_schema,
- PolicyService* policy_service,
- PrefService* prefs,
- const scoped_refptr<base::TaskRunner>& task_runner)
- : get_details_(get_details),
- chrome_schema_(chrome_schema),
- policy_service_(policy_service),
- prefs_(prefs),
- task_runner_(task_runner) {
-}
-
-PolicyStatisticsCollector::~PolicyStatisticsCollector() {
-}
-
-void PolicyStatisticsCollector::Initialize() {
- using base::Time;
- using base::TimeDelta;
-
- TimeDelta update_rate = TimeDelta::FromMilliseconds(kStatisticsUpdateRate);
- Time last_update = Time::FromInternalValue(
- prefs_->GetInt64(policy_prefs::kLastPolicyStatisticsUpdate));
- TimeDelta delay = std::max(Time::Now() - last_update, TimeDelta::FromDays(0));
- if (delay >= update_rate)
- CollectStatistics();
- else
- ScheduleUpdate(update_rate - delay);
-}
-
-// static
-void PolicyStatisticsCollector::RegisterPrefs(PrefRegistrySimple* registry) {
- registry->RegisterInt64Pref(policy_prefs::kLastPolicyStatisticsUpdate, 0);
-}
-
-void PolicyStatisticsCollector::RecordPolicyUse(int id) {
- base::UmaHistogramSparse("Enterprise.Policies", id);
-}
-
-void PolicyStatisticsCollector::CollectStatistics() {
- const PolicyMap& policies = policy_service_->GetPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
-
- // Collect statistics.
- for (Schema::Iterator it(chrome_schema_.GetPropertiesIterator());
- !it.IsAtEnd(); it.Advance()) {
- if (policies.Get(it.key())) {
- const PolicyDetails* details = get_details_.Run(it.key());
- if (details)
- RecordPolicyUse(details->id);
- else
- NOTREACHED();
- }
- }
-
- // Take care of next update.
- prefs_->SetInt64(policy_prefs::kLastPolicyStatisticsUpdate,
- base::Time::Now().ToInternalValue());
- ScheduleUpdate(base::TimeDelta::FromMilliseconds(kStatisticsUpdateRate));
-}
-
-void PolicyStatisticsCollector::ScheduleUpdate(base::TimeDelta delay) {
- update_callback_.Reset(base::Bind(
- &PolicyStatisticsCollector::CollectStatistics,
- base::Unretained(this)));
- task_runner_->PostDelayedTask(FROM_HERE, update_callback_.callback(), delay);
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_statistics_collector.h b/components/policy/core/common/policy_statistics_collector.h
deleted file mode 100644
index f373fd5672..0000000000
--- a/components/policy/core/common/policy_statistics_collector.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_STATISTICS_COLLECTOR_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_STATISTICS_COLLECTOR_H_
-
-#include "base/cancelable_callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
-#include "components/policy/core/common/policy_details.h"
-#include "components/policy/core/common/schema.h"
-#include "components/policy/policy_export.h"
-
-class PrefService;
-class PrefRegistrySimple;
-
-namespace base {
-class TaskRunner;
-}
-
-namespace policy {
-
-class PolicyService;
-
-// Manages regular updates of policy usage UMA histograms.
-class POLICY_EXPORT PolicyStatisticsCollector {
- public:
- // Policy usage statistics update rate, in milliseconds.
- static const int kStatisticsUpdateRate;
-
- // Neither |policy_service| nor |prefs| can be NULL and must stay valid
- // throughout the lifetime of PolicyStatisticsCollector.
- PolicyStatisticsCollector(const GetChromePolicyDetailsCallback& get_details,
- const Schema& chrome_schema,
- PolicyService* policy_service,
- PrefService* prefs,
- const scoped_refptr<base::TaskRunner>& task_runner);
- virtual ~PolicyStatisticsCollector();
-
- // Completes initialization and starts periodical statistic updates.
- void Initialize();
-
- static void RegisterPrefs(PrefRegistrySimple* registry);
-
- protected:
- // protected virtual for mocking.
- virtual void RecordPolicyUse(int id);
-
- private:
- void CollectStatistics();
- void ScheduleUpdate(base::TimeDelta delay);
-
- GetChromePolicyDetailsCallback get_details_;
- Schema chrome_schema_;
- PolicyService* policy_service_;
- PrefService* prefs_;
-
- base::CancelableClosure update_callback_;
-
- const scoped_refptr<base::TaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyStatisticsCollector);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_STATISTICS_COLLECTOR_H_
diff --git a/components/policy/core/common/policy_statistics_collector_unittest.cc b/components/policy/core/common/policy_statistics_collector_unittest.cc
deleted file mode 100644
index 80d24980f8..0000000000
--- a/components/policy/core/common/policy_statistics_collector_unittest.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/policy/core/common/policy_statistics_collector.h"
-
-#include <cstring>
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/values.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/mock_policy_service.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_pref_names.h"
-#include "components/policy/core/common/policy_test_utils.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/testing_pref_service.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-using testing::ReturnRef;
-
-// Arbitrary policy names used for testing.
-const char kTestPolicy1[] = "Test Policy 1";
-const char kTestPolicy2[] = "Test Policy 2";
-
-const int kTestPolicy1Id = 42;
-const int kTestPolicy2Id = 123;
-
-const char kTestChromeSchema[] =
- "{"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"Test Policy 1\": { \"type\": \"string\" },"
- " \"Test Policy 2\": { \"type\": \"string\" }"
- " }"
- "}";
-
-const PolicyDetails kTestPolicyDetails[] = {
- // is_deprecated is_device_policy id max_external_data_size
- { false, false, kTestPolicy1Id, 0 },
- { false, false, kTestPolicy2Id, 0 },
-};
-
-class TestPolicyStatisticsCollector : public PolicyStatisticsCollector {
- public:
- TestPolicyStatisticsCollector(
- const GetChromePolicyDetailsCallback& get_details,
- const Schema& chrome_schema,
- PolicyService* policy_service,
- PrefService* prefs,
- const scoped_refptr<base::TaskRunner>& task_runner)
- : PolicyStatisticsCollector(get_details,
- chrome_schema,
- policy_service,
- prefs,
- task_runner) {}
-
- MOCK_METHOD1(RecordPolicyUse, void(int));
-};
-
-} // namespace
-
-class PolicyStatisticsCollectorTest : public testing::Test {
- protected:
- PolicyStatisticsCollectorTest()
- : update_delay_(base::TimeDelta::FromMilliseconds(
- PolicyStatisticsCollector::kStatisticsUpdateRate)),
- task_runner_(new base::TestSimpleTaskRunner()) {
- }
-
- void SetUp() override {
- std::string error;
- chrome_schema_ = Schema::Parse(kTestChromeSchema, &error);
- ASSERT_TRUE(chrome_schema_.valid()) << error;
-
- policy_details_.SetDetails(kTestPolicy1, &kTestPolicyDetails[0]);
- policy_details_.SetDetails(kTestPolicy2, &kTestPolicyDetails[1]);
-
- prefs_.registry()->RegisterInt64Pref(
- policy_prefs::kLastPolicyStatisticsUpdate, 0);
-
- // Set up default function behaviour.
- EXPECT_CALL(policy_service_,
- GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME,
- std::string())))
- .WillRepeatedly(ReturnRef(policy_map_));
-
- // Arbitrary negative value (so it'll be different from |update_delay_|).
- last_delay_ = base::TimeDelta::FromDays(-1);
- policy_map_.Clear();
- policy_statistics_collector_.reset(new TestPolicyStatisticsCollector(
- policy_details_.GetCallback(),
- chrome_schema_,
- &policy_service_,
- &prefs_,
- task_runner_));
- }
-
- void SetPolicy(const std::string& name) {
- policy_map_.Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true),
- nullptr);
- }
-
- base::TimeDelta GetFirstDelay() const {
- if (!task_runner_->HasPendingTask()) {
- ADD_FAILURE();
- return base::TimeDelta();
- }
- return task_runner_->NextPendingTaskDelay();
- }
-
- const base::TimeDelta update_delay_;
-
- base::TimeDelta last_delay_;
-
- PolicyDetailsMap policy_details_;
- Schema chrome_schema_;
- TestingPrefServiceSimple prefs_;
- MockPolicyService policy_service_;
- PolicyMap policy_map_;
-
- scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- std::unique_ptr<TestPolicyStatisticsCollector> policy_statistics_collector_;
-};
-
-TEST_F(PolicyStatisticsCollectorTest, CollectPending) {
- SetPolicy(kTestPolicy1);
-
- prefs_.SetInt64(policy_prefs::kLastPolicyStatisticsUpdate,
- (base::Time::Now() - update_delay_).ToInternalValue());
-
- EXPECT_CALL(*policy_statistics_collector_, RecordPolicyUse(kTestPolicy1Id));
-
- policy_statistics_collector_->Initialize();
- EXPECT_EQ(1u, task_runner_->NumPendingTasks());
- EXPECT_EQ(update_delay_, GetFirstDelay());
-}
-
-TEST_F(PolicyStatisticsCollectorTest, CollectPendingVeryOld) {
- SetPolicy(kTestPolicy1);
-
- // Must not be 0.0 (read comment for Time::FromDoubleT).
- prefs_.SetInt64(policy_prefs::kLastPolicyStatisticsUpdate,
- base::Time::FromDoubleT(1.0).ToInternalValue());
-
- EXPECT_CALL(*policy_statistics_collector_, RecordPolicyUse(kTestPolicy1Id));
-
- policy_statistics_collector_->Initialize();
- EXPECT_EQ(1u, task_runner_->NumPendingTasks());
- EXPECT_EQ(update_delay_, GetFirstDelay());
-}
-
-TEST_F(PolicyStatisticsCollectorTest, CollectLater) {
- SetPolicy(kTestPolicy1);
-
- prefs_.SetInt64(policy_prefs::kLastPolicyStatisticsUpdate,
- (base::Time::Now() - update_delay_ / 2).ToInternalValue());
-
- policy_statistics_collector_->Initialize();
- EXPECT_EQ(1u, task_runner_->NumPendingTasks());
- EXPECT_LT(GetFirstDelay(), update_delay_);
-}
-
-TEST_F(PolicyStatisticsCollectorTest, MultiplePolicies) {
- SetPolicy(kTestPolicy1);
- SetPolicy(kTestPolicy2);
-
- prefs_.SetInt64(policy_prefs::kLastPolicyStatisticsUpdate,
- (base::Time::Now() - update_delay_).ToInternalValue());
-
- EXPECT_CALL(*policy_statistics_collector_, RecordPolicyUse(kTestPolicy1Id));
- EXPECT_CALL(*policy_statistics_collector_, RecordPolicyUse(kTestPolicy2Id));
-
- policy_statistics_collector_->Initialize();
- EXPECT_EQ(1u, task_runner_->NumPendingTasks());
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/policy_switches.cc b/components/policy/core/common/policy_switches.cc
deleted file mode 100644
index 7bea73e2fe..0000000000
--- a/components/policy/core/common/policy_switches.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_switches.h"
-
-namespace policy {
-namespace switches {
-
-// Specifies the URL at which to fetch configuration policy from the device
-// management backend.
-const char kDeviceManagementUrl[] = "device-management-url";
-
-// Disables fetching and storing cloud policy for components.
-const char kDisableComponentCloudPolicy[] = "disable-component-cloud-policy";
-
-// Always treat user as affiliated.
-// TODO(antrim): Remove once test servers correctly produce affiliation ids.
-const char kUserAlwaysAffiliated[] = "user-always-affiliated";
-
-} // namespace switches
-} // namespace policy
diff --git a/components/policy/core/common/policy_switches.h b/components/policy/core/common/policy_switches.h
deleted file mode 100644
index 08d13cb5ff..0000000000
--- a/components/policy/core/common/policy_switches.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_SWITCHES_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_SWITCHES_H_
-
-#include "components/policy/policy_export.h"
-
-#include "build/build_config.h"
-
-namespace policy {
-namespace switches {
-
-POLICY_EXPORT extern const char kDeviceManagementUrl[];
-POLICY_EXPORT extern const char kDisableComponentCloudPolicy[];
-POLICY_EXPORT extern const char kUserAlwaysAffiliated[];
-
-} // namespace switches
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_SWITCHES_H_
diff --git a/components/policy/core/common/policy_test_utils.cc b/components/policy/core/common/policy_test_utils.cc
deleted file mode 100644
index d51eea90a4..0000000000
--- a/components/policy/core/common/policy_test_utils.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/policy_test_utils.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "components/policy/core/common/policy_bundle.h"
-
-#if defined(OS_IOS) || defined(OS_MACOSX)
-#include <CoreFoundation/CoreFoundation.h>
-
-#include "base/mac/scoped_cftyperef.h"
-#endif
-
-namespace policy {
-
-PolicyDetailsMap::PolicyDetailsMap() {}
-
-PolicyDetailsMap::~PolicyDetailsMap() {}
-
-GetChromePolicyDetailsCallback PolicyDetailsMap::GetCallback() const {
- return base::Bind(&PolicyDetailsMap::Lookup, base::Unretained(this));
-}
-
-void PolicyDetailsMap::SetDetails(const std::string& policy,
- const PolicyDetails* details) {
- map_[policy] = details;
-}
-
-const PolicyDetails* PolicyDetailsMap::Lookup(const std::string& policy) const {
- PolicyDetailsMapping::const_iterator it = map_.find(policy);
- return it == map_.end() ? NULL : it->second;
-}
-
-bool PolicyServiceIsEmpty(const PolicyService* service) {
- const PolicyMap& map = service->GetPolicies(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
- if (!map.empty()) {
- base::DictionaryValue dict;
- for (PolicyMap::const_iterator it = map.begin(); it != map.end(); ++it)
- dict.SetKey(it->first, it->second.value->Clone());
- LOG(WARNING) << "There are pre-existing policies in this machine: " << dict;
- }
- return map.empty();
-}
-
-#if defined(OS_IOS) || defined(OS_MACOSX)
-CFPropertyListRef ValueToProperty(const base::Value& value) {
- switch (value.type()) {
- case base::Value::Type::NONE:
- return kCFNull;
-
- case base::Value::Type::BOOLEAN: {
- bool bool_value;
- if (value.GetAsBoolean(&bool_value))
- return bool_value ? kCFBooleanTrue : kCFBooleanFalse;
- break;
- }
-
- case base::Value::Type::INTEGER: {
- int int_value;
- if (value.GetAsInteger(&int_value)) {
- return CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType,
- &int_value);
- }
- break;
- }
-
- case base::Value::Type::DOUBLE: {
- double double_value;
- if (value.GetAsDouble(&double_value)) {
- return CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType,
- &double_value);
- }
- break;
- }
-
- case base::Value::Type::STRING: {
- std::string string_value;
- if (value.GetAsString(&string_value))
- return base::SysUTF8ToCFStringRef(string_value);
- break;
- }
-
- case base::Value::Type::DICTIONARY: {
- const base::DictionaryValue* dict_value;
- if (value.GetAsDictionary(&dict_value)) {
- // |dict| is owned by the caller.
- CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
- kCFAllocatorDefault, dict_value->size(),
- &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- for (base::DictionaryValue::Iterator iterator(*dict_value);
- !iterator.IsAtEnd(); iterator.Advance()) {
- // CFDictionaryAddValue() retains both |key| and |value|, so make sure
- // the references are balanced.
- base::ScopedCFTypeRef<CFStringRef> key(
- base::SysUTF8ToCFStringRef(iterator.key()));
- base::ScopedCFTypeRef<CFPropertyListRef> cf_value(
- ValueToProperty(iterator.value()));
- if (cf_value)
- CFDictionaryAddValue(dict, key, cf_value);
- }
- return dict;
- }
- break;
- }
-
- case base::Value::Type::LIST: {
- const base::ListValue* list;
- if (value.GetAsList(&list)) {
- CFMutableArrayRef array =
- CFArrayCreateMutable(NULL, list->GetSize(), &kCFTypeArrayCallBacks);
- for (const auto& entry : *list) {
- // CFArrayAppendValue() retains |cf_value|, so make sure the reference
- // created by ValueToProperty() is released.
- base::ScopedCFTypeRef<CFPropertyListRef> cf_value(
- ValueToProperty(entry));
- if (cf_value)
- CFArrayAppendValue(array, cf_value);
- }
- return array;
- }
- break;
- }
-
- case base::Value::Type::BINARY:
- // This type isn't converted (though it can be represented as CFData)
- // because there's no equivalent JSON type, and policy values can only
- // take valid JSON values.
- break;
- }
-
- return NULL;
-}
-#endif // defined(OS_IOS) || defined(OS_MACOSX)
-
-} // namespace policy
-
-std::ostream& operator<<(std::ostream& os, const policy::PolicyBundle& bundle) {
- os << "{" << std::endl;
- for (policy::PolicyBundle::const_iterator iter = bundle.begin();
- iter != bundle.end(); ++iter) {
- os << " \"" << iter->first << "\": " << *iter->second << "," << std::endl;
- }
- os << "}";
- return os;
-}
-
-std::ostream& operator<<(std::ostream& os, policy::PolicyScope scope) {
- switch (scope) {
- case policy::POLICY_SCOPE_USER:
- return os << "POLICY_SCOPE_USER";
- case policy::POLICY_SCOPE_MACHINE:
- return os << "POLICY_SCOPE_MACHINE";
- }
- return os << "POLICY_SCOPE_UNKNOWN(" << int(scope) << ")";
-}
-
-std::ostream& operator<<(std::ostream& os, policy::PolicyLevel level) {
- switch (level) {
- case policy::POLICY_LEVEL_RECOMMENDED:
- return os << "POLICY_LEVEL_RECOMMENDED";
- case policy::POLICY_LEVEL_MANDATORY:
- return os << "POLICY_LEVEL_MANDATORY";
- }
- return os << "POLICY_LEVEL_UNKNOWN(" << int(level) << ")";
-}
-
-std::ostream& operator<<(std::ostream& os, policy::PolicyDomain domain) {
- switch (domain) {
- case policy::POLICY_DOMAIN_CHROME:
- return os << "POLICY_DOMAIN_CHROME";
- case policy::POLICY_DOMAIN_EXTENSIONS:
- return os << "POLICY_DOMAIN_EXTENSIONS";
- case policy::POLICY_DOMAIN_SIGNIN_EXTENSIONS:
- return os << "POLICY_DOMAIN_SIGNIN_EXTENSIONS";
- case policy::POLICY_DOMAIN_SIZE:
- break;
- }
- return os << "POLICY_DOMAIN_UNKNOWN(" << int(domain) << ")";
-}
-
-std::ostream& operator<<(std::ostream& os, const policy::PolicyMap& policies) {
- os << "{" << std::endl;
- for (const auto& iter : policies)
- os << " \"" << iter.first << "\": " << iter.second << "," << std::endl;
- os << "}";
- return os;
-}
-
-std::ostream& operator<<(std::ostream& os, const policy::PolicyMap::Entry& e) {
- return os << "{" << std::endl
- << " \"level\": " << e.level << "," << std::endl
- << " \"scope\": " << e.scope << "," << std::endl
- << " \"value\": " << *e.value << "}";
-}
-
-std::ostream& operator<<(std::ostream& os, const policy::PolicyNamespace& ns) {
- return os << ns.domain << "/" << ns.component_id;
-}
diff --git a/components/policy/core/common/policy_test_utils.h b/components/policy/core/common/policy_test_utils.h
deleted file mode 100644
index c76a7bb63a..0000000000
--- a/components/policy/core/common/policy_test_utils.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_TEST_UTILS_H_
-#define COMPONENTS_POLICY_CORE_COMMON_POLICY_TEST_UTILS_H_
-
-#include <map>
-#include <ostream>
-#include <string>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "components/policy/core/common/policy_details.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_service.h"
-#include "components/policy/core/common/policy_types.h"
-
-namespace policy {
-
-class PolicyBundle;
-struct PolicyNamespace;
-
-// A mapping of policy names to PolicyDetails that can be used to set the
-// PolicyDetails for test policies.
-class PolicyDetailsMap {
- public:
- PolicyDetailsMap();
- ~PolicyDetailsMap();
-
- // The returned callback's lifetime is tied to |this| object.
- GetChromePolicyDetailsCallback GetCallback() const;
-
- // Does not take ownership of |details|.
- void SetDetails(const std::string& policy, const PolicyDetails* details);
-
- private:
- typedef std::map<std::string, const PolicyDetails*> PolicyDetailsMapping;
-
- const PolicyDetails* Lookup(const std::string& policy) const;
-
- PolicyDetailsMapping map_;
-
- DISALLOW_COPY_AND_ASSIGN(PolicyDetailsMap);
-};
-
-// Returns true if |service| is not serving any policies. Otherwise logs the
-// current policies and returns false.
-bool PolicyServiceIsEmpty(const PolicyService* service);
-
-#if defined(OS_IOS) || defined(OS_MACOSX)
-
-// Converts a base::Value to the equivalent CFPropertyListRef.
-// The returned value is owned by the caller.
-CFPropertyListRef ValueToProperty(const base::Value& value);
-
-#endif
-
-} // namespace policy
-
-std::ostream& operator<<(std::ostream& os, const policy::PolicyBundle& bundle);
-std::ostream& operator<<(std::ostream& os, policy::PolicyScope scope);
-std::ostream& operator<<(std::ostream& os, policy::PolicyLevel level);
-std::ostream& operator<<(std::ostream& os, policy::PolicyDomain domain);
-std::ostream& operator<<(std::ostream& os, const policy::PolicyMap& policies);
-std::ostream& operator<<(std::ostream& os, const policy::PolicyMap::Entry& e);
-std::ostream& operator<<(std::ostream& os, const policy::PolicyNamespace& ns);
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_TEST_UTILS_H_
diff --git a/components/policy/core/common/preg_parser.cc b/components/policy/core/common/preg_parser.cc
deleted file mode 100644
index a4fada30e4..0000000000
--- a/components/policy/core/common/preg_parser.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright (c) 2013 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 "components/policy/core/common/preg_parser.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/sys_byteorder.h"
-#include "base/values.h"
-#include "components/policy/core/common/registry_dict.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#else
-// Registry data type constants.
-#define REG_NONE 0
-#define REG_SZ 1
-#define REG_EXPAND_SZ 2
-#define REG_BINARY 3
-#define REG_DWORD_LITTLE_ENDIAN 4
-#define REG_DWORD_BIG_ENDIAN 5
-#define REG_LINK 6
-#define REG_MULTI_SZ 7
-#define REG_RESOURCE_LIST 8
-#define REG_FULL_RESOURCE_DESCRIPTOR 9
-#define REG_RESOURCE_REQUIREMENTS_LIST 10
-#define REG_QWORD_LITTLE_ENDIAN 11
-#endif
-
-using RegistryDict = policy::RegistryDict;
-
-namespace {
-
-// Maximum PReg file size we're willing to accept.
-const int64_t kMaxPRegFileSize = 1024 * 1024 * 16;
-static_assert(kMaxPRegFileSize <= std::numeric_limits<ptrdiff_t>::max(),
- "Max PReg file size too large.");
-
-// Maximum number of components in registry key names. This corresponds to the
-// maximum nesting level of RegistryDict trees.
-const size_t kMaxKeyNameComponents = 1024;
-
-// Constants for PReg file delimiters.
-const base::char16 kDelimBracketOpen = L'[';
-const base::char16 kDelimBracketClose = L']';
-const base::char16 kDelimSemicolon = L';';
-
-// Registry path separator.
-const base::char16 kRegistryPathSeparator[] = {L'\\', L'\0'};
-
-// Magic strings for the PReg value field to trigger special actions.
-const char kActionTriggerPrefix[] = "**";
-const char kActionTriggerDeleteValues[] = "deletevalues";
-const char kActionTriggerDel[] = "del.";
-const char kActionTriggerDelVals[] = "delvals";
-const char kActionTriggerDeleteKeys[] = "deletekeys";
-const char kActionTriggerSecureKey[] = "securekey";
-const char kActionTriggerSoft[] = "soft";
-
-// Returns the character at |cursor| and increments it, unless the end is here
-// in which case -1 is returned. The calling code must guarantee that
-// end - *cursor does not overflow ptrdiff_t.
-int NextChar(const uint8_t** cursor, const uint8_t* end) {
- // Only read the character if a full base::char16 is available.
- // This comparison makes sure no overflow can happen.
- if (*cursor >= end ||
- end - *cursor < static_cast<ptrdiff_t>(sizeof(base::char16)))
- return -1;
-
- int result = **cursor | (*(*cursor + 1) << 8);
- *cursor += sizeof(base::char16);
- return result;
-}
-
-// Reads a fixed-size field from a PReg file. The calling code must guarantee
-// that both end - *cursor and size do not overflow ptrdiff_t.
-bool ReadFieldBinary(const uint8_t** cursor,
- const uint8_t* end,
- uint32_t size,
- uint8_t* data) {
- if (size == 0)
- return true;
-
- // Be careful to prevent possible overflows here (don't do *cursor + size).
- if (*cursor >= end || end - *cursor < static_cast<ptrdiff_t>(size))
- return false;
- const uint8_t* field_end = *cursor + size;
- std::copy(*cursor, field_end, data);
- *cursor = field_end;
- return true;
-}
-
-bool ReadField32(const uint8_t** cursor, const uint8_t* end, uint32_t* data) {
- uint32_t value = 0;
- if (!ReadFieldBinary(cursor, end, sizeof(uint32_t),
- reinterpret_cast<uint8_t*>(&value))) {
- return false;
- }
- *data = base::ByteSwapToLE32(value);
- return true;
-}
-
-// Reads a string field from a file.
-bool ReadFieldString(const uint8_t** cursor,
- const uint8_t* end,
- base::string16* str) {
- int current = -1;
- while ((current = NextChar(cursor, end)) > 0x0000)
- *str += current;
-
- return current == L'\0';
-}
-
-// Converts the UTF16 |data| to an UTF8 string |value|. Returns false if the
-// resulting UTF8 string contains invalid characters.
-bool DecodePRegStringValue(const std::vector<uint8_t>& data,
- std::string* value) {
- size_t len = data.size() / sizeof(base::char16);
- if (len <= 0) {
- value->clear();
- return true;
- }
-
- const base::char16* chars =
- reinterpret_cast<const base::char16*>(data.data());
- base::string16 utf16_str;
- std::transform(chars, chars + len - 1, std::back_inserter(utf16_str),
- base::ByteSwapToLE16);
- // Note: UTF16ToUTF8() only checks whether all chars are valid code points,
- // but not whether they're valid characters. IsStringUTF8(), however, does.
- *value = base::UTF16ToUTF8(utf16_str);
- if (!base::IsStringUTF8(*value)) {
- LOG(ERROR) << "String '" << *value << "' is not a valid UTF8 string";
- value->clear();
- return false;
- }
- return true;
-}
-
-// Decodes a value from a PReg file given as a uint8_t vector.
-bool DecodePRegValue(uint32_t type,
- const std::vector<uint8_t>& data,
- std::unique_ptr<base::Value>* value) {
- std::string data_utf8;
- switch (type) {
- case REG_SZ:
- case REG_EXPAND_SZ:
- if (!DecodePRegStringValue(data, &data_utf8))
- return false;
- value->reset(new base::Value(data_utf8));
- return true;
- case REG_DWORD_LITTLE_ENDIAN:
- case REG_DWORD_BIG_ENDIAN:
- if (data.size() == sizeof(uint32_t)) {
- uint32_t val = *reinterpret_cast<const uint32_t*>(data.data());
- if (type == REG_DWORD_BIG_ENDIAN)
- val = base::NetToHost32(val);
- else
- val = base::ByteSwapToLE32(val);
- value->reset(new base::Value(static_cast<int>(val)));
- return true;
- } else {
- LOG(ERROR) << "Bad data size " << data.size();
- }
- break;
- case REG_NONE:
- case REG_LINK:
- case REG_MULTI_SZ:
- case REG_RESOURCE_LIST:
- case REG_FULL_RESOURCE_DESCRIPTOR:
- case REG_RESOURCE_REQUIREMENTS_LIST:
- case REG_QWORD_LITTLE_ENDIAN:
- default:
- LOG(ERROR) << "Unsupported registry data type " << type;
- }
-
- return false;
-}
-
-// Returns true if the registry key |key_name| belongs to the sub-tree specified
-// by the key |root|.
-bool KeyRootEquals(const base::string16& key_name, const base::string16& root) {
- if (root.empty())
- return true;
-
- if (!base::StartsWith(key_name, root, base::CompareCase::INSENSITIVE_ASCII))
- return false;
-
- // Handle the case where |root| == "ABC" and |key_name| == "ABCDE\FG". This
- // should not be interpreted as a match.
- return key_name.length() == root.length() ||
- key_name.at(root.length()) == kRegistryPathSeparator[0];
-}
-
-// Adds |value| and |data| to |dict| or an appropriate sub-dictionary indicated
-// by |key_name|. Creates sub-dictionaries if necessary. Also handles special
-// action triggers, see |kActionTrigger*|, that can, for instance, remove an
-// existing value.
-void HandleRecord(const base::string16& key_name,
- const base::string16& value,
- uint32_t type,
- const std::vector<uint8_t>& data,
- RegistryDict* dict) {
- // Locate/create the dictionary to place the value in.
- std::vector<base::string16> path;
-
- std::vector<base::StringPiece16> key_name_components =
- base::SplitStringPiece(key_name, kRegistryPathSeparator,
- base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (key_name_components.size() > kMaxKeyNameComponents) {
- LOG(ERROR) << "Encountered a key which has more than "
- << kMaxKeyNameComponents << " components.";
- return;
- }
- for (const base::StringPiece16& key_name_component : key_name_components) {
- if (key_name_component.empty())
- continue;
-
- const std::string name = base::UTF16ToUTF8(key_name_component);
- RegistryDict* subdict = dict->GetKey(name);
- if (!subdict) {
- subdict = new RegistryDict();
- dict->SetKey(name, base::WrapUnique(subdict));
- }
- dict = subdict;
- }
-
- if (value.empty())
- return;
-
- std::string value_name(base::UTF16ToUTF8(value));
- if (!base::StartsWith(value_name, kActionTriggerPrefix,
- base::CompareCase::SENSITIVE)) {
- std::unique_ptr<base::Value> value;
- if (DecodePRegValue(type, data, &value))
- dict->SetValue(value_name, std::move(value));
- return;
- }
-
- std::string data_utf8;
- std::string action_trigger(base::ToLowerASCII(
- value_name.substr(arraysize(kActionTriggerPrefix) - 1)));
- if (action_trigger == kActionTriggerDeleteValues) {
- if (DecodePRegStringValue(data, &data_utf8)) {
- for (const std::string& value :
- base::SplitString(data_utf8, ";", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY))
- dict->RemoveValue(value);
- }
- } else if (base::StartsWith(action_trigger, kActionTriggerDeleteKeys,
- base::CompareCase::SENSITIVE)) {
- if (DecodePRegStringValue(data, &data_utf8)) {
- for (const std::string& key :
- base::SplitString(data_utf8, ";", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY))
- dict->RemoveKey(key);
- }
- } else if (base::StartsWith(action_trigger, kActionTriggerDel,
- base::CompareCase::SENSITIVE)) {
- dict->RemoveValue(value_name.substr(arraysize(kActionTriggerPrefix) - 1 +
- arraysize(kActionTriggerDel) - 1));
- } else if (base::StartsWith(action_trigger, kActionTriggerDelVals,
- base::CompareCase::SENSITIVE)) {
- // Delete all values.
- dict->ClearValues();
- } else if (base::StartsWith(action_trigger, kActionTriggerSecureKey,
- base::CompareCase::SENSITIVE) ||
- base::StartsWith(action_trigger, kActionTriggerSoft,
- base::CompareCase::SENSITIVE)) {
- // Doesn't affect values.
- } else {
- LOG(ERROR) << "Bad action trigger " << value_name;
- }
-}
-
-} // namespace
-
-namespace policy {
-namespace preg_parser {
-
-const char kPRegFileHeader[8] = {'P', 'R', 'e', 'g',
- '\x01', '\x00', '\x00', '\x00'};
-
-bool ReadFile(const base::FilePath& file_path,
- const base::string16& root,
- RegistryDict* dict,
- PolicyLoadStatusSampler* status) {
- base::MemoryMappedFile mapped_file;
- if (!mapped_file.Initialize(file_path) || !mapped_file.IsValid()) {
- PLOG(ERROR) << "Failed to map " << file_path.value();
- status->Add(POLICY_LOAD_STATUS_READ_ERROR);
- return false;
- }
-
- return ReadDataInternal(
- mapped_file.data(), mapped_file.length(), root, dict, status,
- base::StringPrintf("file '%" PRIsFP "'", file_path.value().c_str()));
-}
-
-POLICY_EXPORT bool ReadDataInternal(const uint8_t* preg_data,
- size_t preg_data_size,
- const base::string16& root,
- RegistryDict* dict,
- PolicyLoadStatusSampler* status,
- const std::string& debug_name) {
- DCHECK(status);
- DCHECK(root.empty() || root.back() != kRegistryPathSeparator[0]);
-
- // Check data size.
- if (preg_data_size > kMaxPRegFileSize) {
- LOG(ERROR) << "PReg " << debug_name << " too large: " << preg_data_size;
- status->Add(POLICY_LOAD_STATUS_TOO_BIG);
- return false;
- }
-
- // Check the header.
- const int kHeaderSize = arraysize(kPRegFileHeader);
- if (!preg_data || preg_data_size < kHeaderSize ||
- memcmp(kPRegFileHeader, preg_data, kHeaderSize) != 0) {
- LOG(ERROR) << "Bad PReg " << debug_name;
- status->Add(POLICY_LOAD_STATUS_PARSE_ERROR);
- return false;
- }
-
- // Parse data, which is expected to be UCS-2 and little-endian. The latter I
- // couldn't find documentation on, but the example I saw were all
- // little-endian. It'd be interesting to check on big-endian hardware.
- const uint8_t* cursor = preg_data + kHeaderSize;
- const uint8_t* end = preg_data + preg_data_size;
- while (true) {
- if (cursor == end)
- return true;
-
- if (NextChar(&cursor, end) != kDelimBracketOpen)
- break;
-
- // Read the record fields.
- base::string16 key_name;
- base::string16 value;
- uint32_t type = 0;
- uint32_t size = 0;
- std::vector<uint8_t> data;
-
- if (!ReadFieldString(&cursor, end, &key_name))
- break;
-
- int current = NextChar(&cursor, end);
- if (current == kDelimSemicolon) {
- if (!ReadFieldString(&cursor, end, &value))
- break;
- current = NextChar(&cursor, end);
- }
-
- if (current == kDelimSemicolon) {
- if (!ReadField32(&cursor, end, &type))
- break;
- current = NextChar(&cursor, end);
- }
-
- if (current == kDelimSemicolon) {
- if (!ReadField32(&cursor, end, &size))
- break;
- current = NextChar(&cursor, end);
- }
-
- if (current == kDelimSemicolon) {
- if (size > kMaxPRegFileSize)
- break;
- data.resize(size);
- if (!ReadFieldBinary(&cursor, end, size, data.data()))
- break;
- current = NextChar(&cursor, end);
- }
-
- if (current != kDelimBracketClose)
- break;
-
- // Process the record if it is within the |root| subtree.
- if (KeyRootEquals(key_name, root))
- HandleRecord(key_name.substr(root.size()), value, type, data, dict);
- }
-
- LOG(ERROR) << "Error parsing PReg " << debug_name << " at offset "
- << (reinterpret_cast<const uint8_t*>(cursor - 1) - preg_data);
- status->Add(POLICY_LOAD_STATUS_PARSE_ERROR);
- return false;
-}
-
-} // namespace preg_parser
-} // namespace policy
diff --git a/components/policy/core/common/preg_parser.h b/components/policy/core/common/preg_parser.h
deleted file mode 100644
index cf9bb37b15..0000000000
--- a/components/policy/core/common/preg_parser.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2013 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.
-
-// This file provides a parser for PReg files which are used for storing group
-// policy settings in the file system. The file format is documented here:
-//
-// http://msdn.microsoft.com/en-us/library/windows/desktop/aa374407(v=vs.85).aspx
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_PREG_PARSER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_PREG_PARSER_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "components/policy/core/common/policy_load_status.h"
-#include "components/policy/policy_export.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace policy {
-
-class RegistryDict;
-
-namespace preg_parser {
-
-// The magic header in PReg files: ASCII "PReg" + version (0x0001).
-POLICY_EXPORT extern const char kPRegFileHeader[8];
-
-// Reads the PReg file at |file_path| and writes the registry data to |dict|.
-// |root| specifies the registry subtree the caller is interested in, everything
-// else gets ignored. It may be empty if all keys should be returned, but it
-// must NOT end with a backslash.
-POLICY_EXPORT bool ReadFile(const base::FilePath& file_path,
- const base::string16& root,
- RegistryDict* dict,
- PolicyLoadStatusSampler* status);
-
-// Similar to ReadFile, but reads from |preg_data| of length |preg_data_size|
-// instead of a file. |debug_name| is printed out along with error messages.
-// Used internally and for testing only. All other callers should use ReadFile
-// instead.
-POLICY_EXPORT bool ReadDataInternal(const uint8_t* preg_data,
- size_t preg_data_size,
- const base::string16& root,
- RegistryDict* dict,
- PolicyLoadStatusSampler* status,
- const std::string& debug_name);
-
-} // namespace preg_parser
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_PREG_PARSER_H_
diff --git a/components/policy/core/common/preg_parser_fuzzer.cc b/components/policy/core/common/preg_parser_fuzzer.cc
deleted file mode 100644
index 003031f719..0000000000
--- a/components/policy/core/common/preg_parser_fuzzer.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2017 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 <stddef.h>
-#include <stdint.h>
-
-#include <base/strings/utf_string_conversions.h>
-#include "base/strings/string16.h"
-
-#include "components/policy/core/common/policy_load_status.h"
-#include "components/policy/core/common/preg_parser.h"
-#include "components/policy/core/common/registry_dict.h"
-
-namespace {
-
-const char kRegistryChromePolicyKey[] = "SOFTWARE\\Policies\\Chromium";
-
-} // namespace
-
-namespace policy {
-namespace preg_parser {
-
-// Disable logging.
-struct Environment {
- Environment() : root(base::ASCIIToUTF16(kRegistryChromePolicyKey)) {
- logging::SetMinLogLevel(logging::LOG_FATAL);
- }
-
- const base::string16 root;
-};
-
-Environment* env = new Environment();
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- // Note: Don't use PolicyLoadStatusUmaReporter here, it leaks!
- PolicyLoadStatusSampler status;
- RegistryDict dict;
- ReadDataInternal(data, size, env->root, &dict, &status, "data");
- return 0;
-}
-
-} // namespace preg_parser
-} // namespace policy
diff --git a/components/policy/core/common/preg_parser_unittest.cc b/components/policy/core/common/preg_parser_unittest.cc
deleted file mode 100644
index 43d84c2682..0000000000
--- a/components/policy/core/common/preg_parser_unittest.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2013 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 "components/policy/core/common/preg_parser.h"
-
-#include <utility>
-
-#include "base/base_paths.h"
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/json/json_writer.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/path_service.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "components/policy/core/common/policy_load_status.h"
-#include "components/policy/core/common/registry_dict.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-namespace preg_parser {
-namespace {
-
-// Preg files are relative to |kRegistryPolBaseDir|.
-const char kRegistryPolBaseDir[] = "chrome/test/data/policy/gpo";
-const char kRegistryPolFile[] = "parser_test/registry.pol";
-const char kInvalidEncodingRegistryPolFile[] = "invalid_encoding/registry.pol";
-const char kNonExistingRegistryPolFile[] = "does_not_exist.pol";
-
-const char kRegistryKey[] = "SOFTWARE\\Policies\\Chromium";
-
-// Check whether two RegistryDicts equal each other.
-testing::AssertionResult RegistryDictEquals(const RegistryDict& a,
- const RegistryDict& b) {
- auto iter_key_a = a.keys().begin();
- auto iter_key_b = b.keys().begin();
- for (; iter_key_a != a.keys().end() && iter_key_b != b.keys().end();
- ++iter_key_a, ++iter_key_b) {
- if (iter_key_a->first != iter_key_b->first) {
- return testing::AssertionFailure() << "Key mismatch " << iter_key_a->first
- << " vs. " << iter_key_b->first;
- }
- testing::AssertionResult result =
- RegistryDictEquals(*iter_key_a->second, *iter_key_b->second);
- if (!result)
- return result;
- }
- if (iter_key_a != a.keys().end())
- return testing::AssertionFailure()
- << "key mismatch, a has extra key " << iter_key_a->first;
- if (iter_key_b != b.keys().end())
- return testing::AssertionFailure()
- << "key mismatch, b has extra key " << iter_key_b->first;
-
- auto iter_value_a = a.values().begin();
- auto iter_value_b = b.values().begin();
- for (; iter_value_a != a.values().end() && iter_value_b != b.values().end();
- ++iter_value_a, ++iter_value_b) {
- if (iter_value_a->first != iter_value_b->first ||
- *iter_value_a->second != *iter_value_b->second) {
- return testing::AssertionFailure()
- << "Value mismatch " << iter_value_a->first << "="
- << *iter_value_a->second << " vs. " << iter_value_b->first << "="
- << *iter_value_b->second;
- }
- }
- if (iter_value_a != a.values().end())
- return testing::AssertionFailure()
- << "Value mismatch, a has extra value " << iter_value_a->first << "="
- << *iter_value_a->second;
- if (iter_value_b != b.values().end())
- return testing::AssertionFailure()
- << "Value mismatch, b has extra value " << iter_value_b->first << "="
- << *iter_value_b->second;
-
- return testing::AssertionSuccess();
-}
-
-void SetInteger(RegistryDict* dict, const std::string& name, int value) {
- dict->SetValue(name, base::WrapUnique<base::Value>(new base::Value(value)));
-}
-
-void SetString(RegistryDict* dict,
- const std::string& name,
- const std::string& value) {
- dict->SetValue(name, base::WrapUnique<base::Value>(new base::Value(value)));
-}
-
-class PRegParserTest : public testing::Test {
- protected:
- void SetUp() override {
- ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir_));
- test_data_dir_ = test_data_dir_.AppendASCII(kRegistryPolBaseDir);
- }
-
- base::FilePath test_data_dir_;
-};
-
-TEST_F(PRegParserTest, TestParseFile) {
- // Prepare the test dictionary with some data so the test can check that the
- // PReg action triggers work, i.e. remove these items.
- RegistryDict dict;
- SetInteger(&dict, "DeleteValuesTest1", 1);
- SetString(&dict, "DeleteValuesTest2", "2");
- dict.SetKey("DeleteKeysTest1", std::make_unique<RegistryDict>());
- std::unique_ptr<RegistryDict> delete_keys_test(new RegistryDict());
- SetInteger(delete_keys_test.get(), "DeleteKeysTest2Entry", 1);
- dict.SetKey("DeleteKeysTest2", std::move(delete_keys_test));
- SetInteger(&dict, "DelTest", 1);
- std::unique_ptr<RegistryDict> subdict(new RegistryDict());
- SetInteger(subdict.get(), "DelValsTest1", 1);
- SetString(subdict.get(), "DelValsTest2", "2");
- subdict->SetKey("DelValsTest3", std::make_unique<RegistryDict>());
- dict.SetKey("DelValsTest", std::move(subdict));
-
- // Run the parser.
- base::FilePath test_file(test_data_dir_.AppendASCII(kRegistryPolFile));
- PolicyLoadStatusUmaReporter status;
- ASSERT_TRUE(preg_parser::ReadFile(test_file, base::ASCIIToUTF16(kRegistryKey),
- &dict, &status));
-
- // Build the expected output dictionary.
- RegistryDict expected;
- std::unique_ptr<RegistryDict> del_vals_dict(new RegistryDict());
- del_vals_dict->SetKey("DelValsTest3", std::make_unique<RegistryDict>());
- expected.SetKey("DelValsTest", std::move(del_vals_dict));
- SetInteger(&expected, "HomepageIsNewTabPage", 1);
- SetString(&expected, "HomepageLocation", "http://www.example.com");
- SetInteger(&expected, "RestoreOnStartup", 4);
- std::unique_ptr<RegistryDict> startup_urls(new RegistryDict());
- SetString(startup_urls.get(), "1", "http://www.chromium.org");
- SetString(startup_urls.get(), "2", "http://www.example.com");
- expected.SetKey("RestoreOnStartupURLs", std::move(startup_urls));
- SetInteger(&expected, "ShowHomeButton", 1);
- SetString(&expected, "Snowman", "\xE2\x98\x83");
- SetString(&expected, "Empty", "");
-
- EXPECT_TRUE(RegistryDictEquals(dict, expected));
-}
-
-TEST_F(PRegParserTest, SubstringRootInvalid) {
- // A root of "Aa/Bb/Cc" should not be considered a valid root for a
- // key like "Aa/Bb/C".
- base::FilePath test_file(test_data_dir_.AppendASCII(kRegistryPolFile));
- RegistryDict empty;
- PolicyLoadStatusUmaReporter status;
-
- // No data should be loaded for partial roots ("Aa/Bb/C").
- RegistryDict dict1;
- ASSERT_TRUE(preg_parser::ReadFile(
- test_file, base::ASCIIToUTF16("SOFTWARE\\Policies\\Chro"), &dict1,
- &status));
- EXPECT_TRUE(RegistryDictEquals(dict1, empty));
-
- // Safety check with kRegistryKey (dict should not be empty).
- RegistryDict dict2;
- ASSERT_TRUE(preg_parser::ReadFile(test_file, base::ASCIIToUTF16(kRegistryKey),
- &dict2, &status));
- EXPECT_FALSE(RegistryDictEquals(dict2, empty));
-}
-
-TEST_F(PRegParserTest, RejectInvalidStrings) {
- // Tests whether strings with invalid characters are rejected.
- base::FilePath test_file(
- test_data_dir_.AppendASCII(kInvalidEncodingRegistryPolFile));
- PolicyLoadStatusUmaReporter status;
- RegistryDict dict;
- ASSERT_TRUE(preg_parser::ReadFile(test_file, base::ASCIIToUTF16(kRegistryKey),
- &dict, &status));
-
- RegistryDict empty;
- EXPECT_TRUE(RegistryDictEquals(dict, empty));
-}
-
-TEST_F(PRegParserTest, LoadStatusSampling) {
- // Tests load status sampling.
- PolicyLoadStatusUmaReporter status;
- RegistryDict dict;
- base::FilePath test_file(
- test_data_dir_.AppendASCII(kNonExistingRegistryPolFile));
- ASSERT_FALSE(preg_parser::ReadFile(
- test_file, base::ASCIIToUTF16(kRegistryKey), &dict, &status));
-
- PolicyLoadStatusSampler::StatusSet expected_status_set;
- expected_status_set[POLICY_LOAD_STATUS_STARTED] = true;
- expected_status_set[POLICY_LOAD_STATUS_READ_ERROR] = true;
- EXPECT_EQ(expected_status_set, status.GetStatusSet());
-}
-
-} // namespace
-} // namespace preg_parser
-} // namespace policy
diff --git a/components/policy/core/common/proxy_policy_provider.cc b/components/policy/core/common/proxy_policy_provider.cc
deleted file mode 100644
index a1af2c2bbd..0000000000
--- a/components/policy/core/common/proxy_policy_provider.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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 "components/policy/core/common/proxy_policy_provider.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/logging.h"
-#include "components/policy/core/common/policy_bundle.h"
-
-namespace policy {
-
-ProxyPolicyProvider::ProxyPolicyProvider() : delegate_(NULL) {}
-
-ProxyPolicyProvider::~ProxyPolicyProvider() {
- DCHECK(!delegate_);
-}
-
-void ProxyPolicyProvider::SetDelegate(ConfigurationPolicyProvider* delegate) {
- if (delegate_)
- delegate_->RemoveObserver(this);
- delegate_ = delegate;
- if (delegate_) {
- delegate_->AddObserver(this);
- OnUpdatePolicy(delegate_);
- } else {
- UpdatePolicy(std::unique_ptr<PolicyBundle>(new PolicyBundle()));
- }
-}
-
-void ProxyPolicyProvider::Shutdown() {
- // Note: the delegate is not owned by the proxy provider, so this call is not
- // forwarded. The same applies for the Init() call.
- // Just drop the delegate without propagating updates here.
- if (delegate_) {
- delegate_->RemoveObserver(this);
- delegate_ = NULL;
- }
- ConfigurationPolicyProvider::Shutdown();
-}
-
-void ProxyPolicyProvider::RefreshPolicies() {
- if (delegate_) {
- delegate_->RefreshPolicies();
- } else {
- // Subtle: if a RefreshPolicies() call comes after Shutdown() then the
- // current bundle should be served instead. This also does the right thing
- // if SetDelegate() was never called before.
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
- bundle->CopyFrom(policies());
- UpdatePolicy(std::move(bundle));
- }
-}
-
-void ProxyPolicyProvider::OnUpdatePolicy(
- ConfigurationPolicyProvider* provider) {
- DCHECK_EQ(delegate_, provider);
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
- bundle->CopyFrom(delegate_->policies());
- UpdatePolicy(std::move(bundle));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/proxy_policy_provider.h b/components/policy/core/common/proxy_policy_provider.h
deleted file mode 100644
index 2585d145cc..0000000000
--- a/components/policy/core/common/proxy_policy_provider.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_PROXY_POLICY_PROVIDER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_PROXY_POLICY_PROVIDER_H_
-
-#include "base/macros.h"
-#include "components/policy/core/common/configuration_policy_provider.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// A policy provider implementation that acts as a proxy for another policy
-// provider, swappable at any point.
-//
-// Note that ProxyPolicyProvider correctly forwards RefreshPolicies() calls to
-// the delegate if present. If there is no delegate, the refresh results in an
-// immediate (empty) policy update.
-//
-// Furthermore, IsInitializationComplete() is implemented trivially - it always
-// returns true. Given that the delegate may be swapped at any point, there's no
-// point in trying to carry over initialization status from the delegate.
-//
-// This policy provider implementation is used to inject browser-global policy
-// originating from the user policy configured on the primary Chrome OS user
-// (i.e. the user logging in from the login screen). This way, policy settings
-// on the primary user propagate into g_browser_process->local_state_().
-//
-// The bizarre situation of user-scoped policy settings which are implemented
-// browser-global wouldn't exist in an ideal world. However, for historic
-// and technical reasons there are policy settings that are scoped to the user
-// but are implemented to take effect for the entire browser instance. A good
-// example for this are policies that affect the Chrome network stack in areas
-// where there's no profile-specific context. The meta data in
-// policy_templates.json allows to identify the policies in this bucket; they'll
-// have per_profile set to False, supported_on including chrome_os, and
-// dynamic_refresh set to True.
-class POLICY_EXPORT ProxyPolicyProvider
- : public ConfigurationPolicyProvider,
- public ConfigurationPolicyProvider::Observer {
- public:
- ProxyPolicyProvider();
- ~ProxyPolicyProvider() override;
-
- // Updates the provider this proxy delegates to.
- void SetDelegate(ConfigurationPolicyProvider* delegate);
-
- // ConfigurationPolicyProvider:
- void Shutdown() override;
- void RefreshPolicies() override;
-
- // ConfigurationPolicyProvider::Observer:
- void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override;
-
- private:
- ConfigurationPolicyProvider* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(ProxyPolicyProvider);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_PROXY_POLICY_PROVIDER_H_
diff --git a/components/policy/core/common/proxy_policy_provider_unittest.cc b/components/policy/core/common/proxy_policy_provider_unittest.cc
deleted file mode 100644
index fcd9317c77..0000000000
--- a/components/policy/core/common/proxy_policy_provider_unittest.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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 "components/policy/core/common/proxy_policy_provider.h"
-#include <memory>
-#include "base/callback.h"
-#include "base/macros.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/mock_configuration_policy_provider.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/core/common/schema_registry.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::Mock;
-
-namespace policy {
-
-class ProxyPolicyProviderTest : public testing::Test {
- protected:
- ProxyPolicyProviderTest() {
- mock_provider_.Init();
- proxy_provider_.Init(&schema_registry_);
- proxy_provider_.AddObserver(&observer_);
- }
-
- ~ProxyPolicyProviderTest() override {
- proxy_provider_.RemoveObserver(&observer_);
- proxy_provider_.Shutdown();
- mock_provider_.Shutdown();
- }
-
- SchemaRegistry schema_registry_;
- MockConfigurationPolicyObserver observer_;
- MockConfigurationPolicyProvider mock_provider_;
- ProxyPolicyProvider proxy_provider_;
-
- static std::unique_ptr<PolicyBundle> CopyBundle(const PolicyBundle& bundle) {
- std::unique_ptr<PolicyBundle> copy(new PolicyBundle());
- copy->CopyFrom(bundle);
- return copy;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ProxyPolicyProviderTest);
-};
-
-TEST_F(ProxyPolicyProviderTest, Init) {
- EXPECT_TRUE(proxy_provider_.IsInitializationComplete(POLICY_DOMAIN_CHROME));
- EXPECT_TRUE(PolicyBundle().Equals(proxy_provider_.policies()));
-}
-
-TEST_F(ProxyPolicyProviderTest, Delegate) {
- PolicyBundle bundle;
- bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value"),
- nullptr);
- mock_provider_.UpdatePolicy(CopyBundle(bundle));
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&proxy_provider_));
- proxy_provider_.SetDelegate(&mock_provider_);
- Mock::VerifyAndClearExpectations(&observer_);
- EXPECT_TRUE(bundle.Equals(proxy_provider_.policies()));
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&proxy_provider_));
- bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("new value"),
- nullptr);
- mock_provider_.UpdatePolicy(CopyBundle(bundle));
- Mock::VerifyAndClearExpectations(&observer_);
- EXPECT_TRUE(bundle.Equals(proxy_provider_.policies()));
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&proxy_provider_));
- proxy_provider_.SetDelegate(NULL);
- EXPECT_TRUE(PolicyBundle().Equals(proxy_provider_.policies()));
-}
-
-TEST_F(ProxyPolicyProviderTest, RefreshPolicies) {
- EXPECT_CALL(observer_, OnUpdatePolicy(&proxy_provider_));
- proxy_provider_.RefreshPolicies();
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&proxy_provider_));
- proxy_provider_.SetDelegate(&mock_provider_);
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&proxy_provider_)).Times(0);
- EXPECT_CALL(mock_provider_, RefreshPolicies());
- proxy_provider_.RefreshPolicies();
- Mock::VerifyAndClearExpectations(&observer_);
- Mock::VerifyAndClearExpectations(&mock_provider_);
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&proxy_provider_));
- mock_provider_.UpdatePolicy(
- std::unique_ptr<PolicyBundle>(new PolicyBundle()));
- Mock::VerifyAndClearExpectations(&observer_);
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/schema_map.cc b/components/policy/core/common/schema_map.cc
deleted file mode 100644
index 0779cd3dc2..0000000000
--- a/components/policy/core/common/schema_map.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/schema_map.h"
-
-#include "base/logging.h"
-#include "base/values.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_map.h"
-
-namespace policy {
-
-SchemaMap::SchemaMap() {}
-
-SchemaMap::SchemaMap(DomainMap& map) {
- map_.swap(map);
-}
-
-SchemaMap::~SchemaMap() {}
-
-const DomainMap& SchemaMap::GetDomains() const {
- return map_;
-}
-
-const ComponentMap* SchemaMap::GetComponents(PolicyDomain domain) const {
- const auto it = map_.find(domain);
- return it == map_.end() ? nullptr : &it->second;
-}
-
-const Schema* SchemaMap::GetSchema(const PolicyNamespace& ns) const {
- const ComponentMap* map = GetComponents(ns.domain);
- if (!map)
- return nullptr;
- const auto it = map->find(ns.component_id);
- return it == map->end() ? nullptr : &it->second;
-}
-
-void SchemaMap::FilterBundle(PolicyBundle* bundle) const {
- for (const auto& bundle_item : *bundle) {
- const PolicyNamespace& ns = bundle_item.first;
- const std::unique_ptr<PolicyMap>& policy_map = bundle_item.second;
-
- // Chrome policies are not filtered, so that typos appear in about:policy.
- // Everything else gets filtered, so that components only see valid policy.
- if (ns.domain == POLICY_DOMAIN_CHROME)
- continue;
-
- const Schema* schema = GetSchema(ns);
-
- if (!schema) {
- policy_map->Clear();
- continue;
- }
-
- if (!schema->valid()) {
- // Don't serve unknown policies.
- policy_map->Clear();
- continue;
- }
-
- for (auto it_map = policy_map->begin(); it_map != policy_map->end();) {
- const std::string& policy_name = it_map->first;
- const base::Value* policy_value = it_map->second.value.get();
- Schema policy_schema = schema->GetProperty(policy_name);
- ++it_map;
- std::string error_path;
- std::string error;
- if (!policy_value ||
- !policy_schema.Validate(*policy_value,
- SCHEMA_STRICT,
- &error_path,
- &error)) {
- LOG(ERROR) << "Dropping policy " << policy_name << " of component "
- << ns.component_id << " due to error at "
- << (error_path.empty() ? "root" : error_path) << ": "
- << error;
- policy_map->Erase(policy_name);
- }
- }
- }
-}
-
-bool SchemaMap::HasComponents() const {
- for (const auto& item : map_) {
- const PolicyDomain& domain = item.first;
- const ComponentMap& component_map = item.second;
- if (domain == POLICY_DOMAIN_CHROME)
- continue;
- if (!component_map.empty())
- return true;
- }
- return false;
-}
-
-void SchemaMap::GetChanges(const scoped_refptr<SchemaMap>& older,
- PolicyNamespaceList* removed,
- PolicyNamespaceList* added) const {
- GetNamespacesNotInOther(older.get(), added);
- older->GetNamespacesNotInOther(this, removed);
-}
-
-void SchemaMap::GetNamespacesNotInOther(const SchemaMap* other,
- PolicyNamespaceList* list) const {
- list->clear();
- for (const auto& item : map_) {
- const PolicyDomain& domain = item.first;
- const ComponentMap& component_map = item.second;
- for (const auto& comp : component_map) {
- const std::string& component_id = comp.first;
- const PolicyNamespace ns(domain, component_id);
- if (!other->GetSchema(ns))
- list->push_back(ns);
- }
- }
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/schema_map.h b/components/policy/core/common/schema_map.h
deleted file mode 100644
index 835941e853..0000000000
--- a/components/policy/core/common/schema_map.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_SCHEMA_MAP_H_
-#define COMPONENTS_POLICY_CORE_COMMON_SCHEMA_MAP_H_
-
-#include <map>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/core/common/schema.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-class PolicyBundle;
-
-// Maps component id (e.g. extension id) to schema.
-typedef std::map<std::string, Schema> ComponentMap;
-typedef std::map<PolicyDomain, ComponentMap> DomainMap;
-
-// Contains a mapping of policy namespaces (domain + component ID) to its
-// corresponding Schema.
-// This class is thread-safe.
-class POLICY_EXPORT SchemaMap : public base::RefCountedThreadSafe<SchemaMap> {
- public:
- SchemaMap();
- // Takes ownership of |map| (its contents will be swapped).
- // TODO(emaxx): Change to use move semantics.
- explicit SchemaMap(DomainMap& map);
-
- const DomainMap& GetDomains() const;
-
- const ComponentMap* GetComponents(PolicyDomain domain) const;
-
- const Schema* GetSchema(const PolicyNamespace& ns) const;
-
- // Removes all the policies in |bundle| that don't match the known schemas.
- // Unknown components are also dropped.
- void FilterBundle(PolicyBundle* bundle) const;
-
- // Returns true if this map contains at least one component of a domain other
- // than POLICY_DOMAIN_CHROME.
- bool HasComponents() const;
-
- void GetChanges(const scoped_refptr<SchemaMap>& older,
- PolicyNamespaceList* removed,
- PolicyNamespaceList* added) const;
-
- private:
- friend class base::RefCountedThreadSafe<SchemaMap>;
-
- void GetNamespacesNotInOther(const SchemaMap* other,
- PolicyNamespaceList* list) const;
-
- ~SchemaMap();
-
- DomainMap map_;
-
- DISALLOW_COPY_AND_ASSIGN(SchemaMap);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_SCHEMA_MAP_H_
diff --git a/components/policy/core/common/schema_map_unittest.cc b/components/policy/core/common/schema_map_unittest.cc
deleted file mode 100644
index 96916e5cc1..0000000000
--- a/components/policy/core/common/schema_map_unittest.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/schema_map.h"
-#include <memory>
-
-#include "base/memory/weak_ptr.h"
-#include "base/values.h"
-#include "components/policy/core/common/external_data_fetcher.h"
-#include "components/policy/core/common/external_data_manager.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/core/common/schema.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-const char kTestSchema[] =
- "{"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"string\": { \"type\": \"string\" },"
- " \"integer\": { \"type\": \"integer\" },"
- " \"boolean\": { \"type\": \"boolean\" },"
- " \"null\": { \"type\": \"null\" },"
- " \"double\": { \"type\": \"number\" },"
- " \"list\": {"
- " \"type\": \"array\","
- " \"items\": { \"type\": \"string\" }"
- " },"
- " \"object\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"a\": { \"type\": \"string\" },"
- " \"b\": { \"type\": \"integer\" }"
- " }"
- " }"
- " }"
- "}";
-
-} // namespace
-
-class SchemaMapTest : public testing::Test {
- protected:
- Schema CreateTestSchema() {
- std::string error;
- Schema schema = Schema::Parse(kTestSchema, &error);
- if (!schema.valid())
- ADD_FAILURE() << error;
- return schema;
- }
-
- scoped_refptr<SchemaMap> CreateTestMap() {
- Schema schema = CreateTestSchema();
- ComponentMap component_map;
- component_map["extension-1"] = schema;
- component_map["extension-2"] = schema;
- component_map["legacy-extension"] = Schema();
-
- DomainMap domain_map;
- domain_map[POLICY_DOMAIN_EXTENSIONS] = component_map;
-
- return new SchemaMap(domain_map);
- }
-};
-
-TEST_F(SchemaMapTest, Empty) {
- scoped_refptr<SchemaMap> map = new SchemaMap();
- EXPECT_TRUE(map->GetDomains().empty());
- EXPECT_FALSE(map->GetComponents(POLICY_DOMAIN_CHROME));
- EXPECT_FALSE(map->GetComponents(POLICY_DOMAIN_EXTENSIONS));
- EXPECT_FALSE(map->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, "")));
- EXPECT_FALSE(map->HasComponents());
-}
-
-TEST_F(SchemaMapTest, HasComponents) {
- scoped_refptr<SchemaMap> map = new SchemaMap();
- EXPECT_FALSE(map->HasComponents());
-
- // The Chrome schema does not count as a component.
- Schema schema = CreateTestSchema();
- ComponentMap component_map;
- component_map[""] = schema;
- DomainMap domain_map;
- domain_map[POLICY_DOMAIN_CHROME] = component_map;
- map = new SchemaMap(domain_map);
- EXPECT_FALSE(map->HasComponents());
-
- // An extension schema does.
- domain_map[POLICY_DOMAIN_EXTENSIONS] = component_map;
- map = new SchemaMap(domain_map);
- EXPECT_TRUE(map->HasComponents());
-}
-
-TEST_F(SchemaMapTest, Lookups) {
- scoped_refptr<SchemaMap> map = CreateTestMap();
- ASSERT_TRUE(map.get());
- EXPECT_TRUE(map->HasComponents());
-
- EXPECT_FALSE(map->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_CHROME, "")));
- EXPECT_FALSE(map->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_CHROME, "extension-1")));
- EXPECT_FALSE(map->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_CHROME, "legacy-extension")));
- EXPECT_FALSE(map->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "")));
- EXPECT_FALSE(map->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "extension-3")));
-
- const Schema* schema =
- map->GetSchema(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "extension-1"));
- ASSERT_TRUE(schema);
- EXPECT_TRUE(schema->valid());
-
- schema = map->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "legacy-extension"));
- ASSERT_TRUE(schema);
- EXPECT_FALSE(schema->valid());
-}
-
-TEST_F(SchemaMapTest, FilterBundle) {
- std::string error;
- Schema schema = Schema::Parse(kTestSchema, &error);
- ASSERT_TRUE(schema.valid()) << error;
-
- DomainMap domain_map;
- domain_map[POLICY_DOMAIN_EXTENSIONS]["abc"] = schema;
- scoped_refptr<SchemaMap> schema_map = new SchemaMap(domain_map);
-
- PolicyBundle bundle;
- schema_map->FilterBundle(&bundle);
- const PolicyBundle empty_bundle;
- EXPECT_TRUE(bundle.Equals(empty_bundle));
-
- // The Chrome namespace isn't filtered.
- PolicyBundle expected_bundle;
- PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
- expected_bundle.Get(chrome_ns).Set(
- "ChromePolicy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value"), nullptr);
- bundle.CopyFrom(expected_bundle);
-
- // Unknown components are filtered out.
- PolicyNamespace another_extension_ns(POLICY_DOMAIN_EXTENSIONS, "xyz");
- bundle.Get(another_extension_ns)
- .Set("AnotherExtensionPolicy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value"),
- nullptr);
- schema_map->FilterBundle(&bundle);
- EXPECT_TRUE(bundle.Equals(expected_bundle));
-
- PolicyNamespace extension_ns(POLICY_DOMAIN_EXTENSIONS, "abc");
- PolicyMap& map = expected_bundle.Get(extension_ns);
- base::ListValue list;
- list.AppendString("a");
- list.AppendString("b");
- map.Set("list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, list.CreateDeepCopy(), nullptr);
- map.Set("boolean", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
- map.Set("integer", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
- map.Set("null", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(), nullptr);
- map.Set("double", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1.2), nullptr);
- base::DictionaryValue dict;
- dict.SetString("a", "b");
- dict.SetInteger("b", 2);
- map.Set("object", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, dict.CreateDeepCopy(), nullptr);
- map.Set("string", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value"), nullptr);
-
- bundle.MergeFrom(expected_bundle);
- bundle.Get(extension_ns)
- .Set("Unexpected", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("to-be-removed"),
- nullptr);
-
- schema_map->FilterBundle(&bundle);
- EXPECT_TRUE(bundle.Equals(expected_bundle));
-
- // Mismatched types are also removed.
- bundle.Clear();
- PolicyMap& badmap = bundle.Get(extension_ns);
- badmap.Set("list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
- nullptr);
- badmap.Set("boolean", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
- badmap.Set("integer", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
- nullptr);
- badmap.Set("null", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
- nullptr);
- badmap.Set("double", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
- nullptr);
- badmap.Set("object", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(false),
- nullptr);
- badmap.Set("string", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, nullptr,
- std::make_unique<ExternalDataFetcher>(nullptr, std::string()));
-
- schema_map->FilterBundle(&bundle);
- EXPECT_TRUE(bundle.Equals(empty_bundle));
-}
-
-TEST_F(SchemaMapTest, LegacyComponents) {
- std::string error;
- Schema schema = Schema::Parse(
- "{"
- " \"type\":\"object\","
- " \"properties\": {"
- " \"String\": { \"type\": \"string\" }"
- " }"
- "}", &error);
- ASSERT_TRUE(schema.valid()) << error;
-
- DomainMap domain_map;
- domain_map[POLICY_DOMAIN_EXTENSIONS]["with-schema"] = schema;
- domain_map[POLICY_DOMAIN_EXTENSIONS]["without-schema"] = Schema();
- scoped_refptr<SchemaMap> schema_map = new SchemaMap(domain_map);
-
- // |bundle| contains policies loaded by a policy provider.
- PolicyBundle bundle;
-
- // Known components with schemas are filtered.
- PolicyNamespace extension_ns(POLICY_DOMAIN_EXTENSIONS, "with-schema");
- bundle.Get(extension_ns)
- .Set("String", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value 1"),
- nullptr);
-
- // The Chrome namespace isn't filtered.
- PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
- bundle.Get(chrome_ns).Set("ChromePolicy", POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>("value 3"), nullptr);
-
- PolicyBundle expected_bundle;
- expected_bundle.MergeFrom(bundle);
-
- // Known components without a schema are filtered out completely.
- PolicyNamespace without_schema_ns(POLICY_DOMAIN_EXTENSIONS, "without-schema");
- bundle.Get(without_schema_ns)
- .Set("Schemaless", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value 2"),
- nullptr);
-
- // Unknown policies of known components with a schema are removed.
- bundle.Get(extension_ns)
- .Set("Surprise", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value 4"),
- nullptr);
-
- // Unknown components are removed.
- PolicyNamespace unknown_ns(POLICY_DOMAIN_EXTENSIONS, "unknown");
- bundle.Get(unknown_ns)
- .Set("Surprise", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("value 5"),
- nullptr);
-
- schema_map->FilterBundle(&bundle);
- EXPECT_TRUE(bundle.Equals(expected_bundle));
-}
-
-TEST_F(SchemaMapTest, GetChanges) {
- DomainMap map;
- map[POLICY_DOMAIN_CHROME][""] = Schema();
- scoped_refptr<SchemaMap> older = new SchemaMap(map);
- map[POLICY_DOMAIN_CHROME][""] = Schema();
- scoped_refptr<SchemaMap> newer = new SchemaMap(map);
-
- PolicyNamespaceList removed;
- PolicyNamespaceList added;
- newer->GetChanges(older, &removed, &added);
- EXPECT_TRUE(removed.empty());
- EXPECT_TRUE(added.empty());
-
- map[POLICY_DOMAIN_CHROME][""] = Schema();
- map[POLICY_DOMAIN_EXTENSIONS]["xyz"] = Schema();
- newer = new SchemaMap(map);
- newer->GetChanges(older, &removed, &added);
- EXPECT_TRUE(removed.empty());
- ASSERT_EQ(1u, added.size());
- EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), added[0]);
-
- older = newer;
- map[POLICY_DOMAIN_EXTENSIONS]["abc"] = Schema();
- newer = new SchemaMap(map);
- newer->GetChanges(older, &removed, &added);
- ASSERT_EQ(2u, removed.size());
- EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_CHROME, ""), removed[0]);
- EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), removed[1]);
- ASSERT_EQ(1u, added.size());
- EXPECT_EQ(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"), added[0]);
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/schema_registry.cc b/components/policy/core/common/schema_registry.cc
deleted file mode 100644
index e44f3d7751..0000000000
--- a/components/policy/core/common/schema_registry.cc
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/schema_registry.h"
-
-#include "base/logging.h"
-#include "extensions/buildflags/buildflags.h"
-
-namespace policy {
-
-SchemaRegistry::Observer::~Observer() {}
-
-SchemaRegistry::InternalObserver::~InternalObserver() {}
-
-SchemaRegistry::SchemaRegistry() : schema_map_(new SchemaMap) {
- for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i)
- domains_ready_[i] = false;
-#if !BUILDFLAG(ENABLE_EXTENSIONS)
- SetExtensionsDomainsReady();
-#endif
-}
-
-SchemaRegistry::~SchemaRegistry() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- for (auto& observer : internal_observers_)
- observer.OnSchemaRegistryShuttingDown(this);
-}
-
-void SchemaRegistry::RegisterComponent(const PolicyNamespace& ns,
- const Schema& schema) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- ComponentMap map;
- map[ns.component_id] = schema;
- RegisterComponents(ns.domain, map);
-}
-
-void SchemaRegistry::RegisterComponents(PolicyDomain domain,
- const ComponentMap& components) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Don't issue notifications if nothing is being registered.
- if (components.empty())
- return;
- // Assume that a schema was updated if the namespace was already registered
- // before.
- DomainMap map(schema_map_->GetDomains());
- for (ComponentMap::const_iterator it = components.begin();
- it != components.end(); ++it) {
- map[domain][it->first] = it->second;
- }
- schema_map_ = new SchemaMap(map);
- Notify(true);
-}
-
-void SchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DomainMap map(schema_map_->GetDomains());
- if (map[ns.domain].erase(ns.component_id) != 0) {
- schema_map_ = new SchemaMap(map);
- Notify(false);
- } else {
- NOTREACHED();
- }
-}
-
-bool SchemaRegistry::IsReady() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i) {
- if (!domains_ready_[i])
- return false;
- }
- return true;
-}
-
-void SchemaRegistry::SetDomainReady(PolicyDomain domain) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (domains_ready_[domain])
- return;
- domains_ready_[domain] = true;
- if (IsReady()) {
- for (auto& observer : observers_)
- observer.OnSchemaRegistryReady();
- }
-}
-
-void SchemaRegistry::SetAllDomainsReady() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- for (int i = 0; i < POLICY_DOMAIN_SIZE; ++i)
- SetDomainReady(static_cast<PolicyDomain>(i));
-}
-
-void SchemaRegistry::SetExtensionsDomainsReady() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- SetDomainReady(POLICY_DOMAIN_EXTENSIONS);
- SetDomainReady(POLICY_DOMAIN_SIGNIN_EXTENSIONS);
-}
-
-void SchemaRegistry::AddObserver(Observer* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- observers_.AddObserver(observer);
-}
-
-void SchemaRegistry::RemoveObserver(Observer* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- observers_.RemoveObserver(observer);
-}
-
-void SchemaRegistry::AddInternalObserver(InternalObserver* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- internal_observers_.AddObserver(observer);
-}
-
-void SchemaRegistry::RemoveInternalObserver(InternalObserver* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- internal_observers_.RemoveObserver(observer);
-}
-
-void SchemaRegistry::Notify(bool has_new_schemas) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- for (auto& observer : observers_)
- observer.OnSchemaRegistryUpdated(has_new_schemas);
-}
-
-CombinedSchemaRegistry::CombinedSchemaRegistry()
- : own_schema_map_(new SchemaMap) {
- // The combined registry is always ready, since it can always start tracking
- // another registry that is not ready yet and going from "ready" to "not
- // ready" is not allowed.
- SetAllDomainsReady();
-}
-
-CombinedSchemaRegistry::~CombinedSchemaRegistry() {}
-
-void CombinedSchemaRegistry::Track(SchemaRegistry* registry) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- registries_.insert(registry);
- registry->AddObserver(this);
- registry->AddInternalObserver(this);
- // Recombine the maps only if the |registry| has any components other than
- // POLICY_DOMAIN_CHROME.
- if (registry->schema_map()->HasComponents())
- Combine(true);
-}
-
-void CombinedSchemaRegistry::RegisterComponents(
- PolicyDomain domain,
- const ComponentMap& components) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DomainMap map(own_schema_map_->GetDomains());
- for (ComponentMap::const_iterator it = components.begin();
- it != components.end(); ++it) {
- map[domain][it->first] = it->second;
- }
- own_schema_map_ = new SchemaMap(map);
- Combine(true);
-}
-
-void CombinedSchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DomainMap map(own_schema_map_->GetDomains());
- if (map[ns.domain].erase(ns.component_id) != 0) {
- own_schema_map_ = new SchemaMap(map);
- Combine(false);
- } else {
- NOTREACHED();
- }
-}
-
-void CombinedSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- Combine(has_new_schemas);
-}
-
-void CombinedSchemaRegistry::OnSchemaRegistryShuttingDown(
- SchemaRegistry* registry) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- registry->RemoveObserver(this);
- registry->RemoveInternalObserver(this);
- if (registries_.erase(registry) != 0) {
- if (registry->schema_map()->HasComponents())
- Combine(false);
- } else {
- NOTREACHED();
- }
-}
-
-void CombinedSchemaRegistry::Combine(bool has_new_schemas) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // If two registries publish a Schema for the same component then it's
- // undefined which version gets in the combined registry.
- //
- // The common case is that both registries want policy for the same component,
- // and the Schemas should be the same; in that case this makes no difference.
- //
- // But if the Schemas are different then one of the components is out of date.
- // In that case the policy loaded will be valid only for one of them, until
- // the outdated components are updated. This is a known limitation of the
- // way policies are loaded currently, but isn't a problem worth fixing for
- // the time being.
- DomainMap map(own_schema_map_->GetDomains());
- for (std::set<SchemaRegistry*>::const_iterator reg_it = registries_.begin();
- reg_it != registries_.end(); ++reg_it) {
- const DomainMap& reg_domain_map = (*reg_it)->schema_map()->GetDomains();
- for (DomainMap::const_iterator domain_it = reg_domain_map.begin();
- domain_it != reg_domain_map.end(); ++domain_it) {
- const ComponentMap& reg_component_map = domain_it->second;
- for (ComponentMap::const_iterator comp_it = reg_component_map.begin();
- comp_it != reg_component_map.end(); ++comp_it) {
- map[domain_it->first][comp_it->first] = comp_it->second;
- }
- }
- }
- schema_map_ = new SchemaMap(map);
- Notify(has_new_schemas);
-}
-
-ForwardingSchemaRegistry::ForwardingSchemaRegistry(SchemaRegistry* wrapped)
- : wrapped_(wrapped) {
- schema_map_ = wrapped_->schema_map();
- wrapped_->AddObserver(this);
- wrapped_->AddInternalObserver(this);
- UpdateReadiness();
-}
-
-ForwardingSchemaRegistry::~ForwardingSchemaRegistry() {
- if (wrapped_) {
- wrapped_->RemoveObserver(this);
- wrapped_->RemoveInternalObserver(this);
- }
-}
-
-void ForwardingSchemaRegistry::RegisterComponents(
- PolicyDomain domain,
- const ComponentMap& components) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // POLICY_DOMAIN_CHROME is skipped to avoid spurious updates when a new
- // Profile is created. If the ForwardingSchemaRegistry is used outside
- // device-level accounts then this should become configurable.
- if (wrapped_ && domain != POLICY_DOMAIN_CHROME)
- wrapped_->RegisterComponents(domain, components);
- // Ignore otherwise.
-}
-
-void ForwardingSchemaRegistry::UnregisterComponent(const PolicyNamespace& ns) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (wrapped_)
- wrapped_->UnregisterComponent(ns);
- // Ignore otherwise.
-}
-
-void ForwardingSchemaRegistry::OnSchemaRegistryUpdated(bool has_new_schemas) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- schema_map_ = wrapped_->schema_map();
- Notify(has_new_schemas);
-}
-
-void ForwardingSchemaRegistry::OnSchemaRegistryReady() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- UpdateReadiness();
-}
-
-void ForwardingSchemaRegistry::OnSchemaRegistryShuttingDown(
- SchemaRegistry* registry) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_EQ(wrapped_, registry);
- wrapped_->RemoveObserver(this);
- wrapped_->RemoveInternalObserver(this);
- wrapped_ = nullptr;
- // Keep serving the same |schema_map_|.
-}
-
-void ForwardingSchemaRegistry::UpdateReadiness() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (wrapped_->IsReady())
- SetAllDomainsReady();
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/schema_registry.h b/components/policy/core/common/schema_registry.h
deleted file mode 100644
index a1d26a5934..0000000000
--- a/components/policy/core/common/schema_registry.h
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_SCHEMA_REGISTRY_H_
-#define COMPONENTS_POLICY_CORE_COMMON_SCHEMA_REGISTRY_H_
-
-#include <set>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/observer_list.h"
-#include "base/sequence_checker.h"
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/core/common/schema.h"
-#include "components/policy/core/common/schema_map.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-class SchemaMap;
-
-// Holds the main reference to the current SchemaMap, and allows a list of
-// observers to get notified whenever it is updated.
-// This object is not thread safe and must be used from the owner's thread,
-// usually UI.
-class POLICY_EXPORT SchemaRegistry {
- public:
- class POLICY_EXPORT Observer {
- public:
- // Invoked whenever schemas are registered or unregistered.
- // |has_new_schemas| is true if a new component has been registered since
- // the last update; this allows observers to ignore updates when
- // components are unregistered but still get a handle to the current map
- // (e.g. for periodic reloads).
- virtual void OnSchemaRegistryUpdated(bool has_new_schemas) = 0;
-
- // Invoked when all policy domains become ready.
- virtual void OnSchemaRegistryReady() {}
-
- protected:
- virtual ~Observer();
- };
-
- // This observer is only meant to be used by subclasses.
- class POLICY_EXPORT InternalObserver {
- public:
- // Invoked when |registry| is about to be destroyed.
- virtual void OnSchemaRegistryShuttingDown(SchemaRegistry* registry) = 0;
-
- protected:
- virtual ~InternalObserver();
- };
-
- SchemaRegistry();
- virtual ~SchemaRegistry();
-
- const scoped_refptr<SchemaMap>& schema_map() const { return schema_map_; }
-
- // Register a single component.
- void RegisterComponent(const PolicyNamespace& ns,
- const Schema& schema);
-
- // Register a list of components for a given domain.
- virtual void RegisterComponents(PolicyDomain domain,
- const ComponentMap& components);
-
- virtual void UnregisterComponent(const PolicyNamespace& ns);
-
- // Returns true if all domains have registered the initial components.
- bool IsReady() const;
-
- // This indicates that the initial components for |domain| have all been
- // registered. It must be invoked at least once for each policy domain;
- // subsequent calls for the same domain are ignored.
- void SetDomainReady(PolicyDomain domain);
- // This is equivalent to calling |SetDomainReady| with each of the policy
- // domains.
- void SetAllDomainsReady();
- // This is equivalent to calling |SetDomainReady| with each of the domains
- // that correspond to policy for extensions.
- void SetExtensionsDomainsReady();
-
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
- void AddInternalObserver(InternalObserver* observer);
- void RemoveInternalObserver(InternalObserver* observer);
-
- protected:
- void Notify(bool has_new_schemas);
-
- SEQUENCE_CHECKER(sequence_checker_);
-
- scoped_refptr<SchemaMap> schema_map_;
-
- private:
- base::ObserverList<Observer, true> observers_;
- base::ObserverList<InternalObserver, true> internal_observers_;
- bool domains_ready_[POLICY_DOMAIN_SIZE];
-
- DISALLOW_COPY_AND_ASSIGN(SchemaRegistry);
-};
-
-// A registry that combines the maps of other registries.
-class POLICY_EXPORT CombinedSchemaRegistry
- : public SchemaRegistry,
- public SchemaRegistry::Observer,
- public SchemaRegistry::InternalObserver {
- public:
- CombinedSchemaRegistry();
- ~CombinedSchemaRegistry() override;
-
- void Track(SchemaRegistry* registry);
-
- // SchemaRegistry:
- void RegisterComponents(PolicyDomain domain,
- const ComponentMap& components) override;
- void UnregisterComponent(const PolicyNamespace& ns) override;
-
- // SchemaRegistry::Observer:
- void OnSchemaRegistryUpdated(bool has_new_schemas) override;
-
- // SchemaRegistry::InternalObserver:
- void OnSchemaRegistryShuttingDown(SchemaRegistry* registry) override;
-
- private:
- void Combine(bool has_new_schemas);
-
- std::set<SchemaRegistry*> registries_;
- scoped_refptr<SchemaMap> own_schema_map_;
-
- DISALLOW_COPY_AND_ASSIGN(CombinedSchemaRegistry);
-};
-
-// A registry that wraps another schema registry.
-class POLICY_EXPORT ForwardingSchemaRegistry
- : public SchemaRegistry,
- public SchemaRegistry::Observer,
- public SchemaRegistry::InternalObserver {
- public:
- // This registry will stop updating its SchemaMap when |wrapped| is
- // destroyed.
- explicit ForwardingSchemaRegistry(SchemaRegistry* wrapped);
- ~ForwardingSchemaRegistry() override;
-
- // SchemaRegistry:
- void RegisterComponents(PolicyDomain domain,
- const ComponentMap& components) override;
- void UnregisterComponent(const PolicyNamespace& ns) override;
-
- // SchemaRegistry::Observer:
- void OnSchemaRegistryUpdated(bool has_new_schemas) override;
- void OnSchemaRegistryReady() override;
-
- // SchemaRegistry::InternalObserver:
- void OnSchemaRegistryShuttingDown(SchemaRegistry* registry) override;
-
- private:
- void UpdateReadiness();
-
- SchemaRegistry* wrapped_;
-
- DISALLOW_COPY_AND_ASSIGN(ForwardingSchemaRegistry);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_SCHEMA_REGISTRY_H_
diff --git a/components/policy/core/common/schema_registry_tracking_policy_provider.cc b/components/policy/core/common/schema_registry_tracking_policy_provider.cc
deleted file mode 100644
index 5f15b33fda..0000000000
--- a/components/policy/core/common/schema_registry_tracking_policy_provider.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/schema_registry_tracking_policy_provider.h"
-
-#include <utility>
-
-#include "components/policy/core/common/schema_map.h"
-#include "components/policy/core/common/schema_registry.h"
-
-namespace policy {
-
-SchemaRegistryTrackingPolicyProvider::SchemaRegistryTrackingPolicyProvider(
- ConfigurationPolicyProvider* delegate)
- : delegate_(delegate), state_(WAITING_FOR_REGISTRY_READY) {
- delegate_->AddObserver(this);
- // Serve the initial |delegate_| policies.
- OnUpdatePolicy(delegate_);
-}
-
-SchemaRegistryTrackingPolicyProvider::~SchemaRegistryTrackingPolicyProvider() {
- delegate_->RemoveObserver(this);
-}
-
-void SchemaRegistryTrackingPolicyProvider::Init(SchemaRegistry* registry) {
- ConfigurationPolicyProvider::Init(registry);
- if (registry->IsReady())
- OnSchemaRegistryReady();
-}
-
-bool SchemaRegistryTrackingPolicyProvider::IsInitializationComplete(
- PolicyDomain domain) const {
- if (domain == POLICY_DOMAIN_CHROME)
- return delegate_->IsInitializationComplete(domain);
- // This provider keeps its own state for all the other domains.
- return state_ == READY;
-}
-
-void SchemaRegistryTrackingPolicyProvider::RefreshPolicies() {
- delegate_->RefreshPolicies();
-}
-
-void SchemaRegistryTrackingPolicyProvider::OnSchemaRegistryReady() {
- DCHECK_EQ(WAITING_FOR_REGISTRY_READY, state_);
- // This provider's registry is ready, meaning that it has all the initial
- // components schemas; the delegate's registry should also see them now,
- // since it's tracking the former.
- // Asking the delegate to RefreshPolicies now means that the next
- // OnUpdatePolicy from the delegate will have the initial policy for
- // components.
- if (!schema_map()->HasComponents()) {
- // If there are no component registered for this provider then there's no
- // need to reload.
- state_ = READY;
- OnUpdatePolicy(delegate_);
- return;
- }
-
- state_ = WAITING_FOR_REFRESH;
- RefreshPolicies();
-}
-
-void SchemaRegistryTrackingPolicyProvider::OnSchemaRegistryUpdated(
- bool has_new_schemas) {
- if (state_ != READY)
- return;
- if (has_new_schemas) {
- RefreshPolicies();
- } else {
- // Remove the policies that were being served for the component that have
- // been removed. This is important so that update notifications are also
- // sent in case those component are reinstalled during the current session.
- OnUpdatePolicy(delegate_);
- }
-}
-
-void SchemaRegistryTrackingPolicyProvider::OnUpdatePolicy(
- ConfigurationPolicyProvider* provider) {
- DCHECK_EQ(delegate_, provider);
-
- if (state_ == WAITING_FOR_REFRESH)
- state_ = READY;
-
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle());
- if (state_ == READY) {
- bundle->CopyFrom(delegate_->policies());
- schema_map()->FilterBundle(bundle.get());
- } else {
- // Always pass on the Chrome policy, even if the components are not ready
- // yet.
- const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
- bundle->Get(chrome_ns).CopyFrom(delegate_->policies().Get(chrome_ns));
- }
-
- UpdatePolicy(std::move(bundle));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/schema_registry_tracking_policy_provider.h b/components/policy/core/common/schema_registry_tracking_policy_provider.h
deleted file mode 100644
index 1ec64c3bc9..0000000000
--- a/components/policy/core/common/schema_registry_tracking_policy_provider.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef COMPONENTS_POLICY_CORE_COMMON_SCHEMA_REGISTRY_TRACKING_POLICY_PROVIDER_H_
-#define COMPONENTS_POLICY_CORE_COMMON_SCHEMA_REGISTRY_TRACKING_POLICY_PROVIDER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "components/policy/core/common/configuration_policy_provider.h"
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/policy_export.h"
-
-namespace policy {
-
-// A policy provider that relies on a delegate provider to obtain policy
-// settings, but uses a different SchemaRegistry to determine which policy
-// namespaces to request from the delegate provider.
-//
-// This provider tracks the SchemaRegistry's state, and becomes ready after
-// making sure the delegate provider has refreshed its policies with an updated
-// view of the complete schema. It is expected that the delegate's
-// SchemaRegistry is a CombinedSchemaRegistry tracking the
-// SchemaRegistryTrackingPolicyProvider's registry.
-//
-// This policy provider implementation is used to wrap the platform policy
-// provider for use with individual profiles, which may have different
-// SchemaRegistries. The SchemaRegistryTrackingPolicyProvider ensures that
-// initialization completion is only signaled for non-Chrome PolicyDomains after
-// the SchemaRegistry is fully initialized. This is important to avoid flapping
-// on startup due to asynchronous SchemaRegistry initialization while the
-// underlying policy provider has already completed initialization.
-//
-// A concrete example of this is POLICY_DOMAIN_EXTENSIONS, which registers
-// the PolicyNamespaces for the different extensions it's interested in based
-// on what extensions are installed in a Profile. Before that happens, the
-// underlying policy providers will not load the corresponding policy, so at
-// startup there would be a window during which the policy appears to be not
-// present. This is avoided by only flagging POLICY_DOMAIN_EXTENSIONS ready
-// once the corresponding SchemaRegistry has been fully initialized with the
-// list of installed extensions.
-class POLICY_EXPORT SchemaRegistryTrackingPolicyProvider
- : public ConfigurationPolicyProvider,
- public ConfigurationPolicyProvider::Observer {
- public:
- // The |delegate| must outlive this provider.
- explicit SchemaRegistryTrackingPolicyProvider(
- ConfigurationPolicyProvider* delegate);
- ~SchemaRegistryTrackingPolicyProvider() override;
-
- // ConfigurationPolicyProvider:
- //
- // Note that Init() and Shutdown() are not forwarded to the |delegate_|, since
- // this provider does not own it and its up to the |delegate_|'s owner to
- // initialize it and shut it down.
- //
- // Note also that this provider may have a SchemaRegistry passed in Init()
- // that doesn't match the |delegate_|'s; therefore OnSchemaRegistryUpdated()
- // and OnSchemaRegistryReady() are not forwarded either. It is assumed that
- // the |delegate_|'s SchemaRegistry contains a superset of this provider's
- // SchemaRegistry though (i.e. it's a CombinedSchemaRegistry that contains
- // this provider's SchemaRegistry).
- //
- // This provider manages its own initialization state for all policy domains
- // except POLICY_DOMAIN_CHROME, whose status is always queried from the
- // |delegate_|. RefreshPolicies() calls are also forwarded, since this
- // provider doesn't have a "real" policy source of its own.
- void Init(SchemaRegistry* registry) override;
- bool IsInitializationComplete(PolicyDomain domain) const override;
- void RefreshPolicies() override;
- void OnSchemaRegistryReady() override;
- void OnSchemaRegistryUpdated(bool has_new_schemas) override;
-
- // ConfigurationPolicyProvider::Observer:
- void OnUpdatePolicy(ConfigurationPolicyProvider* provider) override;
-
- private:
- enum InitializationState {
- WAITING_FOR_REGISTRY_READY,
- WAITING_FOR_REFRESH,
- READY,
- };
-
- ConfigurationPolicyProvider* delegate_;
- InitializationState state_;
-
- DISALLOW_COPY_AND_ASSIGN(SchemaRegistryTrackingPolicyProvider);
-};
-
-} // namespace policy
-
-#endif // COMPONENTS_POLICY_CORE_COMMON_SCHEMA_REGISTRY_TRACKING_POLICY_PROVIDER_H_
diff --git a/components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc b/components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc
deleted file mode 100644
index 5def4983f4..0000000000
--- a/components/policy/core/common/schema_registry_tracking_policy_provider_unittest.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/schema_registry_tracking_policy_provider.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/values.h"
-#include "components/policy/core/common/mock_configuration_policy_provider.h"
-#include "components/policy/core/common/policy_bundle.h"
-#include "components/policy/core/common/policy_map.h"
-#include "components/policy/core/common/policy_types.h"
-#include "components/policy/core/common/schema.h"
-#include "components/policy/core/common/schema_registry.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::Mock;
-using testing::Return;
-using testing::_;
-
-namespace policy {
-
-namespace {
-
-const char kTestSchema[] =
- "{"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"foo\": { \"type\": \"string\" }"
- " }"
- "}";
-
-} // namespace
-
-class SchemaRegistryTrackingPolicyProviderTest : public testing::Test {
- protected:
- SchemaRegistryTrackingPolicyProviderTest()
- : schema_registry_tracking_provider_(&mock_provider_) {
- mock_provider_.Init();
- schema_registry_tracking_provider_.Init(&schema_registry_);
- schema_registry_tracking_provider_.AddObserver(&observer_);
- }
-
- ~SchemaRegistryTrackingPolicyProviderTest() override {
- schema_registry_tracking_provider_.RemoveObserver(&observer_);
- schema_registry_tracking_provider_.Shutdown();
- mock_provider_.Shutdown();
- }
-
- Schema CreateTestSchema() {
- std::string error;
- Schema schema = Schema::Parse(kTestSchema, &error);
- if (!schema.valid())
- ADD_FAILURE() << error;
- return schema;
- }
-
- SchemaRegistry schema_registry_;
- MockConfigurationPolicyObserver observer_;
- MockConfigurationPolicyProvider mock_provider_;
- SchemaRegistryTrackingPolicyProvider schema_registry_tracking_provider_;
-};
-
-TEST_F(SchemaRegistryTrackingPolicyProviderTest, Empty) {
- EXPECT_FALSE(schema_registry_.IsReady());
- EXPECT_FALSE(schema_registry_tracking_provider_.IsInitializationComplete(
- POLICY_DOMAIN_EXTENSIONS));
-
- EXPECT_CALL(mock_provider_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
- .WillOnce(Return(false));
- EXPECT_FALSE(schema_registry_tracking_provider_.IsInitializationComplete(
- POLICY_DOMAIN_CHROME));
- Mock::VerifyAndClearExpectations(&mock_provider_);
-
- const PolicyBundle empty_bundle;
- EXPECT_TRUE(
- schema_registry_tracking_provider_.policies().Equals(empty_bundle));
-}
-
-TEST_F(SchemaRegistryTrackingPolicyProviderTest, PassOnChromePolicy) {
- PolicyBundle bundle;
- const PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, "");
- bundle.Get(chrome_ns).Set("policy", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>("visible"), nullptr);
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&schema_registry_tracking_provider_));
- std::unique_ptr<PolicyBundle> delegate_bundle(new PolicyBundle);
- delegate_bundle->CopyFrom(bundle);
- delegate_bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
- .Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("not visible"),
- nullptr);
- mock_provider_.UpdatePolicy(std::move(delegate_bundle));
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_FALSE(schema_registry_tracking_provider_.IsInitializationComplete(
- POLICY_DOMAIN_EXTENSIONS));
- EXPECT_TRUE(schema_registry_tracking_provider_.policies().Equals(bundle));
-}
-
-TEST_F(SchemaRegistryTrackingPolicyProviderTest, RefreshPolicies) {
- EXPECT_CALL(mock_provider_, RefreshPolicies());
- schema_registry_tracking_provider_.RefreshPolicies();
- Mock::VerifyAndClearExpectations(&mock_provider_);
-}
-
-TEST_F(SchemaRegistryTrackingPolicyProviderTest, SchemaReady) {
- EXPECT_CALL(observer_, OnUpdatePolicy(&schema_registry_tracking_provider_));
- schema_registry_.SetAllDomainsReady();
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_TRUE(schema_registry_tracking_provider_.IsInitializationComplete(
- policy::POLICY_DOMAIN_EXTENSIONS));
-}
-
-TEST_F(SchemaRegistryTrackingPolicyProviderTest, SchemaReadyWithComponents) {
- PolicyMap policy_map;
- policy_map.Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("omg"),
- nullptr);
- std::unique_ptr<PolicyBundle> bundle(new PolicyBundle);
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")).CopyFrom(policy_map);
- bundle->Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
- .CopyFrom(policy_map);
- EXPECT_CALL(observer_, OnUpdatePolicy(&schema_registry_tracking_provider_));
- mock_provider_.UpdatePolicy(std::move(bundle));
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_CALL(mock_provider_, RefreshPolicies()).Times(0);
- schema_registry_.RegisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), CreateTestSchema());
- schema_registry_.SetExtensionsDomainsReady();
- Mock::VerifyAndClearExpectations(&mock_provider_);
-
- EXPECT_CALL(mock_provider_, RefreshPolicies());
- schema_registry_.SetDomainReady(POLICY_DOMAIN_CHROME);
- Mock::VerifyAndClearExpectations(&mock_provider_);
-
- EXPECT_FALSE(schema_registry_tracking_provider_.IsInitializationComplete(
- policy::POLICY_DOMAIN_EXTENSIONS));
- PolicyBundle expected_bundle;
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, ""))
- .CopyFrom(policy_map);
- EXPECT_TRUE(
- schema_registry_tracking_provider_.policies().Equals(expected_bundle));
-
- EXPECT_CALL(observer_, OnUpdatePolicy(&schema_registry_tracking_provider_));
- schema_registry_tracking_provider_.OnUpdatePolicy(&mock_provider_);
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_TRUE(schema_registry_tracking_provider_.IsInitializationComplete(
- policy::POLICY_DOMAIN_EXTENSIONS));
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"))
- .CopyFrom(policy_map);
- EXPECT_TRUE(
- schema_registry_tracking_provider_.policies().Equals(expected_bundle));
-}
-
-TEST_F(SchemaRegistryTrackingPolicyProviderTest, DelegateUpdates) {
- schema_registry_.RegisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz"), CreateTestSchema());
- EXPECT_FALSE(schema_registry_.IsReady());
- EXPECT_FALSE(schema_registry_tracking_provider_.IsInitializationComplete(
- policy::POLICY_DOMAIN_EXTENSIONS));
-
- PolicyMap policy_map;
- policy_map.Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("omg"),
- nullptr);
- // Chrome policy updates are visible even if the components aren't ready.
- EXPECT_CALL(observer_, OnUpdatePolicy(&schema_registry_tracking_provider_));
- mock_provider_.UpdateChromePolicy(policy_map);
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_CALL(mock_provider_, RefreshPolicies());
- schema_registry_.SetAllDomainsReady();
- EXPECT_TRUE(schema_registry_.IsReady());
- Mock::VerifyAndClearExpectations(&mock_provider_);
- EXPECT_FALSE(schema_registry_tracking_provider_.IsInitializationComplete(
- policy::POLICY_DOMAIN_EXTENSIONS));
-
- // The provider becomes ready after this refresh completes, and policy updates
- // are visible after that.
- EXPECT_CALL(observer_, OnUpdatePolicy(_));
- mock_provider_.UpdateChromePolicy(policy_map);
- Mock::VerifyAndClearExpectations(&observer_);
-
- EXPECT_TRUE(schema_registry_tracking_provider_.IsInitializationComplete(
- policy::POLICY_DOMAIN_EXTENSIONS));
-
- // Updates continue to be visible.
- EXPECT_CALL(observer_, OnUpdatePolicy(_));
- mock_provider_.UpdateChromePolicy(policy_map);
- Mock::VerifyAndClearExpectations(&observer_);
-}
-
-TEST_F(SchemaRegistryTrackingPolicyProviderTest, RemoveAndAddComponent) {
- EXPECT_CALL(mock_provider_, RefreshPolicies());
- const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "xyz");
- schema_registry_.RegisterComponent(ns, CreateTestSchema());
- schema_registry_.SetAllDomainsReady();
- Mock::VerifyAndClearExpectations(&mock_provider_);
-
- // Serve policy for |ns|.
- PolicyBundle platform_policy;
- platform_policy.Get(ns).Set("foo", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
- POLICY_SOURCE_CLOUD,
- std::make_unique<base::Value>("omg"), nullptr);
- std::unique_ptr<PolicyBundle> copy(new PolicyBundle);
- copy->CopyFrom(platform_policy);
- EXPECT_CALL(observer_, OnUpdatePolicy(_));
- mock_provider_.UpdatePolicy(std::move(copy));
- Mock::VerifyAndClearExpectations(&observer_);
- EXPECT_TRUE(
- schema_registry_tracking_provider_.policies().Equals(platform_policy));
-
- // Now remove that component.
- EXPECT_CALL(observer_, OnUpdatePolicy(_));
- schema_registry_.UnregisterComponent(ns);
- Mock::VerifyAndClearExpectations(&observer_);
- const PolicyBundle empty;
- EXPECT_TRUE(schema_registry_tracking_provider_.policies().Equals(empty));
-
- // Adding it back should serve the current policies again, even though they
- // haven't changed on the platform provider.
- EXPECT_CALL(mock_provider_, RefreshPolicies());
- schema_registry_.RegisterComponent(ns, CreateTestSchema());
- Mock::VerifyAndClearExpectations(&mock_provider_);
-
- EXPECT_CALL(observer_, OnUpdatePolicy(_));
- copy.reset(new PolicyBundle);
- copy->CopyFrom(platform_policy);
- mock_provider_.UpdatePolicy(std::move(copy));
- Mock::VerifyAndClearExpectations(&observer_);
- EXPECT_TRUE(
- schema_registry_tracking_provider_.policies().Equals(platform_policy));
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/schema_registry_unittest.cc b/components/policy/core/common/schema_registry_unittest.cc
deleted file mode 100644
index aea54d1cc3..0000000000
--- a/components/policy/core/common/schema_registry_unittest.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/schema_registry.h"
-
-#include <memory>
-
-#include "components/policy/core/common/policy_namespace.h"
-#include "components/policy/core/common/schema.h"
-#include "extensions/buildflags/buildflags.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::Mock;
-using ::testing::_;
-
-namespace policy {
-
-namespace {
-
-const char kTestSchema[] =
- "{"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"string\": { \"type\": \"string\" },"
- " \"integer\": { \"type\": \"integer\" },"
- " \"boolean\": { \"type\": \"boolean\" },"
- " \"null\": { \"type\": \"null\" },"
- " \"double\": { \"type\": \"number\" },"
- " \"list\": {"
- " \"type\": \"array\","
- " \"items\": { \"type\": \"string\" }"
- " },"
- " \"object\": {"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"a\": { \"type\": \"string\" },"
- " \"b\": { \"type\": \"integer\" }"
- " }"
- " }"
- " }"
- "}";
-
-class MockSchemaRegistryObserver : public SchemaRegistry::Observer {
- public:
- MockSchemaRegistryObserver() {}
- ~MockSchemaRegistryObserver() override {}
-
- MOCK_METHOD1(OnSchemaRegistryUpdated, void(bool));
- MOCK_METHOD0(OnSchemaRegistryReady, void());
-};
-
-bool SchemaMapEquals(const scoped_refptr<SchemaMap>& schema_map1,
- const scoped_refptr<SchemaMap>& schema_map2) {
- PolicyNamespaceList added;
- PolicyNamespaceList removed;
- schema_map1->GetChanges(schema_map2, &removed, &added);
- return added.empty() && removed.empty();
-}
-
-} // namespace
-
-TEST(SchemaRegistryTest, Notifications) {
- std::string error;
- Schema schema = Schema::Parse(kTestSchema, &error);
- ASSERT_TRUE(schema.valid()) << error;
-
- MockSchemaRegistryObserver observer;
- SchemaRegistry registry;
- registry.AddObserver(&observer);
-
- ASSERT_TRUE(registry.schema_map().get());
- EXPECT_FALSE(registry.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- registry.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
- schema);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Re-register also triggers notifications, because the Schema might have
- // changed.
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- registry.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
- schema);
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_TRUE(registry.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
- registry.UnregisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_FALSE(registry.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
-
- // Registering multiple components at once issues only one notification.
- ComponentMap components;
- components["abc"] = schema;
- components["def"] = schema;
- components["xyz"] = schema;
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- registry.RegisterComponents(POLICY_DOMAIN_EXTENSIONS, components);
- Mock::VerifyAndClearExpectations(&observer);
-
- registry.RemoveObserver(&observer);
-}
-
-TEST(SchemaRegistryTest, IsReady) {
- SchemaRegistry registry;
- MockSchemaRegistryObserver observer;
- registry.AddObserver(&observer);
-
- EXPECT_FALSE(registry.IsReady());
-#if BUILDFLAG(ENABLE_EXTENSIONS)
- EXPECT_CALL(observer, OnSchemaRegistryReady()).Times(0);
- registry.SetExtensionsDomainsReady();
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_FALSE(registry.IsReady());
-#endif
- EXPECT_CALL(observer, OnSchemaRegistryReady());
- registry.SetDomainReady(POLICY_DOMAIN_CHROME);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(registry.IsReady());
- EXPECT_CALL(observer, OnSchemaRegistryReady()).Times(0);
- registry.SetDomainReady(POLICY_DOMAIN_CHROME);
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(registry.IsReady());
-
- CombinedSchemaRegistry combined;
- EXPECT_TRUE(combined.IsReady());
-
- registry.RemoveObserver(&observer);
-}
-
-TEST(SchemaRegistryTest, Combined) {
- std::string error;
- Schema schema = Schema::Parse(kTestSchema, &error);
- ASSERT_TRUE(schema.valid()) << error;
-
- MockSchemaRegistryObserver observer;
- std::unique_ptr<SchemaRegistry> registry1(new SchemaRegistry);
- std::unique_ptr<SchemaRegistry> registry2(new SchemaRegistry);
- CombinedSchemaRegistry combined;
- combined.AddObserver(&observer);
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
- registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
- schema);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Starting to track a registry issues notifications when it comes with new
- // schemas.
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- combined.Track(registry1.get());
- Mock::VerifyAndClearExpectations(&observer);
-
- // Adding a new empty registry does not trigger notifications.
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
- combined.Track(registry2.get());
- Mock::VerifyAndClearExpectations(&observer);
-
- // Adding the same component to the combined registry itself triggers
- // notifications.
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- combined.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
- schema);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Adding components to the sub-registries triggers notifications.
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- registry2->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
- schema);
- Mock::VerifyAndClearExpectations(&observer);
-
- // If the same component is published in 2 sub-registries then the combined
- // registry publishes one of them.
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"),
- schema);
- Mock::VerifyAndClearExpectations(&observer);
-
- ASSERT_EQ(1u, combined.schema_map()->GetDomains().size());
- ASSERT_TRUE(combined.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS));
- ASSERT_EQ(
- 2u,
- combined.schema_map()->GetComponents(POLICY_DOMAIN_EXTENSIONS)->size());
- EXPECT_TRUE(combined.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
- EXPECT_TRUE(combined.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
- EXPECT_FALSE(combined.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "xyz")));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
- registry1->UnregisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
- Mock::VerifyAndClearExpectations(&observer);
- // Still registered at the combined registry.
- EXPECT_TRUE(combined.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
- combined.UnregisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
- Mock::VerifyAndClearExpectations(&observer);
- // Now it's gone.
- EXPECT_FALSE(combined.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc")));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
- registry1->UnregisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
- Mock::VerifyAndClearExpectations(&observer);
- // Still registered at registry2.
- EXPECT_TRUE(combined.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
- registry2->UnregisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def"));
- Mock::VerifyAndClearExpectations(&observer);
- // Now it's gone.
- EXPECT_FALSE(combined.schema_map()->GetSchema(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "def")));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true)).Times(2);
- registry1->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
- schema);
- registry2->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "hij"),
- schema);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Untracking |registry1| doesn't trigger an update notification, because it
- // doesn't contain any components.
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(_)).Times(0);
- registry1.reset();
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
- registry2.reset();
- Mock::VerifyAndClearExpectations(&observer);
-
- combined.RemoveObserver(&observer);
-}
-
-TEST(SchemaRegistryTest, ForwardingSchemaRegistry) {
- std::unique_ptr<SchemaRegistry> registry(new SchemaRegistry);
- ForwardingSchemaRegistry forwarding(registry.get());
- MockSchemaRegistryObserver observer;
- forwarding.AddObserver(&observer);
-
- EXPECT_FALSE(registry->IsReady());
- EXPECT_FALSE(forwarding.IsReady());
- // They always have the same SchemaMap.
- EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(true));
- registry->RegisterComponent(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"),
- Schema());
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
-
- EXPECT_CALL(observer, OnSchemaRegistryUpdated(false));
- registry->UnregisterComponent(
- PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "abc"));
- Mock::VerifyAndClearExpectations(&observer);
- EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
-
- // No notifications expected for these calls.
- EXPECT_FALSE(registry->IsReady());
- EXPECT_FALSE(forwarding.IsReady());
-
- registry->SetExtensionsDomainsReady();
- EXPECT_FALSE(registry->IsReady());
- EXPECT_FALSE(forwarding.IsReady());
-
- EXPECT_CALL(observer, OnSchemaRegistryReady());
- registry->SetDomainReady(POLICY_DOMAIN_CHROME);
- EXPECT_TRUE(registry->IsReady());
- EXPECT_TRUE(forwarding.IsReady());
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_TRUE(SchemaMapEquals(registry->schema_map(), forwarding.schema_map()));
- Mock::VerifyAndClearExpectations(&observer);
-
- forwarding.SetExtensionsDomainsReady();
- forwarding.SetDomainReady(POLICY_DOMAIN_CHROME);
- EXPECT_TRUE(forwarding.IsReady());
-
- // Keep the same SchemaMap when the original registry is gone.
- // No notifications are expected in this case either.
- scoped_refptr<SchemaMap> schema_map = registry->schema_map();
- registry.reset();
- EXPECT_TRUE(SchemaMapEquals(schema_map, forwarding.schema_map()));
- Mock::VerifyAndClearExpectations(&observer);
-
- forwarding.RemoveObserver(&observer);
-}
-
-TEST(SchemaRegistryTest, ForwardingSchemaRegistryReadiness) {
- std::unique_ptr<SchemaRegistry> registry(new SchemaRegistry);
-
- ForwardingSchemaRegistry forwarding_1(registry.get());
- EXPECT_FALSE(registry->IsReady());
- EXPECT_FALSE(forwarding_1.IsReady());
-
- // Once the wrapped registry gets ready, the forwarding schema registry
- // becomes ready too.
- registry->SetAllDomainsReady();
- EXPECT_TRUE(registry->IsReady());
- EXPECT_TRUE(forwarding_1.IsReady());
-
- // The wrapped registry was ready at the time when the forwarding registry was
- // constructed, so the forwarding registry is immediately ready too.
- ForwardingSchemaRegistry forwarding_2(registry.get());
- EXPECT_TRUE(forwarding_2.IsReady());
-
- // Destruction of the wrapped registry doesn't change the readiness of the
- // forwarding registry.
- registry.reset();
- EXPECT_TRUE(forwarding_1.IsReady());
- EXPECT_TRUE(forwarding_2.IsReady());
-}
-
-} // namespace policy
diff --git a/components/policy/core/common/schema_unittest.cc b/components/policy/core/common/schema_unittest.cc
deleted file mode 100644
index 4e861d126c..0000000000
--- a/components/policy/core/common/schema_unittest.cc
+++ /dev/null
@@ -1,1286 +0,0 @@
-// Copyright 2013 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 "components/policy/core/common/schema.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "components/policy/core/common/schema_internal.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-#define TestSchemaValidation(a, b, c, d) \
- TestSchemaValidationHelper( \
- base::StringPrintf("%s:%i", __FILE__, __LINE__), a, b, c, d)
-
-const char kTestSchema[] = R"({
- "type": "object",
- "properties": {
- "Boolean": { "type": "boolean" },
- "Integer": { "type": "integer" },
- "Null": { "type": "null" },
- "Number": { "type": "number" },
- "String": { "type": "string" },
- "Array": {
- "type": "array",
- "items": { "type": "string" }
- },
- "ArrayOfObjects": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "one": { "type": "string" },
- "two": { "type": "integer" }
- }
- }
- },
- "ArrayOfArray": {
- "type": "array",
- "items": {
- "type": "array",
- "items": { "type": "string" }
- }
- },
- "Object": {
- "type": "object",
- "properties": {
- "one": { "type": "boolean" },
- "two": { "type": "integer" }
- },
- "additionalProperties": { "type": "string" }
- },
- "ObjectOfObject": {
- "type": "object",
- "properties": {
- "Object": {
- "type": "object",
- "properties": {
- "one": { "type": "string" },
- "two": { "type": "integer" }
- }
- }
- }
- },
- "IntegerWithEnums": {
- "type": "integer",
- "enum": [1, 2, 3]
- },
- "IntegerWithEnumsGaps": {
- "type": "integer",
- "enum": [10, 20, 30]
- },
- "StringWithEnums": {
- "type": "string",
- "enum": ["one", "two", "three"]
- },
- "IntegerWithRange": {
- "type": "integer",
- "minimum": 1,
- "maximum": 3
- },
- "ObjectOfArray": {
- "type": "object",
- "properties": {
- "List": {
- "type": "array",
- "items": { "type": "integer" }
- }
- }
- },
- "ArrayOfObjectOfArray": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "List": {
- "type": "array",
- "items": { "type": "string" }
- }
- }
- }
- },
- "StringWithPattern": {
- "type": "string",
- "pattern": "^foo+$"
- },
- "ObjectWithPatternProperties": {
- "type": "object",
- "patternProperties": {
- "^foo+$": { "type": "integer" },
- "^bar+$": {
- "type": "string",
- "enum": ["one", "two"]
- }
- },
- "properties": {
- "bar": {
- "type": "string",
- "enum": ["one", "three"]
- }
- }
- },
- "ObjectWithRequiredProperties": {
- "type": "object",
- "properties": {
- "Integer": {
- "type": "integer",
- "enum": [1, 2]
- },
- "String": { "type": "string" },
- "Number": { "type": "number" }
- },
- "patternProperties": {
- "^Integer": {
- "type": "integer",
- "enum": [1, 3]
- }
- },
- "required": [ "Integer", "String" ]
- }
- }
-})";
-
-bool ParseFails(const std::string& content) {
- std::string error;
- Schema schema = Schema::Parse(content, &error);
- if (schema.valid())
- return false;
- EXPECT_FALSE(error.empty());
- return true;
-}
-
-void TestSchemaValidationHelper(const std::string& source,
- Schema schema,
- const base::Value& value,
- SchemaOnErrorStrategy strategy,
- bool expected_return_value) {
- std::string error;
- static const char kNoErrorReturned[] = "No error returned.";
-
- // Test that Schema::Validate() works as expected.
- error = kNoErrorReturned;
- bool returned = schema.Validate(value, strategy, nullptr, &error);
- ASSERT_EQ(expected_return_value, returned) << source << ": " << error;
-
- // Test that Schema::Normalize() will return the same value as
- // Schema::Validate().
- error = kNoErrorReturned;
- std::unique_ptr<base::Value> cloned_value(value.DeepCopy());
- bool touched = false;
- returned =
- schema.Normalize(cloned_value.get(), strategy, nullptr, &error, &touched);
- EXPECT_EQ(expected_return_value, returned) << source << ": " << error;
-
- bool strictly_valid = schema.Validate(value, SCHEMA_STRICT, nullptr, &error);
- EXPECT_EQ(touched, !strictly_valid && returned) << source;
-
- // Test that Schema::Normalize() have actually dropped invalid and unknown
- // properties.
- if (expected_return_value) {
- EXPECT_TRUE(schema.Validate(*cloned_value, SCHEMA_STRICT, nullptr, &error))
- << source;
- EXPECT_TRUE(schema.Normalize(cloned_value.get(), SCHEMA_STRICT, nullptr,
- &error, nullptr))
- << source;
- }
-}
-
-void TestSchemaValidationWithPath(Schema schema,
- const base::Value& value,
- const std::string& expected_failure_path) {
- std::string error_path = "NOT_SET";
- std::string error;
-
- bool returned = schema.Validate(value, SCHEMA_STRICT, &error_path, &error);
- ASSERT_FALSE(returned) << error_path;
- EXPECT_EQ(error_path, expected_failure_path);
-}
-
-std::string SchemaObjectWrapper(const std::string& subschema) {
- return "{"
- " \"type\": \"object\","
- " \"properties\": {"
- " \"SomePropertyName\":" + subschema +
- " }"
- "}";
-}
-
-} // namespace
-
-TEST(SchemaTest, MinimalSchema) {
- EXPECT_FALSE(ParseFails(R"({ "type": "object" })"));
-}
-
-TEST(SchemaTest, InvalidSchemas) {
- EXPECT_TRUE(ParseFails(""));
- EXPECT_TRUE(ParseFails("omg"));
- EXPECT_TRUE(ParseFails("\"omg\""));
- EXPECT_TRUE(ParseFails("123"));
- EXPECT_TRUE(ParseFails("[]"));
- EXPECT_TRUE(ParseFails("null"));
- EXPECT_TRUE(ParseFails("{}"));
-
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "additionalProperties": { "type":"object" }
- })"));
-
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "patternProperties": { "a+b*": { "type": "object" } }
- })"));
-
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "properties": { "Policy": { "type": "bogus" } }
- })"));
-
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "properties": { "Policy": { "type": ["string", "number"] } }
- })"));
-
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "properties": { "Policy": { "type": "any" } }
- })"));
-
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "properties": { "Policy": 123 }
- })"));
-
- EXPECT_FALSE(ParseFails(R"({
- "type": "object",
- "unknown attribute": "is ignored"
- })"));
-}
-
-TEST(SchemaTest, Ownership) {
- std::string error;
- Schema schema = Schema::Parse(R"({
- "type": "object",
- "properties": {
- "sub": {
- "type": "object",
- "properties": {
- "subsub": { "type": "string" }
- }
- }
- }
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- schema = schema.GetKnownProperty("sub");
- ASSERT_TRUE(schema.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- {
- Schema::Iterator it = schema.GetPropertiesIterator();
- ASSERT_FALSE(it.IsAtEnd());
- EXPECT_STREQ("subsub", it.key());
-
- schema = it.schema();
- it.Advance();
- EXPECT_TRUE(it.IsAtEnd());
- }
-
- ASSERT_TRUE(schema.valid());
- EXPECT_EQ(base::Value::Type::STRING, schema.type());
-
- // This test shouldn't leak nor use invalid memory.
-}
-
-TEST(SchemaTest, ValidSchema) {
- std::string error;
- Schema schema = Schema::Parse(kTestSchema, &error);
- ASSERT_TRUE(schema.valid()) << error;
-
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
- EXPECT_FALSE(schema.GetProperty("invalid").valid());
-
- Schema sub = schema.GetProperty("Boolean");
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::BOOLEAN, sub.type());
-
- sub = schema.GetProperty("Integer");
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::INTEGER, sub.type());
-
- sub = schema.GetProperty("Null");
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::NONE, sub.type());
-
- sub = schema.GetProperty("Number");
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::DOUBLE, sub.type());
-
- sub = schema.GetProperty("String");
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::STRING, sub.type());
-
- sub = schema.GetProperty("Array");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::LIST, sub.type());
- sub = sub.GetItems();
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::STRING, sub.type());
-
- sub = schema.GetProperty("ArrayOfObjects");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::LIST, sub.type());
- sub = sub.GetItems();
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::DICTIONARY, sub.type());
- Schema subsub = sub.GetProperty("one");
- ASSERT_TRUE(subsub.valid());
- EXPECT_EQ(base::Value::Type::STRING, subsub.type());
- subsub = sub.GetProperty("two");
- ASSERT_TRUE(subsub.valid());
- EXPECT_EQ(base::Value::Type::INTEGER, subsub.type());
- subsub = sub.GetProperty("invalid");
- EXPECT_FALSE(subsub.valid());
-
- sub = schema.GetProperty("ArrayOfArray");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::LIST, sub.type());
- sub = sub.GetItems();
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::LIST, sub.type());
- sub = sub.GetItems();
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::STRING, sub.type());
-
- sub = schema.GetProperty("Object");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, sub.type());
- subsub = sub.GetProperty("one");
- ASSERT_TRUE(subsub.valid());
- EXPECT_EQ(base::Value::Type::BOOLEAN, subsub.type());
- subsub = sub.GetProperty("two");
- ASSERT_TRUE(subsub.valid());
- EXPECT_EQ(base::Value::Type::INTEGER, subsub.type());
- subsub = sub.GetProperty("undeclared");
- ASSERT_TRUE(subsub.valid());
- EXPECT_EQ(base::Value::Type::STRING, subsub.type());
-
- sub = schema.GetProperty("IntegerWithEnums");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::INTEGER, sub.type());
-
- sub = schema.GetProperty("IntegerWithEnumsGaps");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::INTEGER, sub.type());
-
- sub = schema.GetProperty("StringWithEnums");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::STRING, sub.type());
-
- sub = schema.GetProperty("IntegerWithRange");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::INTEGER, sub.type());
-
- sub = schema.GetProperty("StringWithPattern");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::STRING, sub.type());
-
- sub = schema.GetProperty("ObjectWithPatternProperties");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, sub.type());
-
- sub = schema.GetProperty("ObjectWithRequiredProperties");
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, sub.type());
-
- struct {
- const char* expected_key;
- base::Value::Type expected_type;
- } kExpectedProperties[] = {
- { "Array", base::Value::Type::LIST },
- { "ArrayOfArray", base::Value::Type::LIST },
- { "ArrayOfObjectOfArray", base::Value::Type::LIST },
- { "ArrayOfObjects", base::Value::Type::LIST },
- { "Boolean", base::Value::Type::BOOLEAN },
- { "Integer", base::Value::Type::INTEGER },
- { "IntegerWithEnums", base::Value::Type::INTEGER },
- { "IntegerWithEnumsGaps", base::Value::Type::INTEGER },
- { "IntegerWithRange", base::Value::Type::INTEGER },
- { "Null", base::Value::Type::NONE },
- { "Number", base::Value::Type::DOUBLE },
- { "Object", base::Value::Type::DICTIONARY },
- { "ObjectOfArray", base::Value::Type::DICTIONARY },
- { "ObjectOfObject", base::Value::Type::DICTIONARY },
- { "ObjectWithPatternProperties", base::Value::Type::DICTIONARY },
- { "ObjectWithRequiredProperties", base::Value::Type::DICTIONARY },
- { "String", base::Value::Type::STRING },
- { "StringWithEnums", base::Value::Type::STRING },
- { "StringWithPattern", base::Value::Type::STRING },
- };
- Schema::Iterator it = schema.GetPropertiesIterator();
- for (size_t i = 0; i < arraysize(kExpectedProperties); ++i) {
- ASSERT_FALSE(it.IsAtEnd());
- EXPECT_STREQ(kExpectedProperties[i].expected_key, it.key());
- ASSERT_TRUE(it.schema().valid());
- EXPECT_EQ(kExpectedProperties[i].expected_type, it.schema().type());
- it.Advance();
- }
- EXPECT_TRUE(it.IsAtEnd());
-}
-
-TEST(SchemaTest, Lookups) {
- std::string error;
-
- Schema schema = Schema::Parse(R"({ "type": "object" })", &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- // This empty schema should never find named properties.
- EXPECT_FALSE(schema.GetKnownProperty("").valid());
- EXPECT_FALSE(schema.GetKnownProperty("xyz").valid());
- EXPECT_TRUE(schema.GetPropertiesIterator().IsAtEnd());
-
- schema = Schema::Parse(R"({
- "type": "object",
- "properties": {
- "Boolean": { "type": "boolean" }
- }
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- EXPECT_FALSE(schema.GetKnownProperty("").valid());
- EXPECT_FALSE(schema.GetKnownProperty("xyz").valid());
- EXPECT_TRUE(schema.GetKnownProperty("Boolean").valid());
-
- schema = Schema::Parse(R"({
- "type": "object",
- "properties": {
- "bb" : { "type": "null" },
- "aa" : { "type": "boolean" },
- "abab" : { "type": "string" },
- "ab" : { "type": "number" },
- "aba" : { "type": "integer" }
- }
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- EXPECT_FALSE(schema.GetKnownProperty("").valid());
- EXPECT_FALSE(schema.GetKnownProperty("xyz").valid());
-
- struct {
- const char* expected_key;
- base::Value::Type expected_type;
- } kExpectedKeys[] = {
- { "aa", base::Value::Type::BOOLEAN },
- { "ab", base::Value::Type::DOUBLE },
- { "aba", base::Value::Type::INTEGER },
- { "abab", base::Value::Type::STRING },
- { "bb", base::Value::Type::NONE },
- };
- for (size_t i = 0; i < arraysize(kExpectedKeys); ++i) {
- Schema sub = schema.GetKnownProperty(kExpectedKeys[i].expected_key);
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(kExpectedKeys[i].expected_type, sub.type());
- }
-
- schema = Schema::Parse(R"(
- {
- "type": "object",
- "properties": {
- "String": { "type": "string" },
- "Object": {
- "type": "object",
- "properties": {"Integer": {"type": "integer"}},
- "required": [ "Integer" ]
- },
- "Number": { "type": "number" }
- },
- "required": [ "String", "Object"]
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- EXPECT_EQ(std::vector<std::string>({"String", "Object"}),
- schema.GetRequiredProperties());
-
- schema = schema.GetKnownProperty("Object");
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- EXPECT_EQ(std::vector<std::string>({"Integer"}),
- schema.GetRequiredProperties());
-}
-
-TEST(SchemaTest, Wrap) {
- const internal::SchemaNode kSchemas[] = {
- { base::Value::Type::DICTIONARY, 0 }, // 0: root node
- { base::Value::Type::BOOLEAN, -1 }, // 1
- { base::Value::Type::INTEGER, -1 }, // 2
- { base::Value::Type::DOUBLE, -1 }, // 3
- { base::Value::Type::STRING, -1 }, // 4
- { base::Value::Type::LIST, 4 }, // 5: list of strings.
- { base::Value::Type::LIST, 5 }, // 6: list of lists of strings.
- { base::Value::Type::INTEGER, 0 }, // 7: integer enumerations.
- { base::Value::Type::INTEGER, 1 }, // 8: ranged integers.
- { base::Value::Type::STRING, 2 }, // 9: string enumerations.
- { base::Value::Type::STRING, 3 }, // 10: string with pattern.
- { base::Value::Type::DICTIONARY, 1 }, // 11: dictionary with required
- // properties
- };
-
- const internal::PropertyNode kPropertyNodes[] = {
- { "Boolean", 1}, // 0
- { "DictRequired", 11}, // 1
- { "Integer", 2}, // 2
- { "List", 5}, // 3
- { "Number", 3}, // 4
- { "String", 4}, // 5
- { "IntEnum", 7}, // 6
- { "RangedInt", 8}, // 7
- { "StrEnum", 9}, // 8
- { "StrPat", 10}, // 9
- { "bar+$", 4}, // 10
- { "String", 4}, // 11
- { "Number", 3}, // 12
- };
-
- const internal::PropertiesNode kProperties[] = {
- // 0 to 10 (exclusive) are the known properties in kPropertyNodes, 9 is
- // patternProperties and 6 is the additionalProperties node.
- { 0, 10, 11, 0, 0, 6 },
- // 11 to 13 (exclusive) are the known properties in kPropertyNodes. 0 to
- // 1 (exclusive) are the required properties in kRequired. -1 indicates
- // no additionalProperties.
- { 11, 13, 13, 0, 1, -1 },
- };
-
- const internal::RestrictionNode kRestriction[] = {
- {{0, 3}}, // 0: [1, 2, 3]
- {{5, 1}}, // 1: minimum = 1, maximum = 5
- {{0, 3}}, // 2: ["one", "two", "three"]
- {{3, 3}}, // 3: pattern "foo+"
- };
-
- const char* kRequired[] = {"String"};
-
- const int kIntEnums[] = {1, 2, 3};
-
- const char* kStringEnums[] = {
- "one", // 0
- "two", // 1
- "three", // 2
- "foo+", // 3
- };
-
- const internal::SchemaData kData = {
- kSchemas,
- kPropertyNodes,
- kProperties,
- kRestriction,
- kRequired,
- kIntEnums,
- kStringEnums,
- };
-
- Schema schema = Schema::Wrap(&kData);
- ASSERT_TRUE(schema.valid());
- EXPECT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- struct {
- const char* key;
- base::Value::Type type;
- } kExpectedProperties[] = {
- { "Boolean", base::Value::Type::BOOLEAN },
- { "DictRequired", base::Value::Type::DICTIONARY },
- { "Integer", base::Value::Type::INTEGER },
- { "List", base::Value::Type::LIST },
- { "Number", base::Value::Type::DOUBLE },
- { "String", base::Value::Type::STRING },
- { "IntEnum", base::Value::Type::INTEGER },
- { "RangedInt", base::Value::Type::INTEGER },
- { "StrEnum", base::Value::Type::STRING },
- { "StrPat", base::Value::Type::STRING },
- };
-
- Schema::Iterator it = schema.GetPropertiesIterator();
- for (size_t i = 0; i < arraysize(kExpectedProperties); ++i) {
- ASSERT_FALSE(it.IsAtEnd());
- EXPECT_STREQ(kExpectedProperties[i].key, it.key());
- Schema sub = it.schema();
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(kExpectedProperties[i].type, sub.type());
-
- if (sub.type() == base::Value::Type::LIST) {
- Schema items = sub.GetItems();
- ASSERT_TRUE(items.valid());
- EXPECT_EQ(base::Value::Type::STRING, items.type());
- }
-
- it.Advance();
- }
- EXPECT_TRUE(it.IsAtEnd());
-
- Schema sub = schema.GetAdditionalProperties();
- ASSERT_TRUE(sub.valid());
- ASSERT_EQ(base::Value::Type::LIST, sub.type());
- Schema subsub = sub.GetItems();
- ASSERT_TRUE(subsub.valid());
- ASSERT_EQ(base::Value::Type::LIST, subsub.type());
- Schema subsubsub = subsub.GetItems();
- ASSERT_TRUE(subsubsub.valid());
- ASSERT_EQ(base::Value::Type::STRING, subsubsub.type());
-
- SchemaList schema_list = schema.GetPatternProperties("barr");
- ASSERT_EQ(1u, schema_list.size());
- sub = schema_list[0];
- ASSERT_TRUE(sub.valid());
- EXPECT_EQ(base::Value::Type::STRING, sub.type());
-
- EXPECT_TRUE(schema.GetPatternProperties("ba").empty());
- EXPECT_TRUE(schema.GetPatternProperties("bar+$").empty());
-
- Schema dict = schema.GetKnownProperty("DictRequired");
- ASSERT_TRUE(dict.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, dict.type());
-
- EXPECT_EQ(std::vector<std::string>({"String"}), dict.GetRequiredProperties());
-}
-
-TEST(SchemaTest, Validate) {
- std::string error;
- Schema schema = Schema::Parse(kTestSchema, &error);
- ASSERT_TRUE(schema.valid()) << error;
-
- base::DictionaryValue bundle;
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
-
- // Wrong type, expected integer.
- bundle.SetBoolean("Integer", true);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
-
- // Wrong type, expected list of strings.
- {
- bundle.Clear();
- base::ListValue list;
- list.AppendInteger(1);
- bundle.SetKey("Array", std::move(list));
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- }
-
- // Wrong type in a sub-object.
- {
- bundle.Clear();
- base::DictionaryValue dict;
- dict.SetString("one", "one");
- bundle.SetKey("Object", std::move(dict));
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- }
-
- // Unknown name.
- bundle.Clear();
- bundle.SetBoolean("Unknown", true);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
-
- // All of these will be valid.
- bundle.Clear();
- bundle.SetBoolean("Boolean", true);
- bundle.SetInteger("Integer", 123);
- bundle.Set("Null", std::make_unique<base::Value>());
- bundle.SetDouble("Number", 3.14);
- bundle.SetString("String", "omg");
-
- {
- base::ListValue list;
- list.AppendString("a string");
- list.AppendString("another string");
- bundle.SetKey("Array", std::move(list));
- }
-
- {
- base::DictionaryValue dict;
- dict.SetString("one", "string");
- dict.SetInteger("two", 2);
- base::ListValue list;
- list.GetList().push_back(dict.Clone());
- list.GetList().push_back(std::move(dict));
- bundle.SetKey("ArrayOfObjects", std::move(list));
- }
-
- {
- base::ListValue list;
- list.AppendString("a string");
- list.AppendString("another string");
- base::ListValue listlist;
- listlist.GetList().push_back(list.Clone());
- listlist.GetList().push_back(std::move(list));
- bundle.SetKey("ArrayOfArray", std::move(listlist));
- }
-
- {
- base::DictionaryValue dict;
- dict.SetBoolean("one", true);
- dict.SetInteger("two", 2);
- dict.SetString("additionally", "a string");
- dict.SetString("and also", "another string");
- bundle.SetKey("Object", std::move(dict));
- }
-
- {
- base::DictionaryValue dict;
- dict.SetInteger("Integer", 1);
- dict.SetString("String", "a string");
- dict.SetDouble("Number", 3.14);
- bundle.SetKey("ObjectWithRequiredProperties", std::move(dict));
- }
-
- bundle.SetInteger("IntegerWithEnums", 1);
- bundle.SetInteger("IntegerWithEnumsGaps", 20);
- bundle.SetString("StringWithEnums", "two");
- bundle.SetInteger("IntegerWithRange", 3);
-
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
-
- bundle.SetInteger("IntegerWithEnums", 0);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnums", 1);
-
- bundle.SetInteger("IntegerWithEnumsGaps", 0);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 9);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 10);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
- bundle.SetInteger("IntegerWithEnumsGaps", 11);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 19);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 21);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 29);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 30);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
- bundle.SetInteger("IntegerWithEnumsGaps", 31);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 100);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithEnumsGaps", 20);
-
- bundle.SetString("StringWithEnums", "FOUR");
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetString("StringWithEnums", "two");
-
- bundle.SetInteger("IntegerWithRange", 4);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- bundle.SetInteger("IntegerWithRange", 3);
-
- // Unknown top level property.
- bundle.SetString("boom", "bang");
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true);
- TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_UNKNOWN, true);
- TestSchemaValidationWithPath(schema, bundle, "");
- bundle.Remove("boom", nullptr);
-
- // Invalid top level property.
- bundle.SetInteger("Boolean", 12345);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
- TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_INVALID, true);
- TestSchemaValidationWithPath(schema, bundle, "Boolean");
- bundle.SetBoolean("Boolean", true);
-
- // Tests on ObjectOfObject.
- {
- Schema subschema = schema.GetProperty("ObjectOfObject");
- ASSERT_TRUE(subschema.valid());
- base::DictionaryValue root;
-
- // Unknown property.
- root.SetBoolean("Object.three", false);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
- TestSchemaValidationWithPath(subschema, root, "Object");
- root.Remove("Object.three", nullptr);
-
- // Invalid property.
- root.SetInteger("Object.one", 12345);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
- TestSchemaValidationWithPath(subschema, root, "Object.one");
- root.Remove("Object.one", nullptr);
- }
-
- // Tests on ArrayOfObjects.
- {
- Schema subschema = schema.GetProperty("ArrayOfObjects");
- ASSERT_TRUE(subschema.valid());
- base::ListValue root;
-
- // Unknown property.
- std::unique_ptr<base::DictionaryValue> dict_value(
- new base::DictionaryValue());
- dict_value->SetBoolean("three", true);
- root.Append(std::move(dict_value));
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
- TestSchemaValidationWithPath(subschema, root, "items[0]");
- root.Remove(root.GetSize() - 1, nullptr);
-
- // Invalid property.
- dict_value.reset(new base::DictionaryValue());
- dict_value->SetBoolean("two", true);
- root.Append(std::move(dict_value));
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
- TestSchemaValidationWithPath(subschema, root, "items[0].two");
- root.Remove(root.GetSize() - 1, nullptr);
- }
-
- // Tests on ObjectOfArray.
- {
- Schema subschema = schema.GetProperty("ObjectOfArray");
- ASSERT_TRUE(subschema.valid());
- base::DictionaryValue root;
-
- base::ListValue* list_value =
- root.SetList("List", std::make_unique<base::ListValue>());
-
- // Test that there are not errors here.
- list_value->AppendInteger(12345);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
-
- // Invalid list item.
- list_value->AppendString("blabla");
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
- TestSchemaValidationWithPath(subschema, root, "List.items[1]");
- }
-
- // Tests on ArrayOfObjectOfArray.
- {
- Schema subschema = schema.GetProperty("ArrayOfObjectOfArray");
- ASSERT_TRUE(subschema.valid());
- base::ListValue root;
-
- auto dict_value = std::make_unique<base::DictionaryValue>();
- base::ListValue* list_value =
- dict_value->SetList("List", std::make_unique<base::ListValue>());
- root.Append(std::move(dict_value));
-
- // Test that there are not errors here.
- list_value->AppendString("blabla");
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
-
- // Invalid list item.
- list_value->AppendInteger(12345);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
- TestSchemaValidationWithPath(subschema, root, "items[0].List.items[1]");
- }
-
- // Tests on StringWithPattern.
- {
- Schema subschema = schema.GetProperty("StringWithPattern");
- ASSERT_TRUE(subschema.valid());
-
- TestSchemaValidation(subschema, base::Value("foobar"), SCHEMA_STRICT,
- false);
- TestSchemaValidation(subschema, base::Value("foo"), SCHEMA_STRICT, true);
- TestSchemaValidation(subschema, base::Value("fo"), SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, base::Value("fooo"), SCHEMA_STRICT, true);
- TestSchemaValidation(subschema, base::Value("^foo+$"), SCHEMA_STRICT,
- false);
- }
-
- // Tests on ObjectWithPatternProperties.
- {
- Schema subschema = schema.GetProperty("ObjectWithPatternProperties");
- ASSERT_TRUE(subschema.valid());
- base::DictionaryValue root;
-
- ASSERT_EQ(1u, subschema.GetPatternProperties("fooo").size());
- ASSERT_EQ(1u, subschema.GetPatternProperties("foo").size());
- ASSERT_EQ(1u, subschema.GetPatternProperties("barr").size());
- ASSERT_EQ(1u, subschema.GetPatternProperties("bar").size());
- ASSERT_EQ(1u, subschema.GetMatchingProperties("fooo").size());
- ASSERT_EQ(1u, subschema.GetMatchingProperties("foo").size());
- ASSERT_EQ(1u, subschema.GetMatchingProperties("barr").size());
- ASSERT_EQ(2u, subschema.GetMatchingProperties("bar").size());
- ASSERT_TRUE(subschema.GetPatternProperties("foobar").empty());
-
- root.SetInteger("fooo", 123);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
- root.SetBoolean("fooo", false);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- root.Remove("fooo", nullptr);
-
- root.SetInteger("foo", 123);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
- root.SetBoolean("foo", false);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- root.Remove("foo", nullptr);
-
- root.SetString("barr", "one");
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
- root.SetString("barr", "three");
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- root.SetBoolean("barr", false);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- root.Remove("barr", nullptr);
-
- root.SetString("bar", "one");
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
- root.SetString("bar", "two");
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- root.SetString("bar", "three");
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- root.Remove("bar", nullptr);
-
- root.SetInteger("foobar", 123);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
- root.Remove("foobar", nullptr);
- }
-
- // Tests on ObjectWithRequiredProperties
- {
- Schema subschema = schema.GetProperty("ObjectWithRequiredProperties");
- ASSERT_TRUE(subschema.valid());
- base::DictionaryValue root;
-
- // Required property missing.
- root.SetInteger("Integer", 1);
- root.SetDouble("Number", 3.14);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, false);
-
- // Invalid required property.
- root.SetInteger("String", 123);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, false);
- root.SetString("String", "a string");
-
- // Invalid subschema of required property with multiple subschemas.
- //
- // The "Integer" property has two subschemas, one in "properties" and one
- // in "patternProperties". The first test generates a valid schema for the
- // first subschema and the second test generates a valid schema for the
- // second subschema. In both cases validation should fail because one of the
- // required properties is invalid.
- root.SetInteger("Integer", 2);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, false);
-
- root.SetInteger("Integer", 3);
- TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, false);
- TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, false);
- }
-
- // Test that integer to double promotion is allowed.
- bundle.SetInteger("Number", 31415);
- TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
-}
-
-TEST(SchemaTest, InvalidReferences) {
- // References to undeclared schemas fail.
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "properties": {
- "name": { "$ref": "undeclared" }
- }
- })"));
-
- // Can't refer to self.
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "properties": {
- "name": {
- "id": "self",
- "$ref": "self"
- }
- }
- })"));
-
- // Duplicated IDs are invalid.
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "properties": {
- "name": {
- "id": "x",
- "type": "string"
- },
- "another": {
- "id": "x",
- "type": "string"
- }
- }
- })"));
-
- // Main object can't be a reference.
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "id": "main",
- "$ref": "main"
- })"));
-
- EXPECT_TRUE(ParseFails(R"({
- "type": "object",
- "$ref": "main"
- })"));
-}
-
-TEST(SchemaTest, RecursiveReferences) {
- // Verifies that references can go to a parent schema, to define a
- // recursive type.
- std::string error;
- Schema schema = Schema::Parse(R"({
- "type": "object",
- "properties": {
- "bookmarks": {
- "type": "array",
- "id": "ListOfBookmarks",
- "items": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "url": { "type": "string" },
- "children": { "$ref": "ListOfBookmarks" }
- }
- }
- }
- }
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- Schema parent = schema.GetKnownProperty("bookmarks");
- ASSERT_TRUE(parent.valid());
- ASSERT_EQ(base::Value::Type::LIST, parent.type());
-
- // Check the recursive type a number of times.
- for (int i = 0; i < 10; ++i) {
- Schema items = parent.GetItems();
- ASSERT_TRUE(items.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, items.type());
-
- Schema prop = items.GetKnownProperty("name");
- ASSERT_TRUE(prop.valid());
- ASSERT_EQ(base::Value::Type::STRING, prop.type());
-
- prop = items.GetKnownProperty("url");
- ASSERT_TRUE(prop.valid());
- ASSERT_EQ(base::Value::Type::STRING, prop.type());
-
- prop = items.GetKnownProperty("children");
- ASSERT_TRUE(prop.valid());
- ASSERT_EQ(base::Value::Type::LIST, prop.type());
-
- parent = prop;
- }
-}
-
-TEST(SchemaTest, UnorderedReferences) {
- // Verifies that references and IDs can come in any order.
- std::string error;
- Schema schema = Schema::Parse(R"({
- "type": "object",
- "properties": {
- "a": { "$ref": "shared" },
- "b": { "$ref": "shared" },
- "c": { "$ref": "shared" },
- "d": { "$ref": "shared" },
- "e": {
- "type": "boolean",
- "id": "shared"
- },
- "f": { "$ref": "shared" },
- "g": { "$ref": "shared" },
- "h": { "$ref": "shared" },
- "i": { "$ref": "shared" }
- }
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- for (char c = 'a'; c <= 'i'; ++c) {
- Schema sub = schema.GetKnownProperty(std::string(1, c));
- ASSERT_TRUE(sub.valid()) << c;
- ASSERT_EQ(base::Value::Type::BOOLEAN, sub.type()) << c;
- }
-}
-
-TEST(SchemaTest, AdditionalPropertiesReference) {
- // Verifies that "additionalProperties" can be a reference.
- std::string error;
- Schema schema = Schema::Parse(R"({
- "type": "object",
- "properties": {
- "policy": {
- "type": "object",
- "properties": {
- "foo": {
- "type": "boolean",
- "id": "FooId"
- }
- },
- "additionalProperties": { "$ref": "FooId" }
- }
- }
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- Schema policy = schema.GetKnownProperty("policy");
- ASSERT_TRUE(policy.valid());
- ASSERT_EQ(base::Value::Type::DICTIONARY, policy.type());
-
- Schema foo = policy.GetKnownProperty("foo");
- ASSERT_TRUE(foo.valid());
- EXPECT_EQ(base::Value::Type::BOOLEAN, foo.type());
-
- Schema additional = policy.GetAdditionalProperties();
- ASSERT_TRUE(additional.valid());
- EXPECT_EQ(base::Value::Type::BOOLEAN, additional.type());
-
- Schema x = policy.GetProperty("x");
- ASSERT_TRUE(x.valid());
- EXPECT_EQ(base::Value::Type::BOOLEAN, x.type());
-}
-
-TEST(SchemaTest, ItemsReference) {
- // Verifies that "items" can be a reference.
- std::string error;
- Schema schema = Schema::Parse(R"({
- "type": "object",
- "properties": {
- "foo": {
- "type": "boolean",
- "id": "FooId"
- },
- "list": {
- "type": "array",
- "items": { "$ref": "FooId" }
- }
- }
- })",
- &error);
- ASSERT_TRUE(schema.valid()) << error;
- ASSERT_EQ(base::Value::Type::DICTIONARY, schema.type());
-
- Schema foo = schema.GetKnownProperty("foo");
- ASSERT_TRUE(foo.valid());
- EXPECT_EQ(base::Value::Type::BOOLEAN, foo.type());
-
- Schema list = schema.GetKnownProperty("list");
- ASSERT_TRUE(list.valid());
- ASSERT_EQ(base::Value::Type::LIST, list.type());
-
- Schema items = list.GetItems();
- ASSERT_TRUE(items.valid());
- ASSERT_EQ(base::Value::Type::BOOLEAN, items.type());
-}
-
-TEST(SchemaTest, EnumerationRestriction) {
- // Enum attribute is a list.
- EXPECT_TRUE(ParseFails(SchemaObjectWrapper(R"({
- "type": "string",
- "enum": 12
- })")));
-
- // Empty enum attributes is not allowed.
- EXPECT_TRUE(ParseFails(SchemaObjectWrapper(R"({
- "type": "integer",
- "enum": []
- })")));
-
- // Enum elements type should be same as stated.
- EXPECT_TRUE(ParseFails(SchemaObjectWrapper(R"({
- "type": "string",
- "enum": [1, 2, 3]
- })")));
-
- EXPECT_FALSE(ParseFails(SchemaObjectWrapper(R"({
- "type": "integer",
- "enum": [1, 2, 3]
- })")));
-
- EXPECT_FALSE(ParseFails(SchemaObjectWrapper(R"({
- "type": "string",
- "enum": ["1", "2", "3"]
- })")));
-}
-
-TEST(SchemaTest, RangedRestriction) {
- EXPECT_TRUE(ParseFails(SchemaObjectWrapper(R"({
- "type": "integer",
- "minimum": 10,
- "maximum": 5
- })")));
-
- EXPECT_FALSE(ParseFails(SchemaObjectWrapper(R"({
- "type": "integer",
- "minimum": 10,
- "maximum": 20
- })")));
-}
-
-} // namespace policy
diff --git a/components/timers/alarm_timer_unittest.cc b/components/timers/alarm_timer_unittest.cc
deleted file mode 100644
index 868eb787ab..0000000000
--- a/components/timers/alarm_timer_unittest.cc
+++ /dev/null
@@ -1,372 +0,0 @@
-// 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 <sys/timerfd.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "components/timers/alarm_timer_chromeos.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Most of these tests have been lifted right out of timer_unittest.cc with only
-// cosmetic changes. We want the AlarmTimer to be a drop-in replacement for the
-// regular Timer so it should pass the same tests as the Timer class.
-namespace timers {
-namespace {
-const base::TimeDelta kTenMilliseconds = base::TimeDelta::FromMilliseconds(10);
-
-class AlarmTimerTester {
- public:
- AlarmTimerTester(bool* did_run,
- base::TimeDelta delay,
- base::OnceClosure quit_closure)
- : did_run_(did_run),
- quit_closure_(std::move(quit_closure)),
- delay_(delay),
- timer_(new timers::SimpleAlarmTimer()) {}
- void Start() {
- timer_->Start(
- FROM_HERE, delay_,
- base::BindRepeating(&AlarmTimerTester::Run, base::Unretained(this)));
- }
-
- private:
- void Run() {
- *did_run_ = true;
- if (quit_closure_)
- std::move(quit_closure_).Run();
- }
-
- bool* did_run_;
- base::OnceClosure quit_closure_;
- const base::TimeDelta delay_;
- std::unique_ptr<timers::SimpleAlarmTimer> timer_;
-
- DISALLOW_COPY_AND_ASSIGN(AlarmTimerTester);
-};
-
-class SelfDeletingAlarmTimerTester {
- public:
- SelfDeletingAlarmTimerTester(bool* did_run,
- base::TimeDelta delay,
- base::OnceClosure quit_closure)
- : did_run_(did_run),
- quit_closure_(std::move(quit_closure)),
- delay_(delay),
- timer_(new timers::SimpleAlarmTimer()) {}
- void Start() {
- timer_->Start(FROM_HERE, delay_,
- base::BindRepeating(&SelfDeletingAlarmTimerTester::Run,
- base::Unretained(this)));
- }
-
- private:
- void Run() {
- *did_run_ = true;
- timer_.reset();
-
- if (quit_closure_)
- std::move(quit_closure_).Run();
- }
-
- bool* did_run_;
- base::OnceClosure quit_closure_;
- const base::TimeDelta delay_;
- std::unique_ptr<timers::SimpleAlarmTimer> timer_;
-
- DISALLOW_COPY_AND_ASSIGN(SelfDeletingAlarmTimerTester);
-};
-
-} // namespace
-
-//-----------------------------------------------------------------------------
-// Each test is run against each type of MessageLoop. That way we are sure
-// that timers work properly in all configurations.
-
-TEST(AlarmTimerTest, SimpleAlarmTimer) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
-
- base::RunLoop run_loop;
- bool did_run = false;
- AlarmTimerTester f(&did_run, kTenMilliseconds,
- run_loop.QuitWhenIdleClosure());
- f.Start();
-
- run_loop.Run();
-
- EXPECT_TRUE(did_run);
-}
-
-TEST(AlarmTimerTest, SimpleAlarmTimer_Cancel) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
-
- bool did_run_a = false;
- AlarmTimerTester* a =
- new AlarmTimerTester(&did_run_a, kTenMilliseconds, base::OnceClosure());
-
- // This should run before the timer expires.
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
-
- // Now start the timer.
- a->Start();
-
- base::RunLoop run_loop;
- bool did_run_b = false;
- AlarmTimerTester b(&did_run_b, kTenMilliseconds,
- run_loop.QuitWhenIdleClosure());
- b.Start();
-
- run_loop.Run();
-
- EXPECT_FALSE(did_run_a);
- EXPECT_TRUE(did_run_b);
-}
-
-// If underlying timer does not handle this properly, we will crash or fail
-// in full page heap environment.
-TEST(AlarmTimerTest, SelfDeletingAlarmTimer) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
-
- base::RunLoop run_loop;
- bool did_run = false;
- SelfDeletingAlarmTimerTester f(&did_run, kTenMilliseconds,
- run_loop.QuitWhenIdleClosure());
- f.Start();
-
- run_loop.Run();
-
- EXPECT_TRUE(did_run);
-}
-
-TEST(AlarmTimerTest, AlarmTimerZeroDelay) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
-
- base::RunLoop run_loop;
- bool did_run = false;
- AlarmTimerTester f(&did_run, base::TimeDelta(),
- run_loop.QuitWhenIdleClosure());
- f.Start();
-
- run_loop.Run();
-
- EXPECT_TRUE(did_run);
-}
-
-TEST(AlarmTimerTest, AlarmTimerZeroDelay_Cancel) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
-
- bool did_run_a = false;
- AlarmTimerTester* a =
- new AlarmTimerTester(&did_run_a, base::TimeDelta(), base::OnceClosure());
-
- // This should run before the timer expires.
- base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
-
- // Now start the timer.
- a->Start();
-
- base::RunLoop run_loop;
- bool did_run_b = false;
- AlarmTimerTester b(&did_run_b, base::TimeDelta(),
- run_loop.QuitWhenIdleClosure());
- b.Start();
-
- run_loop.Run();
-
- EXPECT_FALSE(did_run_a);
- EXPECT_TRUE(did_run_b);
-}
-
-TEST(AlarmTimerTest, MessageLoopShutdown) {
- // This test is designed to verify that shutdown of the
- // message loop does not cause crashes if there were pending
- // timers not yet fired. It may only trigger exceptions
- // if debug heap checking is enabled.
- bool did_run = false;
- {
- auto loop = std::make_unique<base::MessageLoopForIO>();
- auto file_descriptor_watcher =
- std::make_unique<base::FileDescriptorWatcher>(loop.get());
- AlarmTimerTester a(&did_run, kTenMilliseconds, base::OnceClosure());
- AlarmTimerTester b(&did_run, kTenMilliseconds, base::OnceClosure());
- AlarmTimerTester c(&did_run, kTenMilliseconds, base::OnceClosure());
- AlarmTimerTester d(&did_run, kTenMilliseconds, base::OnceClosure());
-
- a.Start();
- b.Start();
-
- // Allow FileDescriptorWatcher to start watching the timers. Without this,
- // tasks posted by FileDescriptorWatcher::WatchReadable() are leaked.
- base::RunLoop().RunUntilIdle();
-
- // MessageLoop and FileDescriptorWatcher destruct.
- file_descriptor_watcher.reset();
- loop.reset();
- } // SimpleAlarmTimers destruct. SHOULD NOT CRASH, of course.
-
- EXPECT_FALSE(did_run);
-}
-
-TEST(AlarmTimerTest, NonRepeatIsRunning) {
- {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- timers::SimpleAlarmTimer timer;
- EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
-
- // Allow FileDescriptorWatcher to start watching the timer. Without this, a
- // task posted by FileDescriptorWatcher::WatchReadable() is leaked.
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(timer.IsRunning());
- timer.Stop();
- EXPECT_FALSE(timer.IsRunning());
- ASSERT_FALSE(timer.user_task().is_null());
- timer.Reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(timer.IsRunning());
- }
-}
-
-TEST(AlarmTimerTest, RetainNonRepeatIsRunning) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- timers::SimpleAlarmTimer timer;
- EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
-
- // Allow FileDescriptorWatcher to start watching the timer. Without this, a
- // task posted by FileDescriptorWatcher::WatchReadable() is leaked.
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(timer.IsRunning());
- timer.Reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(timer.IsRunning());
- timer.Stop();
- EXPECT_FALSE(timer.IsRunning());
- timer.Reset();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(timer.IsRunning());
-}
-
-namespace {
-
-bool g_callback_happened1 = false;
-bool g_callback_happened2 = false;
-
-void ClearAllCallbackHappened() {
- g_callback_happened1 = false;
- g_callback_happened2 = false;
-}
-
-void SetCallbackHappened1(base::OnceClosure quit_closure) {
- g_callback_happened1 = true;
- if (quit_closure)
- std::move(quit_closure).Run();
-}
-
-void SetCallbackHappened2(base::OnceClosure quit_closure) {
- g_callback_happened2 = true;
- if (quit_closure)
- std::move(quit_closure).Run();
-}
-
-TEST(AlarmTimerTest, ContinuationStopStart) {
- ClearAllCallbackHappened();
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- timers::SimpleAlarmTimer timer;
- timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::BindRepeating(&SetCallbackHappened1,
- base::DoNothing().Repeatedly()));
- timer.Stop();
-
- base::RunLoop run_loop;
- timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(40),
- base::BindRepeating(&SetCallbackHappened2,
- run_loop.QuitWhenIdleClosure()));
- run_loop.Run();
-
- EXPECT_FALSE(g_callback_happened1);
- EXPECT_TRUE(g_callback_happened2);
-}
-
-TEST(AlarmTimerTest, ContinuationReset) {
- ClearAllCallbackHappened();
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
-
- base::RunLoop run_loop;
- timers::SimpleAlarmTimer timer;
- timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::BindRepeating(&SetCallbackHappened1,
- run_loop.QuitWhenIdleClosure()));
- timer.Reset();
- ASSERT_FALSE(timer.user_task().is_null());
- run_loop.Run();
- EXPECT_TRUE(g_callback_happened1);
-}
-
-// Verify that no crash occurs if a timer is deleted while its callback is
-// running.
-TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunning) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- base::RunLoop run_loop;
-
- // Will be deleted by the callback.
- timers::SimpleAlarmTimer* timer = new timers::SimpleAlarmTimer;
-
- timer->Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(10),
- base::BindRepeating(
- [](timers::SimpleAlarmTimer* timer, base::RunLoop* run_loop) {
- delete timer;
- run_loop->Quit();
- },
- timer, &run_loop));
- run_loop.Run();
-}
-
-// Verify that no crash occurs if a zero-delay timer is deleted while its
-// callback is running.
-TEST(AlarmTimerTest, DeleteTimerWhileCallbackIsRunningZeroDelay) {
- base::MessageLoopForIO loop;
- base::FileDescriptorWatcher file_descriptor_watcher(&loop);
- base::RunLoop run_loop;
-
- // Will be deleted by the callback.
- timers::SimpleAlarmTimer* timer = new timers::SimpleAlarmTimer;
-
- timer->Start(
- FROM_HERE, base::TimeDelta(),
- base::BindRepeating(
- [](timers::SimpleAlarmTimer* timer, base::RunLoop* run_loop) {
- delete timer;
- run_loop->Quit();
- },
- timer, &run_loop));
- run_loop.Run();
-}
-
-} // namespace
-} // namespace timers
diff --git a/dbus/bus_unittest.cc b/dbus/bus_unittest.cc
deleted file mode 100644
index f00d1e9374..0000000000
--- a/dbus/bus_unittest.cc
+++ /dev/null
@@ -1,420 +0,0 @@
-// Copyright (c) 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.
-
-#include "dbus/bus.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/threading/thread.h"
-#include "dbus/exported_object.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "dbus/scoped_dbus_error.h"
-#include "dbus/test_service.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-namespace {
-
-// Test helper for BusTest.ListenForServiceOwnerChange that wraps a
-// base::RunLoop. At Run() time, the caller pass in the expected number of
-// quit calls, and at QuitIfConditionIsSatisified() time, only quit the RunLoop
-// if the expected number of quit calls have been reached.
-class RunLoopWithExpectedCount {
- public:
- RunLoopWithExpectedCount() : expected_quit_calls_(0), actual_quit_calls_(0) {}
- ~RunLoopWithExpectedCount() = default;
-
- void Run(int expected_quit_calls) {
- DCHECK_EQ(0, expected_quit_calls_);
- DCHECK_EQ(0, actual_quit_calls_);
- expected_quit_calls_ = expected_quit_calls;
- run_loop_.reset(new base::RunLoop());
- run_loop_->Run();
- }
-
- void QuitIfConditionIsSatisified() {
- if (++actual_quit_calls_ != expected_quit_calls_)
- return;
- run_loop_->Quit();
- expected_quit_calls_ = 0;
- actual_quit_calls_ = 0;
- }
-
- private:
- std::unique_ptr<base::RunLoop> run_loop_;
- int expected_quit_calls_;
- int actual_quit_calls_;
-
- DISALLOW_COPY_AND_ASSIGN(RunLoopWithExpectedCount);
-};
-
-// Test helper for BusTest.ListenForServiceOwnerChange.
-void OnServiceOwnerChanged(RunLoopWithExpectedCount* run_loop_state,
- std::string* service_owner,
- int* num_of_owner_changes,
- const std::string& new_service_owner) {
- *service_owner = new_service_owner;
- ++(*num_of_owner_changes);
- run_loop_state->QuitIfConditionIsSatisified();
-}
-
-} // namespace
-
-TEST(BusTest, GetObjectProxy) {
- Bus::Options options;
- scoped_refptr<Bus> bus = new Bus(options);
-
- ObjectProxy* object_proxy1 =
- bus->GetObjectProxy("org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy1);
-
- // This should return the same object.
- ObjectProxy* object_proxy2 =
- bus->GetObjectProxy("org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy2);
- EXPECT_EQ(object_proxy1, object_proxy2);
-
- // This should not.
- ObjectProxy* object_proxy3 =
- bus->GetObjectProxy(
- "org.chromium.TestService",
- ObjectPath("/org/chromium/DifferentTestObject"));
- ASSERT_TRUE(object_proxy3);
- EXPECT_NE(object_proxy1, object_proxy3);
-
- bus->ShutdownAndBlock();
-}
-
-TEST(BusTest, GetObjectProxyIgnoreUnknownService) {
- Bus::Options options;
- scoped_refptr<Bus> bus = new Bus(options);
-
- ObjectProxy* object_proxy1 =
- bus->GetObjectProxyWithOptions(
- "org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"),
- ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
- ASSERT_TRUE(object_proxy1);
-
- // This should return the same object.
- ObjectProxy* object_proxy2 =
- bus->GetObjectProxyWithOptions(
- "org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"),
- ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
- ASSERT_TRUE(object_proxy2);
- EXPECT_EQ(object_proxy1, object_proxy2);
-
- // This should not.
- ObjectProxy* object_proxy3 =
- bus->GetObjectProxyWithOptions(
- "org.chromium.TestService",
- ObjectPath("/org/chromium/DifferentTestObject"),
- ObjectProxy::IGNORE_SERVICE_UNKNOWN_ERRORS);
- ASSERT_TRUE(object_proxy3);
- EXPECT_NE(object_proxy1, object_proxy3);
-
- bus->ShutdownAndBlock();
-}
-
-TEST(BusTest, RemoveObjectProxy) {
- // Setup the current thread's MessageLoop.
- base::MessageLoop message_loop;
-
- // Start the D-Bus thread.
- base::Thread::Options thread_options;
- thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
- base::Thread dbus_thread("D-Bus thread");
- dbus_thread.StartWithOptions(thread_options);
-
- // Create the bus.
- Bus::Options options;
- options.dbus_task_runner = dbus_thread.task_runner();
- scoped_refptr<Bus> bus = new Bus(options);
- ASSERT_FALSE(bus->shutdown_completed());
-
- // Try to remove a non existant object proxy should return false.
- ASSERT_FALSE(bus->RemoveObjectProxy("org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"),
- base::DoNothing()));
-
- ObjectProxy* object_proxy1 =
- bus->GetObjectProxy("org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy1);
-
- // Increment the reference count to the object proxy to avoid destroying it
- // while removing the object.
- object_proxy1->AddRef();
-
- // Remove the object from the bus. This will invalidate any other usage of
- // object_proxy1 other than destroy it. We keep this object for a comparison
- // at a later time.
- ASSERT_TRUE(bus->RemoveObjectProxy("org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"),
- base::DoNothing()));
-
- // This should return a different object because the first object was removed
- // from the bus, but not deleted from memory.
- ObjectProxy* object_proxy2 =
- bus->GetObjectProxy("org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy2);
-
- // Compare the new object with the first object. The first object still exists
- // thanks to the increased reference.
- EXPECT_NE(object_proxy1, object_proxy2);
-
- // Release object_proxy1.
- object_proxy1->Release();
-
- // Shut down synchronously.
- bus->ShutdownOnDBusThreadAndBlock();
- EXPECT_TRUE(bus->shutdown_completed());
- dbus_thread.Stop();
-}
-
-TEST(BusTest, GetExportedObject) {
- Bus::Options options;
- scoped_refptr<Bus> bus = new Bus(options);
-
- ExportedObject* object_proxy1 =
- bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy1);
-
- // This should return the same object.
- ExportedObject* object_proxy2 =
- bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy2);
- EXPECT_EQ(object_proxy1, object_proxy2);
-
- // This should not.
- ExportedObject* object_proxy3 =
- bus->GetExportedObject(
- ObjectPath("/org/chromium/DifferentTestObject"));
- ASSERT_TRUE(object_proxy3);
- EXPECT_NE(object_proxy1, object_proxy3);
-
- bus->ShutdownAndBlock();
-}
-
-TEST(BusTest, UnregisterExportedObject) {
- // Start the D-Bus thread.
- base::Thread::Options thread_options;
- thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
- base::Thread dbus_thread("D-Bus thread");
- dbus_thread.StartWithOptions(thread_options);
-
- // Create the bus.
- Bus::Options options;
- options.dbus_task_runner = dbus_thread.task_runner();
- scoped_refptr<Bus> bus = new Bus(options);
- ASSERT_FALSE(bus->shutdown_completed());
-
- ExportedObject* object_proxy1 =
- bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy1);
-
- // Increment the reference count to the object proxy to avoid destroying it
- // calling UnregisterExportedObject. This ensures the dbus::ExportedObject is
- // not freed from memory. See http://crbug.com/137846 for details.
- object_proxy1->AddRef();
-
- bus->UnregisterExportedObject(ObjectPath("/org/chromium/TestObject"));
-
- // This should return a new object because the object_proxy1 is still in
- // alloc'ed memory.
- ExportedObject* object_proxy2 =
- bus->GetExportedObject(ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(object_proxy2);
- EXPECT_NE(object_proxy1, object_proxy2);
-
- // Release the incremented reference.
- object_proxy1->Release();
-
- // Shut down synchronously.
- bus->ShutdownOnDBusThreadAndBlock();
- EXPECT_TRUE(bus->shutdown_completed());
- dbus_thread.Stop();
-}
-
-TEST(BusTest, ShutdownAndBlock) {
- Bus::Options options;
- scoped_refptr<Bus> bus = new Bus(options);
- ASSERT_FALSE(bus->shutdown_completed());
-
- // Shut down synchronously.
- bus->ShutdownAndBlock();
- EXPECT_TRUE(bus->shutdown_completed());
-}
-
-TEST(BusTest, ShutdownAndBlockWithDBusThread) {
- // Start the D-Bus thread.
- base::Thread::Options thread_options;
- thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
- base::Thread dbus_thread("D-Bus thread");
- dbus_thread.StartWithOptions(thread_options);
-
- // Create the bus.
- Bus::Options options;
- options.dbus_task_runner = dbus_thread.task_runner();
- scoped_refptr<Bus> bus = new Bus(options);
- ASSERT_FALSE(bus->shutdown_completed());
-
- // Shut down synchronously.
- bus->ShutdownOnDBusThreadAndBlock();
- EXPECT_TRUE(bus->shutdown_completed());
- dbus_thread.Stop();
-}
-
-TEST(BusTest, DoubleAddAndRemoveMatch) {
- Bus::Options options;
- scoped_refptr<Bus> bus = new Bus(options);
- ScopedDBusError error;
-
- bus->Connect();
-
- // Adds the same rule twice.
- bus->AddMatch(
- "type='signal',interface='org.chromium.TestService',path='/'",
- error.get());
- ASSERT_FALSE(error.is_set());
-
- bus->AddMatch(
- "type='signal',interface='org.chromium.TestService',path='/'",
- error.get());
- ASSERT_FALSE(error.is_set());
-
- // Removes the same rule twice.
- ASSERT_TRUE(bus->RemoveMatch(
- "type='signal',interface='org.chromium.TestService',path='/'",
- error.get()));
- ASSERT_FALSE(error.is_set());
-
- // The rule should be still in the bus since it was removed only once.
- // A second removal shouldn't give an error.
- ASSERT_TRUE(bus->RemoveMatch(
- "type='signal',interface='org.chromium.TestService',path='/'",
- error.get()));
- ASSERT_FALSE(error.is_set());
-
- // A third attemp to remove the same rule should fail.
- ASSERT_FALSE(bus->RemoveMatch(
- "type='signal',interface='org.chromium.TestService',path='/'",
- error.get()));
-
- bus->ShutdownAndBlock();
-}
-
-TEST(BusTest, ListenForServiceOwnerChange) {
- base::MessageLoopForIO message_loop;
-
- // This enables FileDescriptorWatcher, which is required by dbus::Watch.
- base::FileDescriptorWatcher file_descriptor_watcher(&message_loop);
-
- RunLoopWithExpectedCount run_loop_state;
-
- // Create the bus.
- Bus::Options bus_options;
- scoped_refptr<Bus> bus = new Bus(bus_options);
-
- // Add a listener.
- std::string service_owner1;
- int num_of_owner_changes1 = 0;
- Bus::GetServiceOwnerCallback callback1 =
- base::Bind(&OnServiceOwnerChanged,
- &run_loop_state,
- &service_owner1,
- &num_of_owner_changes1);
- bus->ListenForServiceOwnerChange("org.chromium.TestService", callback1);
- // This should be a no-op.
- bus->ListenForServiceOwnerChange("org.chromium.TestService", callback1);
- base::RunLoop().RunUntilIdle();
-
- // Nothing has happened yet. Check initial state.
- EXPECT_TRUE(service_owner1.empty());
- EXPECT_EQ(0, num_of_owner_changes1);
-
- // Make an ownership change.
- ASSERT_TRUE(bus->RequestOwnershipAndBlock("org.chromium.TestService",
- Bus::REQUIRE_PRIMARY));
- run_loop_state.Run(1);
-
- {
- // Get the current service owner and check to make sure the listener got
- // the right value.
- std::string current_service_owner =
- bus->GetServiceOwnerAndBlock("org.chromium.TestService",
- Bus::REPORT_ERRORS);
- ASSERT_FALSE(current_service_owner.empty());
-
- // Make sure the listener heard about the new owner.
- EXPECT_EQ(current_service_owner, service_owner1);
-
- // Test the second ListenForServiceOwnerChange() above is indeed a no-op.
- EXPECT_EQ(1, num_of_owner_changes1);
- }
-
- // Add a second listener.
- std::string service_owner2;
- int num_of_owner_changes2 = 0;
- Bus::GetServiceOwnerCallback callback2 =
- base::Bind(&OnServiceOwnerChanged,
- &run_loop_state,
- &service_owner2,
- &num_of_owner_changes2);
- bus->ListenForServiceOwnerChange("org.chromium.TestService", callback2);
- base::RunLoop().RunUntilIdle();
-
- // Release the ownership and make sure the service owner listeners fire with
- // the right values and the right number of times.
- ASSERT_TRUE(bus->ReleaseOwnership("org.chromium.TestService"));
- run_loop_state.Run(2);
-
- EXPECT_TRUE(service_owner1.empty());
- EXPECT_TRUE(service_owner2.empty());
- EXPECT_EQ(2, num_of_owner_changes1);
- EXPECT_EQ(1, num_of_owner_changes2);
-
- // Unlisten so shutdown can proceed correctly.
- bus->UnlistenForServiceOwnerChange("org.chromium.TestService", callback1);
- bus->UnlistenForServiceOwnerChange("org.chromium.TestService", callback2);
- base::RunLoop().RunUntilIdle();
-
- // Shut down synchronously.
- bus->ShutdownAndBlock();
- EXPECT_TRUE(bus->shutdown_completed());
-}
-
-TEST(BusTest, GetConnectionName) {
- Bus::Options options;
- scoped_refptr<Bus> bus = new Bus(options);
-
- // Connection name is empty since bus is not connected.
- EXPECT_FALSE(bus->is_connected());
- EXPECT_TRUE(bus->GetConnectionName().empty());
-
- // Connect bus to D-Bus.
- bus->Connect();
-
- // Connection name is not empty after connection is established.
- EXPECT_TRUE(bus->is_connected());
- EXPECT_FALSE(bus->GetConnectionName().empty());
-
- // Shut down synchronously.
- bus->ShutdownAndBlock();
- EXPECT_TRUE(bus->shutdown_completed());
-}
-
-} // namespace dbus
diff --git a/dbus/dbus_statistics_unittest.cc b/dbus/dbus_statistics_unittest.cc
deleted file mode 100644
index 164d0b3521..0000000000
--- a/dbus/dbus_statistics_unittest.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) 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.
-
-#include "dbus/dbus_statistics.h"
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-class DBusStatisticsTest : public testing::Test {
- public:
- DBusStatisticsTest() = default;
-
- void SetUp() override { statistics::Initialize(); }
-
- void TearDown() override { statistics::Shutdown(); }
-
- protected:
- void AddTestMethodCalls() {
- statistics::AddSentMethodCall(
- "service1", "service1.interface1", "method1");
- statistics::AddReceivedSignal(
- "service1", "service1.interface1", "method1");
- statistics::AddBlockingSentMethodCall(
- "service1", "service1.interface1", "method1");
-
- statistics::AddSentMethodCall(
- "service1", "service1.interface1", "method2");
- statistics::AddSentMethodCall(
- "service1", "service1.interface1", "method2");
- statistics::AddReceivedSignal(
- "service1", "service1.interface1", "method2");
-
- statistics::AddSentMethodCall(
- "service1", "service1.interface1", "method3");
- statistics::AddSentMethodCall(
- "service1", "service1.interface1", "method3");
- statistics::AddSentMethodCall(
- "service1", "service1.interface1", "method3");
-
- statistics::AddSentMethodCall(
- "service1", "service1.interface2", "method1");
-
- statistics::AddSentMethodCall(
- "service1", "service1.interface2", "method2");
-
- statistics::AddSentMethodCall(
- "service2", "service2.interface1", "method1");
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DBusStatisticsTest);
-};
-
-TEST_F(DBusStatisticsTest, TestDBusStatsBasic) {
- int sent = 0, received = 0, block = 0;
-
- // Add a sent call
- statistics::AddSentMethodCall("service1", "service1.interface1", "method1");
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface1", "method1", &sent, &received, &block));
- EXPECT_EQ(1, sent);
- EXPECT_EQ(0, received);
- EXPECT_EQ(0, block);
-
- // Add a received call
- statistics::AddReceivedSignal("service1", "service1.interface1", "method1");
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface1", "method1", &sent, &received, &block));
- EXPECT_EQ(1, sent);
- EXPECT_EQ(1, received);
- EXPECT_EQ(0, block);
-
- // Add a block call
- statistics::AddBlockingSentMethodCall(
- "service1", "service1.interface1", "method1");
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface1", "method1", &sent, &received, &block));
- EXPECT_EQ(1, sent);
- EXPECT_EQ(1, received);
- EXPECT_EQ(1, block);
-}
-
-TEST_F(DBusStatisticsTest, TestDBusStatsMulti) {
- int sent = 0, received = 0, block = 0;
-
- // Add some more stats to exercise accessing multiple different stats.
- AddTestMethodCalls();
-
- // Make sure all entries can be found in the set and their counts were
- // incremented correctly.
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface1", "method1", &sent, &received, &block));
- EXPECT_EQ(1, sent);
- EXPECT_EQ(1, received);
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface1", "method2", &sent, &received, &block));
- EXPECT_EQ(2, sent);
- EXPECT_EQ(1, received);
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface1", "method3", &sent, &received, &block));
- EXPECT_EQ(3, sent);
- EXPECT_EQ(0, received);
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface2", "method1", &sent, &received, &block));
- EXPECT_EQ(1, sent);
- EXPECT_EQ(0, received);
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service1", "service1.interface2", "method2", &sent, &received, &block));
- EXPECT_EQ(1, sent);
- EXPECT_EQ(0, received);
- ASSERT_TRUE(statistics::testing::GetCalls(
- "service2", "service2.interface1", "method1", &sent, &received, &block));
- EXPECT_EQ(1, sent);
- EXPECT_EQ(0, received);
-
- ASSERT_FALSE(statistics::testing::GetCalls(
- "service1", "service1.interface3", "method2", &sent, &received, &block));
-}
-
-TEST_F(DBusStatisticsTest, TestGetAsString) {
- std::string output_none = GetAsString(statistics::SHOW_SERVICE,
- statistics::FORMAT_TOTALS);
- EXPECT_EQ("No DBus calls.", output_none);
-
- AddTestMethodCalls();
-
- std::string output_service = GetAsString(statistics::SHOW_SERVICE,
- statistics::FORMAT_TOTALS);
- const std::string expected_output_service(
- "service1: Sent (BLOCKING): 1 Sent: 8 Received: 2\n"
- "service2: Sent: 1\n");
- EXPECT_EQ(expected_output_service, output_service);
-
- std::string output_interface = GetAsString(statistics::SHOW_INTERFACE,
- statistics::FORMAT_TOTALS);
- const std::string expected_output_interface(
- "service1.interface1: Sent (BLOCKING): 1 Sent: 6 Received: 2\n"
- "service1.interface2: Sent: 2\n"
- "service2.interface1: Sent: 1\n");
- EXPECT_EQ(expected_output_interface, output_interface);
-
- std::string output_per_minute = GetAsString(statistics::SHOW_INTERFACE,
- statistics::FORMAT_PER_MINUTE);
- const std::string expected_output_per_minute(
- "service1.interface1: Sent (BLOCKING): 1/min Sent: 6/min"
- " Received: 2/min\n"
- "service1.interface2: Sent: 2/min\n"
- "service2.interface1: Sent: 1/min\n");
- EXPECT_EQ(expected_output_per_minute, output_per_minute);
-
- std::string output_all = GetAsString(statistics::SHOW_INTERFACE,
- statistics::FORMAT_ALL);
- const std::string expected_output_all(
- "service1.interface1: Sent (BLOCKING): 1 (1/min) Sent: 6 (6/min)"
- " Received: 2 (2/min)\n"
- "service1.interface2: Sent: 2 (2/min)\n"
- "service2.interface1: Sent: 1 (1/min)\n");
- EXPECT_EQ(expected_output_all, output_all);
-
-
- std::string output_method = GetAsString(statistics::SHOW_METHOD,
- statistics::FORMAT_TOTALS);
- const std::string expected_output_method(
- "service1.interface1.method1: Sent (BLOCKING): 1 Sent: 1 Received: 1\n"
- "service1.interface1.method2: Sent: 2 Received: 1\n"
- "service1.interface1.method3: Sent: 3\n"
- "service1.interface2.method1: Sent: 1\n"
- "service1.interface2.method2: Sent: 1\n"
- "service2.interface1.method1: Sent: 1\n");
- EXPECT_EQ(expected_output_method, output_method);
-
-}
-
-} // namespace dbus
diff --git a/dbus/end_to_end_async_unittest.cc b/dbus/end_to_end_async_unittest.cc
deleted file mode 100644
index 73e11c4b56..0000000000
--- a/dbus/end_to_end_async_unittest.cc
+++ /dev/null
@@ -1,645 +0,0 @@
-// Copyright (c) 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.
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "dbus/bus.h"
-#include "dbus/message.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "dbus/test_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-namespace {
-
-// See comments in ObjectProxy::RunResponseCallback() for why the number was
-// chosen.
-const int kHugePayloadSize = 64 << 20; // 64 MB
-
-} // namespace
-
-// The end-to-end test exercises the asynchronous APIs in ObjectProxy and
-// ExportedObject.
-class EndToEndAsyncTest : public testing::Test {
- public:
- void SetUp() override {
- // Make the main thread not to allow IO.
- base::ThreadRestrictions::SetIOAllowed(false);
-
- // Start the D-Bus thread.
- dbus_thread_.reset(new base::Thread("D-Bus Thread"));
- base::Thread::Options thread_options;
- thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
- ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
-
- // Start the test service, using the D-Bus thread.
- TestService::Options options;
- options.dbus_task_runner = dbus_thread_->task_runner();
- test_service_.reset(new TestService(options));
- ASSERT_TRUE(test_service_->StartService());
- ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service_->HasDBusThread());
-
- // Create the client, using the D-Bus thread.
- Bus::Options bus_options;
- bus_options.bus_type = Bus::SESSION;
- bus_options.connection_type = Bus::PRIVATE;
- bus_options.dbus_task_runner = dbus_thread_->task_runner();
- bus_ = new Bus(bus_options);
- object_proxy_ = bus_->GetObjectProxy(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(bus_->HasDBusThread());
-
- // Connect to the "Test" signal of "org.chromium.TestInterface" from
- // the remote object.
- object_proxy_->ConnectToSignal(
- "org.chromium.TestInterface",
- "Test",
- base::Bind(&EndToEndAsyncTest::OnTestSignal,
- base::Unretained(this)),
- base::Bind(&EndToEndAsyncTest::OnConnected,
- base::Unretained(this)));
- // Wait until the object proxy is connected to the signal.
- run_loop_.reset(new base::RunLoop());
- run_loop_->Run();
-
- // Connect to the "Test2" signal of "org.chromium.TestInterface" from
- // the remote object. There was a bug where we were emitting error
- // messages like "Requested to remove an unknown match rule: ..." at
- // the shutdown of Bus when an object proxy is connected to more than
- // one signal of the same interface. See crosbug.com/23382 for details.
- object_proxy_->ConnectToSignal(
- "org.chromium.TestInterface",
- "Test2",
- base::Bind(&EndToEndAsyncTest::OnTest2Signal,
- base::Unretained(this)),
- base::Bind(&EndToEndAsyncTest::OnConnected,
- base::Unretained(this)));
- // Wait until the object proxy is connected to the signal.
- run_loop_.reset(new base::RunLoop());
- run_loop_->Run();
-
- // Create a second object proxy for the root object.
- root_object_proxy_ = bus_->GetObjectProxy(test_service_->service_name(),
- ObjectPath("/"));
- ASSERT_TRUE(bus_->HasDBusThread());
-
- // Connect to the "Test" signal of "org.chromium.TestInterface" from
- // the root remote object too.
- root_object_proxy_->ConnectToSignal(
- "org.chromium.TestInterface",
- "Test",
- base::Bind(&EndToEndAsyncTest::OnRootTestSignal,
- base::Unretained(this)),
- base::Bind(&EndToEndAsyncTest::OnConnected,
- base::Unretained(this)));
- // Wait until the root object proxy is connected to the signal.
- run_loop_.reset(new base::RunLoop());
- run_loop_->Run();
- }
-
- void TearDown() override {
- bus_->ShutdownOnDBusThreadAndBlock();
-
- // Shut down the service.
- test_service_->ShutdownAndBlock();
-
- // Reset to the default.
- base::ThreadRestrictions::SetIOAllowed(true);
-
- // Stopping a thread is considered an IO operation, so do this after
- // allowing IO.
- test_service_->Stop();
- }
-
- protected:
- // Replaces the bus with a broken one.
- void SetUpBrokenBus() {
- // Shut down the existing bus.
- bus_->ShutdownOnDBusThreadAndBlock();
-
- // Create new bus with invalid address.
- const char kInvalidAddress[] = "";
- Bus::Options bus_options;
- bus_options.bus_type = Bus::CUSTOM_ADDRESS;
- bus_options.address = kInvalidAddress;
- bus_options.connection_type = Bus::PRIVATE;
- bus_options.dbus_task_runner = dbus_thread_->task_runner();
- bus_ = new Bus(bus_options);
- ASSERT_TRUE(bus_->HasDBusThread());
-
- // Create new object proxy.
- object_proxy_ = bus_->GetObjectProxy(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestObject"));
- }
-
- // Calls the method asynchronously. OnResponse() will be called once the
- // response is received.
- void CallMethod(MethodCall* method_call,
- int timeout_ms) {
- object_proxy_->CallMethod(method_call,
- timeout_ms,
- base::Bind(&EndToEndAsyncTest::OnResponse,
- base::Unretained(this)));
- }
-
- // Calls the method asynchronously. OnResponse() will be called once the
- // response is received without error, otherwise OnError() will be called.
- void CallMethodWithErrorCallback(MethodCall* method_call,
- int timeout_ms) {
- object_proxy_->CallMethodWithErrorCallback(
- method_call,
- timeout_ms,
- base::Bind(&EndToEndAsyncTest::OnResponse, base::Unretained(this)),
- base::Bind(&EndToEndAsyncTest::OnError, base::Unretained(this)));
- }
-
- // Wait for the give number of responses.
- void WaitForResponses(size_t num_responses) {
- while (response_strings_.size() < num_responses) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- }
-
- // Called when the response is received.
- void OnResponse(Response* response) {
- // |response| will be deleted on exit of the function. Copy the
- // payload to |response_strings_|.
- if (response) {
- MessageReader reader(response);
- std::string response_string;
- ASSERT_TRUE(reader.PopString(&response_string));
- response_strings_.push_back(response_string);
- } else {
- response_strings_.push_back(std::string());
- }
- run_loop_->Quit();
- };
-
- // Wait for the given number of errors.
- void WaitForErrors(size_t num_errors) {
- while (error_names_.size() < num_errors) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- }
-
- // Called when an error is received.
- void OnError(ErrorResponse* error) {
- // |error| will be deleted on exit of the function. Copy the payload to
- // |error_names_|.
- if (error) {
- ASSERT_NE("", error->GetErrorName());
- error_names_.push_back(error->GetErrorName());
- } else {
- error_names_.push_back(std::string());
- }
- run_loop_->Quit();
- }
-
- // Called when the "Test" signal is received, in the main thread.
- // Copy the string payload to |test_signal_string_|.
- void OnTestSignal(Signal* signal) {
- MessageReader reader(signal);
- ASSERT_TRUE(reader.PopString(&test_signal_string_));
- run_loop_->Quit();
- }
-
- // Called when the "Test" signal is received, in the main thread, by
- // the root object proxy. Copy the string payload to
- // |root_test_signal_string_|.
- void OnRootTestSignal(Signal* signal) {
- MessageReader reader(signal);
- ASSERT_TRUE(reader.PopString(&root_test_signal_string_));
- run_loop_->Quit();
- }
-
- // Called when the "Test2" signal is received, in the main thread.
- void OnTest2Signal(Signal* signal) {
- MessageReader reader(signal);
- run_loop_->Quit();
- }
-
- // Called when connected to the signal.
- void OnConnected(const std::string& interface_name,
- const std::string& signal_name,
- bool success) {
- ASSERT_TRUE(success);
- run_loop_->Quit();
- }
-
- // Wait for the hey signal to be received.
- void WaitForTestSignal() {
- // OnTestSignal() will quit the message loop.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
-
- base::MessageLoop message_loop_;
- std::unique_ptr<base::RunLoop> run_loop_;
- std::vector<std::string> response_strings_;
- std::vector<std::string> error_names_;
- std::unique_ptr<base::Thread> dbus_thread_;
- scoped_refptr<Bus> bus_;
- ObjectProxy* object_proxy_;
- ObjectProxy* root_object_proxy_;
- std::unique_ptr<TestService> test_service_;
- // Text message from "Test" signal.
- std::string test_signal_string_;
- // Text message from "Test" signal delivered to root.
- std::string root_test_signal_string_;
-};
-
-TEST_F(EndToEndAsyncTest, Echo) {
- const char* kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
-
- // Check the response.
- WaitForResponses(1);
- EXPECT_EQ(kHello, response_strings_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, EchoWithErrorCallback) {
- const char* kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethodWithErrorCallback(&method_call, timeout_ms);
-
- // Check the response.
- WaitForResponses(1);
- EXPECT_EQ(kHello, response_strings_[0]);
- EXPECT_TRUE(error_names_.empty());
-}
-
-// Call Echo method three times.
-TEST_F(EndToEndAsyncTest, EchoThreeTimes) {
- const char* kMessages[] = { "foo", "bar", "baz" };
-
- for (size_t i = 0; i < arraysize(kMessages); ++i) {
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kMessages[i]);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
- }
-
- // Check the responses.
- WaitForResponses(3);
- // Sort as the order of the returned messages is not deterministic.
- std::sort(response_strings_.begin(), response_strings_.end());
- EXPECT_EQ("bar", response_strings_[0]);
- EXPECT_EQ("baz", response_strings_[1]);
- EXPECT_EQ("foo", response_strings_[2]);
-}
-
-TEST_F(EndToEndAsyncTest, Echo_HugePayload) {
- const std::string kHugePayload(kHugePayloadSize, 'o');
-
- // Create the method call with a huge payload.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHugePayload);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
-
- // This caused a DCHECK failure before. Ensure that the issue is fixed.
- WaitForResponses(1);
- EXPECT_EQ(kHugePayload, response_strings_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, BrokenBus) {
- const char* kHello = "hello";
-
- // Set up a broken bus.
- SetUpBrokenBus();
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
- WaitForResponses(1);
-
- // Should fail because of the broken bus.
- ASSERT_EQ("", response_strings_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, BrokenBusWithErrorCallback) {
- const char* kHello = "hello";
-
- // Set up a broken bus.
- SetUpBrokenBus();
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethodWithErrorCallback(&method_call, timeout_ms);
- WaitForErrors(1);
-
- // Should fail because of the broken bus.
- ASSERT_TRUE(response_strings_.empty());
- ASSERT_EQ("", error_names_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, Timeout) {
- const char* kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method with timeout of 0ms.
- const int timeout_ms = 0;
- CallMethod(&method_call, timeout_ms);
- WaitForResponses(1);
-
- // Should fail because of timeout.
- ASSERT_EQ("", response_strings_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, TimeoutWithErrorCallback) {
- const char* kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "SlowEcho");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method with timeout of 0ms.
- const int timeout_ms = 0;
- CallMethodWithErrorCallback(&method_call, timeout_ms);
- WaitForErrors(1);
-
- // Should fail because of timeout.
- ASSERT_TRUE(response_strings_.empty());
- ASSERT_EQ(DBUS_ERROR_NO_REPLY, error_names_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, CancelPendingCalls) {
- const char* kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
-
- // Remove the object proxy before receiving the result.
- // This results in cancelling the pending method call.
- bus_->RemoveObjectProxy(test_service_->service_name(),
- ObjectPath("/org/chromium/TestObject"),
- base::DoNothing());
-
- // We shouldn't receive any responses. Wait for a while just to make sure.
- run_loop_.reset(new base::RunLoop);
- message_loop_.task_runner()->PostDelayedTask(
- FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
- run_loop_->Run();
- EXPECT_TRUE(response_strings_.empty());
-}
-
-// Tests calling a method that sends its reply asynchronously.
-TEST_F(EndToEndAsyncTest, AsyncEcho) {
- const char* kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "AsyncEcho");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
-
- // Check the response.
- WaitForResponses(1);
- EXPECT_EQ(kHello, response_strings_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, NonexistentMethod) {
- MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
- WaitForResponses(1);
-
- // Should fail because the method is nonexistent.
- ASSERT_EQ("", response_strings_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, NonexistentMethodWithErrorCallback) {
- MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethodWithErrorCallback(&method_call, timeout_ms);
- WaitForErrors(1);
-
- // Should fail because the method is nonexistent.
- ASSERT_TRUE(response_strings_.empty());
- ASSERT_EQ(DBUS_ERROR_UNKNOWN_METHOD, error_names_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, BrokenMethod) {
- MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethod(&method_call, timeout_ms);
- WaitForResponses(1);
-
- // Should fail because the method is broken.
- ASSERT_EQ("", response_strings_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, BrokenMethodWithErrorCallback) {
- MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethodWithErrorCallback(&method_call, timeout_ms);
- WaitForErrors(1);
-
- // Should fail because the method is broken.
- ASSERT_TRUE(response_strings_.empty());
- ASSERT_EQ(DBUS_ERROR_FAILED, error_names_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, InvalidServiceName) {
- // Bus name cannot contain '/'.
- const std::string invalid_service_name = ":1/2";
-
- // Replace object proxy with new one.
- object_proxy_ = bus_->GetObjectProxy(invalid_service_name,
- ObjectPath("/org/chromium/TestObject"));
-
- MethodCall method_call("org.chromium.TestInterface", "Echo");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- CallMethodWithErrorCallback(&method_call, timeout_ms);
- WaitForErrors(1);
-
- // Should fail because of the invalid bus name.
- ASSERT_TRUE(response_strings_.empty());
- ASSERT_EQ("", error_names_[0]);
-}
-
-TEST_F(EndToEndAsyncTest, EmptyResponseCallback) {
- const char* kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method with an empty callback.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- object_proxy_->CallMethod(&method_call, timeout_ms, base::DoNothing());
- // Post a delayed task to quit the message loop.
- run_loop_.reset(new base::RunLoop);
- message_loop_.task_runner()->PostDelayedTask(
- FROM_HERE, run_loop_->QuitClosure(), TestTimeouts::tiny_timeout());
- run_loop_->Run();
- // We cannot tell if the empty callback is called, but at least we can
- // check if the test does not crash.
-}
-
-TEST_F(EndToEndAsyncTest, TestSignal) {
- const char kMessage[] = "hello, world";
- // Send the test signal from the exported object.
- test_service_->SendTestSignal(kMessage);
- // Receive the signal with the object proxy. The signal is handled in
- // EndToEndAsyncTest::OnTestSignal() in the main thread.
- WaitForTestSignal();
- ASSERT_EQ(kMessage, test_signal_string_);
-}
-
-TEST_F(EndToEndAsyncTest, TestSignalFromRoot) {
- const char kMessage[] = "hello, world";
- // Object proxies are tied to a particular object path, if a signal
- // arrives from a different object path like "/" the first object proxy
- // |object_proxy_| should not handle it, and should leave it for the root
- // object proxy |root_object_proxy_|.
- test_service_->SendTestSignalFromRoot(kMessage);
- WaitForTestSignal();
- // Verify the signal was not received by the specific proxy.
- ASSERT_TRUE(test_signal_string_.empty());
- // Verify the string WAS received by the root proxy.
- ASSERT_EQ(kMessage, root_test_signal_string_);
-}
-
-TEST_F(EndToEndAsyncTest, TestHugeSignal) {
- const std::string kHugeMessage(kHugePayloadSize, 'o');
-
- // Send the huge signal from the exported object.
- test_service_->SendTestSignal(kHugeMessage);
- // This caused a DCHECK failure before. Ensure that the issue is fixed.
- WaitForTestSignal();
- ASSERT_EQ(kHugeMessage, test_signal_string_);
-}
-
-class SignalMultipleHandlerTest : public EndToEndAsyncTest {
- public:
- SignalMultipleHandlerTest() = default;
-
- void SetUp() override {
- // Set up base class.
- EndToEndAsyncTest::SetUp();
-
- // Connect the root object proxy's signal handler to a new handler
- // so that we can verify that a second call to ConnectSignal() delivers
- // to both our new handler and the old.
- object_proxy_->ConnectToSignal(
- "org.chromium.TestInterface",
- "Test",
- base::Bind(&SignalMultipleHandlerTest::OnAdditionalTestSignal,
- base::Unretained(this)),
- base::Bind(&SignalMultipleHandlerTest::OnAdditionalConnected,
- base::Unretained(this)));
- // Wait until the object proxy is connected to the signal.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
-
- protected:
- // Called when the "Test" signal is received, in the main thread.
- // Copy the string payload to |additional_test_signal_string_|.
- void OnAdditionalTestSignal(Signal* signal) {
- MessageReader reader(signal);
- ASSERT_TRUE(reader.PopString(&additional_test_signal_string_));
- run_loop_->Quit();
- }
-
- // Called when connected to the signal.
- void OnAdditionalConnected(const std::string& interface_name,
- const std::string& signal_name,
- bool success) {
- ASSERT_TRUE(success);
- run_loop_->Quit();
- }
-
- // Text message from "Test" signal delivered to additional handler.
- std::string additional_test_signal_string_;
-};
-
-TEST_F(SignalMultipleHandlerTest, TestMultipleHandlers) {
- const char kMessage[] = "hello, world";
- // Send the test signal from the exported object.
- test_service_->SendTestSignal(kMessage);
- // Receive the signal with the object proxy.
- WaitForTestSignal();
- // Verify the string WAS received by the original handler.
- ASSERT_EQ(kMessage, test_signal_string_);
- // Verify the signal WAS ALSO received by the additional handler.
- ASSERT_EQ(kMessage, additional_test_signal_string_);
-}
-
-} // namespace dbus
diff --git a/dbus/end_to_end_sync_unittest.cc b/dbus/end_to_end_sync_unittest.cc
deleted file mode 100644
index 0bc146fbde..0000000000
--- a/dbus/end_to_end_sync_unittest.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 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.
-
-#include <memory>
-
-#include "base/memory/ref_counted.h"
-#include "dbus/bus.h"
-#include "dbus/message.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "dbus/test_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-// The end-to-end test exercises the synchronous APIs in ObjectProxy and
-// ExportedObject. The test will launch a thread for the service side
-// operations (i.e. ExportedObject side).
-class EndToEndSyncTest : public testing::Test {
- public:
- EndToEndSyncTest() = default;
-
- void SetUp() override {
- // Start the test service;
- TestService::Options options;
- test_service_.reset(new TestService(options));
- ASSERT_TRUE(test_service_->StartService());
- ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
- ASSERT_FALSE(test_service_->HasDBusThread());
-
- // Create the client.
- Bus::Options client_bus_options;
- client_bus_options.bus_type = Bus::SESSION;
- client_bus_options.connection_type = Bus::PRIVATE;
- client_bus_ = new Bus(client_bus_options);
- object_proxy_ = client_bus_->GetObjectProxy(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_FALSE(client_bus_->HasDBusThread());
- }
-
- void TearDown() override {
- test_service_->ShutdownAndBlock();
- test_service_->Stop();
- client_bus_->ShutdownAndBlock();
- }
-
- protected:
- std::unique_ptr<TestService> test_service_;
- scoped_refptr<Bus> client_bus_;
- ObjectProxy* object_proxy_;
-};
-
-TEST_F(EndToEndSyncTest, Echo) {
- const std::string kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- std::unique_ptr<Response> response(
- object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
- ASSERT_TRUE(response.get());
-
- // Check the response. kHello should be echoed back.
- MessageReader reader(response.get());
- std::string returned_message;
- ASSERT_TRUE(reader.PopString(&returned_message));
- EXPECT_EQ(kHello, returned_message);
-}
-
-TEST_F(EndToEndSyncTest, Timeout) {
- const std::string kHello = "hello";
-
- // Create the method call.
- MethodCall method_call("org.chromium.TestInterface", "DelayedEcho");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method with timeout of 0ms.
- const int timeout_ms = 0;
- std::unique_ptr<Response> response(
- object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
- // Should fail because of timeout.
- ASSERT_FALSE(response.get());
-}
-
-TEST_F(EndToEndSyncTest, NonexistentMethod) {
- MethodCall method_call("org.chromium.TestInterface", "Nonexistent");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- std::unique_ptr<Response> response(
- object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
- ASSERT_FALSE(response.get());
-}
-
-TEST_F(EndToEndSyncTest, BrokenMethod) {
- MethodCall method_call("org.chromium.TestInterface", "BrokenMethod");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- std::unique_ptr<Response> response(
- object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
- ASSERT_FALSE(response.get());
-}
-
-TEST_F(EndToEndSyncTest, InvalidServiceName) {
- // Bus name cannot contain '/'.
- const std::string invalid_service_name = ":1/2";
-
- // Replace object proxy with new one.
- object_proxy_ = client_bus_->GetObjectProxy(
- invalid_service_name, ObjectPath("/org/chromium/TestObject"));
-
- MethodCall method_call("org.chromium.TestInterface", "Echo");
-
- const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
- std::unique_ptr<Response> response(
- object_proxy_->CallMethodAndBlock(&method_call, timeout_ms));
- ASSERT_FALSE(response.get());
-}
-
-} // namespace dbus
diff --git a/dbus/message_unittest.cc b/dbus/message_unittest.cc
deleted file mode 100644
index c17ecf6ed8..0000000000
--- a/dbus/message_unittest.cc
+++ /dev/null
@@ -1,727 +0,0 @@
-// Copyright (c) 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.
-
-#include "dbus/message.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
-#include "dbus/object_path.h"
-#include "dbus/test_proto.pb.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-// Test that a byte can be properly written and read. We only have this
-// test for byte, as repeating this for other basic types is too redundant.
-TEST(MessageTest, AppendAndPopByte) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- writer.AppendByte(123); // The input is 123.
-
- MessageReader reader(message.get());
- ASSERT_TRUE(reader.HasMoreData()); // Should have data to read.
- ASSERT_EQ(Message::BYTE, reader.GetDataType());
- ASSERT_EQ("y", reader.GetDataSignature());
-
- bool bool_value = false;
- // Should fail as the type is not bool here.
- ASSERT_FALSE(reader.PopBool(&bool_value));
-
- uint8_t byte_value = 0;
- ASSERT_TRUE(reader.PopByte(&byte_value));
- EXPECT_EQ(123, byte_value); // Should match with the input.
- ASSERT_FALSE(reader.HasMoreData()); // Should not have more data to read.
-
- // Try to get another byte. Should fail.
- ASSERT_FALSE(reader.PopByte(&byte_value));
-}
-
-// Check all basic types can be properly written and read.
-TEST(MessageTest, AppendAndPopBasicDataTypes) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
-
- // Append 0, 1, 2, 3, 4, 5, 6, 7, 8, "string", "/object/path".
- writer.AppendByte(0);
- writer.AppendBool(true);
- writer.AppendInt16(2);
- writer.AppendUint16(3);
- writer.AppendInt32(4);
- writer.AppendUint32(5);
- writer.AppendInt64(6);
- writer.AppendUint64(7);
- writer.AppendDouble(8.0);
- writer.AppendString("string");
- writer.AppendObjectPath(ObjectPath("/object/path"));
-
- uint8_t byte_value = 0;
- bool bool_value = false;
- int16_t int16_value = 0;
- uint16_t uint16_value = 0;
- int32_t int32_value = 0;
- uint32_t uint32_value = 0;
- int64_t int64_value = 0;
- uint64_t uint64_value = 0;
- double double_value = 0;
- std::string string_value;
- ObjectPath object_path_value;
-
- MessageReader reader(message.get());
- ASSERT_TRUE(reader.HasMoreData());
- ASSERT_EQ("y", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopByte(&byte_value));
- ASSERT_EQ("b", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopBool(&bool_value));
- ASSERT_EQ("n", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopInt16(&int16_value));
- ASSERT_EQ("q", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopUint16(&uint16_value));
- ASSERT_EQ("i", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopInt32(&int32_value));
- ASSERT_EQ("u", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopUint32(&uint32_value));
- ASSERT_EQ("x", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopInt64(&int64_value));
- ASSERT_EQ("t", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopUint64(&uint64_value));
- ASSERT_EQ("d", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopDouble(&double_value));
- ASSERT_EQ("s", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopString(&string_value));
- ASSERT_EQ("o", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopObjectPath(&object_path_value));
- ASSERT_EQ("", reader.GetDataSignature());
- ASSERT_FALSE(reader.HasMoreData());
-
- // 0, 1, 2, 3, 4, 5, 6, 7, 8, "string", "/object/path" should be returned.
- EXPECT_EQ(0, byte_value);
- EXPECT_EQ(true, bool_value);
- EXPECT_EQ(2, int16_value);
- EXPECT_EQ(3U, uint16_value);
- EXPECT_EQ(4, int32_value);
- EXPECT_EQ(5U, uint32_value);
- EXPECT_EQ(6, int64_value);
- EXPECT_EQ(7U, uint64_value);
- EXPECT_DOUBLE_EQ(8.0, double_value);
- EXPECT_EQ("string", string_value);
- EXPECT_EQ(ObjectPath("/object/path"), object_path_value);
-}
-
-// Check all basic types can be properly written and read.
-TEST(MessageTest, AppendAndPopFileDescriptor) {
- if (!IsDBusTypeUnixFdSupported()) {
- LOG(WARNING) << "FD passing is not supported";
- return;
- }
-
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
-
- // Append stdout.
- const int fd_in = 1;
- writer.AppendFileDescriptor(fd_in);
-
- base::ScopedFD fd_out;
-
- MessageReader reader(message.get());
- ASSERT_TRUE(reader.HasMoreData());
- ASSERT_EQ(Message::UNIX_FD, reader.GetDataType());
- ASSERT_EQ("h", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopFileDescriptor(&fd_out));
- ASSERT_FALSE(reader.HasMoreData());
-
- // Stdout should be returned but we cannot check the descriptor
- // value because stdout will be dup'd. Instead check st_rdev
- // which should be identical.
- struct stat sb_stdout;
- int status_stdout = HANDLE_EINTR(fstat(fd_in, &sb_stdout));
- ASSERT_GE(status_stdout, 0);
- struct stat sb_fd;
- int status_fd = HANDLE_EINTR(fstat(fd_out.get(), &sb_fd));
- ASSERT_GE(status_fd, 0);
- EXPECT_EQ(sb_stdout.st_rdev, sb_fd.st_rdev);
-}
-
-// Check all variant types can be properly written and read.
-TEST(MessageTest, AppendAndPopVariantDataTypes) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
-
- // Append 0, 1, 2, 3, 4, 5, 6, 7, 8, "string", "/object/path".
- writer.AppendVariantOfByte(0);
- writer.AppendVariantOfBool(true);
- writer.AppendVariantOfInt16(2);
- writer.AppendVariantOfUint16(3);
- writer.AppendVariantOfInt32(4);
- writer.AppendVariantOfUint32(5);
- writer.AppendVariantOfInt64(6);
- writer.AppendVariantOfUint64(7);
- writer.AppendVariantOfDouble(8.0);
- writer.AppendVariantOfString("string");
- writer.AppendVariantOfObjectPath(ObjectPath("/object/path"));
-
- uint8_t byte_value = 0;
- bool bool_value = false;
- int16_t int16_value = 0;
- uint16_t uint16_value = 0;
- int32_t int32_value = 0;
- uint32_t uint32_value = 0;
- int64_t int64_value = 0;
- uint64_t uint64_value = 0;
- double double_value = 0;
- std::string string_value;
- ObjectPath object_path_value;
-
- MessageReader reader(message.get());
- ASSERT_TRUE(reader.HasMoreData());
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfByte(&byte_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfBool(&bool_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfInt16(&int16_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfUint16(&uint16_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfInt32(&int32_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfUint32(&uint32_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfInt64(&int64_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfUint64(&uint64_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfDouble(&double_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfString(&string_value));
- ASSERT_EQ("v", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopVariantOfObjectPath(&object_path_value));
- ASSERT_EQ("", reader.GetDataSignature());
- ASSERT_FALSE(reader.HasMoreData());
-
- // 0, 1, 2, 3, 4, 5, 6, 7, 8, "string", "/object/path" should be returned.
- EXPECT_EQ(0, byte_value);
- EXPECT_EQ(true, bool_value);
- EXPECT_EQ(2, int16_value);
- EXPECT_EQ(3U, uint16_value);
- EXPECT_EQ(4, int32_value);
- EXPECT_EQ(5U, uint32_value);
- EXPECT_EQ(6, int64_value);
- EXPECT_EQ(7U, uint64_value);
- EXPECT_DOUBLE_EQ(8.0, double_value);
- EXPECT_EQ("string", string_value);
- EXPECT_EQ(ObjectPath("/object/path"), object_path_value);
-}
-
-TEST(MessageTest, ArrayOfBytes) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- std::vector<uint8_t> bytes;
- bytes.push_back(1);
- bytes.push_back(2);
- bytes.push_back(3);
- writer.AppendArrayOfBytes(bytes.data(), bytes.size());
-
- MessageReader reader(message.get());
- const uint8_t* output_bytes = nullptr;
- size_t length = 0;
- ASSERT_EQ("ay", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfBytes(&output_bytes, &length));
- ASSERT_FALSE(reader.HasMoreData());
- ASSERT_EQ(3U, length);
- EXPECT_EQ(1, output_bytes[0]);
- EXPECT_EQ(2, output_bytes[1]);
- EXPECT_EQ(3, output_bytes[2]);
-}
-
-TEST(MessageTest, ArrayOfInt32s) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- std::vector<int32_t> int32s;
- int32s.push_back(1);
- int32s.push_back(2);
- int32s.push_back(3);
- writer.AppendArrayOfInt32s(int32s.data(), int32s.size());
-
- MessageReader reader(message.get());
- const int32_t* output_int32s = nullptr;
- size_t length = 0;
- ASSERT_EQ("ai", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfInt32s(&output_int32s, &length));
- ASSERT_FALSE(reader.HasMoreData());
- ASSERT_EQ(3U, length);
- EXPECT_EQ(1, output_int32s[0]);
- EXPECT_EQ(2, output_int32s[1]);
- EXPECT_EQ(3, output_int32s[2]);
-}
-
-TEST(MessageTest, ArrayOfUint32s) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- std::vector<uint32_t> uint32s;
- uint32s.push_back(1);
- uint32s.push_back(2);
- uint32s.push_back(3);
- writer.AppendArrayOfUint32s(uint32s.data(), uint32s.size());
-
- MessageReader reader(message.get());
- const uint32_t* output_uint32s = nullptr;
- size_t length = 0;
- ASSERT_EQ("au", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfUint32s(&output_uint32s, &length));
- ASSERT_FALSE(reader.HasMoreData());
- ASSERT_EQ(3U, length);
- EXPECT_EQ(1U, output_uint32s[0]);
- EXPECT_EQ(2U, output_uint32s[1]);
- EXPECT_EQ(3U, output_uint32s[2]);
-}
-
-TEST(MessageTest, ArrayOfDoubles) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- std::vector<double> doubles;
- doubles.push_back(0.2);
- doubles.push_back(0.5);
- doubles.push_back(1);
- writer.AppendArrayOfDoubles(doubles.data(), doubles.size());
-
- MessageReader reader(message.get());
- const double* output_doubles = nullptr;
- size_t length = 0;
- ASSERT_EQ("ad", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfDoubles(&output_doubles, &length));
- ASSERT_FALSE(reader.HasMoreData());
- ASSERT_EQ(3U, length);
- EXPECT_EQ(0.2, output_doubles[0]);
- EXPECT_EQ(0.5, output_doubles[1]);
- EXPECT_EQ(1, output_doubles[2]);
-}
-
-TEST(MessageTest, ArrayOfBytes_Empty) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- std::vector<uint8_t> bytes;
- writer.AppendArrayOfBytes(bytes.data(), bytes.size());
-
- MessageReader reader(message.get());
- const uint8_t* output_bytes = nullptr;
- size_t length = 0;
- ASSERT_EQ("ay", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfBytes(&output_bytes, &length));
- ASSERT_FALSE(reader.HasMoreData());
- ASSERT_EQ(0U, length);
- EXPECT_EQ(nullptr, output_bytes);
-}
-
-TEST(MessageTest, ArrayOfStrings) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- std::vector<std::string> strings;
- strings.push_back("fee");
- strings.push_back("fie");
- strings.push_back("foe");
- strings.push_back("fum");
- writer.AppendArrayOfStrings(strings);
-
- MessageReader reader(message.get());
- std::vector<std::string> output_strings;
- ASSERT_EQ("as", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfStrings(&output_strings));
- ASSERT_FALSE(reader.HasMoreData());
- ASSERT_EQ(4U, output_strings.size());
- EXPECT_EQ("fee", output_strings[0]);
- EXPECT_EQ("fie", output_strings[1]);
- EXPECT_EQ("foe", output_strings[2]);
- EXPECT_EQ("fum", output_strings[3]);
-}
-
-TEST(MessageTest, ArrayOfObjectPaths) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- std::vector<ObjectPath> object_paths;
- object_paths.push_back(ObjectPath("/object/path/1"));
- object_paths.push_back(ObjectPath("/object/path/2"));
- object_paths.push_back(ObjectPath("/object/path/3"));
- writer.AppendArrayOfObjectPaths(object_paths);
-
- MessageReader reader(message.get());
- std::vector<ObjectPath> output_object_paths;
- ASSERT_EQ("ao", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfObjectPaths(&output_object_paths));
- ASSERT_FALSE(reader.HasMoreData());
- ASSERT_EQ(3U, output_object_paths.size());
- EXPECT_EQ(ObjectPath("/object/path/1"), output_object_paths[0]);
- EXPECT_EQ(ObjectPath("/object/path/2"), output_object_paths[1]);
- EXPECT_EQ(ObjectPath("/object/path/3"), output_object_paths[2]);
-}
-
-TEST(MessageTest, ProtoBuf) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- TestProto send_message;
- send_message.set_text("testing");
- send_message.set_number(123);
- writer.AppendProtoAsArrayOfBytes(send_message);
-
- MessageReader reader(message.get());
- TestProto receive_message;
- ASSERT_EQ("ay", reader.GetDataSignature());
- ASSERT_TRUE(reader.PopArrayOfBytesAsProto(&receive_message));
- EXPECT_EQ(receive_message.text(), send_message.text());
- EXPECT_EQ(receive_message.number(), send_message.number());
-}
-
-// Test that an array can be properly written and read. We only have this
-// test for array, as repeating this for other container types is too
-// redundant.
-TEST(MessageTest, OpenArrayAndPopArray) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- MessageWriter array_writer(nullptr);
- writer.OpenArray("s", &array_writer); // Open an array of strings.
- array_writer.AppendString("foo");
- array_writer.AppendString("bar");
- array_writer.AppendString("baz");
- writer.CloseContainer(&array_writer);
-
- MessageReader reader(message.get());
- ASSERT_EQ(Message::ARRAY, reader.GetDataType());
- ASSERT_EQ("as", reader.GetDataSignature());
- MessageReader array_reader(nullptr);
- ASSERT_TRUE(reader.PopArray(&array_reader));
- ASSERT_FALSE(reader.HasMoreData()); // Should not have more data to read.
-
- std::string string_value;
- ASSERT_TRUE(array_reader.PopString(&string_value));
- EXPECT_EQ("foo", string_value);
- ASSERT_TRUE(array_reader.PopString(&string_value));
- EXPECT_EQ("bar", string_value);
- ASSERT_TRUE(array_reader.PopString(&string_value));
- EXPECT_EQ("baz", string_value);
- // Should not have more data to read.
- ASSERT_FALSE(array_reader.HasMoreData());
-}
-
-// Create a complex message using array, struct, variant, dict entry, and
-// make sure it can be read properly.
-TEST(MessageTest, CreateComplexMessageAndReadIt) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- {
- MessageWriter array_writer(nullptr);
- // Open an array of variants.
- writer.OpenArray("v", &array_writer);
- {
- // The first value in the array.
- {
- MessageWriter variant_writer(nullptr);
- // Open a variant of a boolean.
- array_writer.OpenVariant("b", &variant_writer);
- variant_writer.AppendBool(true);
- array_writer.CloseContainer(&variant_writer);
- }
-
- // The second value in the array.
- {
- MessageWriter variant_writer(nullptr);
- // Open a variant of a struct that contains a string and an int32_t.
- array_writer.OpenVariant("(si)", &variant_writer);
- {
- MessageWriter struct_writer(nullptr);
- variant_writer.OpenStruct(&struct_writer);
- struct_writer.AppendString("string");
- struct_writer.AppendInt32(123);
- variant_writer.CloseContainer(&struct_writer);
- }
- array_writer.CloseContainer(&variant_writer);
- }
-
- // The third value in the array.
- {
- MessageWriter variant_writer(nullptr);
- // Open a variant of an array of string-to-int64_t dict entries.
- array_writer.OpenVariant("a{sx}", &variant_writer);
- {
- // Opens an array of string-to-int64_t dict entries.
- MessageWriter dict_array_writer(nullptr);
- variant_writer.OpenArray("{sx}", &dict_array_writer);
- {
- // Opens a string-to-int64_t dict entries.
- MessageWriter dict_entry_writer(nullptr);
- dict_array_writer.OpenDictEntry(&dict_entry_writer);
- dict_entry_writer.AppendString("foo");
- dict_entry_writer.AppendInt64(INT64_C(1234567890123456789));
- dict_array_writer.CloseContainer(&dict_entry_writer);
- }
- variant_writer.CloseContainer(&dict_array_writer);
- }
- array_writer.CloseContainer(&variant_writer);
- }
- }
- writer.CloseContainer(&array_writer);
- }
- // What we have created looks like this:
- EXPECT_EQ(
- "message_type: MESSAGE_METHOD_RETURN\n"
- "signature: av\n"
- "\n"
- "array [\n"
- " variant bool true\n"
- " variant struct {\n"
- " string \"string\"\n"
- " int32_t 123\n"
- " }\n"
- " variant array [\n"
- " dict entry {\n"
- " string \"foo\"\n"
- " int64_t 1234567890123456789\n"
- " }\n"
- " ]\n"
- "]\n",
- message->ToString());
-
- MessageReader reader(message.get());
- ASSERT_EQ("av", reader.GetDataSignature());
- MessageReader array_reader(nullptr);
- ASSERT_TRUE(reader.PopArray(&array_reader));
-
- // The first value in the array.
- bool bool_value = false;
- ASSERT_EQ("v", array_reader.GetDataSignature());
- ASSERT_TRUE(array_reader.PopVariantOfBool(&bool_value));
- EXPECT_EQ(true, bool_value);
-
- // The second value in the array.
- {
- MessageReader variant_reader(nullptr);
- ASSERT_TRUE(array_reader.PopVariant(&variant_reader));
- {
- MessageReader struct_reader(nullptr);
- ASSERT_EQ("(si)", variant_reader.GetDataSignature());
- ASSERT_TRUE(variant_reader.PopStruct(&struct_reader));
- std::string string_value;
- ASSERT_TRUE(struct_reader.PopString(&string_value));
- EXPECT_EQ("string", string_value);
- int32_t int32_value = 0;
- ASSERT_TRUE(struct_reader.PopInt32(&int32_value));
- EXPECT_EQ(123, int32_value);
- ASSERT_FALSE(struct_reader.HasMoreData());
- }
- ASSERT_FALSE(variant_reader.HasMoreData());
- }
-
- // The third value in the array.
- {
- MessageReader variant_reader(nullptr);
- ASSERT_TRUE(array_reader.PopVariant(&variant_reader));
- {
- MessageReader dict_array_reader(nullptr);
- ASSERT_EQ("a{sx}", variant_reader.GetDataSignature());
- ASSERT_TRUE(variant_reader.PopArray(&dict_array_reader));
- {
- MessageReader dict_entry_reader(nullptr);
- ASSERT_TRUE(dict_array_reader.PopDictEntry(&dict_entry_reader));
- std::string string_value;
- ASSERT_TRUE(dict_entry_reader.PopString(&string_value));
- EXPECT_EQ("foo", string_value);
- int64_t int64_value = 0;
- ASSERT_TRUE(dict_entry_reader.PopInt64(&int64_value));
- EXPECT_EQ(INT64_C(1234567890123456789), int64_value);
- }
- ASSERT_FALSE(dict_array_reader.HasMoreData());
- }
- ASSERT_FALSE(variant_reader.HasMoreData());
- }
- ASSERT_FALSE(array_reader.HasMoreData());
- ASSERT_FALSE(reader.HasMoreData());
-}
-
-TEST(MessageTest, MethodCall) {
- MethodCall method_call("com.example.Interface", "SomeMethod");
- EXPECT_NE(nullptr, method_call.raw_message());
- EXPECT_EQ(Message::MESSAGE_METHOD_CALL, method_call.GetMessageType());
- EXPECT_EQ("MESSAGE_METHOD_CALL", method_call.GetMessageTypeAsString());
- method_call.SetDestination("com.example.Service");
- method_call.SetPath(ObjectPath("/com/example/Object"));
-
- MessageWriter writer(&method_call);
- writer.AppendString("payload");
-
- EXPECT_EQ(
- "message_type: MESSAGE_METHOD_CALL\n"
- "destination: com.example.Service\n"
- "path: /com/example/Object\n"
- "interface: com.example.Interface\n"
- "member: SomeMethod\n"
- "signature: s\n"
- "\n"
- "string \"payload\"\n",
- method_call.ToString());
-}
-
-TEST(MessageTest, MethodCall_FromRawMessage) {
- DBusMessage* raw_message = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
- dbus_message_set_interface(raw_message, "com.example.Interface");
- dbus_message_set_member(raw_message, "SomeMethod");
-
- std::unique_ptr<MethodCall> method_call(
- MethodCall::FromRawMessage(raw_message));
- EXPECT_EQ("com.example.Interface", method_call->GetInterface());
- EXPECT_EQ("SomeMethod", method_call->GetMember());
-}
-
-TEST(MessageTest, Signal) {
- Signal signal("com.example.Interface", "SomeSignal");
- EXPECT_NE(nullptr, signal.raw_message());
- EXPECT_EQ(Message::MESSAGE_SIGNAL, signal.GetMessageType());
- EXPECT_EQ("MESSAGE_SIGNAL", signal.GetMessageTypeAsString());
- signal.SetPath(ObjectPath("/com/example/Object"));
-
- MessageWriter writer(&signal);
- writer.AppendString("payload");
-
- EXPECT_EQ(
- "message_type: MESSAGE_SIGNAL\n"
- "path: /com/example/Object\n"
- "interface: com.example.Interface\n"
- "member: SomeSignal\n"
- "signature: s\n"
- "\n"
- "string \"payload\"\n",
- signal.ToString());
-}
-
-TEST(MessageTest, Signal_FromRawMessage) {
- DBusMessage* raw_message = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
- dbus_message_set_interface(raw_message, "com.example.Interface");
- dbus_message_set_member(raw_message, "SomeSignal");
-
- std::unique_ptr<Signal> signal(Signal::FromRawMessage(raw_message));
- EXPECT_EQ("com.example.Interface", signal->GetInterface());
- EXPECT_EQ("SomeSignal", signal->GetMember());
-}
-
-TEST(MessageTest, Response) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- EXPECT_TRUE(response->raw_message());
- EXPECT_EQ(Message::MESSAGE_METHOD_RETURN, response->GetMessageType());
- EXPECT_EQ("MESSAGE_METHOD_RETURN", response->GetMessageTypeAsString());
-}
-
-TEST(MessageTest, Response_FromMethodCall) {
- const uint32_t kSerial = 123;
- MethodCall method_call("com.example.Interface", "SomeMethod");
- method_call.SetSerial(kSerial);
-
- std::unique_ptr<Response> response(Response::FromMethodCall(&method_call));
- EXPECT_EQ(Message::MESSAGE_METHOD_RETURN, response->GetMessageType());
- EXPECT_EQ("MESSAGE_METHOD_RETURN", response->GetMessageTypeAsString());
- // The serial should be copied to the reply serial.
- EXPECT_EQ(kSerial, response->GetReplySerial());
-}
-
-TEST(MessageTest, ErrorResponse_FromMethodCall) {
- const uint32_t kSerial = 123;
- const char kErrorMessage[] = "error message";
-
- MethodCall method_call("com.example.Interface", "SomeMethod");
- method_call.SetSerial(kSerial);
-
- std::unique_ptr<ErrorResponse> error_response(ErrorResponse::FromMethodCall(
- &method_call, DBUS_ERROR_FAILED, kErrorMessage));
- EXPECT_EQ(Message::MESSAGE_ERROR, error_response->GetMessageType());
- EXPECT_EQ("MESSAGE_ERROR", error_response->GetMessageTypeAsString());
- // The serial should be copied to the reply serial.
- EXPECT_EQ(kSerial, error_response->GetReplySerial());
-
- // Error message should be added to the payload.
- MessageReader reader(error_response.get());
- std::string error_message;
- ASSERT_TRUE(reader.PopString(&error_message));
- EXPECT_EQ(kErrorMessage, error_message);
-}
-
-TEST(MessageTest, GetAndSetHeaders) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
-
- EXPECT_EQ("", message->GetDestination());
- EXPECT_EQ(ObjectPath(std::string()), message->GetPath());
- EXPECT_EQ("", message->GetInterface());
- EXPECT_EQ("", message->GetMember());
- EXPECT_EQ("", message->GetErrorName());
- EXPECT_EQ("", message->GetSender());
- EXPECT_EQ(0U, message->GetSerial());
- EXPECT_EQ(0U, message->GetReplySerial());
-
- EXPECT_TRUE(message->SetDestination("org.chromium.destination"));
- EXPECT_TRUE(message->SetPath(ObjectPath("/org/chromium/path")));
- EXPECT_TRUE(message->SetInterface("org.chromium.interface"));
- EXPECT_TRUE(message->SetMember("member"));
- EXPECT_TRUE(message->SetErrorName("org.chromium.error"));
- EXPECT_TRUE(message->SetSender(":1.2"));
- message->SetSerial(123);
- message->SetReplySerial(456);
-
- EXPECT_EQ("org.chromium.destination", message->GetDestination());
- EXPECT_EQ(ObjectPath("/org/chromium/path"), message->GetPath());
- EXPECT_EQ("org.chromium.interface", message->GetInterface());
- EXPECT_EQ("member", message->GetMember());
- EXPECT_EQ("org.chromium.error", message->GetErrorName());
- EXPECT_EQ(":1.2", message->GetSender());
- EXPECT_EQ(123U, message->GetSerial());
- EXPECT_EQ(456U, message->GetReplySerial());
-}
-
-TEST(MessageTest, SetInvalidHeaders) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- EXPECT_EQ("", message->GetDestination());
- EXPECT_EQ(ObjectPath(std::string()), message->GetPath());
- EXPECT_EQ("", message->GetInterface());
- EXPECT_EQ("", message->GetMember());
- EXPECT_EQ("", message->GetErrorName());
- EXPECT_EQ("", message->GetSender());
-
- // Empty element between periods.
- EXPECT_FALSE(message->SetDestination("org..chromium"));
- // Trailing '/' is only allowed for the root path.
- EXPECT_FALSE(message->SetPath(ObjectPath("/org/chromium/")));
- // Interface name cannot contain '/'.
- EXPECT_FALSE(message->SetInterface("org/chromium/interface"));
- // Member name cannot begin with a digit.
- EXPECT_FALSE(message->SetMember("1member"));
- // Error name cannot begin with a period.
- EXPECT_FALSE(message->SetErrorName(".org.chromium.error"));
- // Disallowed characters.
- EXPECT_FALSE(message->SetSender("?!#*"));
-
- EXPECT_EQ("", message->GetDestination());
- EXPECT_EQ(ObjectPath(std::string()), message->GetPath());
- EXPECT_EQ("", message->GetInterface());
- EXPECT_EQ("", message->GetMember());
- EXPECT_EQ("", message->GetErrorName());
- EXPECT_EQ("", message->GetSender());
-}
-
-TEST(MessageTest, ToString_LongString) {
- const std::string kLongString(1000, 'o');
-
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- writer.AppendString(kLongString);
-
- ASSERT_EQ(
- "message_type: MESSAGE_METHOD_RETURN\n"
- "signature: s\n\n"
- "string \"oooooooooooooooooooooooooooooooooooooooooooooooo"
- "oooooooooooooooooooooooooooooooooooooooooooooooooooo... "
- "(1000 bytes in total)\"\n",
- message->ToString());
-}
-
-} // namespace dbus
diff --git a/dbus/mock_unittest.cc b/dbus/mock_unittest.cc
deleted file mode 100644
index aa26bc4294..0000000000
--- a/dbus/mock_unittest.cc
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright (c) 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.
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "dbus/message.h"
-#include "dbus/mock_bus.h"
-#include "dbus/mock_exported_object.h"
-#include "dbus/mock_object_proxy.h"
-#include "dbus/object_path.h"
-#include "dbus/scoped_dbus_error.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::Unused;
-
-namespace dbus {
-
-class MockTest : public testing::Test {
- public:
- MockTest() = default;
-
- void SetUp() override {
- // Create a mock bus.
- Bus::Options options;
- options.bus_type = Bus::SYSTEM;
- mock_bus_ = new MockBus(options);
-
- // Create a mock proxy.
- mock_proxy_ = new MockObjectProxy(
- mock_bus_.get(),
- "org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
-
- // Set an expectation so mock_proxy's CallMethodAndBlock() will use
- // CreateMockProxyResponse() to return responses.
- EXPECT_CALL(*mock_proxy_.get(), CallMethodAndBlock(_, _))
- .WillRepeatedly(Invoke(this, &MockTest::CreateMockProxyResponse));
- EXPECT_CALL(*mock_proxy_.get(),
- CallMethodAndBlockWithErrorDetails(_, _, _))
- .WillRepeatedly(
- Invoke(this, &MockTest::CreateMockProxyResponseWithErrorDetails));
-
- // Set an expectation so mock_proxy's CallMethod() will use
- // HandleMockProxyResponseWithMessageLoop() to return responses.
- EXPECT_CALL(*mock_proxy_.get(), DoCallMethod(_, _, _))
- .WillRepeatedly(
- Invoke(this, &MockTest::HandleMockProxyResponseWithMessageLoop));
-
- // Set an expectation so mock_bus's GetObjectProxy() for the given
- // service name and the object path will return mock_proxy_.
- EXPECT_CALL(*mock_bus_.get(),
- GetObjectProxy("org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject")))
- .WillOnce(Return(mock_proxy_.get()));
-
- // ShutdownAndBlock() will be called in TearDown().
- EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
- }
-
- void TearDown() override { mock_bus_->ShutdownAndBlock(); }
-
- // Called when the response is received.
- void OnResponse(Response* response) {
- // |response| will be deleted on exit of the function. Copy the
- // payload to |response_string_|.
- if (response) {
- MessageReader reader(response);
- ASSERT_TRUE(reader.PopString(&response_string_));
- }
- run_loop_->Quit();
- };
-
- protected:
- std::string response_string_;
- base::MessageLoop message_loop_;
- std::unique_ptr<base::RunLoop> run_loop_;
- scoped_refptr<MockBus> mock_bus_;
- scoped_refptr<MockObjectProxy> mock_proxy_;
-
- private:
- // Returns a response for the given method call. Used to implement
- // CallMethodAndBlock() for |mock_proxy_|.
- std::unique_ptr<Response> CreateMockProxyResponse(MethodCall* method_call,
- int timeout_ms) {
- if (method_call->GetInterface() == "org.chromium.TestInterface" &&
- method_call->GetMember() == "Echo") {
- MessageReader reader(method_call);
- std::string text_message;
- if (reader.PopString(&text_message)) {
- std::unique_ptr<Response> response = Response::CreateEmpty();
- MessageWriter writer(response.get());
- writer.AppendString(text_message);
- return response;
- }
- }
-
- LOG(ERROR) << "Unexpected method call: " << method_call->ToString();
- return nullptr;
- }
-
- std::unique_ptr<Response> CreateMockProxyResponseWithErrorDetails(
- MethodCall* method_call, int timeout_ms, ScopedDBusError* error) {
- dbus_set_error(error->get(), DBUS_ERROR_NOT_SUPPORTED, "Not implemented");
- return nullptr;
- }
-
- // Creates a response and runs the given response callback in the
- // message loop with the response. Used to implement for |mock_proxy_|.
- void HandleMockProxyResponseWithMessageLoop(
- MethodCall* method_call,
- int timeout_ms,
- ObjectProxy::ResponseCallback* response_callback) {
- std::unique_ptr<Response> response =
- CreateMockProxyResponse(method_call, timeout_ms);
- message_loop_.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&MockTest::RunResponseCallback, base::Unretained(this),
- std::move(*response_callback), std::move(response)));
- }
-
- // Runs the given response callback with the given response.
- void RunResponseCallback(
- ObjectProxy::ResponseCallback response_callback,
- std::unique_ptr<Response> response) {
- std::move(response_callback).Run(response.get());
- }
-};
-
-// This test demonstrates how to mock a synchronous method call using the
-// mock classes.
-TEST_F(MockTest, CallMethodAndBlock) {
- const char kHello[] = "Hello";
- // Get an object proxy from the mock bus.
- ObjectProxy* proxy = mock_bus_->GetObjectProxy(
- "org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
-
- // Create a method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- std::unique_ptr<Response> response(proxy->CallMethodAndBlock(
- &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
-
- // Check the response.
- ASSERT_TRUE(response.get());
- MessageReader reader(response.get());
- std::string text_message;
- ASSERT_TRUE(reader.PopString(&text_message));
- // The text message should be echo'ed back.
- EXPECT_EQ(kHello, text_message);
-}
-
-TEST_F(MockTest, CallMethodAndBlockWithErrorDetails) {
- // Get an object proxy from the mock bus.
- ObjectProxy* proxy = mock_bus_->GetObjectProxy(
- "org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
-
- // Create a method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
-
- ScopedDBusError error;
- // Call the method.
- std::unique_ptr<Response> response(proxy->CallMethodAndBlockWithErrorDetails(
- &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT, &error));
-
- // Check the response.
- ASSERT_FALSE(response.get());
- ASSERT_TRUE(error.is_set());
- EXPECT_STREQ(DBUS_ERROR_NOT_SUPPORTED, error.name());
- EXPECT_STREQ("Not implemented", error.message());
-}
-
-// This test demonstrates how to mock an asynchronous method call using the
-// mock classes.
-TEST_F(MockTest, CallMethod) {
- const char kHello[] = "hello";
-
- // Get an object proxy from the mock bus.
- ObjectProxy* proxy = mock_bus_->GetObjectProxy(
- "org.chromium.TestService",
- ObjectPath("/org/chromium/TestObject"));
-
- // Create a method call.
- MethodCall method_call("org.chromium.TestInterface", "Echo");
- MessageWriter writer(&method_call);
- writer.AppendString(kHello);
-
- // Call the method.
- run_loop_.reset(new base::RunLoop);
- proxy->CallMethod(&method_call,
- ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::Bind(&MockTest::OnResponse,
- base::Unretained(this)));
- // Run the message loop to let OnResponse be called.
- run_loop_->Run();
-
- EXPECT_EQ(kHello, response_string_);
-}
-
-} // namespace dbus
diff --git a/dbus/object_manager_unittest.cc b/dbus/object_manager_unittest.cc
deleted file mode 100644
index 0fb74adff9..0000000000
--- a/dbus/object_manager_unittest.cc
+++ /dev/null
@@ -1,419 +0,0 @@
-// Copyright (c) 2013 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 "dbus/object_manager.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "dbus/bus.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "dbus/property.h"
-#include "dbus/test_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-// The object manager test exercises the asynchronous APIs in ObjectManager,
-// and by extension PropertySet and Property<>.
-class ObjectManagerTest
- : public testing::Test,
- public ObjectManager::Interface {
- public:
- ObjectManagerTest() : timeout_expired_(false) {
- }
-
- struct Properties : public PropertySet {
- Property<std::string> name;
- Property<int16_t> version;
- Property<std::vector<std::string>> methods;
- Property<std::vector<ObjectPath>> objects;
-
- Properties(ObjectProxy* object_proxy,
- const std::string& interface_name,
- PropertyChangedCallback property_changed_callback)
- : PropertySet(object_proxy, interface_name, property_changed_callback) {
- RegisterProperty("Name", &name);
- RegisterProperty("Version", &version);
- RegisterProperty("Methods", &methods);
- RegisterProperty("Objects", &objects);
- }
- };
-
- PropertySet* CreateProperties(ObjectProxy* object_proxy,
- const ObjectPath& object_path,
- const std::string& interface_name) override {
- Properties* properties = new Properties(
- object_proxy, interface_name,
- base::Bind(&ObjectManagerTest::OnPropertyChanged,
- base::Unretained(this), object_path));
- return static_cast<PropertySet*>(properties);
- }
-
- void SetUp() override {
- // Make the main thread not to allow IO.
- base::ThreadRestrictions::SetIOAllowed(false);
-
- // Start the D-Bus thread.
- dbus_thread_.reset(new base::Thread("D-Bus Thread"));
- base::Thread::Options thread_options;
- thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
- ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
-
- // Start the test service, using the D-Bus thread.
- TestService::Options options;
- options.dbus_task_runner = dbus_thread_->task_runner();
- test_service_.reset(new TestService(options));
- ASSERT_TRUE(test_service_->StartService());
- ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service_->HasDBusThread());
-
- // Create the client, using the D-Bus thread.
- Bus::Options bus_options;
- bus_options.bus_type = Bus::SESSION;
- bus_options.connection_type = Bus::PRIVATE;
- bus_options.dbus_task_runner = dbus_thread_->task_runner();
- bus_ = new Bus(bus_options);
- ASSERT_TRUE(bus_->HasDBusThread());
-
- object_manager_ = bus_->GetObjectManager(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestService"));
- object_manager_->RegisterInterface("org.chromium.TestInterface", this);
-
- WaitForObject();
- }
-
- void TearDown() override {
- bus_->ShutdownOnDBusThreadAndBlock();
-
- // Shut down the service.
- test_service_->ShutdownAndBlock();
-
- // Reset to the default.
- base::ThreadRestrictions::SetIOAllowed(true);
-
- // Stopping a thread is considered an IO operation, so do this after
- // allowing IO.
- test_service_->Stop();
-
- base::RunLoop().RunUntilIdle();
- }
-
- void MethodCallback(Response* response) {
- method_callback_called_ = true;
- run_loop_->Quit();
- }
-
- // Called from the PropertiesChangedAsObjectsReceived test case. The test will
- // not run the message loop if it receives the expected PropertiesChanged
- // signal before the timeout. This method immediately fails the test.
- void PropertiesChangedTestTimeout() {
- timeout_expired_ = true;
- run_loop_->Quit();
-
- FAIL() << "Never received PropertiesChanged";
- }
-
- protected:
- // Called when an object is added.
- void ObjectAdded(const ObjectPath& object_path,
- const std::string& interface_name) override {
- added_objects_.push_back(std::make_pair(object_path, interface_name));
- run_loop_->Quit();
- }
-
- // Called when an object is removed.
- void ObjectRemoved(const ObjectPath& object_path,
- const std::string& interface_name) override {
- removed_objects_.push_back(std::make_pair(object_path, interface_name));
- run_loop_->Quit();
- }
-
- // Called when a property value is updated.
- void OnPropertyChanged(const ObjectPath& object_path,
- const std::string& name) {
- // Store the value of the "Name" property if that's the one that
- // changed.
- Properties* properties = static_cast<Properties*>(
- object_manager_->GetProperties(
- object_path,
- "org.chromium.TestInterface"));
- if (name == properties->name.name())
- last_name_value_ = properties->name.value();
-
- // Store the updated property.
- updated_properties_.push_back(name);
- run_loop_->Quit();
- }
-
- static const size_t kExpectedObjects = 1;
- static const size_t kExpectedProperties = 4;
-
- void WaitForObject() {
- while (added_objects_.size() < kExpectedObjects ||
- updated_properties_.size() < kExpectedProperties) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- for (size_t i = 0; i < kExpectedObjects; ++i)
- added_objects_.erase(added_objects_.begin());
- for (size_t i = 0; i < kExpectedProperties; ++i)
- updated_properties_.erase(updated_properties_.begin());
- }
-
- void WaitForRemoveObject() {
- while (removed_objects_.size() < kExpectedObjects) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- for (size_t i = 0; i < kExpectedObjects; ++i)
- removed_objects_.erase(removed_objects_.begin());
- }
-
- void WaitForMethodCallback() {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- method_callback_called_ = false;
- }
-
- void PerformAction(const std::string& action, const ObjectPath& object_path) {
- ObjectProxy* object_proxy = bus_->GetObjectProxy(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestObject"));
-
- MethodCall method_call("org.chromium.TestInterface", "PerformAction");
- MessageWriter writer(&method_call);
- writer.AppendString(action);
- writer.AppendObjectPath(object_path);
-
- object_proxy->CallMethod(&method_call,
- ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::Bind(&ObjectManagerTest::MethodCallback,
- base::Unretained(this)));
- WaitForMethodCallback();
- }
-
- base::MessageLoop message_loop_;
- std::unique_ptr<base::RunLoop> run_loop_;
- std::unique_ptr<base::Thread> dbus_thread_;
- scoped_refptr<Bus> bus_;
- ObjectManager* object_manager_;
- std::unique_ptr<TestService> test_service_;
-
- std::string last_name_value_;
- bool timeout_expired_;
-
- std::vector<std::pair<ObjectPath, std::string>> added_objects_;
- std::vector<std::pair<ObjectPath, std::string>> removed_objects_;
- std::vector<std::string> updated_properties_;
-
- bool method_callback_called_;
-};
-
-
-TEST_F(ObjectManagerTest, InitialObject) {
- ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
- ObjectPath("/org/chromium/TestObject"));
- EXPECT_NE(nullptr, object_proxy);
-
- Properties* properties = static_cast<Properties*>(
- object_manager_->GetProperties(ObjectPath("/org/chromium/TestObject"),
- "org.chromium.TestInterface"));
- EXPECT_NE(nullptr, properties);
-
- EXPECT_EQ("TestService", properties->name.value());
- EXPECT_EQ(10, properties->version.value());
-
- std::vector<std::string> methods = properties->methods.value();
- ASSERT_EQ(4U, methods.size());
- EXPECT_EQ("Echo", methods[0]);
- EXPECT_EQ("SlowEcho", methods[1]);
- EXPECT_EQ("AsyncEcho", methods[2]);
- EXPECT_EQ("BrokenMethod", methods[3]);
-
- std::vector<ObjectPath> objects = properties->objects.value();
- ASSERT_EQ(1U, objects.size());
- EXPECT_EQ(ObjectPath("/TestObjectPath"), objects[0]);
-}
-
-TEST_F(ObjectManagerTest, UnknownObjectProxy) {
- ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
- ObjectPath("/org/chromium/UnknownObject"));
- EXPECT_EQ(nullptr, object_proxy);
-}
-
-TEST_F(ObjectManagerTest, UnknownObjectProperties) {
- Properties* properties = static_cast<Properties*>(
- object_manager_->GetProperties(ObjectPath("/org/chromium/UnknownObject"),
- "org.chromium.TestInterface"));
- EXPECT_EQ(nullptr, properties);
-}
-
-TEST_F(ObjectManagerTest, UnknownInterfaceProperties) {
- Properties* properties = static_cast<Properties*>(
- object_manager_->GetProperties(ObjectPath("/org/chromium/TestObject"),
- "org.chromium.UnknownService"));
- EXPECT_EQ(nullptr, properties);
-}
-
-TEST_F(ObjectManagerTest, GetObjects) {
- std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
- ASSERT_EQ(1U, object_paths.size());
- EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
-}
-
-TEST_F(ObjectManagerTest, GetObjectsWithInterface) {
- std::vector<ObjectPath> object_paths =
- object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
- ASSERT_EQ(1U, object_paths.size());
- EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
-}
-
-TEST_F(ObjectManagerTest, GetObjectsWithUnknownInterface) {
- std::vector<ObjectPath> object_paths =
- object_manager_->GetObjectsWithInterface("org.chromium.UnknownService");
- EXPECT_EQ(0U, object_paths.size());
-}
-
-TEST_F(ObjectManagerTest, SameObject) {
- ObjectManager* object_manager = bus_->GetObjectManager(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestService"));
- EXPECT_EQ(object_manager_, object_manager);
-}
-
-TEST_F(ObjectManagerTest, DifferentObjectForService) {
- ObjectManager* object_manager = bus_->GetObjectManager(
- "org.chromium.DifferentService",
- ObjectPath("/org/chromium/TestService"));
- EXPECT_NE(object_manager_, object_manager);
-}
-
-TEST_F(ObjectManagerTest, DifferentObjectForPath) {
- ObjectManager* object_manager = bus_->GetObjectManager(
- test_service_->service_name(),
- ObjectPath("/org/chromium/DifferentService"));
- EXPECT_NE(object_manager_, object_manager);
-}
-
-TEST_F(ObjectManagerTest, SecondObject) {
- PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
- WaitForObject();
-
- ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
- ObjectPath("/org/chromium/SecondObject"));
- EXPECT_NE(nullptr, object_proxy);
-
- Properties* properties = static_cast<Properties*>(
- object_manager_->GetProperties(ObjectPath("/org/chromium/SecondObject"),
- "org.chromium.TestInterface"));
- EXPECT_NE(nullptr, properties);
-
- std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
- ASSERT_EQ(2U, object_paths.size());
-
- std::sort(object_paths.begin(), object_paths.end());
- EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths[0]);
- EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[1]);
-
- object_paths =
- object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
- ASSERT_EQ(2U, object_paths.size());
-
- std::sort(object_paths.begin(), object_paths.end());
- EXPECT_EQ(ObjectPath("/org/chromium/SecondObject"), object_paths[0]);
- EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[1]);
-}
-
-TEST_F(ObjectManagerTest, RemoveSecondObject) {
- PerformAction("AddObject", ObjectPath("/org/chromium/SecondObject"));
- WaitForObject();
-
- std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
- ASSERT_EQ(2U, object_paths.size());
-
- PerformAction("RemoveObject", ObjectPath("/org/chromium/SecondObject"));
- WaitForRemoveObject();
-
- ObjectProxy* object_proxy = object_manager_->GetObjectProxy(
- ObjectPath("/org/chromium/SecondObject"));
- EXPECT_EQ(nullptr, object_proxy);
-
- Properties* properties = static_cast<Properties*>(
- object_manager_->GetProperties(ObjectPath("/org/chromium/SecondObject"),
- "org.chromium.TestInterface"));
- EXPECT_EQ(nullptr, properties);
-
- object_paths = object_manager_->GetObjects();
- ASSERT_EQ(1U, object_paths.size());
- EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
-
- object_paths =
- object_manager_->GetObjectsWithInterface("org.chromium.TestInterface");
- ASSERT_EQ(1U, object_paths.size());
- EXPECT_EQ(ObjectPath("/org/chromium/TestObject"), object_paths[0]);
-}
-
-TEST_F(ObjectManagerTest, OwnershipLost) {
- PerformAction("ReleaseOwnership", ObjectPath("/org/chromium/TestService"));
- WaitForRemoveObject();
-
- std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
- ASSERT_EQ(0U, object_paths.size());
-}
-
-TEST_F(ObjectManagerTest, OwnershipLostAndRegained) {
- PerformAction("Ownership", ObjectPath("/org/chromium/TestService"));
- WaitForRemoveObject();
- WaitForObject();
-
- std::vector<ObjectPath> object_paths = object_manager_->GetObjects();
- ASSERT_EQ(1U, object_paths.size());
-}
-
-TEST_F(ObjectManagerTest, PropertiesChangedAsObjectsReceived) {
- // Remove the existing object manager.
- object_manager_->UnregisterInterface("org.chromium.TestInterface");
- run_loop_.reset(new base::RunLoop);
- EXPECT_TRUE(bus_->RemoveObjectManager(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestService"),
- run_loop_->QuitClosure()));
- run_loop_->Run();
-
- PerformAction("SetSendImmediatePropertiesChanged",
- ObjectPath("/org/chromium/TestService"));
-
- object_manager_ = bus_->GetObjectManager(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestService"));
- object_manager_->RegisterInterface("org.chromium.TestInterface", this);
-
- // The newly created object manager should call GetManagedObjects immediately
- // after setting up the match rule for PropertiesChanged. We should process
- // the PropertiesChanged event right after that. If we don't receive it within
- // 2 seconds, then fail the test.
- message_loop_.task_runner()->PostDelayedTask(
- FROM_HERE, base::Bind(&ObjectManagerTest::PropertiesChangedTestTimeout,
- base::Unretained(this)),
- base::TimeDelta::FromSeconds(2));
-
- while (last_name_value_ != "ChangedTestServiceName" && !timeout_expired_) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
-}
-
-} // namespace dbus
diff --git a/dbus/object_proxy_unittest.cc b/dbus/object_proxy_unittest.cc
deleted file mode 100644
index 1f5746faa4..0000000000
--- a/dbus/object_proxy_unittest.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2013 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 "dbus/object_proxy.h"
-#include "base/bind.h"
-#include "base/files/file_descriptor_watcher_posix.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "dbus/bus.h"
-#include "dbus/test_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-namespace {
-
-class ObjectProxyTest : public testing::Test {
- protected:
- ObjectProxyTest() : file_descriptor_watcher_(&message_loop_) {}
-
- void SetUp() override {
- Bus::Options bus_options;
- bus_options.bus_type = Bus::SESSION;
- bus_options.connection_type = Bus::PRIVATE;
- bus_ = new Bus(bus_options);
- }
-
- void TearDown() override { bus_->ShutdownAndBlock(); }
-
- base::MessageLoopForIO message_loop_;
-
- // This enables FileDescriptorWatcher, which is required by dbus::Watch.
- base::FileDescriptorWatcher file_descriptor_watcher_;
-
- scoped_refptr<Bus> bus_;
-};
-
-// Used as a WaitForServiceToBeAvailableCallback.
-void OnServiceIsAvailable(bool* dest_service_is_available,
- int* num_calls,
- bool src_service_is_available) {
- *dest_service_is_available = src_service_is_available;
- (*num_calls)++;
-}
-
-// Used as a callback for TestService::RequestOwnership().
-void OnOwnershipRequestDone(bool success) {
- ASSERT_TRUE(success);
-}
-
-// Used as a callback for TestService::ReleaseOwnership().
-void OnOwnershipReleased() {}
-
-TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableRunOnce) {
- TestService::Options options;
- TestService test_service(options);
- ObjectProxy* object_proxy = bus_->GetObjectProxy(
- test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
-
- // The callback is not yet called because the service is not available.
- int num_calls = 0;
- bool service_is_available = false;
- object_proxy->WaitForServiceToBeAvailable(
- base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, num_calls);
-
- // Start the service. The callback should be called asynchronously.
- ASSERT_TRUE(test_service.StartService());
- ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service.has_ownership());
- num_calls = 0;
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, num_calls);
- EXPECT_TRUE(service_is_available);
-
- // Release the service's ownership of its name. The callback should not be
- // invoked again.
- test_service.ReleaseOwnership(base::Bind(&OnOwnershipReleased));
- num_calls = 0;
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, num_calls);
-
- // Take ownership of the name and check that the callback is not called.
- test_service.RequestOwnership(base::Bind(&OnOwnershipRequestDone));
- num_calls = 0;
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, num_calls);
-}
-
-TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableAlreadyRunning) {
- TestService::Options options;
- TestService test_service(options);
- ObjectProxy* object_proxy = bus_->GetObjectProxy(
- test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
-
- ASSERT_TRUE(test_service.StartService());
- ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service.has_ownership());
-
- // Since the service is already running, the callback should be invoked
- // immediately (but asynchronously, rather than the callback being invoked
- // directly within WaitForServiceToBeAvailable()).
- int num_calls = 0;
- bool service_is_available = false;
- object_proxy->WaitForServiceToBeAvailable(
- base::Bind(&OnServiceIsAvailable, &service_is_available, &num_calls));
- EXPECT_EQ(0, num_calls);
-
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, num_calls);
- EXPECT_TRUE(service_is_available);
-}
-
-TEST_F(ObjectProxyTest, WaitForServiceToBeAvailableMultipleCallbacks) {
- TestService::Options options;
- TestService test_service(options);
- ObjectProxy* object_proxy = bus_->GetObjectProxy(
- test_service.service_name(), ObjectPath("/org/chromium/TestObject"));
-
- // Register two callbacks.
- int num_calls_1 = 0, num_calls_2 = 0;
- bool service_is_available_1 = false, service_is_available_2 = false;
- object_proxy->WaitForServiceToBeAvailable(
- base::Bind(&OnServiceIsAvailable, &service_is_available_1, &num_calls_1));
- object_proxy->WaitForServiceToBeAvailable(
- base::Bind(&OnServiceIsAvailable, &service_is_available_2, &num_calls_2));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0, num_calls_1);
- EXPECT_EQ(0, num_calls_2);
-
- // Start the service and confirm that both callbacks are invoked.
- ASSERT_TRUE(test_service.StartService());
- ASSERT_TRUE(test_service.WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service.has_ownership());
- num_calls_1 = 0;
- num_calls_2 = 0;
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, num_calls_1);
- EXPECT_EQ(1, num_calls_2);
- EXPECT_TRUE(service_is_available_1);
- EXPECT_TRUE(service_is_available_2);
-}
-
-} // namespace
-} // namespace dbus
diff --git a/dbus/property_unittest.cc b/dbus/property_unittest.cc
deleted file mode 100644
index 5b26edd156..0000000000
--- a/dbus/property_unittest.cc
+++ /dev/null
@@ -1,545 +0,0 @@
-// Copyright (c) 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.
-
-#include "dbus/property.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "dbus/bus.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "dbus/test_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-// The property test exerises the asynchronous APIs in PropertySet and
-// Property<>.
-class PropertyTest : public testing::Test {
- public:
- PropertyTest() = default;
-
- struct Properties : public PropertySet {
- Property<std::string> name;
- Property<int16_t> version;
- Property<std::vector<std::string>> methods;
- Property<std::vector<ObjectPath>> objects;
- Property<std::vector<uint8_t>> bytes;
-
- Properties(ObjectProxy* object_proxy,
- PropertyChangedCallback property_changed_callback)
- : PropertySet(object_proxy,
- "org.chromium.TestInterface",
- property_changed_callback) {
- RegisterProperty("Name", &name);
- RegisterProperty("Version", &version);
- RegisterProperty("Methods", &methods);
- RegisterProperty("Objects", &objects);
- RegisterProperty("Bytes", &bytes);
- }
- };
-
- void SetUp() override {
- // Make the main thread not to allow IO.
- base::ThreadRestrictions::SetIOAllowed(false);
-
- // Start the D-Bus thread.
- dbus_thread_.reset(new base::Thread("D-Bus Thread"));
- base::Thread::Options thread_options;
- thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
- ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
-
- // Start the test service, using the D-Bus thread.
- TestService::Options options;
- options.dbus_task_runner = dbus_thread_->task_runner();
- test_service_.reset(new TestService(options));
- ASSERT_TRUE(test_service_->StartService());
- ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service_->HasDBusThread());
-
- // Create the client, using the D-Bus thread.
- Bus::Options bus_options;
- bus_options.bus_type = Bus::SESSION;
- bus_options.connection_type = Bus::PRIVATE;
- bus_options.dbus_task_runner = dbus_thread_->task_runner();
- bus_ = new Bus(bus_options);
- object_proxy_ = bus_->GetObjectProxy(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(bus_->HasDBusThread());
-
- // Create the properties structure
- properties_.reset(new Properties(
- object_proxy_,
- base::Bind(&PropertyTest::OnPropertyChanged,
- base::Unretained(this))));
- properties_->ConnectSignals();
- properties_->GetAll();
- }
-
- void TearDown() override {
- bus_->ShutdownOnDBusThreadAndBlock();
-
- // Shut down the service.
- test_service_->ShutdownAndBlock();
-
- // Reset to the default.
- base::ThreadRestrictions::SetIOAllowed(true);
-
- // Stopping a thread is considered an IO operation, so do this after
- // allowing IO.
- test_service_->Stop();
- }
-
- // Generic callback, bind with a string |id| for passing to
- // WaitForCallback() to ensure the callback for the right method is
- // waited for.
- void PropertyCallback(const std::string& id, bool success) {
- last_callback_ = id;
- run_loop_->Quit();
- }
-
- // Generic method callback, that might be used together with
- // WaitForMethodCallback to test wether method was succesfully called.
- void MethodCallback(Response* response) { run_loop_->Quit(); }
-
- protected:
- // Called when a property value is updated.
- void OnPropertyChanged(const std::string& name) {
- updated_properties_.push_back(name);
- run_loop_->Quit();
- }
-
- // Waits for the given number of updates.
- void WaitForUpdates(size_t num_updates) {
- while (updated_properties_.size() < num_updates) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- for (size_t i = 0; i < num_updates; ++i)
- updated_properties_.erase(updated_properties_.begin());
- }
-
- // Name, Version, Methods, Objects
- static const int kExpectedSignalUpdates = 5;
-
- // Waits for initial values to be set.
- void WaitForGetAll() {
- WaitForUpdates(kExpectedSignalUpdates);
- }
-
- // Waits until MethodCallback is called.
- void WaitForMethodCallback() {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
-
- // Waits for the callback. |id| is the string bound to the callback when
- // the method call is made that identifies it and distinguishes from any
- // other; you can set this to whatever you wish.
- void WaitForCallback(const std::string& id) {
- while (last_callback_ != id) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- }
-
- base::MessageLoop message_loop_;
- std::unique_ptr<base::RunLoop> run_loop_;
- std::unique_ptr<base::Thread> dbus_thread_;
- scoped_refptr<Bus> bus_;
- ObjectProxy* object_proxy_;
- std::unique_ptr<Properties> properties_;
- std::unique_ptr<TestService> test_service_;
- // Properties updated.
- std::vector<std::string> updated_properties_;
- // Last callback received.
- std::string last_callback_;
-};
-
-TEST_F(PropertyTest, InitialValues) {
- EXPECT_FALSE(properties_->name.is_valid());
- EXPECT_FALSE(properties_->version.is_valid());
-
- WaitForGetAll();
-
- EXPECT_TRUE(properties_->name.is_valid());
- EXPECT_EQ("TestService", properties_->name.value());
- EXPECT_TRUE(properties_->version.is_valid());
- EXPECT_EQ(10, properties_->version.value());
-
- std::vector<std::string> methods = properties_->methods.value();
- ASSERT_EQ(4U, methods.size());
- EXPECT_EQ("Echo", methods[0]);
- EXPECT_EQ("SlowEcho", methods[1]);
- EXPECT_EQ("AsyncEcho", methods[2]);
- EXPECT_EQ("BrokenMethod", methods[3]);
-
- std::vector<ObjectPath> objects = properties_->objects.value();
- ASSERT_EQ(1U, objects.size());
- EXPECT_EQ(ObjectPath("/TestObjectPath"), objects[0]);
-
- std::vector<uint8_t> bytes = properties_->bytes.value();
- ASSERT_EQ(4U, bytes.size());
- EXPECT_EQ('T', bytes[0]);
- EXPECT_EQ('e', bytes[1]);
- EXPECT_EQ('s', bytes[2]);
- EXPECT_EQ('t', bytes[3]);
-}
-
-TEST_F(PropertyTest, UpdatedValues) {
- WaitForGetAll();
-
- // Update the value of the "Name" property, this value should not change.
- properties_->name.Get(base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this),
- "Name"));
- WaitForCallback("Name");
- WaitForUpdates(1);
-
- EXPECT_EQ("TestService", properties_->name.value());
-
- // Update the value of the "Version" property, this value should be changed.
- properties_->version.Get(base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this),
- "Version"));
- WaitForCallback("Version");
- WaitForUpdates(1);
-
- EXPECT_EQ(20, properties_->version.value());
-
- // Update the value of the "Methods" property, this value should not change
- // and should not grow to contain duplicate entries.
- properties_->methods.Get(base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this),
- "Methods"));
- WaitForCallback("Methods");
- WaitForUpdates(1);
-
- std::vector<std::string> methods = properties_->methods.value();
- ASSERT_EQ(4U, methods.size());
- EXPECT_EQ("Echo", methods[0]);
- EXPECT_EQ("SlowEcho", methods[1]);
- EXPECT_EQ("AsyncEcho", methods[2]);
- EXPECT_EQ("BrokenMethod", methods[3]);
-
- // Update the value of the "Objects" property, this value should not change
- // and should not grow to contain duplicate entries.
- properties_->objects.Get(base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this),
- "Objects"));
- WaitForCallback("Objects");
- WaitForUpdates(1);
-
- std::vector<ObjectPath> objects = properties_->objects.value();
- ASSERT_EQ(1U, objects.size());
- EXPECT_EQ(ObjectPath("/TestObjectPath"), objects[0]);
-
- // Update the value of the "Bytes" property, this value should not change
- // and should not grow to contain duplicate entries.
- properties_->bytes.Get(base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this),
- "Bytes"));
- WaitForCallback("Bytes");
- WaitForUpdates(1);
-
- std::vector<uint8_t> bytes = properties_->bytes.value();
- ASSERT_EQ(4U, bytes.size());
- EXPECT_EQ('T', bytes[0]);
- EXPECT_EQ('e', bytes[1]);
- EXPECT_EQ('s', bytes[2]);
- EXPECT_EQ('t', bytes[3]);
-}
-
-TEST_F(PropertyTest, Get) {
- WaitForGetAll();
-
- // Ask for the new Version property.
- properties_->version.Get(base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this),
- "Get"));
- WaitForCallback("Get");
-
- // Make sure we got a property update too.
- WaitForUpdates(1);
-
- EXPECT_EQ(20, properties_->version.value());
-}
-
-TEST_F(PropertyTest, Set) {
- WaitForGetAll();
-
- // Set a new name.
- properties_->name.Set("NewService",
- base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this),
- "Set"));
- WaitForCallback("Set");
-
- // TestService sends a property update.
- WaitForUpdates(1);
-
- EXPECT_EQ("NewService", properties_->name.value());
-}
-
-TEST_F(PropertyTest, Invalidate) {
- WaitForGetAll();
-
- EXPECT_TRUE(properties_->name.is_valid());
-
- // Invalidate name.
- MethodCall method_call("org.chromium.TestInterface", "PerformAction");
- MessageWriter writer(&method_call);
- writer.AppendString("InvalidateProperty");
- writer.AppendObjectPath(ObjectPath("/org/chromium/TestService"));
- object_proxy_->CallMethod(
- &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::Bind(&PropertyTest::MethodCallback, base::Unretained(this)));
- WaitForMethodCallback();
-
- // TestService sends a property update.
- WaitForUpdates(1);
-
- EXPECT_FALSE(properties_->name.is_valid());
-
- // Set name to something valid.
- properties_->name.Set("NewService",
- base::Bind(&PropertyTest::PropertyCallback,
- base::Unretained(this), "Set"));
- WaitForCallback("Set");
-
- // TestService sends a property update.
- WaitForUpdates(1);
-
- EXPECT_TRUE(properties_->name.is_valid());
-}
-
-TEST(PropertyTestStatic, ReadWriteStringMap) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- MessageWriter variant_writer(nullptr);
- MessageWriter variant_array_writer(nullptr);
- MessageWriter struct_entry_writer(nullptr);
-
- writer.OpenVariant("a{ss}", &variant_writer);
- variant_writer.OpenArray("{ss}", &variant_array_writer);
- const char* items[] = {"One", "Two", "Three", "Four"};
- for (unsigned i = 0; i < arraysize(items); ++i) {
- variant_array_writer.OpenDictEntry(&struct_entry_writer);
- struct_entry_writer.AppendString(items[i]);
- struct_entry_writer.AppendString(base::UintToString(i + 1));
- variant_array_writer.CloseContainer(&struct_entry_writer);
- }
- variant_writer.CloseContainer(&variant_array_writer);
- writer.CloseContainer(&variant_writer);
-
- MessageReader reader(message.get());
- Property<std::map<std::string, std::string>> string_map;
- EXPECT_TRUE(string_map.PopValueFromReader(&reader));
- ASSERT_EQ(4U, string_map.value().size());
- EXPECT_EQ("1", string_map.value().at("One"));
- EXPECT_EQ("2", string_map.value().at("Two"));
- EXPECT_EQ("3", string_map.value().at("Three"));
- EXPECT_EQ("4", string_map.value().at("Four"));
-}
-
-TEST(PropertyTestStatic, SerializeStringMap) {
- std::map<std::string, std::string> test_map;
- test_map["Hi"] = "There";
- test_map["Map"] = "Test";
- test_map["Random"] = "Text";
-
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
-
- Property<std::map<std::string, std::string>> string_map;
- string_map.ReplaceSetValueForTesting(test_map);
- string_map.AppendSetValueToWriter(&writer);
-
- MessageReader reader(message.get());
- EXPECT_TRUE(string_map.PopValueFromReader(&reader));
- EXPECT_EQ(test_map, string_map.value());
-}
-
-TEST(PropertyTestStatic, ReadWriteNetAddressArray) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- MessageWriter variant_writer(nullptr);
- MessageWriter variant_array_writer(nullptr);
- MessageWriter struct_entry_writer(nullptr);
-
- writer.OpenVariant("a(ayq)", &variant_writer);
- variant_writer.OpenArray("(ayq)", &variant_array_writer);
- uint8_t ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
- for (uint16_t i = 0; i < 5; ++i) {
- variant_array_writer.OpenStruct(&struct_entry_writer);
- ip_bytes[4] = 0x30 + i;
- struct_entry_writer.AppendArrayOfBytes(ip_bytes, arraysize(ip_bytes));
- struct_entry_writer.AppendUint16(i);
- variant_array_writer.CloseContainer(&struct_entry_writer);
- }
- variant_writer.CloseContainer(&variant_array_writer);
- writer.CloseContainer(&variant_writer);
-
- MessageReader reader(message.get());
- Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>> ip_list;
- EXPECT_TRUE(ip_list.PopValueFromReader(&reader));
-
- ASSERT_EQ(5U, ip_list.value().size());
- size_t item_index = 0;
- for (auto& item : ip_list.value()) {
- ASSERT_EQ(5U, item.first.size());
- ip_bytes[4] = 0x30 + item_index;
- EXPECT_EQ(0, memcmp(ip_bytes, item.first.data(), 5U));
- EXPECT_EQ(item_index, item.second);
- ++item_index;
- }
-}
-
-TEST(PropertyTestStatic, SerializeNetAddressArray) {
- std::vector<std::pair<std::vector<uint8_t>, uint16_t>> test_list;
-
- uint8_t ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
- for (uint16_t i = 0; i < 5; ++i) {
- ip_bytes[4] = 0x30 + i;
- std::vector<uint8_t> bytes(ip_bytes, ip_bytes + arraysize(ip_bytes));
- test_list.push_back(make_pair(bytes, 16));
- }
-
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
-
- Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>> ip_list;
- ip_list.ReplaceSetValueForTesting(test_list);
- ip_list.AppendSetValueToWriter(&writer);
-
- MessageReader reader(message.get());
- EXPECT_TRUE(ip_list.PopValueFromReader(&reader));
- EXPECT_EQ(test_list, ip_list.value());
-}
-
-TEST(PropertyTestStatic, ReadWriteStringToByteVectorMap) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- MessageWriter variant_writer(nullptr);
- MessageWriter dict_writer(nullptr);
-
- writer.OpenVariant("a{sv}", &variant_writer);
- variant_writer.OpenArray("{sv}", &dict_writer);
-
- const char* keys[] = {"One", "Two", "Three", "Four"};
- const std::vector<uint8_t> values[] = {{1}, {1, 2}, {1, 2, 3}, {1, 2, 3, 4}};
- for (unsigned i = 0; i < arraysize(keys); ++i) {
- MessageWriter entry_writer(nullptr);
- dict_writer.OpenDictEntry(&entry_writer);
-
- entry_writer.AppendString(keys[i]);
-
- MessageWriter value_varient_writer(nullptr);
- entry_writer.OpenVariant("ay", &value_varient_writer);
- value_varient_writer.AppendArrayOfBytes(values[i].data(), values[i].size());
- entry_writer.CloseContainer(&value_varient_writer);
-
- dict_writer.CloseContainer(&entry_writer);
- }
-
- variant_writer.CloseContainer(&dict_writer);
- writer.CloseContainer(&variant_writer);
-
- MessageReader reader(message.get());
- Property<std::map<std::string, std::vector<uint8_t>>> test_property;
- EXPECT_TRUE(test_property.PopValueFromReader(&reader));
-
- ASSERT_EQ(arraysize(keys), test_property.value().size());
- for (unsigned i = 0; i < arraysize(keys); ++i)
- EXPECT_EQ(values[i], test_property.value().at(keys[i]));
-}
-
-TEST(PropertyTestStatic, SerializeStringToByteVectorMap) {
- std::map<std::string, std::vector<uint8_t>> test_map;
- test_map["Hi"] = {1, 2, 3};
- test_map["Map"] = {0xab, 0xcd};
- test_map["Random"] = {0x0};
-
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
-
- Property<std::map<std::string, std::vector<uint8_t>>> test_property;
- test_property.ReplaceSetValueForTesting(test_map);
- test_property.AppendSetValueToWriter(&writer);
-
- MessageReader reader(message.get());
- EXPECT_TRUE(test_property.PopValueFromReader(&reader));
- EXPECT_EQ(test_map, test_property.value());
-}
-
-TEST(PropertyTestStatic, ReadWriteUInt16ToByteVectorMap) {
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
- MessageWriter variant_writer(nullptr);
- MessageWriter dict_writer(nullptr);
-
- writer.OpenVariant("a{qv}", &variant_writer);
- variant_writer.OpenArray("{qv}", &dict_writer);
-
- const uint16_t keys[] = {11, 12, 13, 14};
- const std::vector<uint8_t> values[] = {{1}, {1, 2}, {1, 2, 3}, {1, 2, 3, 4}};
- for (unsigned i = 0; i < arraysize(keys); ++i) {
- MessageWriter entry_writer(nullptr);
- dict_writer.OpenDictEntry(&entry_writer);
-
- entry_writer.AppendUint16(keys[i]);
-
- MessageWriter value_varient_writer(nullptr);
- entry_writer.OpenVariant("ay", &value_varient_writer);
- value_varient_writer.AppendArrayOfBytes(values[i].data(), values[i].size());
- entry_writer.CloseContainer(&value_varient_writer);
-
- dict_writer.CloseContainer(&entry_writer);
- }
-
- variant_writer.CloseContainer(&dict_writer);
- writer.CloseContainer(&variant_writer);
-
- MessageReader reader(message.get());
- Property<std::map<uint16_t, std::vector<uint8_t>>> test_property;
- EXPECT_TRUE(test_property.PopValueFromReader(&reader));
-
- ASSERT_EQ(arraysize(keys), test_property.value().size());
- for (unsigned i = 0; i < arraysize(keys); ++i)
- EXPECT_EQ(values[i], test_property.value().at(keys[i]));
-}
-
-TEST(PropertyTestStatic, SerializeUInt16ToByteVectorMap) {
- std::map<uint16_t, std::vector<uint8_t>> test_map;
- test_map[11] = {1, 2, 3};
- test_map[12] = {0xab, 0xcd};
- test_map[13] = {0x0};
-
- std::unique_ptr<Response> message(Response::CreateEmpty());
- MessageWriter writer(message.get());
-
- Property<std::map<uint16_t, std::vector<uint8_t>>> test_property;
- test_property.ReplaceSetValueForTesting(test_map);
- test_property.AppendSetValueToWriter(&writer);
-
- MessageReader reader(message.get());
- EXPECT_TRUE(test_property.PopValueFromReader(&reader));
- EXPECT_EQ(test_map, test_property.value());
-}
-
-} // namespace dbus
diff --git a/dbus/signal_sender_verification_unittest.cc b/dbus/signal_sender_verification_unittest.cc
deleted file mode 100644
index 3cc22f926b..0000000000
--- a/dbus/signal_sender_verification_unittest.cc
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright (c) 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.
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "dbus/bus.h"
-#include "dbus/message.h"
-#include "dbus/object_proxy.h"
-#include "dbus/test_service.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-// The test for sender verification in ObjectProxy.
-class SignalSenderVerificationTest : public testing::Test {
- public:
- SignalSenderVerificationTest()
- : on_name_owner_changed_called_(false),
- on_ownership_called_(false) {
- }
-
- void SetUp() override {
- // Make the main thread not to allow IO.
- base::ThreadRestrictions::SetIOAllowed(false);
-
- // Start the D-Bus thread.
- dbus_thread_.reset(new base::Thread("D-Bus Thread"));
- base::Thread::Options thread_options;
- thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
- ASSERT_TRUE(dbus_thread_->StartWithOptions(thread_options));
-
- // Create the test service, using the D-Bus thread.
- TestService::Options options;
- options.dbus_task_runner = dbus_thread_->task_runner();
- test_service_.reset(new TestService(options));
-
- // Create the client, using the D-Bus thread.
- Bus::Options bus_options;
- bus_options.bus_type = Bus::SESSION;
- bus_options.connection_type = Bus::PRIVATE;
- bus_options.dbus_task_runner = dbus_thread_->task_runner();
- bus_ = new Bus(bus_options);
- object_proxy_ = bus_->GetObjectProxy(
- test_service_->service_name(),
- ObjectPath("/org/chromium/TestObject"));
- ASSERT_TRUE(bus_->HasDBusThread());
-
- object_proxy_->SetNameOwnerChangedCallback(
- base::Bind(&SignalSenderVerificationTest::OnNameOwnerChanged,
- base::Unretained(this),
- &on_name_owner_changed_called_));
-
- // Connect to the "Test" signal of "org.chromium.TestInterface" from
- // the remote object.
- object_proxy_->ConnectToSignal(
- "org.chromium.TestInterface",
- "Test",
- base::Bind(&SignalSenderVerificationTest::OnTestSignal,
- base::Unretained(this)),
- base::Bind(&SignalSenderVerificationTest::OnConnected,
- base::Unretained(this)));
- // Wait until the object proxy is connected to the signal.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
-
- // Start the test service.
- ASSERT_TRUE(test_service_->StartService());
- ASSERT_TRUE(test_service_->WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service_->HasDBusThread());
- ASSERT_TRUE(test_service_->has_ownership());
-
- // Same setup for the second TestService. This service should not have the
- // ownership of the name at this point.
- options.service_name = test_service_->service_name();
- test_service2_.reset(new TestService(options));
- ASSERT_TRUE(test_service2_->StartService());
- ASSERT_TRUE(test_service2_->WaitUntilServiceIsStarted());
- ASSERT_TRUE(test_service2_->HasDBusThread());
- ASSERT_FALSE(test_service2_->has_ownership());
-
- // The name should be owned and known at this point.
- if (!on_name_owner_changed_called_) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- ASSERT_FALSE(latest_name_owner_.empty());
- }
-
- void TearDown() override {
- bus_->ShutdownOnDBusThreadAndBlock();
-
- // Shut down the service.
- test_service_->ShutdownAndBlock();
- test_service2_->ShutdownAndBlock();
-
- // Reset to the default.
- base::ThreadRestrictions::SetIOAllowed(true);
-
- // Stopping a thread is considered an IO operation, so do this after
- // allowing IO.
- test_service_->Stop();
- test_service2_->Stop();
- }
-
- void OnOwnership(bool expected, bool success) {
- ASSERT_EQ(expected, success);
- // PostTask to quit the MessageLoop as this is called from D-Bus thread.
- message_loop_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&SignalSenderVerificationTest::OnOwnershipInternal,
- base::Unretained(this)));
- }
-
- void OnOwnershipInternal() {
- on_ownership_called_ = true;
- run_loop_->Quit();
- }
-
- void OnNameOwnerChanged(bool* called_flag,
- const std::string& old_owner,
- const std::string& new_owner) {
- latest_name_owner_ = new_owner;
- *called_flag = true;
- run_loop_->Quit();
- }
-
- // Called when the "Test" signal is received, in the main thread.
- // Copy the string payload to |test_signal_string_|.
- void OnTestSignal(Signal* signal) {
- MessageReader reader(signal);
- ASSERT_TRUE(reader.PopString(&test_signal_string_));
- run_loop_->Quit();
- }
-
- // Called when connected to the signal.
- void OnConnected(const std::string& interface_name,
- const std::string& signal_name,
- bool success) {
- ASSERT_TRUE(success);
- run_loop_->Quit();
- }
-
- protected:
- // Wait for the hey signal to be received.
- void WaitForTestSignal() {
- // OnTestSignal() will quit the message loop.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
-
- // Stopping a thread is considered an IO operation, so we need to fiddle with
- // thread restrictions before and after calling Stop() on a TestService.
- void SafeServiceStop(TestService* test_service) {
- base::ThreadRestrictions::SetIOAllowed(true);
- test_service->Stop();
- base::ThreadRestrictions::SetIOAllowed(false);
- }
-
- base::MessageLoop message_loop_;
- std::unique_ptr<base::RunLoop> run_loop_;
- std::unique_ptr<base::Thread> dbus_thread_;
- scoped_refptr<Bus> bus_;
- ObjectProxy* object_proxy_;
- std::unique_ptr<TestService> test_service_;
- std::unique_ptr<TestService> test_service2_;
- // Text message from "Test" signal.
- std::string test_signal_string_;
-
- // The known latest name owner of TestService. Updated in OnNameOwnerChanged.
- std::string latest_name_owner_;
-
- // Boolean flags to record callback calls.
- bool on_name_owner_changed_called_;
- bool on_ownership_called_;
-};
-
-TEST_F(SignalSenderVerificationTest, TestSignalAccepted) {
- const char kMessage[] = "hello, world";
- // Send the test signal from the exported object.
- test_service_->SendTestSignal(kMessage);
- // Receive the signal with the object proxy. The signal is handled in
- // SignalSenderVerificationTest::OnTestSignal() in the main thread.
- WaitForTestSignal();
- ASSERT_EQ(kMessage, test_signal_string_);
-}
-
-TEST_F(SignalSenderVerificationTest, TestSignalRejected) {
- const char kNewMessage[] = "hello, new world";
- test_service2_->SendTestSignal(kNewMessage);
-
- // This test tests that our callback is NOT called by the ObjectProxy.
- // Sleep to have message delivered to the client via the D-Bus service.
- base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
-
- ASSERT_EQ("", test_signal_string_);
-}
-
-// Flaky. https://crbug.com/785555
-TEST_F(SignalSenderVerificationTest, DISABLED_TestOwnerChanged) {
- const char kMessage[] = "hello, world";
-
- // Send the test signal from the exported object.
- test_service_->SendTestSignal(kMessage);
- // Receive the signal with the object proxy. The signal is handled in
- // SignalSenderVerificationTest::OnTestSignal() in the main thread.
- WaitForTestSignal();
- ASSERT_EQ(kMessage, test_signal_string_);
-
- // Release and acquire the name ownership.
- // latest_name_owner_ should be non empty as |test_service_| owns the name.
- ASSERT_FALSE(latest_name_owner_.empty());
- test_service_->ShutdownAndBlock();
- // OnNameOwnerChanged will PostTask to quit the message loop.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- // latest_name_owner_ should be empty as the owner is gone.
- ASSERT_TRUE(latest_name_owner_.empty());
-
- // Reset the flag as NameOwnerChanged is already received in setup.
- on_name_owner_changed_called_ = false;
- on_ownership_called_ = false;
- test_service2_->RequestOwnership(
- base::Bind(&SignalSenderVerificationTest::OnOwnership,
- base::Unretained(this), true));
- // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
- // but there's no expected order of those 2 event.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- if (!on_name_owner_changed_called_ || !on_ownership_called_) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- ASSERT_TRUE(on_name_owner_changed_called_);
- ASSERT_TRUE(on_ownership_called_);
-
- // latest_name_owner_ becomes non empty as the new owner appears.
- ASSERT_FALSE(latest_name_owner_.empty());
-
- // Now the second service owns the name.
- const char kNewMessage[] = "hello, new world";
-
- test_service2_->SendTestSignal(kNewMessage);
- WaitForTestSignal();
- ASSERT_EQ(kNewMessage, test_signal_string_);
-}
-
-// Flaky. https://crbug.com/785555
-TEST_F(SignalSenderVerificationTest, DISABLED_TestOwnerStealing) {
- // Release and acquire the name ownership.
- // latest_name_owner_ should be non empty as |test_service_| owns the name.
- ASSERT_FALSE(latest_name_owner_.empty());
- test_service_->ShutdownAndBlock();
- // OnNameOwnerChanged will PostTask to quit the message loop.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- // latest_name_owner_ should be empty as the owner is gone.
- ASSERT_TRUE(latest_name_owner_.empty());
- // Reset the flag as NameOwnerChanged is already received in setup.
- on_name_owner_changed_called_ = false;
-
- // Start a test service that allows theft, using the D-Bus thread.
- TestService::Options options;
- options.dbus_task_runner = dbus_thread_->task_runner();
- options.request_ownership_options = Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT;
- options.service_name = test_service_->service_name();
- TestService stealable_test_service(options);
- ASSERT_TRUE(stealable_test_service.StartService());
- ASSERT_TRUE(stealable_test_service.WaitUntilServiceIsStarted());
- ASSERT_TRUE(stealable_test_service.HasDBusThread());
- ASSERT_TRUE(stealable_test_service.has_ownership());
-
- // OnNameOwnerChanged will PostTask to quit the message loop.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
-
- // Send a signal to check that the service is correctly owned.
- const char kMessage[] = "hello, world";
-
- // Send the test signal from the exported object.
- stealable_test_service.SendTestSignal(kMessage);
- // Receive the signal with the object proxy. The signal is handled in
- // SignalSenderVerificationTest::OnTestSignal() in the main thread.
- WaitForTestSignal();
- ASSERT_EQ(kMessage, test_signal_string_);
-
- // Reset the flag as NameOwnerChanged was called above.
- on_name_owner_changed_called_ = false;
- test_service2_->RequestOwnership(
- base::Bind(&SignalSenderVerificationTest::OnOwnership,
- base::Unretained(this), true));
- // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
- // but there's no expected order of those 2 event.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- if (!on_name_owner_changed_called_ || !on_ownership_called_) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- ASSERT_TRUE(on_name_owner_changed_called_);
- ASSERT_TRUE(on_ownership_called_);
-
- // Now the second service owns the name.
- const char kNewMessage[] = "hello, new world";
-
- test_service2_->SendTestSignal(kNewMessage);
- WaitForTestSignal();
- ASSERT_EQ(kNewMessage, test_signal_string_);
-
- SafeServiceStop(&stealable_test_service);
-}
-
-// Fails on Linux ChromiumOS Tests
-TEST_F(SignalSenderVerificationTest, DISABLED_TestMultipleObjects) {
- const char kMessage[] = "hello, world";
-
- ObjectProxy* object_proxy2 = bus_->GetObjectProxy(
- test_service_->service_name(),
- ObjectPath("/org/chromium/DifferentObject"));
-
- bool second_name_owner_changed_called = false;
- object_proxy2->SetNameOwnerChangedCallback(
- base::Bind(&SignalSenderVerificationTest::OnNameOwnerChanged,
- base::Unretained(this),
- &second_name_owner_changed_called));
-
- // Connect to a signal on the additional remote object to trigger the
- // name owner matching.
- object_proxy2->ConnectToSignal(
- "org.chromium.DifferentTestInterface",
- "Test",
- base::Bind(&SignalSenderVerificationTest::OnTestSignal,
- base::Unretained(this)),
- base::Bind(&SignalSenderVerificationTest::OnConnected,
- base::Unretained(this)));
- // Wait until the object proxy is connected to the signal.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
-
- // Send the test signal from the exported object.
- test_service_->SendTestSignal(kMessage);
- // Receive the signal with the object proxy. The signal is handled in
- // SignalSenderVerificationTest::OnTestSignal() in the main thread.
- WaitForTestSignal();
- ASSERT_EQ(kMessage, test_signal_string_);
-
- // Release and acquire the name ownership.
- // latest_name_owner_ should be non empty as |test_service_| owns the name.
- ASSERT_FALSE(latest_name_owner_.empty());
- test_service_->ShutdownAndBlock();
- // OnNameOwnerChanged will PostTask to quit the message loop.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- // latest_name_owner_ should be empty as the owner is gone.
- ASSERT_TRUE(latest_name_owner_.empty());
-
- // Reset the flag as NameOwnerChanged is already received in setup.
- on_name_owner_changed_called_ = false;
- second_name_owner_changed_called = false;
- test_service2_->RequestOwnership(
- base::Bind(&SignalSenderVerificationTest::OnOwnership,
- base::Unretained(this), true));
- // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop,
- // but there's no expected order of those 2 event.
- while (!on_name_owner_changed_called_ || !second_name_owner_changed_called ||
- !on_ownership_called_) {
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- }
- ASSERT_TRUE(on_name_owner_changed_called_);
- ASSERT_TRUE(second_name_owner_changed_called);
- ASSERT_TRUE(on_ownership_called_);
-
- // latest_name_owner_ becomes non empty as the new owner appears.
- ASSERT_FALSE(latest_name_owner_.empty());
-
- // Now the second service owns the name.
- const char kNewMessage[] = "hello, new world";
-
- test_service2_->SendTestSignal(kNewMessage);
- WaitForTestSignal();
- ASSERT_EQ(kNewMessage, test_signal_string_);
-}
-
-} // namespace dbus
diff --git a/dbus/string_util_unittest.cc b/dbus/string_util_unittest.cc
deleted file mode 100644
index 3d0ff51efd..0000000000
--- a/dbus/string_util_unittest.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 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.
-
-#include "dbus/string_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-TEST(StringUtilTest, IsValidObjectPath) {
- EXPECT_TRUE(IsValidObjectPath("/"));
- EXPECT_TRUE(IsValidObjectPath("/foo/bar"));
- EXPECT_TRUE(IsValidObjectPath("/hoge_fuga/piyo123"));
- // Empty string.
- EXPECT_FALSE(IsValidObjectPath(std::string()));
- // Empty element.
- EXPECT_FALSE(IsValidObjectPath("//"));
- EXPECT_FALSE(IsValidObjectPath("/foo//bar"));
- EXPECT_FALSE(IsValidObjectPath("/foo///bar"));
- // Trailing '/'.
- EXPECT_FALSE(IsValidObjectPath("/foo/"));
- EXPECT_FALSE(IsValidObjectPath("/foo/bar/"));
- // Not beginning with '/'.
- EXPECT_FALSE(IsValidObjectPath("foo/bar"));
- // Invalid characters.
- EXPECT_FALSE(IsValidObjectPath("/foo.bar"));
- EXPECT_FALSE(IsValidObjectPath("/foo/*"));
- EXPECT_FALSE(IsValidObjectPath("/foo/bar(1)"));
-}
-
-} // namespace dbus
diff --git a/dbus/util_unittest.cc b/dbus/util_unittest.cc
deleted file mode 100644
index 4bf6efa2ae..0000000000
--- a/dbus/util_unittest.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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 "dbus/util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-TEST(UtilTest, GetAbsoluteMemberName) {
- EXPECT_EQ("InterfaceName.MemberName",
- GetAbsoluteMemberName("InterfaceName", "MemberName"));
- EXPECT_EQ(".", GetAbsoluteMemberName("", ""));
-}
-
-} // namespace dbus
diff --git a/dbus/values_util_unittest.cc b/dbus/values_util_unittest.cc
deleted file mode 100644
index 5a0b81e9f9..0000000000
--- a/dbus/values_util_unittest.cc
+++ /dev/null
@@ -1,687 +0,0 @@
-// Copyright (c) 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.
-
-#include "dbus/values_util.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <cmath>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/json/json_writer.h"
-#include "base/macros.h"
-#include "base/values.h"
-#include "dbus/message.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dbus {
-
-TEST(ValuesUtilTest, PopBasicTypes) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append basic type values.
- MessageWriter writer(response.get());
- const uint8_t kByteValue = 42;
- writer.AppendByte(kByteValue);
- const bool kBoolValue = true;
- writer.AppendBool(kBoolValue);
- const int16_t kInt16Value = -43;
- writer.AppendInt16(kInt16Value);
- const uint16_t kUint16Value = 44;
- writer.AppendUint16(kUint16Value);
- const int32_t kInt32Value = -45;
- writer.AppendInt32(kInt32Value);
- const uint32_t kUint32Value = 46;
- writer.AppendUint32(kUint32Value);
- const int64_t kInt64Value = -47;
- writer.AppendInt64(kInt64Value);
- const uint64_t kUint64Value = 48;
- writer.AppendUint64(kUint64Value);
- const double kDoubleValue = 4.9;
- writer.AppendDouble(kDoubleValue);
- const std::string kStringValue = "fifty";
- writer.AppendString(kStringValue);
- const std::string kEmptyStringValue;
- writer.AppendString(kEmptyStringValue);
- const ObjectPath kObjectPathValue("/ObjectPath");
- writer.AppendObjectPath(kObjectPathValue);
-
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- std::unique_ptr<base::Value> expected_value;
- // Pop a byte.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kByteValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a bool.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kBoolValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop an int16_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kInt16Value));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a uint16_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kUint16Value));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop an int32_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kInt32Value));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a uint32_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(static_cast<double>(kUint32Value)));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop an int64_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(static_cast<double>(kInt64Value)));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a uint64_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(static_cast<double>(kUint64Value)));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a double.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kDoubleValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a string.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kStringValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop an empty string.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kEmptyStringValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop an object path.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kObjectPathValue.value()));
- EXPECT_TRUE(value->Equals(expected_value.get()));
-}
-
-TEST(ValuesUtilTest, PopVariant) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append variant values.
- MessageWriter writer(response.get());
- const bool kBoolValue = true;
- writer.AppendVariantOfBool(kBoolValue);
- const int32_t kInt32Value = -45;
- writer.AppendVariantOfInt32(kInt32Value);
- const double kDoubleValue = 4.9;
- writer.AppendVariantOfDouble(kDoubleValue);
- const std::string kStringValue = "fifty";
- writer.AppendVariantOfString(kStringValue);
-
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- std::unique_ptr<base::Value> expected_value;
- // Pop a bool.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kBoolValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop an int32_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kInt32Value));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a double.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kDoubleValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- // Pop a string.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(kStringValue));
- EXPECT_TRUE(value->Equals(expected_value.get()));
-}
-
-// Pop extremely large integers which cannot be precisely represented in
-// double.
-TEST(ValuesUtilTest, PopExtremelyLargeIntegers) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append large integers.
- MessageWriter writer(response.get());
- const int64_t kInt64Value = -123456789012345689LL;
- writer.AppendInt64(kInt64Value);
- const uint64_t kUint64Value = 9876543210987654321ULL;
- writer.AppendUint64(kUint64Value);
-
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- std::unique_ptr<base::Value> expected_value;
- double double_value = 0;
- // Pop an int64_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(static_cast<double>(kInt64Value)));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- ASSERT_TRUE(value->GetAsDouble(&double_value));
- EXPECT_NE(kInt64Value, static_cast<int64_t>(double_value));
- // Pop a uint64_t.
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- expected_value.reset(new base::Value(static_cast<double>(kUint64Value)));
- EXPECT_TRUE(value->Equals(expected_value.get()));
- ASSERT_TRUE(value->GetAsDouble(&double_value));
- EXPECT_NE(kUint64Value, static_cast<uint64_t>(double_value));
-}
-
-TEST(ValuesUtilTest, PopIntArray) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append an int32_t array.
- MessageWriter writer(response.get());
- MessageWriter sub_writer(nullptr);
- std::vector<int32_t> data;
- data.push_back(0);
- data.push_back(1);
- data.push_back(2);
- writer.OpenArray("i", &sub_writer);
- for (size_t i = 0; i != data.size(); ++i)
- sub_writer.AppendInt32(data[i]);
- writer.CloseContainer(&sub_writer);
-
- // Create the expected value.
- std::unique_ptr<base::ListValue> list_value(new base::ListValue);
- for (size_t i = 0; i != data.size(); ++i)
- list_value->AppendInteger(data[i]);
-
- // Pop an int32_t array.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value(PopDataAsValue(&reader));
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(list_value.get()));
-}
-
-TEST(ValuesUtilTest, PopStringArray) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append a string array.
- MessageWriter writer(response.get());
- MessageWriter sub_writer(nullptr);
- std::vector<std::string> data;
- data.push_back("Dreamlifter");
- data.push_back("Beluga");
- data.push_back("Mriya");
- writer.AppendArrayOfStrings(data);
-
- // Create the expected value.
- std::unique_ptr<base::ListValue> list_value(new base::ListValue);
- for (size_t i = 0; i != data.size(); ++i)
- list_value->AppendString(data[i]);
-
- // Pop a string array.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value(PopDataAsValue(&reader));
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(list_value.get()));
-}
-
-TEST(ValuesUtilTest, PopStruct) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append a struct.
- MessageWriter writer(response.get());
- MessageWriter sub_writer(nullptr);
- writer.OpenStruct(&sub_writer);
- const bool kBoolValue = true;
- sub_writer.AppendBool(kBoolValue);
- const int32_t kInt32Value = -123;
- sub_writer.AppendInt32(kInt32Value);
- const double kDoubleValue = 1.23;
- sub_writer.AppendDouble(kDoubleValue);
- const std::string kStringValue = "one two three";
- sub_writer.AppendString(kStringValue);
- writer.CloseContainer(&sub_writer);
-
- // Create the expected value.
- base::ListValue list_value;
- list_value.AppendBoolean(kBoolValue);
- list_value.AppendInteger(kInt32Value);
- list_value.AppendDouble(kDoubleValue);
- list_value.AppendString(kStringValue);
-
- // Pop a struct.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value(PopDataAsValue(&reader));
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&list_value));
-}
-
-TEST(ValuesUtilTest, PopStringToVariantDictionary) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append a dictionary.
- MessageWriter writer(response.get());
- MessageWriter sub_writer(nullptr);
- MessageWriter entry_writer(nullptr);
- writer.OpenArray("{sv}", &sub_writer);
- sub_writer.OpenDictEntry(&entry_writer);
- const std::string kKey1 = "one";
- entry_writer.AppendString(kKey1);
- const bool kBoolValue = true;
- entry_writer.AppendVariantOfBool(kBoolValue);
- sub_writer.CloseContainer(&entry_writer);
- sub_writer.OpenDictEntry(&entry_writer);
- const std::string kKey2 = "two";
- entry_writer.AppendString(kKey2);
- const int32_t kInt32Value = -45;
- entry_writer.AppendVariantOfInt32(kInt32Value);
- sub_writer.CloseContainer(&entry_writer);
- sub_writer.OpenDictEntry(&entry_writer);
- const std::string kKey3 = "three";
- entry_writer.AppendString(kKey3);
- const double kDoubleValue = 4.9;
- entry_writer.AppendVariantOfDouble(kDoubleValue);
- sub_writer.CloseContainer(&entry_writer);
- sub_writer.OpenDictEntry(&entry_writer);
- const std::string kKey4 = "four";
- entry_writer.AppendString(kKey4);
- const std::string kStringValue = "fifty";
- entry_writer.AppendVariantOfString(kStringValue);
- sub_writer.CloseContainer(&entry_writer);
- writer.CloseContainer(&sub_writer);
-
- // Create the expected value.
- base::DictionaryValue dictionary_value;
- dictionary_value.SetBoolean(kKey1, kBoolValue);
- dictionary_value.SetInteger(kKey2, kInt32Value);
- dictionary_value.SetDouble(kKey3, kDoubleValue);
- dictionary_value.SetString(kKey4, kStringValue);
-
- // Pop a dictinoary.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value(PopDataAsValue(&reader));
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&dictionary_value));
-}
-
-TEST(ValuesUtilTest, PopDictionaryWithDottedStringKey) {
- std::unique_ptr<Response> response(Response::CreateEmpty());
- // Append a dictionary.
- MessageWriter writer(response.get());
- MessageWriter sub_writer(nullptr);
- MessageWriter entry_writer(nullptr);
- writer.OpenArray("{sv}", &sub_writer);
- sub_writer.OpenDictEntry(&entry_writer);
- const std::string kKey1 = "www.example.com"; // String including dots.
- entry_writer.AppendString(kKey1);
- const bool kBoolValue = true;
- entry_writer.AppendVariantOfBool(kBoolValue);
- sub_writer.CloseContainer(&entry_writer);
- sub_writer.OpenDictEntry(&entry_writer);
- const std::string kKey2 = ".example"; // String starting with a dot.
- entry_writer.AppendString(kKey2);
- const int32_t kInt32Value = -45;
- entry_writer.AppendVariantOfInt32(kInt32Value);
- sub_writer.CloseContainer(&entry_writer);
- sub_writer.OpenDictEntry(&entry_writer);
- const std::string kKey3 = "example."; // String ending with a dot.
- entry_writer.AppendString(kKey3);
- const double kDoubleValue = 4.9;
- entry_writer.AppendVariantOfDouble(kDoubleValue);
- sub_writer.CloseContainer(&entry_writer);
- writer.CloseContainer(&sub_writer);
-
- // Create the expected value.
- base::DictionaryValue dictionary_value;
- dictionary_value.SetKey(kKey1, base::Value(kBoolValue));
- dictionary_value.SetKey(kKey2, base::Value(kInt32Value));
- dictionary_value.SetKey(kKey3, base::Value(kDoubleValue));
-
- // Pop a dictinoary.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value(PopDataAsValue(&reader));
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&dictionary_value));
-}
-
-TEST(ValuesUtilTest, PopDoubleToIntDictionary) {
- // Create test data.
- const int32_t kValues[] = {0, 1, 1, 2, 3, 5, 8, 13, 21};
- const std::vector<int32_t> values(kValues, kValues + arraysize(kValues));
- std::vector<double> keys(values.size());
- for (size_t i = 0; i != values.size(); ++i)
- keys[i] = std::sqrt(values[i]);
-
- // Append a dictionary.
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- MessageWriter sub_writer(nullptr);
- writer.OpenArray("{di}", &sub_writer);
- for (size_t i = 0; i != values.size(); ++i) {
- MessageWriter entry_writer(nullptr);
- sub_writer.OpenDictEntry(&entry_writer);
- entry_writer.AppendDouble(keys[i]);
- entry_writer.AppendInt32(values[i]);
- sub_writer.CloseContainer(&entry_writer);
- }
- writer.CloseContainer(&sub_writer);
-
- // Create the expected value.
- base::DictionaryValue dictionary_value;
- for (size_t i = 0; i != values.size(); ++i) {
- std::string key_string;
- base::JSONWriter::Write(base::Value(keys[i]), &key_string);
- dictionary_value.SetKey(key_string, base::Value(values[i]));
- }
-
- // Pop a dictionary.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value(PopDataAsValue(&reader));
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&dictionary_value));
-}
-
-TEST(ValuesUtilTest, AppendBasicTypes) {
- const base::Value kBoolValue(false);
- const base::Value kIntegerValue(42);
- const base::Value kDoubleValue(4.2);
- const base::Value kStringValue("string");
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendBasicTypeValueData(&writer, kBoolValue);
- AppendBasicTypeValueData(&writer, kIntegerValue);
- AppendBasicTypeValueData(&writer, kDoubleValue);
- AppendBasicTypeValueData(&writer, kStringValue);
-
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kBoolValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kIntegerValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kDoubleValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kStringValue));
-}
-
-TEST(ValuesUtilTest, AppendBasicTypesAsVariant) {
- const base::Value kBoolValue(false);
- const base::Value kIntegerValue(42);
- const base::Value kDoubleValue(4.2);
- const base::Value kStringValue("string");
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendBasicTypeValueDataAsVariant(&writer, kBoolValue);
- AppendBasicTypeValueDataAsVariant(&writer, kIntegerValue);
- AppendBasicTypeValueDataAsVariant(&writer, kDoubleValue);
- AppendBasicTypeValueDataAsVariant(&writer, kStringValue);
-
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kBoolValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kIntegerValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kDoubleValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kStringValue));
-}
-
-TEST(ValuesUtilTest, AppendValueDataBasicTypes) {
- const base::Value kBoolValue(false);
- const base::Value kIntegerValue(42);
- const base::Value kDoubleValue(4.2);
- const base::Value kStringValue("string");
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendValueData(&writer, kBoolValue);
- AppendValueData(&writer, kIntegerValue);
- AppendValueData(&writer, kDoubleValue);
- AppendValueData(&writer, kStringValue);
-
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kBoolValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kIntegerValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kDoubleValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kStringValue));
-}
-
-TEST(ValuesUtilTest, AppendValueDataAsVariantBasicTypes) {
- const base::Value kBoolValue(false);
- const base::Value kIntegerValue(42);
- const base::Value kDoubleValue(4.2);
- const base::Value kStringValue("string");
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendValueDataAsVariant(&writer, kBoolValue);
- AppendValueDataAsVariant(&writer, kIntegerValue);
- AppendValueDataAsVariant(&writer, kDoubleValue);
- AppendValueDataAsVariant(&writer, kStringValue);
-
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kBoolValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kIntegerValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kDoubleValue));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&kStringValue));
-}
-
-TEST(ValuesUtilTest, AppendDictionary) {
- // Set up the input dictionary.
- const std::string kKey1 = "one";
- const std::string kKey2 = "two";
- const std::string kKey3 = "three";
- const std::string kKey4 = "four";
- const std::string kKey5 = "five";
- const std::string kKey6 = "six";
-
- const bool kBoolValue = true;
- const int32_t kInt32Value = -45;
- const double kDoubleValue = 4.9;
- const std::string kStringValue = "fifty";
-
- auto list_value = std::make_unique<base::ListValue>();
- list_value->AppendBoolean(kBoolValue);
- list_value->AppendInteger(kInt32Value);
-
- auto dictionary_value = std::make_unique<base::DictionaryValue>();
- dictionary_value->SetBoolean(kKey1, kBoolValue);
- dictionary_value->SetInteger(kKey2, kDoubleValue);
-
- base::DictionaryValue test_dictionary;
- test_dictionary.SetBoolean(kKey1, kBoolValue);
- test_dictionary.SetInteger(kKey2, kInt32Value);
- test_dictionary.SetDouble(kKey3, kDoubleValue);
- test_dictionary.SetString(kKey4, kStringValue);
- test_dictionary.Set(kKey5, std::move(list_value));
- test_dictionary.Set(kKey6, std::move(dictionary_value));
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendValueData(&writer, test_dictionary);
- base::Value int_value(kInt32Value);
- AppendValueData(&writer, int_value);
-
- // Read the data.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&test_dictionary));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&int_value));
-}
-
-TEST(ValuesUtilTest, AppendDictionaryAsVariant) {
- // Set up the input dictionary.
- const std::string kKey1 = "one";
- const std::string kKey2 = "two";
- const std::string kKey3 = "three";
- const std::string kKey4 = "four";
- const std::string kKey5 = "five";
- const std::string kKey6 = "six";
-
- const bool kBoolValue = true;
- const int32_t kInt32Value = -45;
- const double kDoubleValue = 4.9;
- const std::string kStringValue = "fifty";
-
- auto list_value = std::make_unique<base::ListValue>();
- list_value->AppendBoolean(kBoolValue);
- list_value->AppendInteger(kInt32Value);
-
- auto dictionary_value = std::make_unique<base::DictionaryValue>();
- dictionary_value->SetBoolean(kKey1, kBoolValue);
- dictionary_value->SetInteger(kKey2, kDoubleValue);
-
- base::DictionaryValue test_dictionary;
- test_dictionary.SetBoolean(kKey1, kBoolValue);
- test_dictionary.SetInteger(kKey2, kInt32Value);
- test_dictionary.SetDouble(kKey3, kDoubleValue);
- test_dictionary.SetString(kKey4, kStringValue);
- test_dictionary.Set(kKey5, std::move(list_value));
- test_dictionary.Set(kKey6, std::move(dictionary_value));
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendValueDataAsVariant(&writer, test_dictionary);
- base::Value int_value(kInt32Value);
- AppendValueData(&writer, int_value);
-
- // Read the data.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&test_dictionary));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&int_value));
-}
-
-TEST(ValuesUtilTest, AppendList) {
- // Set up the input list.
- const std::string kKey1 = "one";
- const std::string kKey2 = "two";
-
- const bool kBoolValue = true;
- const int32_t kInt32Value = -45;
- const double kDoubleValue = 4.9;
- const std::string kStringValue = "fifty";
-
- std::unique_ptr<base::ListValue> list_value(new base::ListValue());
- list_value->AppendBoolean(kBoolValue);
- list_value->AppendInteger(kInt32Value);
-
- std::unique_ptr<base::DictionaryValue> dictionary_value(
- new base::DictionaryValue());
- dictionary_value->SetBoolean(kKey1, kBoolValue);
- dictionary_value->SetInteger(kKey2, kDoubleValue);
-
- base::ListValue test_list;
- test_list.AppendBoolean(kBoolValue);
- test_list.AppendInteger(kInt32Value);
- test_list.AppendDouble(kDoubleValue);
- test_list.AppendString(kStringValue);
- test_list.Append(std::move(list_value));
- test_list.Append(std::move(dictionary_value));
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendValueData(&writer, test_list);
- base::Value int_value(kInt32Value);
- AppendValueData(&writer, int_value);
-
- // Read the data.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&test_list));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&int_value));
-}
-
-TEST(ValuesUtilTest, AppendListAsVariant) {
- // Set up the input list.
- const std::string kKey1 = "one";
- const std::string kKey2 = "two";
-
- const bool kBoolValue = true;
- const int32_t kInt32Value = -45;
- const double kDoubleValue = 4.9;
- const std::string kStringValue = "fifty";
-
- std::unique_ptr<base::ListValue> list_value(new base::ListValue());
- list_value->AppendBoolean(kBoolValue);
- list_value->AppendInteger(kInt32Value);
-
- std::unique_ptr<base::DictionaryValue> dictionary_value(
- new base::DictionaryValue());
- dictionary_value->SetBoolean(kKey1, kBoolValue);
- dictionary_value->SetInteger(kKey2, kDoubleValue);
-
- base::ListValue test_list;
- test_list.AppendBoolean(kBoolValue);
- test_list.AppendInteger(kInt32Value);
- test_list.AppendDouble(kDoubleValue);
- test_list.AppendString(kStringValue);
- test_list.Append(std::move(list_value));
- test_list.Append(std::move(dictionary_value));
-
- std::unique_ptr<Response> response(Response::CreateEmpty());
- MessageWriter writer(response.get());
- AppendValueDataAsVariant(&writer, test_list);
- base::Value int_value(kInt32Value);
- AppendValueData(&writer, int_value);
-
- // Read the data.
- MessageReader reader(response.get());
- std::unique_ptr<base::Value> value;
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&test_list));
- value = PopDataAsValue(&reader);
- ASSERT_NE(nullptr, value);
- EXPECT_TRUE(value->Equals(&int_value));
-}
-
-} // namespace dbus
diff --git a/ipc/ipc_channel_nacl.cc b/ipc/ipc_channel_nacl.cc
new file mode 100644
index 0000000000..190da45453
--- /dev/null
+++ b/ipc/ipc_channel_nacl.cc
@@ -0,0 +1,396 @@
+// Copyright (c) 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.
+
+#include "ipc/ipc_channel_nacl.h"
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_pump_for_io.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner_util.h"
+#include "base/threading/simple_thread.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_message_attachment_set.h"
+#include "ipc/ipc_platform_file_attachment_posix.h"
+#include "native_client/src/public/imc_syscalls.h"
+#include "native_client/src/public/imc_types.h"
+
+namespace IPC {
+
+struct MessageContents {
+ std::vector<char> data;
+ std::vector<int> fds;
+};
+
+namespace {
+
+bool ReadDataOnReaderThread(int pipe, MessageContents* contents) {
+ DCHECK(pipe >= 0);
+ if (pipe < 0)
+ return false;
+
+ contents->data.resize(Channel::kReadBufferSize);
+ contents->fds.resize(NACL_ABI_IMC_DESC_MAX);
+
+ NaClAbiNaClImcMsgIoVec iov = { &contents->data[0], contents->data.size() };
+ NaClAbiNaClImcMsgHdr msg = {
+ &iov, 1, &contents->fds[0], contents->fds.size()
+ };
+
+ int bytes_read = imc_recvmsg(pipe, &msg, 0);
+
+ if (bytes_read <= 0) {
+ // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either
+ // due to error or for regular shutdown).
+ contents->data.clear();
+ contents->fds.clear();
+ return false;
+ }
+ DCHECK(bytes_read);
+ // Resize the buffers down to the number of bytes and fds we actually read.
+ contents->data.resize(bytes_read);
+ contents->fds.resize(msg.desc_length);
+ return true;
+}
+
+} // namespace
+
+// static
+constexpr size_t Channel::kMaximumMessageSize;
+
+class ChannelNacl::ReaderThreadRunner
+ : public base::DelegateSimpleThread::Delegate {
+ public:
+ // |pipe|: A file descriptor from which we will read using imc_recvmsg.
+ // |data_read_callback|: A callback we invoke (on the main thread) when we
+ // have read data.
+ // |failure_callback|: A callback we invoke when we have a failure reading
+ // from |pipe|.
+ // |main_message_loop|: A proxy for the main thread, where we will invoke the
+ // above callbacks.
+ ReaderThreadRunner(
+ int pipe,
+ base::Callback<void(std::unique_ptr<MessageContents>)> data_read_callback,
+ base::Callback<void()> failure_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+
+ // DelegateSimpleThread implementation. Reads data from the pipe in a loop
+ // until either we are told to quit or a read fails.
+ void Run() override;
+
+ private:
+ int pipe_;
+ base::Callback<void(std::unique_ptr<MessageContents>)> data_read_callback_;
+ base::Callback<void ()> failure_callback_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner);
+};
+
+ChannelNacl::ReaderThreadRunner::ReaderThreadRunner(
+ int pipe,
+ base::Callback<void(std::unique_ptr<MessageContents>)> data_read_callback,
+ base::Callback<void()> failure_callback,
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
+ : pipe_(pipe),
+ data_read_callback_(data_read_callback),
+ failure_callback_(failure_callback),
+ main_task_runner_(main_task_runner) {}
+
+void ChannelNacl::ReaderThreadRunner::Run() {
+ while (true) {
+ std::unique_ptr<MessageContents> msg_contents(new MessageContents);
+ bool success = ReadDataOnReaderThread(pipe_, msg_contents.get());
+ if (success) {
+ main_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(data_read_callback_, base::Passed(&msg_contents)));
+ } else {
+ main_task_runner_->PostTask(FROM_HERE, failure_callback_);
+ // Because the read failed, we know we're going to quit. Don't bother
+ // trying to read again.
+ return;
+ }
+ }
+}
+
+ChannelNacl::ChannelNacl(const IPC::ChannelHandle& channel_handle,
+ Mode mode,
+ Listener* listener)
+ : ChannelReader(listener),
+ mode_(mode),
+ waiting_connect_(true),
+ pipe_(-1),
+ weak_ptr_factory_(this) {
+ if (!CreatePipe(channel_handle)) {
+ // The pipe may have been closed already.
+ const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
+ LOG(WARNING) << "Unable to create pipe in " << modestr << " mode";
+ }
+}
+
+ChannelNacl::~ChannelNacl() {
+ CleanUp();
+ Close();
+}
+
+bool ChannelNacl::Connect() {
+ WillConnect();
+
+ if (pipe_ == -1) {
+ DLOG(WARNING) << "Channel creation failed";
+ return false;
+ }
+
+ // Note that Connect is called on the "Channel" thread (i.e., the same thread
+ // where Channel::Send will be called, and the same thread that should receive
+ // messages). The constructor might be invoked on another thread (see
+ // ChannelProxy for an example of that). Therefore, we must wait until Connect
+ // is called to decide which SingleThreadTaskRunner to pass to
+ // ReaderThreadRunner.
+ reader_thread_runner_.reset(new ReaderThreadRunner(
+ pipe_,
+ base::Bind(&ChannelNacl::DidRecvMsg, weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&ChannelNacl::ReadDidFail, weak_ptr_factory_.GetWeakPtr()),
+ base::ThreadTaskRunnerHandle::Get()));
+ reader_thread_.reset(
+ new base::DelegateSimpleThread(reader_thread_runner_.get(),
+ "ipc_channel_nacl reader thread"));
+ reader_thread_->Start();
+ waiting_connect_ = false;
+ // If there were any messages queued before connection, send them.
+ ProcessOutgoingMessages();
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&ChannelNacl::CallOnChannelConnected,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ return true;
+}
+
+void ChannelNacl::Close() {
+ // For now, we assume that at shutdown, the reader thread will be woken with
+ // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we
+ // might simply be killed with no chance to clean up anyway :-).
+ // If untrusted code tries to close the channel prior to shutdown, it's likely
+ // to hang.
+ // TODO(dmichael): Can we do anything smarter here to make sure the reader
+ // thread wakes up and quits?
+ reader_thread_->Join();
+ close(pipe_);
+ pipe_ = -1;
+ reader_thread_runner_.reset();
+ reader_thread_.reset();
+ read_queue_.clear();
+ output_queue_.clear();
+}
+
+bool ChannelNacl::Send(Message* message) {
+ DCHECK(!message->HasAttachments());
+ DVLOG(2) << "sending message @" << message << " on channel @" << this
+ << " with type " << message->type();
+ std::unique_ptr<Message> message_ptr(message);
+
+#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
+ Logging::GetInstance()->OnSendMessage(message_ptr.get());
+#endif // BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
+
+ TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
+ "ChannelNacl::Send",
+ message->header()->flags,
+ TRACE_EVENT_FLAG_FLOW_OUT);
+ output_queue_.push_back(std::move(message_ptr));
+ if (!waiting_connect_)
+ return ProcessOutgoingMessages();
+
+ return true;
+}
+
+void ChannelNacl::DidRecvMsg(std::unique_ptr<MessageContents> contents) {
+ // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from
+ // the reader thread after Close is called. If so, we ignore it.
+ if (pipe_ == -1)
+ return;
+
+ auto data = std::make_unique<std::vector<char>>();
+ data->swap(contents->data);
+ read_queue_.push_back(std::move(data));
+
+ input_attachments_.reserve(contents->fds.size());
+ for (int fd : contents->fds) {
+ input_attachments_.push_back(
+ new internal::PlatformFileAttachment(base::ScopedFD(fd)));
+ }
+ contents->fds.clear();
+
+ // In POSIX, we would be told when there are bytes to read by implementing
+ // OnFileCanReadWithoutBlocking in MessagePumpForIO::FdWatcher. In NaCl, we
+ // instead know at this point because the reader thread posted some data to
+ // us.
+ ProcessIncomingMessages();
+}
+
+void ChannelNacl::ReadDidFail() {
+ Close();
+}
+
+bool ChannelNacl::CreatePipe(
+ const IPC::ChannelHandle& channel_handle) {
+ DCHECK(pipe_ == -1);
+
+ // There's one possible case in NaCl:
+ // 1) It's a channel wrapping a pipe that is given to us.
+ // We don't support these:
+ // 2) It's for a named channel.
+ // 3) It's for a client that we implement ourself.
+ // 4) It's the initial IPC channel.
+
+ if (channel_handle.socket.fd == -1) {
+ NOTIMPLEMENTED();
+ return false;
+ }
+ pipe_ = channel_handle.socket.fd;
+ return true;
+}
+
+bool ChannelNacl::ProcessOutgoingMessages() {
+ DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
+ // no connection?
+ if (output_queue_.empty())
+ return true;
+
+ if (pipe_ == -1)
+ return false;
+
+ // Write out all the messages. The trusted implementation is guaranteed to not
+ // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg.
+ while (!output_queue_.empty()) {
+ std::unique_ptr<Message> msg = std::move(output_queue_.front());
+ output_queue_.pop_front();
+
+ const size_t num_fds = msg->attachment_set()->size();
+ DCHECK(num_fds <= MessageAttachmentSet::kMaxDescriptorsPerMessage);
+ std::vector<int> fds;
+ fds.reserve(num_fds);
+ for (size_t i = 0; i < num_fds; i++) {
+ scoped_refptr<MessageAttachment> attachment =
+ msg->attachment_set()->GetAttachmentAt(i);
+ DCHECK_EQ(MessageAttachment::Type::PLATFORM_FILE, attachment->GetType());
+ fds.push_back(static_cast<internal::PlatformFileAttachment&>(*attachment)
+ .TakePlatformFile());
+ }
+
+ NaClAbiNaClImcMsgIoVec iov = {
+ const_cast<void*>(msg->data()), msg->size()
+ };
+ NaClAbiNaClImcMsgHdr msgh = {&iov, 1, fds.data(), num_fds};
+ ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0);
+
+ DCHECK(bytes_written); // The trusted side shouldn't return 0.
+ if (bytes_written < 0) {
+ // The trusted side should only ever give us an error of EPIPE. We
+ // should never be interrupted, nor should we get EAGAIN.
+ DCHECK(errno == EPIPE);
+ Close();
+ PLOG(ERROR) << "pipe_ error on "
+ << pipe_
+ << " Currently writing message of size: "
+ << msg->size();
+ return false;
+ } else {
+ msg->attachment_set()->CommitAllDescriptors();
+ }
+
+ // Message sent OK!
+ DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type()
+ << " on fd " << pipe_;
+ }
+ return true;
+}
+
+void ChannelNacl::CallOnChannelConnected() {
+ listener()->OnChannelConnected(-1);
+}
+
+ChannelNacl::ReadState ChannelNacl::ReadData(
+ char* buffer,
+ int buffer_len,
+ int* bytes_read) {
+ *bytes_read = 0;
+ if (pipe_ == -1)
+ return READ_FAILED;
+ if (read_queue_.empty())
+ return READ_PENDING;
+ while (!read_queue_.empty() && *bytes_read < buffer_len) {
+ std::vector<char>* vec = read_queue_.front().get();
+ size_t bytes_to_read = buffer_len - *bytes_read;
+ if (vec->size() <= bytes_to_read) {
+ // We can read and discard the entire vector.
+ std::copy(vec->begin(), vec->end(), buffer + *bytes_read);
+ *bytes_read += vec->size();
+ read_queue_.pop_front();
+ } else {
+ // Read all the bytes we can and discard them from the front of the
+ // vector. (This can be slowish, since erase has to move the back of the
+ // vector to the front, but it's hopefully a temporary hack and it keeps
+ // the code simple).
+ std::copy(vec->begin(), vec->begin() + bytes_to_read,
+ buffer + *bytes_read);
+ vec->erase(vec->begin(), vec->begin() + bytes_to_read);
+ *bytes_read += bytes_to_read;
+ }
+ }
+ return READ_SUCCEEDED;
+}
+
+bool ChannelNacl::ShouldDispatchInputMessage(Message* msg) {
+ return true;
+}
+
+bool ChannelNacl::GetAttachments(Message* msg) {
+ uint16_t header_fds = msg->header()->num_fds;
+ CHECK(header_fds == input_attachments_.size());
+ if (header_fds == 0)
+ return true; // Nothing to do.
+
+ for (auto& attachment : input_attachments_) {
+ msg->attachment_set()->AddAttachment(std::move(attachment));
+ }
+ input_attachments_.clear();
+ return true;
+}
+
+bool ChannelNacl::DidEmptyInputBuffers() {
+ // When the input data buffer is empty, the attachments should be too.
+ return input_attachments_.empty();
+}
+
+void ChannelNacl::HandleInternalMessage(const Message& msg) {
+ // The trusted side IPC::Channel should handle the "hello" handshake; we
+ // should not receive the "Hello" message.
+ NOTREACHED();
+}
+
+// Channel's methods
+
+// static
+std::unique_ptr<Channel> Channel::Create(
+ const IPC::ChannelHandle& channel_handle,
+ Mode mode,
+ Listener* listener) {
+ return std::make_unique<ChannelNacl>(channel_handle, mode, listener);
+}
+
+} // namespace IPC
diff --git a/ipc/ipc_channel_nacl.h b/ipc/ipc_channel_nacl.h
new file mode 100644
index 0000000000..06e7f6a271
--- /dev/null
+++ b/ipc/ipc_channel_nacl.h
@@ -0,0 +1,114 @@
+// Copyright (c) 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.
+
+#ifndef IPC_IPC_CHANNEL_NACL_H_
+#define IPC_IPC_CHANNEL_NACL_H_
+
+#include <memory>
+#include <string>
+
+#include "base/containers/circular_deque.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/process/process.h"
+#include "base/threading/simple_thread.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_reader.h"
+
+namespace IPC {
+
+class MessageAttachment;
+
+// Contains the results from one call to imc_recvmsg (data and file
+// descriptors).
+struct MessageContents;
+
+// Similar to the ChannelPosix but for Native Client code.
+// This is somewhat different because sendmsg/recvmsg here do not follow POSIX
+// semantics. Instead, they are implemented by a custom embedding of
+// NaClDescCustom. See NaClIPCAdapter for the trusted-side implementation.
+//
+// We don't need to worry about complicated set up and READWRITE mode for
+// sharing handles. We also currently do not support passing file descriptors or
+// named pipes, and we use background threads to emulate signaling when we can
+// read or write without blocking.
+class ChannelNacl : public Channel,
+ public internal::ChannelReader {
+ public:
+ // Mirror methods of Channel, see ipc_channel.h for description.
+ ChannelNacl(const IPC::ChannelHandle& channel_handle,
+ Mode mode,
+ Listener* listener);
+ ~ChannelNacl() override;
+
+ // Channel implementation.
+ bool Connect() override;
+ void Close() override;
+ bool Send(Message* message) override;
+
+ // Posted to the main thread by ReaderThreadRunner.
+ void DidRecvMsg(std::unique_ptr<MessageContents> contents);
+ void ReadDidFail();
+
+ private:
+ class ReaderThreadRunner;
+
+ bool CreatePipe(const IPC::ChannelHandle& channel_handle);
+ bool ProcessOutgoingMessages();
+ void CallOnChannelConnected();
+
+ // ChannelReader implementation.
+ ReadState ReadData(char* buffer,
+ int buffer_len,
+ int* bytes_read) override;
+ bool ShouldDispatchInputMessage(Message* msg) override;
+ bool GetAttachments(Message* msg) override;
+ bool DidEmptyInputBuffers() override;
+ void HandleInternalMessage(const Message& msg) override;
+
+ Mode mode_;
+ bool waiting_connect_;
+
+ // The pipe used for communication.
+ int pipe_;
+
+ // We use a thread for reading, so that we can simply block on reading and
+ // post the received data back to the main thread to be properly interleaved
+ // with other tasks in the MessagePump.
+ //
+ // imc_recvmsg supports non-blocking reads, but there's no easy way to be
+ // informed when a write or read can be done without blocking (this is handled
+ // by libevent in Posix).
+ std::unique_ptr<ReaderThreadRunner> reader_thread_runner_;
+ std::unique_ptr<base::DelegateSimpleThread> reader_thread_;
+
+ // IPC::ChannelReader expects to be able to call ReadData on us to
+ // synchronously read data waiting in the pipe's buffer without blocking.
+ // Since we can't do that (see 1 and 2 above), the reader thread does blocking
+ // reads and posts the data over to the main thread in MessageContents. Each
+ // MessageContents object is the result of one call to "imc_recvmsg".
+ // DidRecvMsg breaks the MessageContents out in to the data and the file
+ // descriptors, and puts them on these two queues.
+ // TODO(dmichael): There's probably a more efficient way to emulate this with
+ // a circular buffer or something, so we don't have to do so
+ // many heap allocations. But it maybe isn't worth
+ // the trouble given that we probably want to implement 1 and
+ // 2 above in NaCl eventually.
+ // When ReadData is called, it pulls the bytes out of this queue in order.
+ base::circular_deque<std::unique_ptr<std::vector<char>>> read_queue_;
+ // Queue of file descriptor attachments extracted from imc_recvmsg messages.
+ std::vector<scoped_refptr<MessageAttachment>> input_attachments_;
+
+ // This queue is used when a message is sent prior to Connect having been
+ // called. Normally after we're connected, the queue is empty.
+ base::circular_deque<std::unique_ptr<Message>> output_queue_;
+
+ base::WeakPtrFactory<ChannelNacl> weak_ptr_factory_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelNacl);
+};
+
+} // namespace IPC
+
+#endif // IPC_IPC_CHANNEL_NACL_H_
diff --git a/ipc/ipc_test.mojom b/ipc/ipc_test.mojom
deleted file mode 100644
index fc24e37c09..0000000000
--- a/ipc/ipc_test.mojom
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 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.
-
-module IPC.mojom;
-
-interface SimpleTestDriver {
- ExpectValue(int32 value);
-
- [Sync]
- GetExpectedValue() => (int32 value);
-
- [Sync]
- RequestValue() => (int32 value);
-
- RequestQuit() => ();
-};
-
-interface SimpleTestClient {
- [Sync]
- RequestValue() => (int32 value);
-};
-
-interface PingReceiver {
- Ping() => ();
-};
-
-struct TestStruct {};
-
-interface TestStructPasser {
- Pass(TestStruct s);
-};
-
-interface IndirectTestDriver {
- GetPingReceiver(associated PingReceiver& request);
-};
-
-interface Reflector {
- Ping(string value) => (string value);
- [Sync]
- SyncPing(string value) => (string response);
- Quit();
-};
-
-interface AssociatedInterfaceVendor {
- GetTestInterface(associated SimpleTestDriver& interface_reqest);
-};
-
-interface InterfacePassingTestDriver {
- Init() => ();
- GetPingReceiver(array<PingReceiver&> request) => ();
- GetAssociatedPingReceiver(array<associated PingReceiver&> request) => ();
- Quit();
-};
diff --git a/libchrome_tools/files_not_built b/libchrome_tools/files_not_built
deleted file mode 100755
index 64ad444f68..0000000000
--- a/libchrome_tools/files_not_built
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-# List cc files not in BUILD.gn, and not excluded by patterns in BUILD.IGNORE
-# This list can be run by human for sanity check that no imporant things are
-# ignored after each uprev.
-
-cd $(dirname $0)/..
-find . -name '*.cc' \
- | sed -e 's/^\.\///g' \
- | xargs -n 1 -P 1 bash -c \
- 'for i in $(cat BUILD.IGNORE); do grep $i <(echo $0) >/dev/null && exit; done; echo $0' \
- | xargs -n 1 -P 1 sh -c 'grep $0 BUILD.gn >/dev/null || echo $0'
-
diff --git a/libchrome_tools/mojom_generate_type_mappings.py b/libchrome_tools/mojom_generate_type_mappings.py
index a532e307f5..0c8023c40f 100755..100644
--- a/libchrome_tools/mojom_generate_type_mappings.py
+++ b/libchrome_tools/mojom_generate_type_mappings.py
@@ -28,26 +28,11 @@ import os
import subprocess
import sys
+from build import gn_helpers
-try:
- # ../build cannot be loaded if cwd is other directories
- # e.g. when emerge libchrome
- sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
- from build import gn_helpers
-except ImportError:
- # gn_helpers is located at the same directory when building other packages
- # in system directory.
- import gn_helpers
-
-# script in libchrome repositority is used when emerge libchrome.
_GENERATE_TYPE_MAPPINGS_PATH = os.path.join(
os.path.dirname(__file__),
'../mojo/public/tools/bindings/generate_type_mappings.py')
-if not os.path.isfile(_GENERATE_TYPE_MAPPINGS_PATH):
- # use system script in the same dir when building other packages.
- _GENERATE_TYPE_MAPPINGS_PATH = os.path.join(
- os.path.dirname(__file__),
- 'generate_type_mappings.py')
def _read_typemap_config(path):
"""Reads .typemap file.
diff --git a/libchrome_tools/patches/0001-Fix-pending_broker_clients-handling.patch b/libchrome_tools/patches/0001-Fix-pending_broker_clients-handling.patch
deleted file mode 100644
index 2402a1097b..0000000000
--- a/libchrome_tools/patches/0001-Fix-pending_broker_clients-handling.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 6a4ab3d6429ec13e8c875ebc611683bb26453770 Mon Sep 17 00:00:00 2001
-From: Lepton Wu <lepton@chromium.org>
-Date: Tue, 15 Sep 2020 16:58:14 +0000
-Subject: [PATCH] Fix pending_broker_clients handling
-
-We always remove invitee from pending_invitations_ before adding it to
-pending_broker_clients, so the old code actually is buggy and invitees
-in pending_broker_clients_ will never be added as a broker client. Fix
-it by checking peers_ instead of pending_invitations_.
-
-BUG=b:146518063,b:150661600,b:168250032,chromium:1121709
-TEST=manual - Keep running arc.Boot.vm with updated mojo code.
-
-Change-Id: Ib0353944e7d5b9edc04947f8bd2db1442a4ed78d
-Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2411560
-Commit-Queue: Ken Rockot <rockot@google.com>
-Reviewed-by: Ken Rockot <rockot@google.com>
-Auto-Submit: Lepton Wu <lepton@chromium.org>
-Cr-Commit-Position: refs/heads/master@{#807076}
----
- mojo/core/node_controller.cc | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
-diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
-index 298079f4e234..029bd350b08b 100644
---- a/mojo/core/node_controller.cc
-+++ b/mojo/core/node_controller.cc
-@@ -993,11 +993,8 @@ void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
- // Feed the broker any pending invitees of our own.
- while (!pending_broker_clients.empty()) {
- const ports::NodeName& invitee_name = pending_broker_clients.front();
-- auto it = pending_invitations_.find(invitee_name);
-- // If for any reason we don't have a pending invitation for the invitee,
-- // there's nothing left to do: we've already swapped the relevant state into
-- // the stack.
-- if (it != pending_invitations_.end()) {
-+ auto it = peers_.find(invitee_name);
-+ if (it != peers_.end()) {
- broker->AddBrokerClient(invitee_name,
- it->second->CloneRemoteProcessHandle());
- }
---
-2.28.0.618.gf4bc123cb7-goog
-
diff --git a/libchrome_tools/patches/Add-base-NoDestructor-T.patch b/libchrome_tools/patches/Add-base-NoDestructor-T.patch
deleted file mode 100644
index 9c95d4bc0e..0000000000
--- a/libchrome_tools/patches/Add-base-NoDestructor-T.patch
+++ /dev/null
@@ -1,129 +0,0 @@
-From c334673e96ce73cbf1a693c7c85b1450fcd3571c Mon Sep 17 00:00:00 2001
-From: Ben Chan <benchan@chromium.org>
-Date: Fri, 2 Nov 2018 23:07:01 -0700
-Subject: [PATCH] libchrome: add base::NoDestructor<T>
-
-CL:869351 introduces base::NoDestructor<T>, which is preferred in new
-code as a drop-in replacement for a function scoped static T* or T& that
-is dynamically initialized, and a global base::LazyInstance<T>.
-
-This CL patches libchrome to pull in base/no_destructor.h at r599267, so
-that we can migrate existing Chrome OS code to use base::NoDestructor<T>
-before the next libchrome uprev.
-
-BUG=None
-TEST=`emerge-$BOARD librchrome`
-
-Change-Id: I791a70e10da6318ea81eaaec869ba4702361289e
----
- base/no_destructor.h | 98 ++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 98 insertions(+)
- create mode 100644 base/no_destructor.h
-
-diff --git base/no_destructor.h base/no_destructor.h
-new file mode 100644
-index 0000000..21cfef8
---- /dev/null
-+++ base/no_destructor.h
-@@ -0,0 +1,98 @@
-+// Copyright 2018 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.
-+
-+#ifndef BASE_NO_DESTRUCTOR_H_
-+#define BASE_NO_DESTRUCTOR_H_
-+
-+#include <new>
-+#include <utility>
-+
-+namespace base {
-+
-+// A wrapper that makes it easy to create an object of type T with static
-+// storage duration that:
-+// - is only constructed on first access
-+// - never invokes the destructor
-+// in order to satisfy the styleguide ban on global constructors and
-+// destructors.
-+//
-+// Runtime constant example:
-+// const std::string& GetLineSeparator() {
-+// // Forwards to std::string(size_t, char, const Allocator&) constructor.
-+// static const base::NoDestructor<std::string> s(5, '-');
-+// return *s;
-+// }
-+//
-+// More complex initialization with a lambda:
-+// const std::string& GetSessionNonce() {
-+// static const base::NoDestructor<std::string> nonce([] {
-+// std::string s(16);
-+// crypto::RandString(s.data(), s.size());
-+// return s;
-+// }());
-+// return *nonce;
-+// }
-+//
-+// NoDestructor<T> stores the object inline, so it also avoids a pointer
-+// indirection and a malloc. Also note that since C++11 static local variable
-+// initialization is thread-safe and so is this pattern. Code should prefer to
-+// use NoDestructor<T> over:
-+// - A function scoped static T* or T& that is dynamically initialized.
-+// - A global base::LazyInstance<T>.
-+//
-+// Note that since the destructor is never run, this *will* leak memory if used
-+// as a stack or member variable. Furthermore, a NoDestructor<T> should never
-+// have global scope as that may require a static initializer.
-+template <typename T>
-+class NoDestructor {
-+ public:
-+ // Not constexpr; just write static constexpr T x = ...; if the value should
-+ // be a constexpr.
-+ template <typename... Args>
-+ explicit NoDestructor(Args&&... args) {
-+ new (storage_) T(std::forward<Args>(args)...);
-+ }
-+
-+ // Allows copy and move construction of the contained type, to allow
-+ // construction from an initializer list, e.g. for std::vector.
-+ explicit NoDestructor(const T& x) { new (storage_) T(x); }
-+ explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
-+
-+ NoDestructor(const NoDestructor&) = delete;
-+ NoDestructor& operator=(const NoDestructor&) = delete;
-+
-+ ~NoDestructor() = default;
-+
-+ const T& operator*() const { return *get(); }
-+ T& operator*() { return *get(); }
-+
-+ const T* operator->() const { return get(); }
-+ T* operator->() { return get(); }
-+
-+ const T* get() const { return reinterpret_cast<const T*>(storage_); }
-+ T* get() { return reinterpret_cast<T*>(storage_); }
-+
-+ private:
-+ alignas(T) char storage_[sizeof(T)];
-+
-+#if defined(LEAK_SANITIZER)
-+ // TODO(https://crbug.com/812277): This is a hack to work around the fact
-+ // that LSan doesn't seem to treat NoDestructor as a root for reachability
-+ // analysis. This means that code like this:
-+ // static base::NoDestructor<std::vector<int>> v({1, 2, 3});
-+ // is considered a leak. Using the standard leak sanitizer annotations to
-+ // suppress leaks doesn't work: std::vector is implicitly constructed before
-+ // calling the base::NoDestructor constructor.
-+ //
-+ // Unfortunately, I haven't been able to demonstrate this issue in simpler
-+ // reproductions: until that's resolved, hold an explicit pointer to the
-+ // placement-new'd object in leak sanitizer mode to help LSan realize that
-+ // objects allocated by the contained type are still reachable.
-+ T* storage_ptr_ = reinterpret_cast<T*>(storage_);
-+#endif // defined(LEAK_SANITIZER)
-+};
-+
-+} // namespace base
-+
-+#endif // BASE_NO_DESTRUCTOR_H_
---
-2.19.1.930.g4563a0d9d0-goog
-
diff --git a/libchrome_tools/patches/Add-header-files-base-check_op-notreached-h.patch b/libchrome_tools/patches/Add-header-files-base-check_op-notreached-h.patch
deleted file mode 100644
index 8b61fa4d80..0000000000
--- a/libchrome_tools/patches/Add-header-files-base-check_op-notreached-h.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From b69366c4a2f08545bd03e1c0aa6a37562510a2e6 Mon Sep 17 00:00:00 2001
-From: hscham <hscham@chromium.org>
-Date: Wed, 3 Jun 2020 17:26:49 +0900
-Subject: [PATCH] Add header files base/{check_op,notreached}.h
-
-Change-Id: I5267ddeba3a63c7977f093b1a25dff760dbe167b
----
- base/check_op.h | 10 ++++++++++
- base/notreached.h | 10 ++++++++++
- 2 files changed, 20 insertions(+)
- create mode 100644 base/check_op.h
- create mode 100644 base/notreached.h
-
-diff --git a/base/check_op.h b/base/check_op.h
-new file mode 100644
-index 000000000..caa3c3af6
---- /dev/null
-+++ base/check_op.h
-@@ -0,0 +1,10 @@
-+// Copyright 2020 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.
-+
-+#ifndef BASE_CHECK_OP_H_
-+#define BASE_CHECK_OP_H_
-+
-+#include "base/logging.h"
-+
-+#endif // BASE_CHECK_OP_H_
-diff --git a/base/notreached.h b/base/notreached.h
-new file mode 100644
-index 000000000..1eacc44e4
---- /dev/null
-+++ base/notreached.h
-@@ -0,0 +1,10 @@
-+// Copyright 2020 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.
-+
-+#ifndef BASE_NOTREACHED_H_
-+#define BASE_NOTREACHED_H_
-+
-+#include "base/logging.h"
-+
-+#endif // BASE_NOTREACHED_H_
---
-2.27.0.rc2.251.g90737beb825-goog
-
diff --git a/libchrome_tools/patches/Connect-to-NameOwnerChanged-signal-when-setting-call.patch b/libchrome_tools/patches/Connect-to-NameOwnerChanged-signal-when-setting-call.patch
deleted file mode 100644
index 83d2e49e9b..0000000000
--- a/libchrome_tools/patches/Connect-to-NameOwnerChanged-signal-when-setting-call.patch
+++ /dev/null
@@ -1,163 +0,0 @@
-From c2e55024c6a03dcb099270718e70139542d8b0e4 Mon Sep 17 00:00:00 2001
-From: Bing Xue <bingxue@google.com>
-Date: Thu, 1 Aug 2019 15:47:10 -0700
-Subject: [PATCH] Connect to NameOwnerChanged signal when setting callback
-
-In ObjectManager, when ConnectToNameOwnerChangedSignal is called the first time,
-we could have already missed the NameOwnerChanged signal if we get a value from
-UpdateNameOwnerAndBlock. This means NameOwnerChanged callbacks will
-never be called until that service restarts. In ObjectManager we run
-into this problem:
-
-1. ObjectManager::SetupMatchRuleAndFilter is called, calling
-bus_->GetServiceOwnerAndBlock shows empty service name owner.
-
-2. ObjectManager::OnSetupManagerRuleAndFilterComplete callback will call
-object_proxy_->ConnectToSignal, which in turn calls
-ConnectToNameOwnerChangedSignal the first time. At this point,
-UpdateNameOwnerAndBlock calling bus_->GetServiceOwnerAndBlock returns the
-current name owner of the service, this means the NameOwnerChanged signal
-is already sent on system bus.
-
-3. As a result, ObjectManager::NameOwnerChanged is never called while
-the service is already online. This in turn causes GetManagedObject to
-never be called, and the object manager interface never added.
-
-See detailed sample logs in b/138416411.
-
-This CL adds the following:
-
-1. Make SetNameOwnerChangedCallback run
-ConnectToNameOwnerChangedSignal when called. Since ObjectManager calls
-SetNameOwnerChangedCallback before posting SetupMatchRuleAndFilter (in which
-ObjectManager attempts to get the service name owner through a blocking call),
-this removes the time gap described above that causes lost signal.
-
-2. Make dbus thread the only writer to |service_name_owner_|, given that
-connecting to the NameOwnerChanged signal right away in ObjectManager
-ctor causes potential data race in writing to |service_name_owner_| in
-both NameOwnerChanged (on origin thread) and SetupMatchRuleAndFilter (on
-dbus thread).
-
-BUG=b:138416411
-TEST=Manually on device.
-
-Change-Id: Ie95a5b7b303637acadebda151cc478e52b6a1af5
----
- dbus/object_manager.cc | 20 +++++++++++++++++---
- dbus/object_manager.h | 5 +++++
- dbus/object_proxy.cc | 13 +++++++++++++
- dbus/object_proxy.h | 3 +++
- 4 files changed, 38 insertions(+), 3 deletions(-)
-
-diff --git a/dbus/object_manager.cc b/dbus/object_manager.cc
-index 05d4b2ddeabd..44f120864310 100644
---- a/dbus/object_manager.cc
-+++ b/dbus/object_manager.cc
-@@ -187,8 +187,12 @@ bool ObjectManager::SetupMatchRuleAndFilter() {
- if (!bus_->Connect() || !bus_->SetUpAsyncOperations())
- return false;
-
-- service_name_owner_ =
-- bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
-+ // Try to get |service_name_owner_| from dbus if we haven't received any
-+ // NameOwnerChanged signals.
-+ if (service_name_owner_.empty()) {
-+ service_name_owner_ =
-+ bus_->GetServiceOwnerAndBlock(service_name_, Bus::SUPPRESS_ERRORS);
-+ }
-
- const std::string match_rule =
- base::StringPrintf(
-@@ -224,6 +228,7 @@ void ObjectManager::OnSetupMatchRuleAndFilterComplete(bool success) {
- DCHECK(bus_);
- DCHECK(object_proxy_);
- DCHECK(setup_success_);
-+ bus_->AssertOnOriginThread();
-
- // |object_proxy_| is no longer valid if the Bus was shut down before this
- // call. Don't initiate any other action from the origin thread.
-@@ -505,9 +510,18 @@ void ObjectManager::RemoveInterface(const ObjectPath& object_path,
- }
- }
-
-+void ObjectManager::UpdateServiceNameOwner(const std::string& new_owner) {
-+ bus_->AssertOnDBusThread();
-+ service_name_owner_ = new_owner;
-+}
-+
- void ObjectManager::NameOwnerChanged(const std::string& old_owner,
- const std::string& new_owner) {
-- service_name_owner_ = new_owner;
-+ bus_->AssertOnOriginThread();
-+
-+ bus_->GetDBusTaskRunner()->PostTask(
-+ FROM_HERE,
-+ base::BindOnce(&ObjectManager::UpdateServiceNameOwner, this, new_owner));
-
- if (!old_owner.empty()) {
- ObjectMap::iterator iter = object_map_.begin();
-diff --git a/dbus/object_manager.h b/dbus/object_manager.h
-index 05388de8e6eb..4b5fb790412d 100644
---- a/dbus/object_manager.h
-+++ b/dbus/object_manager.h
-@@ -317,6 +317,11 @@ class CHROME_DBUS_EXPORT ObjectManager final
- void NameOwnerChanged(const std::string& old_owner,
- const std::string& new_owner);
-
-+ // Write |new_owner| to |service_name_owner_|. This method makes sure write
-+ // happens on the DBus thread, which is the sole writer to
-+ // |service_name_owner_|.
-+ void UpdateServiceNameOwner(const std::string& new_owner);
-+
- Bus* bus_;
- std::string service_name_;
- std::string service_name_owner_;
-diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc
-index 7adf8f179471..de5785e98307 100644
---- a/dbus/object_proxy.cc
-+++ b/dbus/object_proxy.cc
-@@ -274,6 +274,10 @@ void ObjectProxy::SetNameOwnerChangedCallback(
- bus_->AssertOnOriginThread();
-
- name_owner_changed_callback_ = callback;
-+
-+ bus_->GetDBusTaskRunner()->PostTask(
-+ FROM_HERE,
-+ base::BindOnce(&ObjectProxy::TryConnectToNameOwnerChangedSignal, this));
- }
-
- void ObjectProxy::WaitForServiceToBeAvailable(
-@@ -458,6 +462,15 @@ bool ObjectProxy::ConnectToNameOwnerChangedSignal() {
- return success;
- }
-
-+void ObjectProxy::TryConnectToNameOwnerChangedSignal() {
-+ bus_->AssertOnDBusThread();
-+
-+ bool success = ConnectToNameOwnerChangedSignal();
-+ LOG_IF(WARNING, !success)
-+ << "Failed to connect to NameOwnerChanged signal for object: "
-+ << object_path_.value();
-+}
-+
- bool ObjectProxy::ConnectToSignalInternal(const std::string& interface_name,
- const std::string& signal_name,
- SignalCallback signal_callback) {
-diff --git a/dbus/object_proxy.h b/dbus/object_proxy.h
-index 22e44f1d64c0..b1bf622a12cb 100644
---- a/dbus/object_proxy.h
-+++ b/dbus/object_proxy.h
-@@ -267,6 +267,9 @@ class CHROME_DBUS_EXPORT ObjectProxy
- // Connects to NameOwnerChanged signal.
- bool ConnectToNameOwnerChangedSignal();
-
-+ // Tries to connect to NameOwnerChanged signal, ignores any error.
-+ void TryConnectToNameOwnerChangedSignal();
-+
- // Helper function for ConnectToSignal().
- bool ConnectToSignalInternal(const std::string& interface_name,
- const std::string& signal_name,
---
-2.22.0.770.g0f2c4a37fd-goog
-
diff --git a/libchrome_tools/patches/Fix-TimeDelta.patch b/libchrome_tools/patches/Fix-TimeDelta.patch
deleted file mode 100644
index 65ab874a03..0000000000
--- a/libchrome_tools/patches/Fix-TimeDelta.patch
+++ /dev/null
@@ -1,164 +0,0 @@
-commit db5f2b6e74d6d2e2a9c6f530199067c1d6eff7b6
-Author: Max Morin <maxmorin@chromium.org>
-Date: Mon Aug 27 09:45:24 2018 +0000
-
- Make TimeDelta TriviallyCopyable for std::atomic.
-
- We're having some awkwardness with working around the issue with stuff
- like std::atomic<int64_t> and conversions back and forth. It would be
- preferable to use std::atomic<TimeDelta> directly.
-
- Removes the workaround added for bug 635974, since that was a bug in
- vs 2015 and we use clang now.
-
- Also fixes a couple of lint issues in time.h.
-
- Bug: 635974, 851959, 761570
- Change-Id: I4683f960b0c348748c5f0aaf222da4dda40256ec
- Reviewed-on: https://chromium-review.googlesource.com/1184781
- Commit-Queue: Max Morin <maxmorin@chromium.org>
- Reviewed-by: Yuri Wiitala <miu@chromium.org>
- Reviewed-by: Bruce Dawson <brucedawson@chromium.org>
- Cr-Commit-Position: refs/heads/master@{#586219}
-
-diff --git a/base/time/time.h b/base/time/time.h
-index f4c2f93f30b4..7d4f308545c9 100644
---- a/base/time/time.h
-+++ b/base/time/time.h
-@@ -199,11 +199,6 @@ class BASE_EXPORT TimeDelta {
- double InMicrosecondsF() const;
- int64_t InNanoseconds() const;
-
-- constexpr TimeDelta& operator=(TimeDelta other) {
-- delta_ = other.delta_;
-- return *this;
-- }
--
- // Computations with other deltas. Can easily be made constexpr with C++17 but
- // hard to do until then per limitations around
- // __builtin_(add|sub)_overflow in safe_math_clang_gcc_impl.h :
-@@ -283,11 +278,6 @@ class BASE_EXPORT TimeDelta {
- return delta_ >= other.delta_;
- }
-
--#if defined(OS_WIN)
-- // This works around crbug.com/635974
-- constexpr TimeDelta(const TimeDelta& other) : delta_(other.delta_) {}
--#endif
--
- private:
- friend int64_t time_internal::SaturatedAdd(TimeDelta delta, int64_t value);
- friend int64_t time_internal::SaturatedSub(TimeDelta delta, int64_t value);
-@@ -375,7 +365,7 @@ class TimeBase {
- //
- // DEPRECATED - Do not use in new code. For serializing Time values, prefer
- // Time::ToDeltaSinceWindowsEpoch().InMicroseconds(). http://crbug.com/634507
-- int64_t ToInternalValue() const { return us_; }
-+ constexpr int64_t ToInternalValue() const { return us_; }
-
- // The amount of time since the origin (or "zero") point. This is a syntactic
- // convenience to aid in code readability, mainly for debugging/testing use
-@@ -799,7 +789,7 @@ constexpr TimeDelta TimeDelta::FromDouble(double value) {
- // static
- constexpr TimeDelta TimeDelta::FromProduct(int64_t value,
- int64_t positive_value) {
-- DCHECK(positive_value > 0);
-+ DCHECK(positive_value > 0); // NOLINT, DCHECK_GT isn't constexpr.
- return value > std::numeric_limits<int64_t>::max() / positive_value
- ? Max()
- : value < std::numeric_limits<int64_t>::min() / positive_value
-@@ -903,8 +893,8 @@ class BASE_EXPORT TimeTicks : public time_internal::TimeBase<TimeTicks> {
- return TimeTicks(us);
- }
-
--#if defined(OS_WIN)
- protected:
-+#if defined(OS_WIN)
- typedef DWORD (*TickFunctionType)(void);
- static TickFunctionType SetMockTickFunction(TickFunctionType ticker);
- #endif
-@@ -926,8 +916,7 @@ BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks);
- // thread is running.
- class BASE_EXPORT ThreadTicks : public time_internal::TimeBase<ThreadTicks> {
- public:
-- ThreadTicks() : TimeBase(0) {
-- }
-+ constexpr ThreadTicks() : TimeBase(0) {}
-
- // Returns true if ThreadTicks::Now() is supported on this system.
- static bool IsSupported() WARN_UNUSED_RESULT {
-diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc
-index 5dc8888a3297..ce8cc39cbaec 100644
---- a/base/time/time_unittest.cc
-+++ b/base/time/time_unittest.cc
-@@ -1542,6 +1542,70 @@ TEST(TimeDelta, Overflows) {
- EXPECT_EQ(kOneSecond, (ticks_now + kOneSecond) - ticks_now);
- }
-
-+constexpr TimeTicks TestTimeTicksConstexprCopyAssignment() {
-+ TimeTicks a = TimeTicks::FromInternalValue(12345);
-+ TimeTicks b;
-+ b = a;
-+ return b;
-+}
-+
-+TEST(TimeTicks, ConstexprAndTriviallyCopiable) {
-+ // "Trivially copyable" is necessary for use in std::atomic<TimeTicks>.
-+ static_assert(std::is_trivially_copyable<TimeTicks>(), "");
-+
-+ // Copy ctor.
-+ constexpr TimeTicks a = TimeTicks::FromInternalValue(12345);
-+ constexpr TimeTicks b{a};
-+ static_assert(a.ToInternalValue() == b.ToInternalValue(), "");
-+
-+ // Copy assignment.
-+ static_assert(a.ToInternalValue() ==
-+ TestTimeTicksConstexprCopyAssignment().ToInternalValue(),
-+ "");
-+}
-+
-+constexpr ThreadTicks TestThreadTicksConstexprCopyAssignment() {
-+ ThreadTicks a = ThreadTicks::FromInternalValue(12345);
-+ ThreadTicks b;
-+ b = a;
-+ return b;
-+}
-+
-+TEST(ThreadTicks, ConstexprAndTriviallyCopiable) {
-+ // "Trivially copyable" is necessary for use in std::atomic<ThreadTicks>.
-+ static_assert(std::is_trivially_copyable<ThreadTicks>(), "");
-+
-+ // Copy ctor.
-+ constexpr ThreadTicks a = ThreadTicks::FromInternalValue(12345);
-+ constexpr ThreadTicks b{a};
-+ static_assert(a.ToInternalValue() == b.ToInternalValue(), "");
-+
-+ // Copy assignment.
-+ static_assert(a.ToInternalValue() ==
-+ TestThreadTicksConstexprCopyAssignment().ToInternalValue(),
-+ "");
-+}
-+
-+constexpr TimeDelta TestTimeDeltaConstexprCopyAssignment() {
-+ TimeDelta a = TimeDelta::FromSeconds(1);
-+ TimeDelta b;
-+ b = a;
-+ return b;
-+}
-+
-+TEST(TimeDelta, ConstexprAndTriviallyCopiable) {
-+ // "Trivially copyable" is necessary for use in std::atomic<TimeDelta>.
-+ static_assert(std::is_trivially_copyable<TimeDelta>(), "");
-+
-+ // Copy ctor.
-+ constexpr TimeDelta a = TimeDelta::FromSeconds(1);
-+ constexpr TimeDelta b{a};
-+ static_assert(a == b, "");
-+
-+ // Copy assignment.
-+ static_assert(a == TestTimeDeltaConstexprCopyAssignment(), "");
-+}
-+
- TEST(TimeDeltaLogging, DCheckEqCompiles) {
- DCHECK_EQ(TimeDelta(), TimeDelta());
- }
diff --git a/libchrome_tools/patches/Fix-Wdefaulted-function-deleted-warning-in-MessageLo.patch b/libchrome_tools/patches/Fix-Wdefaulted-function-deleted-warning-in-MessageLo.patch
deleted file mode 100644
index 33855143c9..0000000000
--- a/libchrome_tools/patches/Fix-Wdefaulted-function-deleted-warning-in-MessageLo.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 91fe99136cd57a8eab9c076e4e1699767bcac3fa Mon Sep 17 00:00:00 2001
-From: Hans Wennborg <hans@chromium.org>
-Date: Tue, 2 Oct 2018 16:25:34 +0000
-Subject: [PATCH] Fix -Wdefaulted-function-deleted warning in
- MessageLoopCurrent
-
-The new Clang warning points out that the class can't be copy
-assigned because the current_ member is const. Copy or move
-constructing it is fine though, and that's all that's needed.
-
-Bug: 890307
-Change-Id: I3f4d5e69485b84166ba4dd2356cc7973a5e58da6
-Reviewed-on: https://chromium-review.googlesource.com/1255613
-Reviewed-by: Daniel Cheng <dcheng@chromium.org>
-Cr-Commit-Position: refs/heads/master@{#595867}
----
- base/message_loop/message_loop_current.h | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/base/message_loop/message_loop_current.h b/base/message_loop/message_loop_current.h
-index d623cbc7f7b2..403d0dcc2ddb 100644
---- a/base/message_loop/message_loop_current.h
-+++ b/base/message_loop/message_loop_current.h
-@@ -38,9 +38,9 @@ class MessageLoop;
- class BASE_EXPORT MessageLoopCurrent {
- public:
- // MessageLoopCurrent is effectively just a disguised pointer and is fine to
-- // copy around.
-+ // copy/move around.
- MessageLoopCurrent(const MessageLoopCurrent& other) = default;
-- MessageLoopCurrent& operator=(const MessageLoopCurrent& other) = default;
-+ MessageLoopCurrent(MessageLoopCurrent&& other) = default;
-
- // Returns a proxy object to interact with the MessageLoop running the
- // current thread. It must only be used on the thread it was obtained.
---
-2.22.0.rc2.383.gf4fbbf30c2-goog
-
diff --git a/libchrome_tools/patches/Mojo-Check-if-dispatcher-is-null-in-Core-UnwrapPlatf.patch b/libchrome_tools/patches/Mojo-Check-if-dispatcher-is-null-in-Core-UnwrapPlatf.patch
deleted file mode 100644
index 28ff13bb6f..0000000000
--- a/libchrome_tools/patches/Mojo-Check-if-dispatcher-is-null-in-Core-UnwrapPlatf.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 317fd980dd9504d3fe321b53469fee79e3276fed Mon Sep 17 00:00:00 2001
-From: Ryo Hashimoto <hashimoto@chromium.org>
-Date: Thu, 4 Oct 2018 05:04:22 +0000
-Subject: [PATCH] Mojo: Check if dispatcher is null in
- Core::UnwrapPlatformHandle()
-
-The same check is done in other functions in this .cc file.
-Do the same thing for UnwrapPlatformHandle().
-
-BUG=891990
-TEST=mojo_unittests
-
-Change-Id: I05fe4bfd5edd8ec3fc67aeb9f11879c74fd71dd4
-Reviewed-on: https://chromium-review.googlesource.com/c/1260782
-Reviewed-by: Ken Rockot <rockot@chromium.org>
-Commit-Queue: Ryo Hashimoto <hashimoto@chromium.org>
-Cr-Commit-Position: refs/heads/master@{#596510}
----
- mojo/core/core.cc | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/mojo/core/core.cc b/mojo/core/core.cc
-index 8422ec247a40..32ecea3eae55 100644
---- a/mojo/core/core.cc
-+++ b/mojo/core/core.cc
-@@ -1017,7 +1017,8 @@ MojoResult Core::UnwrapPlatformHandle(
- {
- base::AutoLock lock(handles_->GetLock());
- dispatcher = handles_->GetDispatcher(mojo_handle);
-- if (dispatcher->GetType() != Dispatcher::Type::PLATFORM_HANDLE)
-+ if (!dispatcher ||
-+ dispatcher->GetType() != Dispatcher::Type::PLATFORM_HANDLE)
- return MOJO_RESULT_INVALID_ARGUMENT;
-
- MojoResult result =
---
-2.25.0.225.g125e21ebc7-goog
-
diff --git a/libchrome_tools/patches/Refactor-AlarmTimer-to-report-error-to-the-caller.patch b/libchrome_tools/patches/Refactor-AlarmTimer-to-report-error-to-the-caller.patch
deleted file mode 100644
index 1967794817..0000000000
--- a/libchrome_tools/patches/Refactor-AlarmTimer-to-report-error-to-the-caller.patch
+++ /dev/null
@@ -1,180 +0,0 @@
-From 07763c630b9e6ee4538a86d291bfce8357dec934 Mon Sep 17 00:00:00 2001
-From: Hidehiko Abe <hidehiko@chromium.org>
-Date: Thu, 13 Jun 2019 22:12:42 +0900
-Subject: [PATCH] Refactor AlarmTimer to report error to the caller.
-
-This is to address the comment
-https://chromium-review.googlesource.com/c/aosp/platform/external/libchrome/+/1387893/2/components/timers/alarm_timer_chromeos.h#45
-
-Instead of just upstreaming it, which exposes a method unused in Chromium,
-this CL introduces Create() factory method and drops the code to
-fallback in case of timerfd_create failure.
-
-Now, a caller should check whether Create() returns null or not.
-In case of null, to keep the previous behavior, the caller can
-create an instance of the parent class.
-
-Along with the change, in order to run unittest for the class
-without capability CAP_WAKE_ALARM, this CL also introduces CreateForTesting().
-We used to test just fall-back code paths.
-
-In addition, this CL fixes the FD leak on destruction.
-
-This patch modified the original upstream patch, by
- - keeping the old constructor for backward-compatibility.
- - keeping CanWakeFromSuspend, and calls of CanWakeFromSuspend from Stop
- and Reset, for backward-compatibility, so that unittest won't fail
- due to -1 alarm_fd_ from default constructor when there's no
- capability to alarm.
-
-BUG=None
-TEST=Build and run components_unittests --gtest_filter=AlarmTimerTest*. Run try.
-
-Change-Id: Ieb9660335120565ccff7f192d7a8192ca1e59ebc
-Reviewed-on: https://chromium-review.googlesource.com/c/1411356
-Reviewed-by: Ryo Hashimoto <hashimoto@chromium.org>
-Reviewed-by: Dmitry Titov <dimich@chromium.org>
-Reviewed-by: Dan Erat <derat@chromium.org>
-Commit-Queue: Hidehiko Abe <hidehiko@chromium.org>
-Cr-Commit-Position: refs/heads/master@{#626151}
----
- components/timers/alarm_timer_chromeos.cc | 51 ++++++++++++++---------
- components/timers/alarm_timer_chromeos.h | 27 +++++++-----
- 2 files changed, 49 insertions(+), 29 deletions(-)
-
-diff --git a/components/timers/alarm_timer_chromeos.cc b/components/timers/alarm_timer_chromeos.cc
-index 0b43134..371eb67 100644
---- a/components/timers/alarm_timer_chromeos.cc
-+++ b/components/timers/alarm_timer_chromeos.cc
-@@ -15,13 +15,43 @@
- #include "base/debug/task_annotator.h"
- #include "base/files/file_util.h"
- #include "base/logging.h"
-+#include "base/memory/ptr_util.h"
- #include "base/pending_task.h"
- #include "base/trace_event/trace_event.h"
-
- namespace timers {
-
-+// Keep for backward compatibility to uprev r576279.
- SimpleAlarmTimer::SimpleAlarmTimer()
- : alarm_fd_(timerfd_create(CLOCK_REALTIME_ALARM, 0)), weak_factory_(this) {}
-+// static
-+std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::Create() {
-+ return CreateInternal(CLOCK_REALTIME_ALARM);
-+}
-+
-+// static
-+std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::CreateForTesting() {
-+ // For unittest, use CLOCK_REALTIME in order to run the tests without
-+ // CAP_WAKE_ALARM.
-+ return CreateInternal(CLOCK_REALTIME);
-+}
-+
-+// static
-+std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::CreateInternal(
-+ int clockid) {
-+ base::ScopedFD alarm_fd(timerfd_create(clockid, TFD_CLOEXEC));
-+ if (!alarm_fd.is_valid()) {
-+ PLOG(ERROR) << "Failed to create timer fd";
-+ return nullptr;
-+ }
-+
-+ // Note: std::make_unique<> cannot be used because the constructor is
-+ // private.
-+ return base::WrapUnique(new SimpleAlarmTimer(std::move(alarm_fd)));
-+}
-+
-+SimpleAlarmTimer::SimpleAlarmTimer(base::ScopedFD alarm_fd)
-+ : alarm_fd_(std::move(alarm_fd)), weak_factory_(this) {}
-
- SimpleAlarmTimer::~SimpleAlarmTimer() {
- DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
-@@ -80,7 +97,7 @@ void SimpleAlarmTimer::Reset() {
- alarm_time.it_value.tv_nsec =
- (delay.InMicroseconds() % base::Time::kMicrosecondsPerSecond) *
- base::Time::kNanosecondsPerMicrosecond;
-- if (timerfd_settime(alarm_fd_, 0, &alarm_time, NULL) < 0)
-+ if (timerfd_settime(alarm_fd_.get(), 0, &alarm_time, NULL) < 0)
- PLOG(ERROR) << "Error while setting alarm time. Timer will not fire";
-
- // The timer is running.
-@@ -97,7 +114,7 @@ void SimpleAlarmTimer::Reset() {
- base::debug::TaskAnnotator().WillQueueTask("SimpleAlarmTimer::Reset",
- pending_task_.get());
- alarm_fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
-- alarm_fd_,
-+ alarm_fd_.get(),
- base::BindRepeating(&SimpleAlarmTimer::OnAlarmFdReadableWithoutBlocking,
- weak_factory_.GetWeakPtr()));
- }
-@@ -109,7 +126,7 @@ void SimpleAlarmTimer::OnAlarmFdReadableWithoutBlocking() {
-
- // Read from |alarm_fd_| to ack the event.
- char val[sizeof(uint64_t)];
-- if (!base::ReadFromFD(alarm_fd_, val, sizeof(uint64_t)))
-+ if (!base::ReadFromFD(alarm_fd_.get(), val, sizeof(uint64_t)))
- PLOG(DFATAL) << "Unable to read from timer file descriptor.";
-
- OnTimerFired();
-diff --git a/components/timers/alarm_timer_chromeos.h b/components/timers/alarm_timer_chromeos.h
-index 1ff689e..e1301e9 100644
---- a/components/timers/alarm_timer_chromeos.h
-+++ b/components/timers/alarm_timer_chromeos.h
-@@ -8,6 +8,7 @@
- #include <memory>
-
- #include "base/files/file_descriptor_watcher_posix.h"
-+#include "base/files/scoped_file.h"
- #include "base/macros.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/memory/weak_ptr.h"
-@@ -24,8 +25,7 @@ namespace timers {
- // suspended state. For example, this is useful for running tasks that are
- // needed for maintaining network connectivity, like sending heartbeat messages.
- // Currently, this feature is only available on Chrome OS systems running linux
--// version 3.11 or higher. On all other platforms, the SimpleAlarmTimer behaves
--// exactly the same way as a regular Timer.
-+// version 3.11 or higher.
- //
- // A SimpleAlarmTimer instance can only be used from the sequence on which it
- // was instantiated. Start() and Stop() must be called from a thread that
-@@ -36,7 +36,16 @@ namespace timers {
- // times but not at a regular interval.
- class SimpleAlarmTimer : public base::RetainingOneShotTimer {
- public:
- SimpleAlarmTimer();
-+ // Creates the SimpleAlarmTimer instance, or returns null on failure, e.g.,
-+ // on a platform without timerfd_* system calls support, or missing
-+ // capability (CAP_WAKE_ALARM).
-+ static std::unique_ptr<SimpleAlarmTimer> Create();
-+
-+ // Similar to Create(), but for unittests without capability.
-+ // Specifically, uses CLOCK_REALTIME instead of CLOCK_REALTIME_ALARM.
-+ static std::unique_ptr<SimpleAlarmTimer> CreateForTesting();
-+
- ~SimpleAlarmTimer() override;
-
- // Timer overrides.
-@@ -44,6 +52,11 @@ class SimpleAlarmTimer : public base::RetainingOneShotTimer {
- void Reset() override;
-
- private:
-+ // Shared implementation of Create and CreateForTesting.
-+ static std::unique_ptr<SimpleAlarmTimer> CreateInternal(int clockid);
-+
-+ explicit SimpleAlarmTimer(base::ScopedFD alarm_fd);
-+
- // Called when |alarm_fd_| is readable without blocking. Reads data from
- // |alarm_fd_| and calls OnTimerFired().
- void OnAlarmFdReadableWithoutBlocking();
-@@ -61,5 +74,5 @@ class SimpleAlarmTimer : public base::RetainingOneShotTimer {
- // Timer file descriptor.
-- const int alarm_fd_;
-+ const base::ScopedFD alarm_fd_;
-
- // Watches |alarm_fd_|.
- std::unique_ptr<base::FileDescriptorWatcher::Controller> alarm_fd_watcher_;
---
-2.22.0.rc2.383.gf4fbbf30c2-goog
-
diff --git a/libchrome_tools/patches/WaitForServiceToBeAvailable.patch b/libchrome_tools/patches/WaitForServiceToBeAvailable.patch
deleted file mode 100644
index f8f2b63cc2..0000000000
--- a/libchrome_tools/patches/WaitForServiceToBeAvailable.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From eadafb5815145a401cbfa6da559de01cb35d3a2b Mon Sep 17 00:00:00 2001
-From: Qijiang Fan <fqj@chromium.org>
-Date: Tue, 17 Dec 2019 17:21:54 +0900
-Subject: [PATCH 3/5] mock object proxy WaitForServiceToBeAvailable
-
-Change-Id: I01d2e49547f0e9083df60de69ef254761de2c00e
----
- dbus/mock_object_proxy.cc | 5 +++++
- dbus/mock_object_proxy.h | 6 +++++++
- 2 files changed, 11 insertions(+)
-
-diff --git a/dbus/mock_object_proxy.cc b/dbus/mock_object_proxy.cc
-index 4929486..a1f2edd 100644
---- a/dbus/mock_object_proxy.cc
-+++ b/dbus/mock_object_proxy.cc
-@@ -45,4 +45,9 @@ void MockObjectProxy::ConnectToSignal(
- &on_connected_callback);
- }
-
-+void MockObjectProxy::WaitForServiceToBeAvailable(
-+ WaitForServiceToBeAvailableCallback callback) {
-+ DoWaitForServiceToBeAvailable(&callback);
-+}
-+
- } // namespace dbus
-diff --git a/dbus/mock_object_proxy.h b/dbus/mock_object_proxy.h
-index 7bc2376..abc793a 100644
---- a/dbus/mock_object_proxy.h
-+++ b/dbus/mock_object_proxy.h
-@@ -89,6 +90,12 @@ class MockObjectProxy : public ObjectProxy {
- OnConnectedCallback* on_connected_callback));
- MOCK_METHOD1(SetNameOwnerChangedCallback,
- void(NameOwnerChangedCallback callback));
-+ // This method is not mockable because it takes a move-only argument. To work
-+ // around this. WaitForServiceToBeAvailable implements here calls
-+ // DoWaitForServiceToBeAvailable which is mockable.
-+ void WaitForServiceToBeAvailable(WaitForServiceToBeAvailableCallback callback) override;
-+ MOCK_METHOD1(DoWaitForServiceToBeAvailable,
-+ void(WaitForServiceToBeAvailableCallback* callback));
- MOCK_METHOD0(Detach, void());
-
- protected:
---
-2.24.1.735.g03f4e72817-goog
-
diff --git a/libchrome_tools/patches/components-timers-fix-fd-leak-in-AlarmTimer.patch b/libchrome_tools/patches/components-timers-fix-fd-leak-in-AlarmTimer.patch
deleted file mode 100644
index e98c6918dc..0000000000
--- a/libchrome_tools/patches/components-timers-fix-fd-leak-in-AlarmTimer.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From e18f110107399803dd070088c601f9a5540a2a3f Mon Sep 17 00:00:00 2001
-From: Hidehiko Abe <hidehiko@chromium.org>
-Date: Thu, 3 Oct 2019 02:04:53 +0900
-Subject: [PATCH] components/timers: fix fd leak in AlarmTimer
-
-This is fixed upstream but will take a while to roll back
-into Chrome OS.
-
-BUG=chromium:984593
-TEST=enable/disable wifi repeatedly and see that there is no
- growth of open timerfds
-
-Change-Id: If2af8f8ddf6b9dc31cda36fe5f5454ca0c5819de
----
- components/timers/alarm_timer_chromeos.cc | 8 ++++----
- components/timers/alarm_timer_chromeos.h | 15 ++++++++-------
- 2 files changed, 12 insertions(+), 11 deletions(-)
-
-diff --git a/components/timers/alarm_timer_chromeos.cc b/components/timers/alarm_timer_chromeos.cc
-index 0b43134..f14d889 100644
---- a/components/timers/alarm_timer_chromeos.cc
-+++ b/components/timers/alarm_timer_chromeos.cc
-@@ -80,7 +80,7 @@ void SimpleAlarmTimer::Reset() {
- alarm_time.it_value.tv_nsec =
- (delay.InMicroseconds() % base::Time::kMicrosecondsPerSecond) *
- base::Time::kNanosecondsPerMicrosecond;
-- if (timerfd_settime(alarm_fd_, 0, &alarm_time, NULL) < 0)
-+ if (timerfd_settime(alarm_fd_.get(), 0, &alarm_time, NULL) < 0)
- PLOG(ERROR) << "Error while setting alarm time. Timer will not fire";
-
- // The timer is running.
-@@ -97,7 +97,7 @@ void SimpleAlarmTimer::Reset() {
- base::debug::TaskAnnotator().WillQueueTask("SimpleAlarmTimer::Reset",
- pending_task_.get());
- alarm_fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
-- alarm_fd_,
-+ alarm_fd_.get(),
- base::BindRepeating(&SimpleAlarmTimer::OnAlarmFdReadableWithoutBlocking,
- weak_factory_.GetWeakPtr()));
- }
-@@ -109,7 +109,7 @@ void SimpleAlarmTimer::OnAlarmFdReadableWithoutBlocking() {
-
- // Read from |alarm_fd_| to ack the event.
- char val[sizeof(uint64_t)];
-- if (!base::ReadFromFD(alarm_fd_, val, sizeof(uint64_t)))
-+ if (!base::ReadFromFD(alarm_fd_.get(), val, sizeof(uint64_t)))
- PLOG(DFATAL) << "Unable to read from timer file descriptor.";
-
- OnTimerFired();
-@@ -137,7 +137,7 @@ void SimpleAlarmTimer::OnTimerFired() {
- }
-
- bool SimpleAlarmTimer::CanWakeFromSuspend() const {
-- return alarm_fd_ != -1;
-+ return alarm_fd_.is_valid();
- }
-
- } // namespace timers
-diff --git a/components/timers/alarm_timer_chromeos.h b/components/timers/alarm_timer_chromeos.h
-index 1ff689e..100ba81 100644
---- a/components/timers/alarm_timer_chromeos.h
-+++ b/components/timers/alarm_timer_chromeos.h
-@@ -8,6 +8,7 @@
- #include <memory>
-
- #include "base/files/file_descriptor_watcher_posix.h"
-+#include "base/files/scoped_file.h"
- #include "base/macros.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/memory/weak_ptr.h"
-@@ -43,6 +44,12 @@ class SimpleAlarmTimer : public base::RetainingOneShotTimer {
- void Stop() override;
- void Reset() override;
-
-+ // Tracks whether the timer has the ability to wake the system up from
-+ // suspend. This is a runtime check because we won't know if the system
-+ // supports being woken up from suspend until the constructor actually tries
-+ // to set it up.
-+ bool CanWakeFromSuspend() const;
-+
- private:
- // Called when |alarm_fd_| is readable without blocking. Reads data from
- // |alarm_fd_| and calls OnTimerFired().
-@@ -51,14 +58,8 @@ class SimpleAlarmTimer : public base::RetainingOneShotTimer {
- // Called when the timer fires. Runs the callback.
- void OnTimerFired();
-
-- // Tracks whether the timer has the ability to wake the system up from
-- // suspend. This is a runtime check because we won't know if the system
-- // supports being woken up from suspend until the constructor actually tries
-- // to set it up.
-- bool CanWakeFromSuspend() const;
--
- // Timer file descriptor.
-- const int alarm_fd_;
-+ base::ScopedFD alarm_fd_;
-
- // Watches |alarm_fd_|.
- std::unique_ptr<base::FileDescriptorWatcher::Controller> alarm_fd_watcher_;
---
-2.23.0.581.g78d2f28ef7-goog
-
diff --git a/libchrome_tools/patches/dbus-Add-TryRegisterFallback.patch b/libchrome_tools/patches/dbus-Add-TryRegisterFallback.patch
deleted file mode 100644
index b0ef0b8156..0000000000
--- a/libchrome_tools/patches/dbus-Add-TryRegisterFallback.patch
+++ /dev/null
@@ -1,137 +0,0 @@
-From a4d8dee3905d784f40d8f480eaacae2655e68b47 Mon Sep 17 00:00:00 2001
-From: Sonny Sasaka <sonnysasaka@chromium.org>
-Date: Wed, 11 Jul 2018 20:55:58 -0700
-Subject: [PATCH] dbus: Add TryRegisterFallback
-
-The TryRegisterFallback works just like TryRegisterObjectPath,
-with addition that the registered callbacks also apply to the specified
-object path and its sub paths. This is useful to implement a "catch-all"
-handler.
-
-Currently this is needed by Bluetooth dispatcher which needs to catch
-all method calls to all objects and forward them to another D-Bus
-service.
-
-Bug:862849
----
- dbus/bus.cc | 27 +++++++++++++++++++++------
- dbus/bus.h | 32 ++++++++++++++++++++++++++++++++
- dbus/mock_bus.h | 5 +++++
- 3 files changed, 58 insertions(+), 6 deletions(-)
-
-diff --git a/dbus/bus.cc b/dbus/bus.cc
-index e62058e0dc34..29043609e760 100644
---- a/dbus/bus.cc
-+++ b/dbus/bus.cc
-@@ -722,6 +722,25 @@ bool Bus::TryRegisterObjectPath(const ObjectPath& object_path,
- const DBusObjectPathVTable* vtable,
- void* user_data,
- DBusError* error) {
-+ return TryRegisterObjectPathInternal(
-+ object_path, vtable, user_data, error,
-+ dbus_connection_try_register_object_path);
-+}
-+
-+bool Bus::TryRegisterFallback(const ObjectPath& object_path,
-+ const DBusObjectPathVTable* vtable,
-+ void* user_data,
-+ DBusError* error) {
-+ return TryRegisterObjectPathInternal(object_path, vtable, user_data, error,
-+ dbus_connection_try_register_fallback);
-+}
-+
-+bool Bus::TryRegisterObjectPathInternal(
-+ const ObjectPath& object_path,
-+ const DBusObjectPathVTable* vtable,
-+ void* user_data,
-+ DBusError* error,
-+ TryRegisterObjectPathFunction* register_function) {
- DCHECK(connection_);
- AssertOnDBusThread();
-
-@@ -731,12 +750,8 @@ bool Bus::TryRegisterObjectPath(const ObjectPath& object_path,
- return false;
- }
-
-- const bool success = dbus_connection_try_register_object_path(
-- connection_,
-- object_path.value().c_str(),
-- vtable,
-- user_data,
-- error);
-+ const bool success = register_function(
-+ connection_, object_path.value().c_str(), vtable, user_data, error);
- if (success)
- registered_object_paths_.insert(object_path);
- return success;
-diff --git a/dbus/bus.h b/dbus/bus.h
-index c2c2685afdc4..704a4c3a0b54 100644
---- a/dbus/bus.h
-+++ b/dbus/bus.h
-@@ -520,6 +520,24 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
- void* user_data,
- DBusError* error);
-
-+ // Tries to register the object path and its sub paths.
-+ // Returns true on success.
-+ // Returns false if the object path is already registered.
-+ //
-+ // |message_function| in |vtable| will be called every time when a new
-+ // message sent to the object path (or hierarchically below) arrives.
-+ //
-+ // The same object path must not be added more than once.
-+ //
-+ // See also documentation of |dbus_connection_try_register_fallback| at
-+ // http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html
-+ //
-+ // BLOCKING CALL.
-+ virtual bool TryRegisterFallback(const ObjectPath& object_path,
-+ const DBusObjectPathVTable* vtable,
-+ void* user_data,
-+ DBusError* error);
-+
- // Unregister the object path.
- //
- // BLOCKING CALL.
-@@ -590,8 +608,22 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
- virtual ~Bus();
-
- private:
-+ using TryRegisterObjectPathFunction =
-+ dbus_bool_t(DBusConnection* connection,
-+ const char* object_path,
-+ const DBusObjectPathVTable* vtable,
-+ void* user_data,
-+ DBusError* error);
-+
- friend class base::RefCountedThreadSafe<Bus>;
-
-+ bool TryRegisterObjectPathInternal(
-+ const ObjectPath& object_path,
-+ const DBusObjectPathVTable* vtable,
-+ void* user_data,
-+ DBusError* error,
-+ TryRegisterObjectPathFunction* register_function);
-+
- // Helper function used for RemoveObjectProxy().
- void RemoveObjectProxyInternal(scoped_refptr<dbus::ObjectProxy> object_proxy,
- const base::Closure& callback);
-diff --git a/dbus/mock_bus.h b/dbus/mock_bus.h
-index 216bc64bd068..6b3495db6014 100644
---- a/dbus/mock_bus.h
-+++ b/dbus/mock_bus.h
-@@ -62,6 +62,11 @@ class MockBus : public Bus {
- const DBusObjectPathVTable* vtable,
- void* user_data,
- DBusError* error));
-+ MOCK_METHOD4(TryRegisterFallback,
-+ bool(const ObjectPath& object_path,
-+ const DBusObjectPathVTable* vtable,
-+ void* user_data,
-+ DBusError* error));
- MOCK_METHOD1(UnregisterObjectPath, void(const ObjectPath& object_path));
- MOCK_METHOD0(GetDBusTaskRunner, base::TaskRunner*());
- MOCK_METHOD0(GetOriginTaskRunner, base::TaskRunner*());
---
-2.18.0.203.gfac676dfb9-goog
-
diff --git a/libchrome_tools/patches/dbus-Make-Bus-is_connected-mockable.patch b/libchrome_tools/patches/dbus-Make-Bus-is_connected-mockable.patch
deleted file mode 100644
index 3dd2c8869e..0000000000
--- a/libchrome_tools/patches/dbus-Make-Bus-is_connected-mockable.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From 59bc1c00682f45d54a05aadc2a2e0559f85e4499 Mon Sep 17 00:00:00 2001
-From: Sonny Sasaka <sonnysasaka@chromium.org>
-Date: Thu, 16 Aug 2018 05:09:20 +0000
-Subject: [PATCH] dbus: Make Bus::is_connected() mockable
-
-It's currently not possible to have a unit test that triggers
-Bus::is_connected() because it always returns false. This is currently
-needed by the Bluetooth dispatcher (btdispatch) in Chrome OS.
-
-Bug: 866704
-Change-Id: I04f7e8a22792886d421479c1c7c621eeb27d3a2a
-Reviewed-on: https://chromium-review.googlesource.com/1175216
-Reviewed-by: Ryo Hashimoto <hashimoto@chromium.org>
-Commit-Queue: Sonny Sasaka <sonnysasaka@chromium.org>
-Cr-Commit-Position: refs/heads/master@{#583543}
----
- dbus/bus.cc | 4 ++++
- dbus/bus.h | 2 +-
- dbus/bus_unittest.cc | 4 ++--
- dbus/exported_object.cc | 2 +-
- dbus/mock_bus.h | 1 +
- dbus/object_proxy.cc | 2 +-
- 6 files changed, 10 insertions(+), 5 deletions(-)
-
-diff --git a/dbus/bus.cc b/dbus/bus.cc
-index 2f3db885f561..9d37656ac21c 100644
---- a/dbus/bus.cc
-+++ b/dbus/bus.cc
-@@ -997,6 +997,10 @@ std::string Bus::GetConnectionName() {
- return dbus_bus_get_unique_name(connection_);
- }
-
-+bool Bus::IsConnected() {
-+ return connection_ != nullptr;
-+}
-+
- dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
- AssertOnDBusThread();
-
-diff --git a/dbus/bus.h b/dbus/bus.h
-index 704a4c3a0b54..b082110e589b 100644
---- a/dbus/bus.h
-+++ b/dbus/bus.h
-@@ -601,7 +601,7 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
- std::string GetConnectionName();
-
- // Returns true if the bus is connected to D-Bus.
-- bool is_connected() { return connection_ != nullptr; }
-+ virtual bool IsConnected();
-
- protected:
- // This is protected, so we can define sub classes.
-diff --git a/dbus/exported_object.cc b/dbus/exported_object.cc
-index d6c91b6d2046..5fa1b916f251 100644
---- a/dbus/exported_object.cc
-+++ b/dbus/exported_object.cc
-@@ -280,7 +280,7 @@ void ExportedObject::OnMethodCompleted(std::unique_ptr<MethodCall> method_call,
-
- // Check if the bus is still connected. If the method takes long to
- // complete, the bus may be shut down meanwhile.
-- if (!bus_->is_connected())
-+ if (!bus_->IsConnected())
- return;
-
- if (!response) {
-diff --git a/dbus/mock_bus.h b/dbus/mock_bus.h
-index 6b3495db6014..22807622786a 100644
---- a/dbus/mock_bus.h
-+++ b/dbus/mock_bus.h
-@@ -73,6 +73,7 @@ class MockBus : public Bus {
- MOCK_METHOD0(HasDBusThread, bool());
- MOCK_METHOD0(AssertOnOriginThread, void());
- MOCK_METHOD0(AssertOnDBusThread, void());
-+ MOCK_METHOD0(IsConnected, bool());
-
- protected:
- ~MockBus() override;
-diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc
-index aa5102aec792..3046dbb5f38b 100644
---- a/dbus/object_proxy.cc
-+++ b/dbus/object_proxy.cc
-@@ -288,7 +288,7 @@ void ObjectProxy::WaitForServiceToBeAvailable(
- void ObjectProxy::Detach() {
- bus_->AssertOnDBusThread();
-
-- if (bus_->is_connected())
-+ if (bus_->IsConnected())
- bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this);
-
- for (const auto& match_rule : match_rules_) {
---
-2.21.0.392.gf8f6787159e-goog
-
diff --git a/libchrome_tools/patches/dbus-Remove-LOG-ERROR-in-ObjectProxy.patch b/libchrome_tools/patches/dbus-Remove-LOG-ERROR-in-ObjectProxy.patch
deleted file mode 100644
index 62bdd940e2..0000000000
--- a/libchrome_tools/patches/dbus-Remove-LOG-ERROR-in-ObjectProxy.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From ad887b5aaf4f834dbbd487adfe89d9a5b3d673f2 Mon Sep 17 00:00:00 2001
-From: Sonny Sasaka <sonnysasaka@chromium.org>
-Date: Thu, 9 Aug 2018 22:39:57 +0000
-Subject: [PATCH] dbus: Remove LOG(ERROR) in ObjectProxy
-
-It is a valid use case for a daemon to have multiple ObjectProxies of
-different services with the exact same object path and interface name.
-Currently, this may cause log pollution of "rejecting a message from a
-wrong sender" because one ObjectProxy receives signals intended for
-another ObjectProxy. Since it's actually a valid case and not a bug, it
-shouldn't be logged as error but it may still be logged with VLOG.
-
-Currently this is discovered in Bluetooth daemon (btdispatch) because it
-listens to both BlueZ's and Newblue's objects which have identical
-object paths and interfaces.
-
-Bug: 866704
-Change-Id: I25b6437ec6081e244a47c635c0adedf281530967
-Reviewed-on: https://chromium-review.googlesource.com/1164474
-Reviewed-by: Ryo Hashimoto <hashimoto@chromium.org>
-Commit-Queue: Sonny Sasaka <sonnysasaka@chromium.org>
-Cr-Commit-Position: refs/heads/master@{#581937}
----
- dbus/object_proxy.cc | 11 +++++------
- 1 file changed, 5 insertions(+), 6 deletions(-)
-
-diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc
-index 35835fbdc32c..aa5102aec792 100644
---- a/dbus/object_proxy.cc
-+++ b/dbus/object_proxy.cc
-@@ -519,6 +519,11 @@ DBusHandlerResult ObjectProxy::HandleMessage(
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
-
-+ std::string sender = signal->GetSender();
-+ // Ignore message from sender we are not interested in.
-+ if (service_name_owner_ != sender)
-+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-+
- const std::string interface = signal->GetInterface();
- const std::string member = signal->GetMember();
-
-@@ -534,12 +539,6 @@ DBusHandlerResult ObjectProxy::HandleMessage(
- }
- VLOG(1) << "Signal received: " << signal->ToString();
-
-- std::string sender = signal->GetSender();
-- if (service_name_owner_ != sender) {
-- LOG(ERROR) << "Rejecting a message from a wrong sender.";
-- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-- }
--
- const base::TimeTicks start_time = base::TimeTicks::Now();
- if (bus_->HasDBusThread()) {
- // Post a task to run the method in the origin thread.
---
-2.21.0.392.gf8f6787159e-goog
-
diff --git a/libchrome_tools/patches/dbus-Support-UnexportMethod-from-an-exported-object.patch b/libchrome_tools/patches/dbus-Support-UnexportMethod-from-an-exported-object.patch
deleted file mode 100644
index 1a797bf2a9..0000000000
--- a/libchrome_tools/patches/dbus-Support-UnexportMethod-from-an-exported-object.patch
+++ /dev/null
@@ -1,194 +0,0 @@
-From fb915ed71679feafd4ed53deb2c5ba84862a9e57 Mon Sep 17 00:00:00 2001
-From: Sonny Sasaka <sonnysasaka@chromium.org>
-Date: Mon, 10 Dec 2018 14:03:49 -0800
-Subject: [PATCH] dbus: Support UnexportMethod from an exported object.
-
-Currently there is no way to override a method handler that is already
-registered to an ExportedObject. A support to do so is required to
-correctly implement Chrome OS Bluetooth dispatcher which needs to
-add/remove an interface to an exported object dynamically. Therefore
-this CL adds methods to allow method handlers to be unexported so
-another handler can be exported afterwards.
-
-Bug: 883039
----
- dbus/exported_object.cc | 50 +++++++++++++++++++++++++++++++++++++
- dbus/exported_object.h | 34 +++++++++++++++++++++++++
- dbus/mock_exported_object.h | 7 ++++++
- 3 files changed, 91 insertions(+)
-
-diff --git a/dbus/exported_object.cc b/dbus/exported_object.cc
-index 5fa1b916f251..727a5707b869 100644
---- a/dbus/exported_object.cc
-+++ b/dbus/exported_object.cc
-@@ -68,6 +68,22 @@ bool ExportedObject::ExportMethodAndBlock(
- return true;
- }
-
-+bool ExportedObject::UnexportMethodAndBlock(const std::string& interface_name,
-+ const std::string& method_name) {
-+ bus_->AssertOnDBusThread();
-+
-+ const std::string absolute_method_name =
-+ GetAbsoluteMemberName(interface_name, method_name);
-+ if (method_table_.find(absolute_method_name) == method_table_.end()) {
-+ LOG(ERROR) << absolute_method_name << " is not exported";
-+ return false;
-+ }
-+
-+ method_table_.erase(absolute_method_name);
-+
-+ return true;
-+}
-+
- void ExportedObject::ExportMethod(const std::string& interface_name,
- const std::string& method_name,
- MethodCallCallback method_call_callback,
-@@ -83,6 +99,18 @@ void ExportedObject::ExportMethod(const std::string& interface_name,
- bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task);
- }
-
-+void ExportedObject::UnexportMethod(
-+ const std::string& interface_name,
-+ const std::string& method_name,
-+ OnUnexportedCallback on_unexported_calback) {
-+ bus_->AssertOnOriginThread();
-+
-+ base::Closure task =
-+ base::Bind(&ExportedObject::UnexportMethodInternal, this, interface_name,
-+ method_name, on_unexported_calback);
-+ bus_->GetDBusTaskRunner()->PostTask(FROM_HERE, task);
-+}
-+
- void ExportedObject::SendSignal(Signal* signal) {
- // For signals, the object path should be set to the path to the sender
- // object, which is this exported object here.
-@@ -141,6 +169,19 @@ void ExportedObject::ExportMethodInternal(
- success));
- }
-
-+void ExportedObject::UnexportMethodInternal(
-+ const std::string& interface_name,
-+ const std::string& method_name,
-+ OnUnexportedCallback on_unexported_calback) {
-+ bus_->AssertOnDBusThread();
-+
-+ const bool success = UnexportMethodAndBlock(interface_name, method_name);
-+ bus_->GetOriginTaskRunner()->PostTask(
-+ FROM_HERE,
-+ base::Bind(&ExportedObject::OnUnexported, this, on_unexported_calback,
-+ interface_name, method_name, success));
-+}
-+
- void ExportedObject::OnExported(OnExportedCallback on_exported_callback,
- const std::string& interface_name,
- const std::string& method_name,
-@@ -150,6 +191,15 @@ void ExportedObject::OnExported(OnExportedCallback on_exported_callback,
- on_exported_callback.Run(interface_name, method_name, success);
- }
-
-+void ExportedObject::OnUnexported(OnExportedCallback on_unexported_callback,
-+ const std::string& interface_name,
-+ const std::string& method_name,
-+ bool success) {
-+ bus_->AssertOnOriginThread();
-+
-+ on_unexported_callback.Run(interface_name, method_name, success);
-+}
-+
- void ExportedObject::SendSignalInternal(base::TimeTicks start_time,
- DBusMessage* signal_message) {
- uint32_t serial = 0;
-diff --git a/dbus/exported_object.h b/dbus/exported_object.h
-index 69a63a5e075e..d314083430ef 100644
---- a/dbus/exported_object.h
-+++ b/dbus/exported_object.h
-@@ -60,6 +60,13 @@ class CHROME_DBUS_EXPORT ExportedObject
- bool success)>
- OnExportedCallback;
-
-+ // Called when method unexporting is done.
-+ // |success| indicates whether unexporting was successful or not.
-+ typedef base::Callback<void(const std::string& interface_name,
-+ const std::string& method_name,
-+ bool success)>
-+ OnUnexportedCallback;
-+
- // Exports the method specified by |interface_name| and |method_name|,
- // and blocks until exporting is done. Returns true on success.
- //
-@@ -81,6 +88,11 @@ class CHROME_DBUS_EXPORT ExportedObject
- const std::string& method_name,
- MethodCallCallback method_call_callback);
-
-+ // Unexports the method specified by |interface_name| and |method_name|,
-+ // and blocks until unexporting is done. Returns true on success.
-+ virtual bool UnexportMethodAndBlock(const std::string& interface_name,
-+ const std::string& method_name);
-+
- // Requests to export the method specified by |interface_name| and
- // |method_name|. See Also ExportMethodAndBlock().
- //
-@@ -93,6 +105,17 @@ class CHROME_DBUS_EXPORT ExportedObject
- MethodCallCallback method_call_callback,
- OnExportedCallback on_exported_callback);
-
-+ // Requests to unexport the method specified by |interface_name| and
-+ // |method_name|. See also UnexportMethodAndBlock().
-+ //
-+ // |on_unexported_callback| is called when the method is unexported or
-+ // failed to be unexported, in the origin thread.
-+ //
-+ // Must be called in the origin thread.
-+ virtual void UnexportMethod(const std::string& interface_name,
-+ const std::string& method_name,
-+ OnUnexportedCallback on_unexported_callback);
-+
- // Requests to send the signal from this object. The signal will be sent
- // synchronously if this method is called from the message loop in the D-Bus
- // thread and asynchronously otherwise.
-@@ -117,12 +140,23 @@ class CHROME_DBUS_EXPORT ExportedObject
- MethodCallCallback method_call_callback,
- OnExportedCallback exported_callback);
-
-+ // Helper function for UnexportMethod().
-+ void UnexportMethodInternal(const std::string& interface_name,
-+ const std::string& method_name,
-+ OnUnexportedCallback unexported_callback);
-+
- // Called when the object is exported.
- void OnExported(OnExportedCallback on_exported_callback,
- const std::string& interface_name,
- const std::string& method_name,
- bool success);
-
-+ // Called when a method is unexported.
-+ void OnUnexported(OnExportedCallback on_unexported_callback,
-+ const std::string& interface_name,
-+ const std::string& method_name,
-+ bool success);
-+
- // Helper function for SendSignal().
- void SendSignalInternal(base::TimeTicks start_time,
- DBusMessage* signal_message);
-diff --git a/dbus/mock_exported_object.h b/dbus/mock_exported_object.h
-index 99c363f9b532..9d5b3a894179 100644
---- a/dbus/mock_exported_object.h
-+++ b/dbus/mock_exported_object.h
-@@ -28,6 +28,13 @@ class MockExportedObject : public ExportedObject {
- const std::string& method_name,
- MethodCallCallback method_call_callback,
- OnExportedCallback on_exported_callback));
-+ MOCK_METHOD2(UnexportMethodAndBlock,
-+ bool(const std::string& interface_name,
-+ const std::string& method_name));
-+ MOCK_METHOD3(UnexportMethod,
-+ void(const std::string& interface_name,
-+ const std::string& method_name,
-+ OnUnexportedCallback on_unexported_callback));
- MOCK_METHOD1(SendSignal, void(Signal* signal));
- MOCK_METHOD0(Unregister, void());
-
---
-2.20.0.rc2.403.gdbc3b29805-goog
-
diff --git a/libchrome_tools/patches/enable-location-source.patch b/libchrome_tools/patches/enable-location-source.patch
deleted file mode 100644
index adcafb4c89..0000000000
--- a/libchrome_tools/patches/enable-location-source.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 8f8b73113f4e785543129c806d0e57bcf13d2314 Mon Sep 17 00:00:00 2001
-From: Qijiang Fan <fqj@chromium.org>
-Date: Wed, 18 Dec 2019 17:47:58 +0900
-Subject: [PATCH 4/4] enable location source
-
-Change-Id: I29fd847bc0fa0ace7a9637417a796b64b32485e3
----
- base/debug/debugging_buildflags.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/base/debug/debugging_buildflags.h b/base/debug/debugging_buildflags.h
-index 33e3dd0..a974f83 100644
---- a/base/debug/debugging_buildflags.h
-+++ b/base/debug/debugging_buildflags.h
-@@ -6,7 +6,7 @@
- #define BUILDFLAG_INTERNAL_ENABLE_PROFILING() (0)
- #define BUILDFLAG_INTERNAL_ENABLE_MEMORY_TASK_PROFILER() (0)
- #define BUILDFLAG_INTERNAL_CAN_UNWIND_WITH_FRAME_POINTERS() (0)
--#define BUILDFLAG_INTERNAL_ENABLE_LOCATION_SOURCE() (0)
-+#define BUILDFLAG_INTERNAL_ENABLE_LOCATION_SOURCE() (1)
- #define BUILDFLAG_INTERNAL_CFI_ENFORCEMENT_TRAP() (0)
- #define BUILDFLAG_INTERNAL_ENABLE_MUTEX_PRIORITY_INHERITANCE() (0)
- #endif // BASE_DEBUG_DEBUGGING_FLAGS_H_
---
-2.24.1.735.g03f4e72817-goog
-
diff --git a/libchrome_tools/patches/fix-fd-watcher-leak.patch b/libchrome_tools/patches/fix-fd-watcher-leak.patch
deleted file mode 100644
index 510d077a6d..0000000000
--- a/libchrome_tools/patches/fix-fd-watcher-leak.patch
+++ /dev/null
@@ -1,188 +0,0 @@
-From 9ae1384af2cdd16539e9caaed69b095737e2c272 Mon Sep 17 00:00:00 2001
-From: Qijiang Fan <fqj@chromium.org>
-Date: Tue, 17 Dec 2019 17:32:35 +0900
-Subject: [PATCH] backport upstream patch to fix watcher leak.
-
-https://chromium-review.googlesource.com/c/chromium/src/+/695914
-
-Change-Id: I91928fc00e9845ff75c49c272ff774ff9810f4eb
----
- base/files/file_descriptor_watcher_posix.cc | 104 +++++++++++++++-----
- base/threading/thread_restrictions.h | 4 +
- 2 files changed, 82 insertions(+), 26 deletions(-)
-
-diff --git a/base/files/file_descriptor_watcher_posix.cc b/base/files/file_descriptor_watcher_posix.cc
-index b26bf6c..98d2cec 100644
---- a/base/files/file_descriptor_watcher_posix.cc
-+++ b/base/files/file_descriptor_watcher_posix.cc
-@@ -5,6 +5,7 @@
- #include "base/files/file_descriptor_watcher_posix.h"
-
- #include "base/bind.h"
-+#include "base/callback_helpers.h"
- #include "base/lazy_instance.h"
- #include "base/logging.h"
- #include "base/memory/ptr_util.h"
-@@ -12,6 +13,7 @@
- #include "base/message_loop/message_pump_for_io.h"
- #include "base/sequenced_task_runner.h"
- #include "base/single_thread_task_runner.h"
-+#include "base/synchronization/waitable_event.h"
- #include "base/threading/sequenced_task_runner_handle.h"
- #include "base/threading/thread_checker.h"
- #include "base/threading/thread_local.h"
-@@ -27,21 +29,7 @@ LazyInstance<ThreadLocalPointer<MessageLoopForIO>>::Leaky
-
- } // namespace
-
--FileDescriptorWatcher::Controller::~Controller() {
-- DCHECK(sequence_checker_.CalledOnValidSequence());
--
-- // Delete |watcher_| on the MessageLoopForIO.
-- //
-- // If the MessageLoopForIO is deleted before Watcher::StartWatching() runs,
-- // |watcher_| is leaked. If the MessageLoopForIO is deleted after
-- // Watcher::StartWatching() runs but before the DeleteSoon task runs,
-- // |watcher_| is deleted from Watcher::WillDestroyCurrentMessageLoop().
-- message_loop_for_io_task_runner_->DeleteSoon(FROM_HERE, watcher_.release());
--
-- // Since WeakPtrs are invalidated by the destructor, RunCallback() won't be
-- // invoked after this returns.
--}
--
-+// Move watcher above to prevent delete incomplete type at delete watcher later.
- class FileDescriptorWatcher::Controller::Watcher
- : public MessagePumpForIO::FdWatcher,
- public MessageLoopCurrent::DestructionObserver {
-@@ -90,6 +78,58 @@ class FileDescriptorWatcher::Controller::Watcher
- DISALLOW_COPY_AND_ASSIGN(Watcher);
- };
-
-+FileDescriptorWatcher::Controller::~Controller() {
-+ DCHECK(sequence_checker_.CalledOnValidSequence());
-+
-+ if (message_loop_for_io_task_runner_->BelongsToCurrentThread()) {
-+ // If the MessageLoopForIO and the Controller live on the same thread.
-+ watcher_.reset();
-+ } else {
-+ // Synchronously wait until |watcher_| is deleted on the MessagePumpForIO
-+ // thread. This ensures that the file descriptor is never accessed after
-+ // this destructor returns.
-+ //
-+ // Use a ScopedClosureRunner to ensure that |done| is signaled even if the
-+ // thread doesn't run any more tasks (if PostTask returns true, it means
-+ // that the task was queued, but it doesn't mean that a RunLoop will run the
-+ // task before the queue is deleted).
-+ //
-+ // We considered associating "generations" to file descriptors to avoid the
-+ // synchronous wait. For example, if the IO thread gets a "cancel" for fd=6,
-+ // generation=1 after getting a "start watching" for fd=6, generation=2, it
-+ // can ignore the "Cancel". However, "generations" didn't solve this race:
-+ //
-+ // T1 (client) Start watching fd = 6 with WatchReadable()
-+ // Stop watching fd = 6
-+ // Close fd = 6
-+ // Open a new file, fd = 6 gets reused.
-+ // T2 (io) Watcher::StartWatching()
-+ // Incorrectly starts watching fd = 6 which now refers to a
-+ // different file than when WatchReadable() was called.
-+ WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
-+ WaitableEvent::InitialState::NOT_SIGNALED);
-+ message_loop_for_io_task_runner_->PostTask(
-+ FROM_HERE, BindOnce(
-+ [](Watcher *watcher, ScopedClosureRunner closure) {
-+ // Since |watcher| is a raw pointer, it isn't deleted
-+ // if this callback is deleted before it gets to run.
-+ delete watcher;
-+ // |closure| runs at the end of this scope.
-+ },
-+ Unretained(watcher_.release()),
-+ // TODO(fqj): change to BindOnce after some uprev.
-+ ScopedClosureRunner(Bind(&WaitableEvent::Signal,
-+ Unretained(&done)))));
-+ // TODO(fqj): change to ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
-+ // after uprev to r586297
-+ base::ThreadRestrictions::ScopedAllowWait allow_wait __attribute__((unused));
-+ done.Wait();
-+ }
-+
-+ // Since WeakPtrs are invalidated by the destructor, RunCallback() won't be
-+ // invoked after this returns.
-+}
-+
- FileDescriptorWatcher::Controller::Watcher::Watcher(
- WeakPtr<Controller> controller,
- MessagePumpForIO::Mode mode,
-@@ -150,11 +190,19 @@ void FileDescriptorWatcher::Controller::Watcher::
- WillDestroyCurrentMessageLoop() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
-- // A Watcher is owned by a Controller. When the Controller is deleted, it
-- // transfers ownership of the Watcher to a delete task posted to the
-- // MessageLoopForIO. If the MessageLoopForIO is deleted before the delete task
-- // runs, the following line takes care of deleting the Watcher.
-- delete this;
-+ if (callback_task_runner_->RunsTasksInCurrentSequence()) {
-+ // |controller_| can be accessed directly when Watcher runs on the same
-+ // thread.
-+ controller_->watcher_.reset();
-+ } else {
-+ // If the Watcher and the Controller live on different threads, delete
-+ // |this| synchronously. Pending tasks bound to an unretained Watcher* will
-+ // not run since this loop is dead. The associated Controller still
-+ // technically owns this via unique_ptr but it never uses it directly and
-+ // will ultimately send it to this thread for deletion (and that also won't
-+ // run since the loop being dead).
-+ delete this;
-+ }
- }
-
- FileDescriptorWatcher::Controller::Controller(MessagePumpForIO::Mode mode,
-@@ -172,12 +220,16 @@ FileDescriptorWatcher::Controller::Controller(MessagePumpForIO::Mode mode,
-
- void FileDescriptorWatcher::Controller::StartWatching() {
- DCHECK(sequence_checker_.CalledOnValidSequence());
-- // It is safe to use Unretained() below because |watcher_| can only be deleted
-- // by a delete task posted to |message_loop_for_io_task_runner_| by this
-- // Controller's destructor. Since this delete task hasn't been posted yet, it
-- // can't run before the task posted below.
-- message_loop_for_io_task_runner_->PostTask(
-- FROM_HERE, BindOnce(&Watcher::StartWatching, Unretained(watcher_.get())));
-+ if (message_loop_for_io_task_runner_->BelongsToCurrentThread()) {
-+ watcher_->StartWatching();
-+ } else {
-+ // It is safe to use Unretained() below because |watcher_| can only be deleted
-+ // by a delete task posted to |message_loop_for_io_task_runner_| by this
-+ // Controller's destructor. Since this delete task hasn't been posted yet, it
-+ // can't run before the task posted below.
-+ message_loop_for_io_task_runner_->PostTask(
-+ FROM_HERE, Bind(&Watcher::StartWatching, Unretained(watcher_.get())));
-+ }
- }
-
- void FileDescriptorWatcher::Controller::RunCallback() {
-diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
-index 705ba4d..7532f85 100644
---- a/base/threading/thread_restrictions.h
-+++ b/base/threading/thread_restrictions.h
-@@ -147,6 +147,7 @@ namespace internal {
- class TaskTracker;
- }
-
-+class FileDescriptorWatcher;
- class GetAppOutputScopedAllowBaseSyncPrimitives;
- class SimpleThread;
- class StackSamplingProfiler;
-@@ -479,6 +480,9 @@ class BASE_EXPORT ThreadRestrictions {
- friend class ui::CommandBufferLocal;
- friend class ui::GpuState;
-
-+ // Chrome OS libchrome
-+ friend class base::FileDescriptorWatcher;
-+
- // END ALLOWED USAGE.
- // BEGIN USAGE THAT NEEDS TO BE FIXED.
- friend class ::chromeos::BlockingMethodCaller; // http://crbug.com/125360
---
-2.24.1.735.g03f4e72817-goog
-
diff --git a/libchrome_tools/patches/libchrome-Add-EmptyResponseCallback-for-backward-com.patch b/libchrome_tools/patches/libchrome-Add-EmptyResponseCallback-for-backward-com.patch
deleted file mode 100644
index 80c6dfaea9..0000000000
--- a/libchrome_tools/patches/libchrome-Add-EmptyResponseCallback-for-backward-com.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From f34f528c1fc4512910b2acc586e678ddb53eaf9e Mon Sep 17 00:00:00 2001
-From: Hidehiko Abe <hidehiko@chromium.org>
-Date: Wed, 2 Oct 2019 09:53:00 +0900
-Subject: [PATCH] libchrome: Add EmptyResponseCallback for backward
- compatiblity.
-
-BUG=chromium:909719
-TEST=Build locally.
-
-Change-Id: I4d6c75f267fd6c170b966647c30c91bb02b3ee14
----
- dbus/object_proxy.h | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/dbus/object_proxy.h b/dbus/object_proxy.h
-index 22e44f1..7d62eb9 100644
---- a/dbus/object_proxy.h
-+++ b/dbus/object_proxy.h
-@@ -13,6 +13,7 @@
- #include <string>
- #include <vector>
-
-+#include "base/bind.h"
- #include "base/callback.h"
- #include "base/macros.h"
- #include "base/memory/ref_counted.h"
-@@ -105,6 +106,12 @@ class CHROME_DBUS_EXPORT ObjectProxy
- using OnConnectedCallback =
- base::OnceCallback<void(const std::string&, const std::string&, bool)>;
-
-+ // TOOD(crbug.com/909719): This is just for backward compatibility.
-+ // Remove this callback after clients are migrated.
-+ static ResponseCallback EmptyResponseCallback() {
-+ return base::BindOnce([](Response*){});
-+ }
-+
- // Calls the method of the remote object and blocks until the response
- // is returned. Returns NULL on error with the error details specified
- // in the |error| object.
---
-2.23.0.581.g78d2f28ef7-goog
-
diff --git a/libchrome_tools/patches/libchrome-Introduce-stub-ConvertableToTraceFormat.patch b/libchrome_tools/patches/libchrome-Introduce-stub-ConvertableToTraceFormat.patch
deleted file mode 100644
index bd68077cc7..0000000000
--- a/libchrome_tools/patches/libchrome-Introduce-stub-ConvertableToTraceFormat.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-From f2d560ab2808c87cd60a2962037bf4dabd9781ef Mon Sep 17 00:00:00 2001
-From: Hidehiko Abe <hidehiko@chromium.org>
-Date: Fri, 14 Jun 2019 14:22:33 +0900
-Subject: [PATCH] libchrome: Introduce stub ConvertableToTraceFormat.
-
-BUG=chromium:909719
-TEST=Built locally.
-
-Change-Id: I5c849edc2c5e8370bff6a8b1b83a92e5ef5836c8
----
- base/trace_event/trace_event.h | 13 ++++++++++++-
- 1 file changed, 12 insertions(+), 1 deletion(-)
-
-diff --git a/base/trace_event/trace_event.h b/base/trace_event/trace_event.h
-index 1ce76d9..7385582 100644
---- a/base/trace_event/trace_event.h
-+++ b/base/trace_event/trace_event.h
-@@ -10,6 +10,9 @@
- #include "base/trace_event/common/trace_event_common.h"
- #include "base/trace_event/heap_profiler.h"
-
-+// Indirectly included.
-+#include "base/strings/string_util.h"
-+
- // To avoid -Wunused-* errors, eat expression by macro.
- namespace libchrome_internal {
- template <typename... Args> void Ignore(Args&&... args) {}
-@@ -18,8 +21,9 @@ template <typename... Args> void Ignore(Args&&... args) {}
- (false ? libchrome_internal::Ignore(__VA_ARGS__) : (void) 0)
-
- // Body is effectively empty.
-+#define INTERNAL_TRACE_EVENT_ADD(...) INTERNAL_IGNORE(__VA_ARGS__)
- #define INTERNAL_TRACE_EVENT_ADD_SCOPED(...) INTERNAL_IGNORE(__VA_ARGS__)
--#define INTERNAL_TRACE_TASK_EXECUTION(...)
-+#define INTERNAL_TRACE_TASK_EXECUTION(...) INTERNAL_IGNORE(__VA_ARGS__)
- #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(...) \
- INTERNAL_IGNORE(__VA_ARGS__)
- #define TRACE_ID_MANGLE(val) (val)
-@@ -38,6 +42,13 @@ class TraceLog {
- void SetCurrentThreadBlocksMessageLoop() {}
- };
-
-+class BASE_EXPORT ConvertableToTraceFormat {
-+ public:
-+ ConvertableToTraceFormat() = default;
-+ virtual ~ConvertableToTraceFormat() = default;
-+ virtual void AppendAsTraceFormat(std::string* out) const {};
-+};
-+
- } // namespace trace_event
- } // namespace base
- #else
---
-2.22.0.410.gd8fdbe21b5-goog
-
diff --git a/libchrome_tools/patches/libchrome-Remove-glib-dependency.patch b/libchrome_tools/patches/libchrome-Remove-glib-dependency.patch
deleted file mode 100644
index 418dba196a..0000000000
--- a/libchrome_tools/patches/libchrome-Remove-glib-dependency.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-[200~From 78a4103946854e4e526b0cf407f0b09610b40988 Mon Sep 17 00:00:00 2001
-From: hscham <hscham@chromium.org>
-Date: Mon, 1 Jun 2020 16:50:16 +0900
-Subject: [PATCH] libchrome: Remove glib dependency.
-
-BUG=chromium:361635
-TEST=Ran Pre-CQ.
-
-Change-Id: I8a583851d51c5eaa24bb1506d45d6566f760595c
----
- build/build_config.h | 4 ----
- 1 file changed, 4 deletions(-)
-
-diff --git a/build/build_config.h b/build/build_config.h
-index 0a0024088..b0e2aa26e 100644
---- a/build/build_config.h
-+++ b/build/build_config.h
-@@ -39,10 +39,6 @@
- #elif !defined(__ANDROID_HOST__) // Chrome OS
-
- #define OS_CHROMEOS 1
--// TODO: Remove these once the GLib MessageLoopForUI isn't being used:
--// https://crbug.com/361635
--#define USE_GLIB 1
--#define USE_OZONE 1
-
- #endif // defined(__ANDROID__)
-
---
-2.27.0.rc2.251.g90737beb825-goog
-
diff --git a/libchrome_tools/patches/libchrome-Unpatch-sys.path-update.patch b/libchrome_tools/patches/libchrome-Unpatch-sys.path-update.patch
deleted file mode 100644
index 89d1244792..0000000000
--- a/libchrome_tools/patches/libchrome-Unpatch-sys.path-update.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From 702acfbe733e5b047759a3bfee71c8b63e5814fe Mon Sep 17 00:00:00 2001
-From: Hidehiko Abe <hidehiko@chromium.org>
-Date: Thu, 13 Jun 2019 23:02:42 +0900
-Subject: [PATCH] libchrome: Unpatch sys.path update.
-
-Unlike soong build, original sys.path change works.
-
-BUG=chromium:909719
-TEST=Built locally.
-
-Change-Id: I6c8ac8d4a1d156ddd77ec75485d42a810a9e61fe
----
- build/android/gyp/util/build_utils.py | 12 ++----------
- 1 file changed, 2 insertions(+), 10 deletions(-)
-
-diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
-index 426de03..f1764b9 100644
---- a/build/android/gyp/util/build_utils.py
-+++ b/build/android/gyp/util/build_utils.py
-@@ -25,16 +25,8 @@ import zipfile
- # Some clients do not add //build/android/gyp to PYTHONPATH.
- import md5_check # pylint: disable=relative-import
-
--# pylib conflicts with mojo/public/tools/bindings/pylib. Prioritize
--# build/android/pylib.
--# PYTHONPATH wouldn't help in this case, because soong put source files under
--# temp directory for each build, so the abspath is unknown until the
--# execution.
--#sys.path.append(os.path.join(os.path.dirname(__file__),
--# os.pardir, os.pardir, os.pardir))
--sys.path.insert(0, os.path.join(os.path.dirname(__file__),
-- os.pardir, os.pardir))
--
-+sys.path.append(os.path.join(os.path.dirname(__file__),
-+ os.pardir, os.pardir, os.pardir))
- import gn_helpers
-
- # Definition copied from pylib/constants/__init__.py to avoid adding
---
-2.22.0.rc2.383.gf4fbbf30c2-goog
-
diff --git a/libchrome_tools/patches/libchrome-Update-crypto.patch b/libchrome_tools/patches/libchrome-Update-crypto.patch
deleted file mode 100644
index 45991605cd..0000000000
--- a/libchrome_tools/patches/libchrome-Update-crypto.patch
+++ /dev/null
@@ -1,182 +0,0 @@
-From 23ecc2149133fa0cf369f53b5d7d28e78815bca3 Mon Sep 17 00:00:00 2001
-From: Hidehiko Abe <hidehiko@chromium.org>
-Date: Thu, 13 Jun 2019 22:27:41 +0900
-Subject: [PATCH] libchrome: Update crypto.
-
-libchrome uses OpenSSH, instead of BoringSSH, although its support
-was dropped in Chrome already.
-To lengthen its lifetime, this patch adds minor fix.
-- Use base::data() instead of base::string_as_array().
- The method was removed. cf) crrev.com/c/1056014.
-- Use base::PostTaskAndReply instead of base::WorkerPool.
- The class was removed. cf) crrev.com/c/650368
-- tracked_object::Location is renamed to base::Location.
- cf) crbug.com/763556
-- base::Location::Write was removed. Use ToString().
- cf) crrev.com/c/707310
-- base::MakeUnique was removed. Use std::make_unique.
- cf) crrev.com/c/944048
-
-BUG=chromium:909719
-TEST=Built locally.
-
-Change-Id: I2ba45db7592ea9addc2df230b977ffb950f0b342
----
- crypto/nss_util.cc | 37 ++++++++++++++-----------------------
- crypto/openssl_util.cc | 6 ++----
- crypto/openssl_util.h | 7 +++----
- crypto/sha2.cc | 2 +-
- 4 files changed, 20 insertions(+), 32 deletions(-)
-
-diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
-index a7752d3..f9c6373 100644
---- a/crypto/nss_util.cc
-+++ b/crypto/nss_util.cc
-@@ -38,14 +38,13 @@
- #include "base/files/file_util.h"
- #include "base/lazy_instance.h"
- #include "base/logging.h"
--#include "base/memory/ptr_util.h"
- #include "base/message_loop/message_loop.h"
- #include "base/native_library.h"
- #include "base/stl_util.h"
- #include "base/strings/stringprintf.h"
-+#include "base/task_scheduler/post_task.h"
- #include "base/threading/thread_checker.h"
- #include "base/threading/thread_restrictions.h"
--#include "base/threading/worker_pool.h"
- #include "build/build_config.h"
-
- #if !defined(OS_CHROMEOS)
-@@ -380,22 +379,16 @@ class NSSInitSingleton {
- std::unique_ptr<TPMModuleAndSlot> tpm_args(
- new TPMModuleAndSlot(chaps_module_));
- TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
-- if (base::WorkerPool::PostTaskAndReply(
-- FROM_HERE,
-- base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread,
-- system_slot_id,
-- tpm_args_ptr),
-- base::Bind(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot,
-- base::Unretained(this), // NSSInitSingleton is leaky
-- callback,
-- base::Passed(&tpm_args)),
-- true /* task_is_slow */
-- )) {
-- initializing_tpm_token_ = true;
-- } else {
-- base::MessageLoop::current()->task_runner()->PostTask(
-- FROM_HERE, base::Bind(callback, false));
-- }
-+ base::PostTaskAndReply(
-+ FROM_HERE,
-+ base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread,
-+ system_slot_id,
-+ tpm_args_ptr),
-+ base::Bind(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot,
-+ base::Unretained(this), // NSSInitSingleton is leaky
-+ callback,
-+ base::Passed(&tpm_args)));
-+ initializing_tpm_token_ = true;
- }
-
- static void InitializeTPMTokenOnWorkerThread(CK_SLOT_ID token_slot_id,
-@@ -508,7 +501,7 @@ class NSSInitSingleton {
- "%s %s", kUserNSSDatabaseName, username_hash.c_str());
- ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path));
- chromeos_user_map_[username_hash] =
-- base::MakeUnique<ChromeOSUserData>(std::move(public_slot));
-+ std::make_unique<ChromeOSUserData>(std::move(public_slot));
- return true;
- }
-
-@@ -543,7 +536,7 @@ class NSSInitSingleton {
- std::unique_ptr<TPMModuleAndSlot> tpm_args(
- new TPMModuleAndSlot(chaps_module_));
- TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
-- base::WorkerPool::PostTaskAndReply(
-+ base::PostTaskAndReply(
- FROM_HERE,
- base::Bind(&NSSInitSingleton::InitializeTPMTokenOnWorkerThread,
- slot_id,
-@@ -551,9 +544,7 @@ class NSSInitSingleton {
- base::Bind(&NSSInitSingleton::OnInitializedTPMForChromeOSUser,
- base::Unretained(this), // NSSInitSingleton is leaky
- username_hash,
-- base::Passed(&tpm_args)),
-- true /* task_is_slow */
-- );
-+ base::Passed(&tpm_args)));
- }
-
- void OnInitializedTPMForChromeOSUser(
-diff --git a/crypto/openssl_util.cc b/crypto/openssl_util.cc
-index c1b7a90..b671eab 100644
---- a/crypto/openssl_util.cc
-+++ b/crypto/openssl_util.cc
-@@ -46,15 +46,13 @@ void EnsureOpenSSLInit() {
- #endif
- }
-
--void ClearOpenSSLERRStack(const tracked_objects::Location& location) {
-+void ClearOpenSSLERRStack(const base::Location& location) {
- if (DCHECK_IS_ON() && VLOG_IS_ON(1)) {
- uint32_t error_num = ERR_peek_error();
- if (error_num == 0)
- return;
-
-- std::string message;
-- location.Write(true, true, &message);
-- DVLOG(1) << "OpenSSL ERR_get_error stack from " << message;
-+ DVLOG(1) << "OpenSSL ERR_get_error stack from " << location.ToString();
- ERR_print_errors_cb(&OpenSSLErrorCallback, NULL);
- } else {
- ERR_clear_error();
-diff --git a/crypto/openssl_util.h b/crypto/openssl_util.h
-index d608cde..c3d6cc9 100644
---- a/crypto/openssl_util.h
-+++ b/crypto/openssl_util.h
-@@ -63,8 +63,7 @@ CRYPTO_EXPORT void EnsureOpenSSLInit();
- // Drains the OpenSSL ERR_get_error stack. On a debug build the error codes
- // are send to VLOG(1), on a release build they are disregarded. In most
- // cases you should pass FROM_HERE as the |location|.
--CRYPTO_EXPORT void ClearOpenSSLERRStack(
-- const tracked_objects::Location& location);
-+CRYPTO_EXPORT void ClearOpenSSLERRStack(const base::Location& location);
-
- // Place an instance of this class on the call stack to automatically clear
- // the OpenSSL error stack on function exit.
-@@ -73,7 +72,7 @@ class OpenSSLErrStackTracer {
- // Pass FROM_HERE as |location|, to help track the source of OpenSSL error
- // messages. Note any diagnostic emitted will be tagged with the location of
- // the constructor call as it's not possible to trace a destructor's callsite.
-- explicit OpenSSLErrStackTracer(const tracked_objects::Location& location)
-+ explicit OpenSSLErrStackTracer(const base::Location& location)
- : location_(location) {
- EnsureOpenSSLInit();
- }
-@@ -82,7 +81,7 @@ class OpenSSLErrStackTracer {
- }
-
- private:
-- const tracked_objects::Location location_;
-+ const base::Location location_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(OpenSSLErrStackTracer);
- };
-diff --git a/crypto/sha2.cc b/crypto/sha2.cc
-index 1b302b3..71566a9 100644
---- a/crypto/sha2.cc
-+++ b/crypto/sha2.cc
-@@ -21,7 +21,7 @@ void SHA256HashString(const base::StringPiece& str, void* output, size_t len) {
-
- std::string SHA256HashString(const base::StringPiece& str) {
- std::string output(kSHA256Length, 0);
-- SHA256HashString(str, base::string_as_array(&output), output.size());
-+ SHA256HashString(str, base::data(output), output.size());
- return output;
- }
-
---
-2.22.0.rc2.383.gf4fbbf30c2-goog
-
diff --git a/libchrome_tools/patches/libchrome-fix-integer-overflow-if-microseconds-is-IN.patch b/libchrome_tools/patches/libchrome-fix-integer-overflow-if-microseconds-is-IN.patch
deleted file mode 100644
index a1241b11df..0000000000
--- a/libchrome_tools/patches/libchrome-fix-integer-overflow-if-microseconds-is-IN.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From f7ef75a1ddea9d18e1f166b76e90f948cbfd1f77 Mon Sep 17 00:00:00 2001
-From: Qijiang Fan <fqj@chromium.org>
-Date: Tue, 31 Mar 2020 17:43:16 +0900
-Subject: [PATCH] libchrome: fix integer overflow if microseconds is INT64_MIN
-
-Change-Id: Id3641f6b625f716ae6d134002c0224ed32284939
----
- base/time/time_exploded_posix.cc | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
-diff --git a/base/time/time_exploded_posix.cc b/base/time/time_exploded_posix.cc
-index 627c6b4f8735..2aef3864554e 100644
---- a/base/time/time_exploded_posix.cc
-+++ b/base/time/time_exploded_posix.cc
-@@ -141,8 +141,7 @@ void Time::Explode(bool is_local, Exploded* exploded) const {
- millisecond = milliseconds % kMillisecondsPerSecond;
- } else {
- // Round these *down* (towards -infinity).
-- milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) /
-- kMicrosecondsPerMillisecond;
-+ milliseconds = (microseconds + 1) / kMicrosecondsPerMillisecond - 1;
- seconds =
- (milliseconds - kMillisecondsPerSecond + 1) / kMillisecondsPerSecond;
- // Make this nonnegative (and between 0 and 999 inclusive).
---
-2.24.1
-
diff --git a/libchrome_tools/patches/patches b/libchrome_tools/patches/patches
deleted file mode 100644
index e27bc7afc7..0000000000
--- a/libchrome_tools/patches/patches
+++ /dev/null
@@ -1,75 +0,0 @@
-# This file will be used by emerge in libchrome-XXXX.ebuild to determine the
-# order of applying patches.
-
-# Cherry pick CLs from upstream.
-# Remove these when the libchrome gets enough new.
-# r576565.
-dbus-Add-TryRegisterFallback.patch
-
-# r581937.
-dbus-Remove-LOG-ERROR-in-ObjectProxy.patch
-
-# r582324
-Fix-Wdefaulted-function-deleted-warning-in-MessageLo.patch
-
-# r583543.
-dbus-Make-Bus-is_connected-mockable.patch
-
-# r596510.
-Mojo-Check-if-dispatcher-is-null-in-Core-UnwrapPlatf.patch
-
-# This no_destructor.h is taken from r599267.
-Add-base-NoDestructor-T.patch
-
-# r616020.
-dbus-Support-UnexportMethod-from-an-exported-object.patch
-
-# Add support for SimpleAlarmTimer::Create{,ForTesting} to reflect changes in r626151.
-Refactor-AlarmTimer-to-report-error-to-the-caller.patch
-
-# For backward compatibility.
-# TODO(crbug.com/909719): Remove this patch after clients are updated.
-libchrome-Add-EmptyResponseCallback-for-backward-com.patch
-
-# Undo gn_helper sys.path update.
-libchrome-Unpatch-sys.path-update.patch
-
-# Introduce stub ConvertableToTraceFormat for task_scheduler.
-libchrome-Introduce-stub-ConvertableToTraceFormat.patch
-
-# Fix timing issue with dbus::ObjectManager.
-# # TODO(bingxue): Remove after libchrome uprev past r684392.
-Connect-to-NameOwnerChanged-signal-when-setting-call.patch
-
-# Remove glib dependency.
-# TODO(hidehiko): Fix the config in AOSP libchrome.
-libchrome-Remove-glib-dependency.patch
-
-# Fix FileDescriptorWatcher leak
-# TODO(fqj): Remove after libchrome past r627021.
-fix-fd-watcher-leak.patch
-
-# Misc fix to build older crypto library.
-libchrome-Update-crypto.patch
-
-# Enable location source to add function_name
-enable-location-source.patch
-
-# Add WaitForServiceToBeAvailable back for MockObjectProxy
-WaitForServiceToBeAvailable.patch
-
-# TODO(crbug.com/1044363): Remove after uprev >= r586219.
-Fix-TimeDelta.patch
-
-# TODO(crbug.com/1065504): Remove after uprev to 754979.
-libchrome-fix-integer-overflow-if-microseconds-is-IN.patch
-
-# Forward compatibility for r680000
-r680000-forward-compatibility-patch-part-1.patch
-r680000-forward-compatibility-patch-part-2.patch
-
-# Add base/{check_op,notreached}.h for cbor
-Add-header-files-base-check_op-notreached-h.patch
-
-# Remove after uprev to r807076
-0001-Fix-pending_broker_clients-handling.patch
diff --git a/libchrome_tools/patches/r680000-forward-compatibility-patch-part-1.patch b/libchrome_tools/patches/r680000-forward-compatibility-patch-part-1.patch
deleted file mode 100644
index 2f820e6832..0000000000
--- a/libchrome_tools/patches/r680000-forward-compatibility-patch-part-1.patch
+++ /dev/null
@@ -1,222 +0,0 @@
-From 9d210ed05abf5e527f1de0b30fff62a8a3ae548f Mon Sep 17 00:00:00 2001
-From: hscham <hscham@chromium.org>
-Date: Mon, 13 Apr 2020 10:36:11 +0900
-Subject: [PATCH] libchrome: r680000 forward compatibility patch part 1
-
-This CL includes:
-- Add header files base/hash/{hash,md5,sha1}.h and
- base/system/sys_info.h from base/.
-- Add macro PRFilePath.
-- Add JSONReader::{Read,ReadAndReturnError,ReadToValue}Deprecated, alias
- of the corresponding method without the Deprecated suffix.
-- Add empty class base::CheckedObserver.
-- Add bool operators == and != for base::RepeatingCallback.
-- ScopedClearLastError (up to r758621)
-
-Change-Id: I6ba15f2938c02729e4fd51e5a4a52cb94e7c2a4e
----
- base/callback.h | 8 ++++++++
- base/files/file_path.h | 1 +
- base/hash/hash.h | 8 ++++++++
- base/hash/md5.h | 10 ++++++++++
- base/hash/sha1.h | 10 ++++++++++
- base/json/json_reader.h | 19 +++++++++++++++++++
- base/observer_list_types.h | 24 ++++++++++++++++++++++++
- base/system/sys_info.h | 10 ++++++++++
- 8 files changed, 90 insertions(+)
- create mode 100644 base/hash/hash.h
- create mode 100644 base/hash/md5.h
- create mode 100644 base/hash/sha1.h
- create mode 100644 base/observer_list_types.h
- create mode 100644 base/system/sys_info.h
-
-diff --git a/base/callback.h b/base/callback.h
-index bcda5af58..22a6f0e3e 100644
---- a/base/callback.h
-+++ b/base/callback.h
-@@ -123,6 +123,14 @@ class RepeatingCallback<R(Args...)> : public internal::CallbackBaseCopyable {
- return EqualsInternal(other);
- }
-
-+ bool operator==(const RepeatingCallback& other) const {
-+ return EqualsInternal(other);
-+ }
-+
-+ bool operator!=(const RepeatingCallback& other) const {
-+ return !operator==(other);
-+ }
-+
- R Run(Args... args) const & {
- PolymorphicInvoke f =
- reinterpret_cast<PolymorphicInvoke>(this->polymorphic_invoke());
-diff --git a/base/files/file_path.h b/base/files/file_path.h
-index 2dc15f9d0..36229979d 100644
---- a/base/files/file_path.h
-+++ b/base/files/file_path.h
-@@ -131,6 +131,7 @@
- #define PRIsFP "ls"
- #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- #define PRIsFP "s"
-+#define PRFilePath "s"
- #endif // OS_WIN
-
- namespace base {
-diff --git a/base/hash/hash.h b/base/hash/hash.h
-new file mode 100644
-index 000000000..b35a96fd3
---- /dev/null
-+++ b/base/hash/hash.h
-@@ -0,0 +1,8 @@
-+// Copyright (c) 2011 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.
-+
-+#ifndef BASE_HASH_HASH_H_
-+#define BASE_HASH_HASH_H_
-+#include "base/hash.h"
-+#endif // BASE_HASH_HASH_H_
-diff --git a/base/hash/md5.h b/base/hash/md5.h
-new file mode 100644
-index 000000000..821649319
---- /dev/null
-+++ b/base/hash/md5.h
-@@ -0,0 +1,10 @@
-+// Copyright (c) 2011 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.
-+
-+#ifndef BASE_HASH_MD5_H_
-+#define BASE_HASH_MD5_H_
-+
-+#include "base/md5.h"
-+
-+#endif // BASE_HASH_MD5_H_
-diff --git a/base/hash/sha1.h b/base/hash/sha1.h
-new file mode 100644
-index 000000000..7d3e18212
---- /dev/null
-+++ b/base/hash/sha1.h
-@@ -0,0 +1,10 @@
-+// Copyright (c) 2011 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.
-+
-+#ifndef BASE_HASH_SHA1_H_
-+#define BASE_HASH_SHA1_H_
-+
-+#include "base/sha1.h"
-+
-+#endif // BASE_HASH_SHA1_H_
-diff --git a/base/json/json_reader.h b/base/json/json_reader.h
-index 2c6bd3e47..05de907ce 100644
---- a/base/json/json_reader.h
-+++ b/base/json/json_reader.h
-@@ -98,6 +98,12 @@ class BASE_EXPORT JSONReader {
- static std::unique_ptr<Value> Read(StringPiece json,
- int options = JSON_PARSE_RFC,
- int max_depth = kStackMaxDepth);
-+ inline static std::unique_ptr<Value> ReadDeprecated(
-+ StringPiece json,
-+ int options = JSON_PARSE_RFC,
-+ int max_depth = kStackMaxDepth){
-+ return Read(json, options, max_depth);
-+ }
-
- // Reads and parses |json| like Read(). |error_code_out| and |error_msg_out|
- // are optional. If specified and nullptr is returned, they will be populated
-@@ -110,6 +116,16 @@ class BASE_EXPORT JSONReader {
- std::string* error_msg_out,
- int* error_line_out = nullptr,
- int* error_column_out = nullptr);
-+ inline static std::unique_ptr<Value> ReadAndReturnErrorDeprecated(
-+ StringPiece json,
-+ int options, // JSONParserOptions
-+ int* error_code_out,
-+ std::string* error_msg_out,
-+ int* error_line_out = nullptr,
-+ int* error_column_out = nullptr){
-+ return ReadAndReturnError(json, options, error_code_out, error_msg_out,
-+ error_line_out, error_column_out);
-+ }
-
- // Converts a JSON parse error code into a human readable message.
- // Returns an empty string if error_code is JSON_NO_ERROR.
-@@ -117,6 +133,9 @@ class BASE_EXPORT JSONReader {
-
- // Non-static version of Read() above.
- std::unique_ptr<Value> ReadToValue(StringPiece json);
-+ inline std::unique_ptr<Value> ReadToValueDeprecated(StringPiece json) {
-+ return JSONReader::ReadToValue(json);
-+ }
-
- // Returns the error code if the last call to ReadToValue() failed.
- // Returns JSON_NO_ERROR otherwise.
-diff --git a/base/observer_list_types.h b/base/observer_list_types.h
-new file mode 100644
-index 000000000..8f3889735
---- /dev/null
-+++ b/base/observer_list_types.h
-@@ -0,0 +1,24 @@
-+// Copyright 2018 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.
-+
-+#ifndef BASE_OBSERVER_LIST_TYPES_H_
-+#define BASE_OBSERVER_LIST_TYPES_H_
-+
-+#include "base/base_export.h"
-+#include "base/macros.h"
-+
-+namespace base {
-+class BASE_EXPORT CheckedObserver {
-+ public:
-+ CheckedObserver() {};
-+
-+ protected:
-+ virtual ~CheckedObserver() = default;
-+
-+ DISALLOW_COPY_AND_ASSIGN(CheckedObserver);
-+};
-+
-+} // namespace base
-+
-+#endif // BASE_OBSERVER_LIST_TYPES_H_
-diff --git a/base/scoped_clear_last_error.h b/base/scoped_clear_last_error.h
-new file mode 100644
-index 0000000..066730d
---- /dev/null
-+++ b/base/scoped_clear_last_error.h
-@@ -0,0 +1,14 @@
-+// Copyright (c) 2013 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.
-+
-+#ifndef BASE_SCOPED_CLEAR_LAST_ERROR_H_
-+#define BASE_SCOPED_CLEAR_LAST_ERROR_H_
-+
-+#include "base/scoped_clear_errno.h"
-+
-+namespace base {
-+using ScopedClearLastError = base::ScopedClearErrno;
-+}
-+
-+#endif // BASE_SCOPED_CLEAR_LAST_ERROR_H_
-diff --git a/base/system/sys_info.h b/base/system/sys_info.h
-new file mode 100644
-index 000000000..60676e0e1
---- /dev/null
-+++ b/base/system/sys_info.h
-@@ -0,0 +1,10 @@
-+// Copyright (c) 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.
-+
-+#ifndef BASE_SYSTEM_SYS_INFO_H_
-+#define BASE_SYSTEM_SYS_INFO_H_
-+
-+#include "base/sys_info.h"
-+
-+#endif // BASE_SYSTEM_SYS_INFO_H_
---
-2.26.1.301.g55bc3eb7cb9-goog
-
diff --git a/libchrome_tools/patches/r680000-forward-compatibility-patch-part-2.patch b/libchrome_tools/patches/r680000-forward-compatibility-patch-part-2.patch
deleted file mode 100644
index 0bb346d304..0000000000
--- a/libchrome_tools/patches/r680000-forward-compatibility-patch-part-2.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From e8ce13950e6afc97ea69a36f5f234a7409269086 Mon Sep 17 00:00:00 2001
-From: hscham <hscham@chromium.org>
-Date: Fri, 17 Apr 2020 15:20:53 +0900
-Subject: [PATCH] libchrome: r680000 forward compatibility patch part 2
-
-This CL includes:
-- Rename base::LaunchOptions {,clear_}environ{=>ment}.
-
-Change-Id: I07b9b84d153e942368021be7fb89f0dd07ffebb1
----
- base/process/launch.h | 6 +++---
- base/process/launch_posix.cc | 8 ++++----
- base/process/process_util_unittest.cc | 4 ++--
- 3 files changed, 9 insertions(+), 9 deletions(-)
-
-diff --git a/base/process/launch.h b/base/process/launch.h
-index 7a2def2..84d176e 100644
---- a/base/process/launch.h
-+++ b/base/process/launch.h
-@@ -160,11 +160,11 @@ struct BASE_EXPORT LaunchOptions {
- // Set/unset environment variables. These are applied on top of the parent
- // process environment. Empty (the default) means to inherit the same
- // environment. See AlterEnvironment().
-- EnvironmentMap environ;
-+ EnvironmentMap environment;
-
- // Clear the environment for the new process before processing changes from
-- // |environ|.
-- bool clear_environ = false;
-+ // |environment|.
-+ bool clear_environment = false;
-
- // Remap file descriptors according to the mapping of src_fd->dest_fd to
- // propagate FDs into the child process.
-diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc
-index ec58488..c61db41 100644
---- a/base/process/launch_posix.cc
-+++ b/base/process/launch_posix.cc
-@@ -324,10 +324,10 @@ Process LaunchProcess(const std::vector<std::string>& argv,
- std::unique_ptr<char* []> new_environ;
- char* const empty_environ = nullptr;
- char* const* old_environ = GetEnvironment();
-- if (options.clear_environ)
-+ if (options.clear_environment)
- old_environ = &empty_environ;
-- if (!options.environ.empty())
-- new_environ = AlterEnvironment(old_environ, options.environ);
-+ if (!options.environment.empty())
-+ new_environ = AlterEnvironment(old_environ, options.environment);
-
- sigset_t full_sigset;
- sigfillset(&full_sigset);
-@@ -466,7 +466,7 @@ Process LaunchProcess(const std::vector<std::string>& argv,
- fd_shuffle2.push_back(InjectionArc(value.first, value.second, false));
- }
-
-- if (!options.environ.empty() || options.clear_environ)
-+ if (!options.environment.empty() || options.clear_environment)
- SetEnvironment(new_environ.get());
-
- // fd_shuffle1 is mutated by this call because it cannot malloc.
-diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
-index 4e788b7..a541e48 100644
---- a/base/process/process_util_unittest.cc
-+++ b/base/process/process_util_unittest.cc
-@@ -1162,8 +1162,8 @@ std::string TestLaunchProcess(const std::vector<std::string>& args,
-
- LaunchOptions options;
- options.wait = true;
-- options.environ = env_changes;
-- options.clear_environ = clear_environ;
-+ options.environment = env_changes;
-+ options.clear_environment = clear_environ;
- options.fds_to_remap.emplace_back(fds[1], 1);
- #if defined(OS_LINUX)
- options.clone_flags = clone_flags;
---
-2.26.1.301.g55bc3eb7cb9-goog
-
-diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h
-index f9523b3138ec..a2cc7f73d8f2 100644
---- a/base/test/scoped_task_environment.h
-+++ b/base/test/scoped_task_environment.h
-@@ -81,6 +81,10 @@ class ScopedTaskEnvironment {
- IO,
- };
-
-+ // To introduce TimeSource::MOCK_TIME behaves same as
-+ // MainThreadType::MOCK_TIME.
-+ using TimeSource = MainThreadType;
-+
- enum class ExecutionMode {
- // Tasks are queued and only executed when RunUntilIdle() is explicitly
- // called.
diff --git a/libchrome_tools/uprev/copy_new_files.py b/libchrome_tools/uprev/copy_new_files.py
deleted file mode 100755
index 67da28f4ac..0000000000
--- a/libchrome_tools/uprev/copy_new_files.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
-Utility to copy missing files from Chromium tree to Chromium OS libchrome tree
-based on hard coded rules.
-
-This utility is used to diff current HEAD against given commit in Chromium
-browser master branch, copy missing files after hard-coded filter rules and
-remove unnecessary files. libchrome original files in hard-coded filter rules
-will be untounched.
-"""
-
-import argparse
-import os
-import os.path
-import subprocess
-import sys
-
-import filters
-import utils
-
-def main():
- # Init args
- parser = argparse.ArgumentParser(
- description='Copy file from given commits')
- parser.add_argument(
- 'commit_hash',
- metavar='commit',
- type=str,
- nargs=1,
- help='commit hash to copy files from')
- parser.add_argument(
- '--dry_run',
- dest='dry_run',
- action='store_const',
- const=True,
- default=False)
- arg = parser.parse_args(sys.argv[1:])
-
- # Read file list from HEAD and upstream commit.
- upstream_files = utils.get_file_list(arg.commit_hash[0])
- our_files = utils.get_file_list('HEAD')
-
- # Calculate target file list
- target_files = filters.filter_file(our_files, upstream_files)
-
- # Calculate operations needed
- ops = utils.gen_op(our_files, target_files)
-
- if arg.dry_run:
- # Print ops only on dry-run mode.
- print('\n'.join(repr(x) for x in ops))
- return
- for op, f in ops:
- # Ignore if op is REP because we only want to copy missing files, not to
- # revert custom Chromium OS libchrome patch.
- assert type(op) == utils.DiffOperations
- if op == utils.DiffOperations.DEL:
- subprocess.check_call(['git', 'rm', f.path]),
- elif op == utils.DiffOperations.ADD:
- # Create directory recursively if not exist.
- os.makedirs(os.path.dirname(f.path), exist_ok=True)
- # Read file by git cat-file with blob object id to avoid heavy git checkout.
- with open(f.path, 'wb') as outfile:
- subprocess.check_call(['git', 'cat-file', 'blob', f.id],
- stdout=outfile)
- # Add to git index
- subprocess.check_call(['git', 'add', f.path])
-
-if __name__ == '__main__':
- main()
diff --git a/libchrome_tools/uprev/dirty_uprev.py b/libchrome_tools/uprev/dirty_uprev.py
deleted file mode 100755
index aa8e2bd08e..0000000000
--- a/libchrome_tools/uprev/dirty_uprev.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
-Utility to apply diffs between given two upstream commit hashes to current
-workspace.
-
-This utility diffs files between old_commit and new_commit, with hard-coded
-filter rules, and apply the diff to current HEAD with 3-way-merge supported.
-
-This can be used to uprev a libchrome directory when this is not git history for
-git merge to work.
-"""
-
-import argparse
-import subprocess
-import sys
-
-import filters
-import utils
-
-def main():
- # Init args
- parser = argparse.ArgumentParser(
- description='Copy file from given commits')
- parser.add_argument(
- 'old_commit', metavar='old_commit', type=str, nargs=1,
- help='commit hash in upstream branch or browser repository '
- 'we want to uprev from')
- parser.add_argument(
- 'new_commit', metavar='new_commit', type=str, nargs=1,
- help='commit hash in upstream branch or browser repository '
- 'we want ot uprev to')
- parser.add_argument(
- '--dry_run', dest='dry_run', action='store_const', const=True, default=False)
- parser.add_argument(
- '--is_browser', dest='is_browser', action='store_const', const=True, default=False,
- help='is the commit hash in browser repository')
- arg = parser.parse_args(sys.argv[1:])
-
- # Get old and new files.
- old_files = utils.get_file_list(arg.old_commit[0])
- new_files = utils.get_file_list(arg.new_commit[0])
-
- if arg.is_browser:
- old_files = filters.filter_file([], old_files)
- new_files = filters.filter_file([], new_files)
- assert filters.filter_file(old_files, []) == []
- assert filters.filter_file(new_files, []) == []
-
- # Generate a tree object for new files.
- old_tree = utils.git_mktree(old_files)
- new_tree = utils.git_mktree(new_files)
- newroot = utils.git_commit(old_tree, [])
- squashed = utils.git_commit(new_tree, [newroot])
-
- # Generate patch for git am
- patch = subprocess.check_output(['git', 'format-patch', '--stdout', newroot+b'..'+squashed])
-
- if arg.dry_run:
- print(patch.decode('utf-8'))
- else:
- subprocess.run(['git', 'am', '-3'], input=patch)
-
-
-if __name__ == '__main__':
- main()
diff --git a/libchrome_tools/uprev/filtered_utils.py b/libchrome_tools/uprev/filtered_utils.py
deleted file mode 100644
index 20639b2bee..0000000000
--- a/libchrome_tools/uprev/filtered_utils.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-""" Provides utilities for filtered branch handling. """
-
-import collections
-import re
-import subprocess
-
-import utils
-
-# Keyword to uniquely identify the beginning of upstream history.
-CROS_LIBCHROME_INITIAL_COMMIT = b'CrOS-Libchrome-History-Initial-Commit'
-# Keyword to identify original commit in Chromium browser repository.
-CROS_LIBCHROME_ORIGINAL_COMMIT = b'CrOS-Libchrome-Original-Commit'
-
-
-# Stores metadata required for a git commit.
-GitCommitMetadata = collections.namedtuple(
- 'GitCommitMetadata',
- ['parents', 'original_commits', 'tree', 'authorship', 'title', 'message', 'is_root',]
-)
-
-
-# Stores information for a commit authorship.
-GitCommitAuthorship = collections.namedtuple(
- 'GitCommitAuthorship',
- ['name', 'email', 'time', 'timezone',]
-)
-
-
-def get_metadata(commit_hash):
- """Returns the metadata of the commit specified by the commit_hash.
-
- This function parses the commit message of the commit specified by the
- commit_hash, then returns its GitCommitMetadata instance.
- The commit must be on the filtered branch, otherwise some metadata may be
- omitted.
- Returns metadata from the commit message about commit_hash on the filtered
- branch.
-
- Args:
- commit_hash: the commit hash on the filtered branch.
- """
-
- ret = subprocess.check_output(['git', 'cat-file', 'commit',
- commit_hash]).split(b'\n')
- parents = []
- tree_hash = None
- authorship = None
- author_re = re.compile(rb'^(.*) <(.*)> ([0-9]+) ([^ ])+$')
- while ret:
- line = ret[0]
- ret = ret[1:]
- if not line.strip():
- # End of header. break.
- break
- tag, reminder = line.split(b' ', 1)
- if tag == b'tree':
- tree_hash = reminder
- elif tag == b'author':
- m = author_re.match(reminder)
- assert m, (line, commit_hash)
- authorship = GitCommitAuthorship(m.group(1),
- m.group(2),
- m.group(3),
- m.group(4))
- elif tag == b'parent':
- parents.append(reminder)
-
- title = ret[0] if ret else None
-
- original_commits = []
- is_root = False
- for line in ret:
- if line.startswith(CROS_LIBCHROME_ORIGINAL_COMMIT):
- original_commits.append(line.split(b':')[1].strip())
- if line == CROS_LIBCHROME_INITIAL_COMMIT:
- is_root = True
- msg = b'\n'.join(ret)
- return GitCommitMetadata(parents, original_commits, tree_hash, authorship,
- title, msg, is_root)
-
-
-def get_commits_map(commit_hash, progress_callback):
- """Returns a map from original commit hashes to filtered commit hashes.
-
- This function traverses the filtered branch from the commit specified by
- commit_hash to its root, then parses each commit message and constructs the
- map of those commits.
-
- Args:
- commit_hash: the commit hash on the filtered branch.
- progress_callback: called every commit is being read. Parameters taken
- are (idx, total_commits, current_commit)
- """
- commits_map = {}
- commits_filtered_tree = utils.git_revlist(None, commit_hash)
- for index, commit in enumerate(commits_filtered_tree, start=1):
- if progress_callback:
- progress_callback(index, len(commits_filtered_tree), commit[0])
- meta = get_metadata(commit[0])
- for original_commit in meta.original_commits:
- commits_map[original_commit] = commit[0]
- if meta.is_root:
- assert 'ROOT' not in commits_map
- commits_map['ROOT'] = commit[0]
- return commits_map
diff --git a/libchrome_tools/uprev/filters.py b/libchrome_tools/uprev/filters.py
deleted file mode 100644
index e67a030514..0000000000
--- a/libchrome_tools/uprev/filters.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Provide filters for libchrome tools."""
-
-import re
-
-# Libchrome wants WANT but not WANT_EXCLUDE
-# aka files matching WANT will be copied from upstream_files
-WANT = [
- re.compile(rb'base/((?!(allocator|third_party)/).*$)'),
- re.compile(
- rb'base/allocator/(allocator_shim.cc|allocator_shim_override_linker_wrapped_symbols.h|allocator_shim_override_cpp_symbols.h|allocator_shim_override_libc_symbols.h|allocator_shim_default_dispatch_to_glibc.cc|allocator_shim.h|allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc|allocator_extension.cc|allocator_extension.h|allocator_shim_internals.h)$'
- ),
- re.compile(rb'base/third_party/(dynamic_annotation|icu|nspr|valgrind)'),
- re.compile(rb'build/(android/(gyp/util|pylib/([^/]*$|constants))|[^/]*\.(h|py)$)'),
- re.compile(rb'mojo/'),
- re.compile(rb'dbus/'),
- re.compile(rb'ipc/.*(\.cc|\.h|\.mojom)$'),
- re.compile(rb'ui/gfx/(gfx_export.h|geometry|range)'),
- re.compile(rb'testing/[^/]*\.(cc|h)$'),
- re.compile(rb'third_party/(jinja2|markupsafe|ply)'),
- re.compile(
- rb'components/(json_schema|policy/core/common/[^/]*$|policy/policy_export.h|timers)'
- ),
- re.compile(
- rb'device/bluetooth/bluetooth_(common|advertisement|uuid|export)\.*(h|cc)'
- ),
- re.compile(
- rb'device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.(h|cc)'
- ),
-]
-
-# WANT_EXCLUDE will be excluded from WANT
-WANT_EXCLUDE = [
- re.compile(rb'(.*/)?BUILD.gn$'),
- re.compile(rb'(.*/)?PRESUBMIT.py$'),
- re.compile(rb'(.*/)?OWNERS$'),
- re.compile(rb'(.*/)?SECURITY_OWNERS$'),
- re.compile(rb'(.*/)?DEPS$'),
- re.compile(rb'base/(.*/)?(ios|win|fuchsia|mac|openbsd|freebsd|nacl)/.*'),
- re.compile(rb'.*_(ios|win|mac|fuchsia|openbsd|freebsd|nacl)[_./]'),
- re.compile(rb'.*/(ios|win|mac|fuchsia|openbsd|freebsd|nacl)_'),
- re.compile(rb'dbus/(test_serv(er|ice)\.cc|test_service\.h)$')
-]
-
-# Files matching KEEP should not be touched.
-# aka files matching KEEP will keep its our_files version,
-# and it will be kept even it doesn't exist in upstream.
-# KEEP-KEEP_EXCLUDE must NOT intersect with WANT-WANT_EXCLUDE
-KEEP = [
- re.compile(
- b'(Android.bp|BUILD.gn|crypto|libchrome_tools|MODULE_LICENSE_BSD|NOTICE|OWNERS|PRESUBMIT.cfg|soong|testrunner.cc|third_party)(/.*)?$'
- ),
- re.compile(rb'[^/]*$'),
- re.compile(rb'.*buildflags.h'),
- re.compile(rb'base/android/java/src/org/chromium/base/BuildConfig.java'),
- re.compile(rb'testing/(gmock|gtest)/'),
- re.compile(rb'base/third_party/(libevent|symbolize)'),
-]
-
-# KEEP_EXCLUDE wil be excluded from KEEP.
-KEEP_EXCLUDE = [
- re.compile(rb'third_party/(jinja2|markupsafe|ply)'),
-]
-
-
-def _want_file(path):
- """Returns whether the path wants to be a new file."""
- wanted = False
- for want_file_regex in WANT:
- if want_file_regex.match(path):
- wanted = True
- break
- for exclude_file_regex in WANT_EXCLUDE:
- if exclude_file_regex.match(path):
- wanted = False
- break
- return wanted
-
-
-def _keep_file(path):
- """Returns whether the path wants to be kept untouched in local files."""
- keep = False
- for keep_file_regex in KEEP:
- if keep_file_regex.match(path):
- keep = True
- break
- for exclude_file_regex in KEEP_EXCLUDE:
- if exclude_file_regex.match(path):
- keep = False
- break
- return keep
-
-
-def filter_file(our_files, upstream_files):
- """Generates a list of files we want based on hard-coded rules.
-
- File list must be a list of GitFile.
-
- Args:
- our_files: files in Chromium OS libchrome repository.
- upstream_files: files in Chromium browser repository.
- """
-
- files = []
- for upstream_file in upstream_files:
- if _want_file(upstream_file.path):
- files.append(upstream_file)
- for our_file in our_files:
- if _keep_file(our_file.path):
- files.append(our_file)
- return files
-
-
-def filter_diff(diff):
- """Returns a subset of diff, after running filters.
-
- Args:
- diff: diff to filter. diff contains list of utils.GitDiffTree
- """
- filtered = []
- for change in diff:
- path = change.file.path
- if _want_file(path):
- assert not _keep_file(path)
- filtered.append(change)
- return filtered
diff --git a/libchrome_tools/uprev/generate_filtered_tree.py b/libchrome_tools/uprev/generate_filtered_tree.py
deleted file mode 100755
index 63c678d9b8..0000000000
--- a/libchrome_tools/uprev/generate_filtered_tree.py
+++ /dev/null
@@ -1,257 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import argparse
-import collections
-import datetime
-import os
-import subprocess
-import sys
-import time
-
-import filtered_utils
-import filters
-import lazytree
-import utils
-
-# Use avg speed of last TIMING_DISTANCE commits.
-_TIMING_DISTANCE = 100
-# Verify the tree is consistent (diff-based, and actual) when a commit is made
-# after every _VERIFY_INTEGRITY_DISTANCE in browser repository.
-# Merge commits are always verified.
-_VERIFY_INTEGRITY_DISTANCE = 1000
-
-
-def timing(timing_deque, update=True):
- """Returns a speed (c/s), and updates timing_deque.
-
- Args:
- timing_deque: a deque to store the timing of past _TIMING_DISTANCE.
- update: adds current timestamp to timing_deque if True. It needs to set
- to False, if it wants to be called multiple times with the current
- timestamp.
- """
- first = timing_deque[0]
- now = time.time()
- if update:
- timing_deque.append(now)
- if len(timing_deque) > _TIMING_DISTANCE:
- timing_deque.popleft()
- return _TIMING_DISTANCE / (now - first)
-
-
-def get_start_commit_of_browser_tree(parent_filtered):
- """Returns the last commit committed by the script, and its metadata.
-
- Args:
- parent_filtered: the commit hash of the tip of the filtered branch.
- """
- current = parent_filtered
- while True:
- meta = filtered_utils.get_metadata(current)
- if meta.original_commits:
- return current, meta
- if not meta.parents:
- return None, None
- # Follow main line only
- current = meta.parents[0]
-
-
-def find_filtered_commit(commit, commits_map):
- """Finds the corresponding parent of a browser commit in filtered branch.
-
- If not found, the corresponding commit of its least ancestor is used.
-
- Args:
- commit: commit hash in browser repository.
- commits_map: commit hash mapping from original commit to the one in the
- filtered branch. commits_map may be altered.
- """
- look_for = commit
- while look_for not in commits_map:
- meta = filtered_utils.get_metadata(look_for)
- assert len(meta.parents) <= 1
- if len(meta.parents) == 1:
- look_for = meta.parents[0]
- else:
- look_for = 'ROOT'
- commits_map[commit] = commits_map[look_for]
- return commits_map[look_for]
-
-
-def do_commit(treehash, commithash, meta, commits_map):
- """Makes a commit with the given arguments.
-
- This creates a commit on the filtered branch with preserving the original
- commiter name, email, authored timestamp and the message.
- Also, the special annotation `CrOS-Libchrome-Original-Commit:
- <original-commit-hash>' is appended at the end of commit message.
- The parent commits are identified by the parents of the original commit and
- commits_map.
-
- Args:
- treehash: tree object id for this commit.
- commithash: original commit hash, used to append to commit message.
- meta: meta data of the original commit.
- commits_map: current known commit mapping. commits_map may be altered.
- """
- parents_parameters = []
- for parent in meta.parents:
- parents_parameters.append('-p')
- parents_parameters.append(find_filtered_commit(parent, commits_map))
- msg = (meta.message + b'\n\n' +
- filtered_utils.CROS_LIBCHROME_ORIGINAL_COMMIT +
- b': ' + commithash + b'\n')
- return subprocess.check_output(
- ['git', 'commit-tree'] + parents_parameters + [treehash],
- env=dict(os.environ,
- GIT_AUTHOR_NAME=meta.authorship.name,
- GIT_AUTHOR_EMAIL=meta.authorship.email,
- GIT_AUTHOR_DATE=b' '.join([meta.authorship.time,
- meta.authorship.timezone])),
- input=msg).strip(b'\n')
-
-
-def verify_commit(original_commit, new_tree):
- """Verifies if new_tree is exactly original_commit after filters.
-
- Args:
- original_commit: commit hash in Chromium browser tree.
- new_tree: tree hash created for upstream branch commit.
- """
- expected_file_list = filters.filter_file([], utils.get_file_list(original_commit))
- assert utils.git_mktree(expected_file_list) == new_tree
-
-
-def process_commits(pending_commits, commits_map, progress_callback, commit_callback):
- """Processes new commits in browser repository.
-
- Returns the commit hash of the last commit made.
-
- Args:
- pending_commits: list of tuple (commit hash, parent hashes) to process,
- in topological order.
- commits_map: current known commit mapping. may be altered.
- progress_callback: callback for every commit in pending_commits. It
- should take (idx, total, orig_commit_hash, meta) as parameters.
- commit_callback: callback when a commit is made to filtered branch. It
- should take (orig_commit_hash, new_commit_hash, meta) as parameters.
- """
- last_commit = None
- last_verified = -1
- for i, commit in enumerate(pending_commits, start=1):
- meta = filtered_utils.get_metadata(commit[0])
- if progress_callback:
- progress_callback(i, len(pending_commits), commit[0], meta)
- diff_with_parent = filters.filter_diff(utils.git_difftree(
- meta.parents[0] if meta.parents else None, commit[0]))
- git_lazytree = lazytree.LazyTree(
- filtered_utils.get_metadata(
- find_filtered_commit(meta.parents[0], commits_map)).tree
- if meta.parents else None)
- if len(meta.parents) <= 1 and len(diff_with_parent) == 0:
- # not merge commit AND no diff
- if len(meta.parents) == 1 and meta.parents[0] in commits_map:
- commits_map[commit[0]] = commits_map[meta.parents[0]]
- continue
- for op, f in diff_with_parent:
- if op == utils.DiffOperations.ADD or op == utils.DiffOperations.REP:
- git_lazytree[f.path] = f
- elif op == utils.DiffOperations.DEL:
- del git_lazytree[f.path]
- treehash_after_diff_applied = git_lazytree.hash()
- filtered_commit = do_commit(treehash_after_diff_applied, commit[0],
- meta, commits_map)
- if commit_callback:
- commit_callback(commit[0], filtered_commit, meta)
- commits_map[commit[0]] = filtered_commit
- last_commit = filtered_commit
- if len(meta.parents) > 1 or (i - last_verified >=
- _VERIFY_INTEGRITY_DISTANCE):
- # merge commit OR every _VERIFY_INTEGRITY_DISTANCE
- last_verified = i
- verify_commit(commit[0], treehash_after_diff_applied)
- # Verify last commit
- verify_commit(pending_commits[-1][0], filtered_utils.get_metadata(last_commit).tree)
- return last_commit
-
-
-def main():
- # Init args
- parser = argparse.ArgumentParser(
- description='Copy file from given commits')
- parser.add_argument(
- 'parent_filtered', metavar='parent_filtered', type=str, nargs=1,
- help='commit hash in filtered branch to continue from. usually HEAD of that branch.')
- parser.add_argument(
- 'goal_browser', metavar='goal_browser', type=str, nargs=1,
- help='commit hash in browser master branch.')
- parser.add_argument(
- '--dry_run', dest='dry_run', action='store_const', const=True, default=False)
- arg = parser.parse_args(sys.argv[1:])
-
- # Look for last known commit made by the script in filtered branch.
- print('Looking for last known commit from', arg.parent_filtered[0])
- last_known, meta_last_known = get_start_commit_of_browser_tree(
- arg.parent_filtered[0])
- if last_known:
- print('Continuing from', last_known, meta_last_known)
- else:
- print('No known last commit')
- print('parent on filter branch', arg.parent_filtered[0])
-
- # Get a mapping between browser repository and filtered branch for commits
- # in filtered branch.
- print('reading commits details for commits mapping')
- timing_deque = collections.deque([time.time()])
- commits_map = filtered_utils.get_commits_map(
- arg.parent_filtered[0],
- lambda cur_idx, tot_cnt, cur_hash:
- (
- print('Reading', cur_hash, '%d/%d' % (cur_idx, tot_cnt),
- '%f c/s' % timing(timing_deque),
- end='\r', flush=True),
- ))
- if not 'ROOT' in commits_map:
- commits_map['ROOT'] =subprocess.check_output(
- ['git', 'commit-tree', '-p', arg.parent_filtered[0],
- utils.git_mktree([])],
- input=filtered_utils.CROS_LIBCHROME_INITIAL_COMMIT).strip(b'\n')
- print()
- print('loaded commit mapping of', len(commits_map), 'commit')
-
- # Process newer commits in browser repository from
- # last_known.original_commits
- print('search for commits to filter')
- timing_deque= collections.deque([time.time()])
- pending_commits = utils.git_revlist(
- meta_last_known.original_commits[0] if meta_last_known else None,
- arg.goal_browser[0])
- print(len(pending_commits), 'commits to process')
- new_head = process_commits(
- pending_commits,
- commits_map,
- # Print progress
- lambda cur_idx, tot_cnt, cur_hash, cur_meta: (
- print('Processing',
- cur_hash, '%d/%d' % (cur_idx, tot_cnt),
- '%f c/s' % timing(timing_deque, update=False),
- 'eta %s' % (
- datetime.timedelta(
- seconds=int((tot_cnt - cur_idx) / timing(timing_deque)))),
- cur_meta.title[:50],
- end='\r', flush=True),
- ),
- # Print new commits
- lambda orig_hash, new_hash, commit_meta:
- print(b'%s is commited as %s: %s' % (orig_hash, new_hash,
- commit_meta.title[:50]))
- )
- print()
- print('New HEAD should be', new_head.decode('ascii'))
-
-
-if __name__ == '__main__':
- main()
diff --git a/libchrome_tools/uprev/lazytree.py b/libchrome_tools/uprev/lazytree.py
deleted file mode 100644
index d76fa5c8c1..0000000000
--- a/libchrome_tools/uprev/lazytree.py
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import re
-import subprocess
-
-import utils
-
-
-GIT_LSTREE_RE_LINE = re.compile(rb'^([^ ]*) ([^ ]*) ([^ ]*)\t(.*)$')
-
-
-class LazyTree:
- """LazyTree does git mktree lazily."""
-
- def __init__(self, treehash=None):
- """Initializes a LazyTree.
-
- If treehash is not None, it initializes as the tree object.
-
- Args:
- treehash: tree object id. please do not use a treeish, it will fail
- later.
- """
- if treehash:
- self._treehash = treehash # tree object id of current tree
- self._subtrees = None # map from directory name to sub LazyTree
- self._files = None # map from file naem to utils.GitFile
- return
- # Initialize an empty LazyTree
- self._treehash = None
- self._subtrees = {}
- self._files = {}
-
- def _loadtree(self):
- """Loads _treehash into _subtrees and _files."""
- if self._files is not None: # _subtrees is also not None too here.
- return
- output = subprocess.check_output(['git', 'ls-tree', self._treehash]).split(b'\n')
- self._files = {}
- self._subtrees = {}
- for line in output:
- if not line:
- continue
- m = GIT_LSTREE_RE_LINE.match(line)
- mode, gittype, objecthash, name = m.groups()
- assert gittype == b'blob' or gittype == b'tree'
- assert name not in self._files and name not in self._subtrees
- if gittype == b'blob':
- self._files[name] = utils.GitFile(None, mode, objecthash)
- elif gittype == b'tree':
- self._subtrees[name] = LazyTree(objecthash)
-
- def _remove(self, components):
- """Removes components from self tree.
-
- Args:
- components: the path to remove, relative to self. Each element means
- one level of directory tree.
- """
- self._loadtree()
- self._treehash = None
- if len(components) == 1:
- del self._files[components[0]]
- return
-
- # Remove from subdirectory
- dirname, components = components[0], components[1:]
- subdir = self._subtrees[dirname]
- subdir._remove(components)
- if subdir.is_empty():
- del self._subtrees[dirname]
-
- def __delitem__(self, path):
- """Removes path from self tree.
-
- Args:
- path: the path to remove, relative to self.
- """
- components = path.split(b'/')
- self._remove(components)
-
- def _get(self, components):
- """Returns a file at components in utils.GitFile from self tree.
-
- Args:
- components: path in list instead of separated by /.
- """
- self._loadtree()
- if len(components) == 1:
- return self._files[components[0]]
-
- dirname, components = components[0], components[1:]
- return self._subtrees[dirname]._get(components)
-
- def __getitem__(self, path):
- """Returns a file at path in utils.GitFile from tree.
-
- Args:
- path: path of the file to read.
- """
- components = path.split(b'/')
- return self._get(components)
-
- def _set(self, components, f):
- """Adds or replace a file.
-
- Args:
- components: the path to set, relative to self. Each element means
- one level of directory tree.
- f: a utils.GitFile object.
- """
-
- self._loadtree()
- self._treehash = None
- if len(components) == 1:
- self._files[components[0]] = f
- return
-
- # Add to subdirectory
- dirname, components = components[0], components[1:]
- if dirname not in self._subtrees:
- self._subtrees[dirname] = LazyTree()
- self._subtrees[dirname]._set(components, f)
-
- def __setitem__(self, path, f):
- """Adds or replaces a file.
-
- Args:
- path: the path to set, relative to self
- f: a utils.GitFile object
- """
- assert f.path.endswith(path)
- components = path.split(b'/')
- self._set(components, f)
-
- def is_empty(self):
- """Returns if self is an empty tree."""
- return not self._subtrees and not self._files
-
- def hash(self):
- """Returns the hash of current tree object.
-
- If the object doesn't exist, create it.
- """
- if not self._treehash:
- self._treehash = self._mktree()
- return self._treehash
-
- def _mktree(self):
- """Recreates a tree object recursively.
-
- Lazily if subtree is unchanged.
- """
- keys = list(self._files.keys()) + list(self._subtrees.keys())
- mktree_input = []
- for name in sorted(keys):
- file = self._files.get(name)
- if file:
- mktree_input.append(b'%s blob %s\t%s' % (file.mode, file.id,
- name))
- else:
- mktree_input.append(
- b'040000 tree %s\t%s' % (self._subtrees[name].hash(), name))
- return subprocess.check_output(
- ['git', 'mktree'],
- input=b'\n'.join(mktree_input)).strip(b'\n')
diff --git a/libchrome_tools/uprev/reconnect_history.py b/libchrome_tools/uprev/reconnect_history.py
deleted file mode 100755
index bb6040c694..0000000000
--- a/libchrome_tools/uprev/reconnect_history.py
+++ /dev/null
@@ -1,333 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
-Utility to disconnect history of files from a branch, and reconnect with base on
-a different branch.
-"""
-
-import argparse
-import collections
-import subprocess
-import sys
-
-import filtered_utils
-import lazytree
-import utils
-
-
-class CommitMetadataFactory(dict):
- """Dict-like class to read commit metadata"""
-
- def __missing__(self, key):
- """Reads commit metadata if missing"""
- value = filtered_utils.get_metadata(key)
- self.__setitem__(key, value)
- return value
-
-
-def disconnect(source_commit, ref_commit):
- """Creates a commit that disconnects files from source_commit.
-
- All files existing in ref_commit will be removed from source_commit.
-
- Args:
- source_commit: commit hash to disconnect from.
- ref_commit: commit hash to be a file list reference.
- """
- source_files = utils.get_file_list(source_commit)
- ref_files = utils.get_file_list(ref_commit)
- ref_files_set = set(ref.path for ref in ref_files)
- kept_files = [ref for ref in source_files if ref.path not in ref_files_set]
- tree = utils.git_mktree(kept_files)
- return utils.git_commit(
- tree, [source_commit],
- message=b'Disconnect history from %s' % (source_commit.encode('ascii')))
-
-
-def connect_base(current_commit, base_commit):
- """Creates a merge commit that takes files from base_commit.
-
- Literally it's identical to git merge base_commit in current_commit.
-
- Args:
- current_commit: commit hashes on where to commit to.
- base_commit: commit hashes contains file histories.
- """
- current_files = utils.get_file_list(current_commit)
- base_files = utils.get_file_list(base_commit)
- tree = utils.git_mktree(current_files + base_files)
- return utils.git_commit(
- tree, [current_commit, base_commit],
- message=b'Connect history with base %s' % (base_commit.encode('ascii')))
-
-
-def blame_files(commithash, files):
- """Blames files on givven commithash"""
- blames = {}
- for path in files:
- blames[path] = utils.git_blame(commithash, path)
- return blames
-
-
-def search_blame_line(blames, amend_commits, target_commit_hash):
- """Searches blames matching target_commit_hash in amend_commits
-
- Returns a map from file path to a list of tuple, each tuple has
- len(amend_commits) + 1 elements. 0-th element is the line in blames. and
- 1st to n-th element are corresponding lines in amend_commits blaems.
-
- Args:
- blames: a dict from path to list of GitBlameLine, for files blamed on
- target_commit_hash.
- amend_commits: a list of commit hashes to provide actual history.
- target_commit_hash: commit hash that blames are blaemd on.
- """
- blames_combined = {}
- for blame_file_path, blame_file in blames.items():
- blames_amend = [
- utils.git_blame(commit, blame_file_path) for commit in amend_commits
- ]
- blames_combined[blame_file_path] = [
- blame_combined for blame_combined in zip(blame_file, *blames_amend)
- if blame_combined[0].commit == target_commit_hash
- ]
- return blames_combined
-
-
-def get_track_from_blames(blames_combined, virtual_goal_commit, amend_commits,
- commit_choice_cache, commit_msg_cache):
- """Blames diffs and locate the amend commits.
-
- Returns a tuple containing:
- - a set of commit hashes in amend_commits tree;
- - a line-by-line mapping for files in diff to commit hashes in
- amend_commits tree of diffed lines.
-
- Args:
- blames_combined: a map from path to a list of tuple. each tuple reflect
- one line, and has len(amend_commits)+1 elements. See more details in
- search_blame_line.
- virtual_goal_commit: a commit that contains no useful history for diffs.
- amend_commits: list of HEAD commit hashes that refers to tree that can
- amend the diffs.
- commit_choice_cache: caches user choice on which amend commit to use.
- commit_msg_cache: caches commit metadata.
- """
- blame_untracked_lines = {}
- commits_to_track = set()
-
- for blame_file_path, blame_lines in blames_combined.items():
- blame_untracked_lines[blame_file_path] = []
- for blame_line in blame_lines:
- original_commits = tuple(
- blame_amend.commit for blame_amend in list(blame_line)[1:])
- chosen = commit_choice_cache.get(original_commits)
- if chosen is None:
- for idx, original_commit in enumerate(original_commits):
- print('%d: %s' % (idx,
- commit_msg_cache[original_commit].title))
- # No validation on user_choice since no untrusted user.
- # Also the developer can rerun if entered wrongly by accident.
- user_choice = int(input('Choose patch: '))
- chosen = original_commits[user_choice]
- commit_choice_cache[original_commits] = chosen
- commits_to_track.add(chosen)
- blame_untracked_lines[blame_file_path].append((blame_line[0],
- chosen))
-
- return commits_to_track, blame_untracked_lines
-
-
-def reconstruct_file(blame_goal, blame_base, lines_to_reconstruct,
- virtual_goal_commit):
- """Reconstrucs a file to reflect changes in lines_to_reconstruct.
-
- Takes lines to blame_base, and blame_goal it belongs lines_to_reconstruct.
- It also deletes removed lines nearby.
-
- Returns a binary for the new file content.
-
- Args:
- blame_goal: a list of utils.GitBlameLine blaming the file on
- virtual_goal_commit.
- blame_base: a list of utils.GitBlameLine blaming the file on last
- commited commit.
- lines_to_reconstruct: only to reconstruct these lines, instead of
- everything in blame_goal. It is represented in a list of
- GitBlameLine.
- virtual_goal_commit: commit hash where blame_goal is based on.
- """
- idx_base, idx_goal = 0, 0
- reconstructed_file = []
-
- print('Changed lines are', [line.data for line in lines_to_reconstruct])
- line_iter = iter(lines_to_reconstruct)
- line = next(line_iter, None)
- while idx_base < len(blame_base) or idx_goal< len(blame_goal):
- # Both sides are idendical. We can't compare blame_base, and line
- # directly due to blame commit difference could end up different lineno.
- if (idx_base < len(blame_base) and
- blame_base[idx_base].data == blame_goal[idx_goal].data and
- blame_base[idx_base].commit == blame_goal[idx_goal].commit):
- # We append this line if both sides are identical.
- reconstructed_file.append(blame_base[idx_base].data)
- idx_base += 1
- idx_goal += 1
- should_skip_base = False
- elif line and blame_goal[idx_goal] == line:
- # We append the line from goal, if blame_goal[idx_goal] is the line
- # we're interested in.
- reconstructed_file.append(line.data)
- line = next(line_iter, None)
- idx_goal += 1
- should_skip_base = True
- elif blame_goal[idx_goal].commit == virtual_goal_commit:
- # We skip the line from goal, if the change in not in the commit
- # we're interested. Thus, changed lines in other commits will not be
- # reflected.
- idx_goal += 1
- else:
- # We should skip base if we just appended some lines from goal.
- # This would treat modified lines and append first and skip later.
- # If we didn't append something from goal, lines from base should be
- # preserved because the modified lines are not in the commit we're
- # currently interested in.
- if not should_skip_base:
- reconstructed_file.append(blame_base[idx_base].data)
- idx_base += 1
-
- return b''.join([line + b'\n' for line in reconstructed_file])
-
-
-def reconstruct_files(track_commit, blame_untracked_lines, blames,
- current_base_commit, virtual_goal_commit):
- """Reconstructs files to reflect changes in track_commit.
-
- Returns a map from file path to file content for reconstructed files.
-
- Args:
- track_commit: commit hashes to track, and reconstruct from.
- blame_untracked_lines: a line-by-line mapping regarding selected amend
- commits for diffs. see get_track_from_blames for more.
- blames: a map from filename to list of utils.GitBlameLine
- current_base_commit: commit hashes for HEAD of base that contains base
- history + already committed amend history.
- virtual_goal_commit: commit hash for one giant commit that has no
- history. virtual_goal_commit is one commit ahead of
- current_base_commit.
- """
- lines_to_track = collections.defaultdict(list)
- for file, lines in blame_untracked_lines.items():
- for line in lines:
- if line[1] == track_commit:
- lines_to_track[file].append(line[0])
- constructed_files = {}
- for current_file, current_file_lines in lines_to_track.items():
- print('Reconstructing', current_file, 'for', track_commit)
- blame_base = utils.git_blame(current_base_commit, current_file)
- constructed_files[current_file] = reconstruct_file(
- blames[current_file], blame_base, current_file_lines,
- virtual_goal_commit)
- return constructed_files
-
-
-def main():
- # Init args
- parser = argparse.ArgumentParser(description='Reconnect git history')
- parser.add_argument(
- 'disconnect_from',
- metavar='disconnect_from',
- type=str,
- nargs=1,
- help='disconnect history from this commit')
- parser.add_argument(
- 'base_commit',
- metavar='base_commit',
- type=str,
- nargs=1,
- help='base commit to use the history')
- parser.add_argument(
- 'amend_commits',
- metavar='amend_commits',
- type=str,
- nargs='+',
- help='commits to amend histories from base_commit')
-
- arg = parser.parse_args(sys.argv[1:])
- empty_commit = disconnect(arg.disconnect_from[0], arg.base_commit[0])
- connected_base = connect_base(empty_commit, arg.base_commit[0])
-
- commit_msg_cache = CommitMetadataFactory()
- commit_choice_cache = {}
- last_commit = connected_base
- # In each iteration of the loop, it
- # - re-create the new goal commit, (base + committed history + (one giant)
- # uncommited history).
- # - blame on new goal commit and tot of amend commits. map line-by-line
- # from uncommited to past histories.
- # - choose one of the past commits, reconstruct files to reflect changes in
- # that commit, and create a new commits.
- # last_commit, commit_msg_cache, commit_choice_cache will be persistent
- # across iteratins.
- while True:
- # One commit is processed per iteration.
-
- # Create virtual target commit, and its diff.
- virtual_goal = utils.git_commit(arg.disconnect_from[0] + '^{tree}',
- [last_commit])
- diffs = utils.git_difftree(None, virtual_goal)
- if not diffs:
- print('No diffs are found between %s and goal.' %
- (last_commit.decode('ascii'),))
- break
-
- blames = blame_files(virtual_goal,
- [diff.file.path for diff in diffs])
- blames_combined = search_blame_line(blames, arg.amend_commits,
- virtual_goal)
-
- commits_to_track, blame_untracked_lines = get_track_from_blames(
- blames_combined, virtual_goal, arg.amend_commits,
- commit_choice_cache, commit_msg_cache)
- if not commits_to_track:
- print('no commits to track, stopping')
- break
-
- # Stablely choose one commit from commits_to_track, and reconstruct it.
- track_commit = min(commits_to_track)
- print('Reconstructing commit %s: %s' %
- (track_commit, commit_msg_cache[track_commit].title))
- constructed_files = reconstruct_files(track_commit,
- blame_untracked_lines, blames,
- last_commit, virtual_goal)
-
- # Mktree and commit with re-constructed_files.
- tree = lazytree.LazyTree(filtered_utils.get_metadata(last_commit).tree)
- for filename, filedata in constructed_files.items():
- blob = subprocess.check_output(
- ['git', 'hash-object', '-w', '/dev/stdin'],
- input=filedata).strip()
- tree[filename] = utils.GitFile(filename, tree[filename].mode, blob)
- meta = commit_msg_cache[track_commit]
- last_commit = utils.git_commit(
- tree.hash(), [last_commit],
- (meta.message + b'\n(Reconstructed from ' + track_commit + b')\n'),
- dict(
- GIT_AUTHOR_NAME=meta.authorship.name,
- GIT_AUTHOR_EMAIL=meta.authorship.email,
- GIT_AUTHOR_DATE=b' '.join(
- [meta.authorship.time, meta.authorship.timezone])))
- print('Reconstructed as', last_commit)
- # Make last commit for history reconstruction.
- print(
- utils.git_commit(
- filtered_utils.get_metadata(arg.disconnect_from[0]).tree,
- [last_commit],
- b'Finished history reconstruction\n\nRemoving unnecessary lines\n'))
-
-
-if __name__ == '__main__':
- main()
diff --git a/libchrome_tools/uprev/utils.py b/libchrome_tools/uprev/utils.py
deleted file mode 100644
index cf3c2a4b58..0000000000
--- a/libchrome_tools/uprev/utils.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# Copyright 2020 The Chromium OS Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Provide some basic utility functions for libchrome tools."""
-
-import collections
-import enum
-import os
-import re
-import subprocess
-
-class DiffOperations(enum.Enum):
- """
- Describes operations on files
- """
- ADD = 1
- DEL = 2
- REP = 3
-
-GitFile = collections.namedtuple(
- 'GitFile',
- ['path', 'mode', 'id',]
-)
-
-GitDiffTree = collections.namedtuple(
- 'GitDiffTree',
- ['op', 'file',]
-)
-
-GitBlameLine = collections.namedtuple(
- 'GitBlameLine',
- ['data', 'commit', 'old_line', 'new_line',]
-)
-
-
-GIT_DIFFTREE_RE_LINE = re.compile(rb'^:([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)\t(.*)$')
-
-
-def _reverse(files):
- """Creates a reverse map from file path to file.
-
- Asserts if a file path exist only once in files.
-
- Args:
- files: list of files.
- """
- files_map = {}
- for i in files:
- if i.path in files_map:
- assert i.path not in files_map
- files_map[i.path] = i
- return files_map
-
-
-def get_file_list(commit):
- """Gets a list of the files of the commit.
-
- Args:
- commit: commit hash or refs.
- """
-
- output = subprocess.check_output(['git', 'ls-tree', '-r',
- commit]).split(b'\n')
- files = []
- # Line looks like
- # mode<space>type<space>id<tab>file name
- # split by tab first, and by space.
- re_line = re.compile(rb'^([^ ]*) ([^ ]*) ([^ ]*)\t(.*)$')
- for line in output:
- if not line:
- continue
- match = re_line.match(line)
- mode, gittype, blobhash, path = match.groups()
- if gittype == b'commit':
- continue
- assert gittype == b'blob', '%s\n\n%s' % (str(output), line)
- files.append(GitFile(path, mode, blobhash))
- return files
-
-
-def git_difftree(treeish1, treeish2):
- """Gets diffs between treeish1 and treeish2.
-
- It returns a list of GitDiffTree, each GitDiffTree contains an ADD, DEL or
- REP operation and a GitFile.
-
- Args:
- treeish1, treeish2: treeish to diff.
- treeish can be tree hash or commit hash. If treeish1 is None, it
- generate difftrees with its parent.
- """
- out = None
- if treeish1 is None:
- # Remove first line since it's tree hash printed.
- out = subprocess.check_output(['git', 'diff-tree', '-r',
- treeish2]).split(b'\n')[1:]
- else:
- out = subprocess.check_output(['git', 'diff-tree', '-r',
- treeish1, treeish2]).split(b'\n')
- diff = []
- for line in out:
- if not line:
- continue
- match = GIT_DIFFTREE_RE_LINE.match(line)
- oldmode, newmode, oldhash, newhash, typeofchange, path = match.groups()
- assert typeofchange in b'ADMT', (treeish1, treeish2, line)
- if typeofchange == b'A':
- diff.append(
- GitDiffTree(DiffOperations.ADD,
- GitFile(path, newmode, newhash)))
- elif typeofchange == b'D':
- diff.append(
- GitDiffTree(DiffOperations.DEL,
- GitFile(path, oldmode, oldhash)))
- elif typeofchange == b'M' or typeofchange == b'T':
- diff.append(
- GitDiffTree(DiffOperations.REP,
- GitFile(path, newmode, newhash)))
- else:
- raise Exception(b"Unsupported type: " + line)
- return diff
-
-
-def gen_op(current_files, target_files):
- """Returns an operation list to convert files to target_files.
-
- Generates list of operations (add/delete/replace files) if we want to
- convert current_files in directory to target_files
-
- Args:
- current_files: list of files in current directory.
- target_files: list of files we want it to be in current directory.
- """
- current_file_map = _reverse(current_files)
- target_file_map = _reverse(target_files)
- op = []
- for i in sorted(current_file_map):
- if i not in target_file_map:
- op.append((DiffOperations.DEL, current_file_map[i]))
- for i in sorted(target_file_map):
- if i in current_file_map and current_file_map[i] != target_file_map[i]:
- op.append((DiffOperations.REP, target_file_map[i]))
- elif i not in current_file_map:
- op.append((DiffOperations.ADD, target_file_map[i]))
- return op
-
-
-def git_mktree(files):
- """Returns a git tree object hash after mktree recursively."""
-
- def recursive_default_dict():
- return collections.defaultdict(recursive_default_dict)
-
- tree = recursive_default_dict()
- for f in files:
- directories = f.path.split(b'/')
- directories, filename = directories[:-1], directories[-1]
- cwd = tree
- for directory in directories:
- # If cwd is a GitFile, which means a file and a directory shares the
- # same name.
- assert type(cwd) == collections.defaultdict
- cwd = cwd[directory]
- assert filename not in cwd
- cwd[filename] = f
-
- def _mktree(prefix, node):
- objects = []
- for name, val in node.items():
- prefix.append(name)
- if isinstance(val, collections.defaultdict):
- tree_hash = _mktree(prefix, val)
- objects.append(b'\t'.join(
- [b' '.join([b'040000', b'tree', tree_hash]), name]))
- else:
- path = b'/'.join(prefix)
- assert path == val.path, '%s\n%s' % (str(path), str(val.path))
- objects.append(b'\t'.join(
- [b' '.join([val.mode, b'blob', val.id]), name]))
- prefix.pop(-1)
- return subprocess.check_output(['git', 'mktree'],
- input=b'\n'.join(objects)).strip(b'\n')
-
- return _mktree([], tree)
-
-
-def git_commit(tree, parents, message=b"", extra_env={}):
- """Creates a commit.
-
- Args:
- tree: tree object id.
- parents: parent commit id.
- message: commit message.
- extra_env: extra environment variables passed to git.
- """
- parent_args = []
- for parent in parents:
- parent_args.append('-p')
- parent_args.append(parent)
- return subprocess.check_output(
- ['git', 'commit-tree', tree] + parent_args,
- input=message,
- env=dict(os.environ, **extra_env)).strip(b'\n')
-
-
-def git_revlist(from_commit, to_commit):
- """Returns a list of commits and their parents.
-
- Each item in the list is a tuple, containing two elements.
- The first element is the commit hash; the second element is a list of parent
- commits' hash.
- """
-
- commits = []
- ret = None
- if from_commit is None:
- ret = subprocess.check_output(['git', 'rev-list', to_commit,
- '--topo-order', '--parents'])
- else:
- # b'...'.join() later requires all variable to be binary-typed.
- if type(from_commit) == str:
- from_commit = from_commit.encode('ascii')
- if type(to_commit) == str:
- to_commit = to_commit.encode('ascii')
- commit_range = b'...'.join([from_commit, to_commit])
- ret = subprocess.check_output(['git', 'rev-list', commit_range,
- '--topo-order', '--parents'])
- ret = ret.split(b'\n')
- for line in ret:
- if not line:
- continue
- hashes = line.split(b' ')
- commits.append((hashes[0], hashes[1:]))
- return list(reversed(commits))
-
-
-def git_blame(commit, filepath):
- """Returns line-by-line git blame.
-
- Return value is represented by a list of GitBlameLine.
-
- Args:
- commit: commit hash to blame at.
- filepath: file to blame.
- """
- output = subprocess.check_output(['git', 'blame', '-p',
- commit, filepath])
- commit, old_line, new_line = None, None, None
- blames = []
- COMMIT_LINE_PREFIX = re.compile(b'^[0-9a-f]* ')
- for line in output.split(b'\n'):
- if not line:
- continue
- if line[0] == ord(b'\t'):
- assert commit != None
- blames.append(GitBlameLine(line[1:], commit, old_line, new_line))
- commit, old_line, new_line = None, None, None
- elif COMMIT_LINE_PREFIX.match(line):
- commit, old_line, new_line = line.split(b' ', 3)[0:3]
- return blames
diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn
new file mode 100644
index 0000000000..f6cd5b6c6c
--- /dev/null
+++ b/mojo/BUILD.gn
@@ -0,0 +1,69 @@
+# 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.
+
+import("//build/config/ui.gni")
+import("//testing/test.gni")
+
+group("mojo") {
+ # Meta-target, don't link into production code.
+ testonly = true
+ deps = [
+ ":tests",
+ ]
+
+ if (!(is_linux && current_cpu == "x86")) {
+ deps += [ "//mojo/public" ]
+ }
+
+ if (is_android) {
+ deps += [ "//mojo/public/java/system" ]
+ }
+
+ deps += [ "//services/service_manager:all" ]
+}
+
+group("tests") {
+ testonly = true
+ deps = [
+ ":mojo_perftests",
+ ":mojo_unittests",
+ "//ipc:ipc_tests",
+ "//services/service_manager/tests",
+ ]
+}
+
+test("mojo_unittests") {
+ deps = [
+ "//mojo/core:test_sources",
+ "//mojo/core/test:run_all_unittests",
+ "//mojo/public/cpp/base:tests",
+ "//mojo/public/cpp/bindings/tests",
+ "//mojo/public/cpp/platform/tests",
+ "//mojo/public/cpp/system/tests",
+ ]
+}
+
+test("mojo_perftests") {
+ deps = [
+ "//mojo/core/test:run_all_perftests",
+ "//mojo/core/test:test_support",
+ "//mojo/public/c/system/tests:perftests",
+ "//mojo/public/cpp/bindings/tests:perftests",
+ ]
+
+ if (!is_ios) {
+ sources = [
+ "//mojo/core/message_pipe_perftest.cc",
+ ]
+
+ deps += [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core:embedder_internal",
+ "//mojo/core:test_utils",
+ "//mojo/core/embedder",
+ "//testing/gtest",
+ ]
+ }
+}
diff --git a/mojo/PRESUBMIT.py b/mojo/PRESUBMIT.py
new file mode 100644
index 0000000000..2766055a5d
--- /dev/null
+++ b/mojo/PRESUBMIT.py
@@ -0,0 +1,44 @@
+# 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.
+
+"""Presubmit script for mojo
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+import os.path
+
+def CheckChangeOnUpload(input_api, output_api):
+ # Additional python module paths (we're in src/mojo/); not everyone needs
+ # them, but it's easiest to add them to everyone's path.
+ # For ply and jinja2:
+ third_party_path = os.path.join(
+ input_api.PresubmitLocalPath(), "..", "third_party")
+ # For the bindings generator:
+ mojo_public_bindings_pylib_path = os.path.join(
+ input_api.PresubmitLocalPath(), "public", "tools", "bindings", "pylib")
+ # For the python bindings:
+ mojo_python_bindings_path = os.path.join(
+ input_api.PresubmitLocalPath(), "public", "python")
+ # TODO(vtl): Don't lint these files until the (many) problems are fixed
+ # (possibly by deleting/rewriting some files).
+ temporary_black_list = input_api.DEFAULT_BLACK_LIST + \
+ (r".*\bpublic[\\\/]tools[\\\/]bindings[\\\/]pylib[\\\/]mojom[\\\/]"
+ r"generate[\\\/].+\.py$",
+ r".*\bpublic[\\\/]tools[\\\/]bindings[\\\/]generators[\\\/].+\.py$",
+ r".*\bspy[\\\/]ui[\\\/].+\.py$",
+ r".*\btools[\\\/]pylib[\\\/]transitive_hash\.py$",
+ r".*\btools[\\\/]test_runner\.py$")
+
+ results = []
+ pylint_extra_paths = [
+ third_party_path,
+ mojo_public_bindings_pylib_path,
+ mojo_python_bindings_path,
+ ]
+ results += input_api.canned_checks.RunPylint(
+ input_api, output_api, extra_paths_list=pylint_extra_paths,
+ black_list=temporary_black_list)
+ return results
diff --git a/mojo/core/BUILD.gn b/mojo/core/BUILD.gn
new file mode 100644
index 0000000000..49a537bcb7
--- /dev/null
+++ b/mojo/core/BUILD.gn
@@ -0,0 +1,325 @@
+# Copyright 2018 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.
+
+import("//build/config/nacl/config.gni")
+import("//testing/test.gni")
+
+component("embedder_internal") {
+ output_name = "mojo_core_embedder_internal"
+ public_deps = [
+ ":impl_for_embedder",
+ ]
+ visibility = [
+ ":test_sources",
+ "//mojo:*",
+ "//mojo/core/embedder",
+ ]
+}
+
+# Bits of the EDK library which do not depend on public API linkage. It is
+# not allowed for this target or any of its transitive dependencies to depend
+# on anything under //mojo/public beyond strict C type definitions.
+#
+# This is templated because it's consumed by both the ":embedder_internal"
+# component library as well as the ":mojo_core" shared library. In the former
+# case we want to export symbols, but in the latter case we don't. The template
+# stamps out two nearly identical targets which differ only in what symbols they
+# export.
+template("core_impl_source_set") {
+ source_set(target_name) {
+ if (invoker.for_shared_library) {
+ visibility = [ ":shared_library" ]
+ } else {
+ visibility = [ ":embedder_internal" ]
+ }
+
+ public = [
+ "channel.h",
+ "configuration.h",
+ "connection_params.h",
+ "core.h",
+ "data_pipe_consumer_dispatcher.h",
+ "data_pipe_control_message.h",
+ "data_pipe_producer_dispatcher.h",
+ "dispatcher.h",
+ "embedder/configuration.h",
+ "embedder/process_error_callback.h",
+ "entrypoints.h",
+ "handle_signals_state.h",
+ "handle_table.h",
+ "invitation_dispatcher.h",
+ "message_pipe_dispatcher.h",
+ "node_controller.h",
+ "options_validation.h",
+ "platform_handle_dispatcher.h",
+ "platform_handle_utils.h",
+ "platform_shared_memory_mapping.h",
+ "request_context.h",
+ "scoped_process_handle.h",
+ "shared_buffer_dispatcher.h",
+ "user_message_impl.h",
+ ]
+
+ sources = [
+ "atomic_flag.h",
+ "broker.h",
+ "broker_win.cc",
+ "channel.cc",
+ "channel_win.cc",
+ "configuration.cc",
+ "connection_params.cc",
+ "core.cc",
+ "data_pipe_consumer_dispatcher.cc",
+ "data_pipe_control_message.cc",
+ "data_pipe_producer_dispatcher.cc",
+ "dispatcher.cc",
+ "entrypoints.cc",
+ "handle_table.cc",
+ "invitation_dispatcher.cc",
+ "message_pipe_dispatcher.cc",
+ "node_channel.cc",
+ "node_channel.h",
+ "node_controller.cc",
+ "platform_handle_dispatcher.cc",
+ "platform_handle_in_transit.cc",
+ "platform_handle_in_transit.h",
+ "platform_handle_utils.cc",
+ "platform_shared_memory_mapping.cc",
+ "request_context.cc",
+ "scoped_process_handle.cc",
+ "shared_buffer_dispatcher.cc",
+ "user_message_impl.cc",
+ "watch.cc",
+ "watch.h",
+ "watcher_dispatcher.cc",
+ "watcher_dispatcher.h",
+ "watcher_set.cc",
+ "watcher_set.h",
+ ]
+
+ public_deps = [
+ "//base",
+ "//mojo/core/ports",
+ "//mojo/public/c/system:headers",
+ "//mojo/public/cpp/platform",
+ ]
+
+ if (is_fuchsia) {
+ sources += [ "channel_fuchsia.cc" ]
+
+ public_deps += [ "//third_party/fuchsia-sdk:fdio" ]
+ }
+
+ if (is_posix) {
+ if (!is_nacl || is_nacl_nonsfi) {
+ sources += [
+ "broker_posix.cc",
+ "channel_posix.cc",
+ ]
+ }
+ }
+
+ if (is_mac && !is_ios) {
+ sources += [
+ "mach_port_relay.cc",
+ "mach_port_relay.h",
+ ]
+ }
+
+ if (!is_nacl || is_nacl_nonsfi) {
+ sources += [
+ "broker_host.cc",
+ "broker_host.h",
+ ]
+ }
+
+ defines = []
+ if (invoker.for_shared_library) {
+ defines += [ "MOJO_CORE_SHARED_LIBRARY" ]
+ } else {
+ defines += [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ]
+ }
+
+ deps = []
+ if (is_android) {
+ deps += [ "//third_party/ashmem" ]
+ }
+ if (!is_nacl) {
+ deps += [ "//crypto" ]
+ }
+
+ if (is_win) {
+ cflags = [ "/wd4324" ] # Structure was padded due to __declspec(align()),
+ # which is uninteresting.
+ }
+
+ # Use target_os == "chromeos" instead of is_chromeos because we need to
+ # build NaCl targets (i.e. IRT) for ChromeOS the same as the rest of ChromeOS.
+ if (is_android || target_os == "chromeos") {
+ defines += [ "MOJO_CORE_LEGACY_PROTOCOL" ]
+ }
+ }
+}
+
+core_impl_source_set("impl_for_embedder") {
+ for_shared_library = false
+}
+
+if (is_chromeos || is_linux || is_android || is_win) {
+ core_impl_source_set("impl_for_shared_library") {
+ for_shared_library = true
+ }
+
+ shared_library("shared_library") {
+ output_name = "mojo_core"
+ sources = [
+ "mojo_core.cc",
+ ]
+ defines = [ "MOJO_CORE_SHARED_LIBRARY" ]
+ deps = [
+ ":impl_for_shared_library",
+ "//mojo/public/c/system:headers",
+ ]
+ if (is_win) {
+ inputs = [
+ "mojo_core.def",
+ ]
+ ldflags = [ "/DEF:" + rebase_path("mojo_core.def", root_build_dir) ]
+ } else {
+ configs += [ ":export_only_thunks_api" ]
+ }
+ }
+
+ if (is_chromeos) {
+ if (target_cpu == "arm" || target_cpu == "arm64") {
+ android32_toolchain = "android_clang_arm"
+ android64_toolchain = "android_clang_arm64"
+ } else {
+ android32_toolchain = "android_clang_x86"
+ android64_toolchain = "android_clang_x64"
+ }
+
+ group("shared_libraries_for_arc") {
+ deps = [
+ ":shared_library_arc32",
+ ":shared_library_arc64",
+ ]
+ }
+
+ copy("shared_library_arc32") {
+ sources = [
+ "${root_out_dir}/${android32_toolchain}/libmojo_core.so",
+ ]
+ outputs = [
+ "${root_out_dir}/libmojo_core_arc32.so",
+ ]
+ deps = [
+ ":shared_library(//build/toolchain/android:${android32_toolchain})",
+ ]
+ }
+
+ copy("shared_library_arc64") {
+ sources = [
+ "${root_out_dir}/${android64_toolchain}/libmojo_core.so",
+ ]
+ outputs = [
+ "${root_out_dir}/libmojo_core_arc64.so",
+ ]
+ deps = [
+ ":shared_library(//build/toolchain/android:${android64_toolchain})",
+ ]
+ }
+ }
+
+ config("export_only_thunks_api") {
+ ldflags = [ "-Wl,--version-script=" +
+ rebase_path("//mojo/core/export_only_thunks_api.lst",
+ root_build_dir) ]
+ }
+
+ if (is_chromeos || is_linux || is_win) {
+ test("mojo_core_unittests") {
+ sources = [
+ "mojo_core_unittest.cc",
+ "run_all_core_unittests.cc",
+ ]
+
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/public/c/system",
+ "//testing/gtest",
+ ]
+
+ data_deps = [
+ ":shared_library",
+ ]
+ }
+ }
+}
+
+source_set("test_utils") {
+ testonly = true
+
+ sources = [
+ "test_utils.cc",
+ "test_utils.h",
+ ]
+
+ public_deps = [
+ "//mojo/public/c/system",
+ "//mojo/public/cpp/system",
+ ]
+
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/test:test_support",
+ "//testing/gtest:gtest",
+ ]
+}
+
+source_set("test_sources") {
+ testonly = true
+ sources = [
+ "channel_unittest.cc",
+ "core_test_base.cc",
+ "core_test_base.h",
+ "core_unittest.cc",
+ "embedder_unittest.cc",
+ "handle_table_unittest.cc",
+ "message_pipe_unittest.cc",
+ "message_unittest.cc",
+ "options_validation_unittest.cc",
+ "platform_handle_dispatcher_unittest.cc",
+ "quota_unittest.cc",
+ "shared_buffer_dispatcher_unittest.cc",
+ "shared_buffer_unittest.cc",
+ "signals_unittest.cc",
+ "trap_unittest.cc",
+ ]
+
+ if (!is_ios) {
+ sources += [
+ "data_pipe_unittest.cc",
+ "invitation_unittest.cc",
+ "multiprocess_message_pipe_unittest.cc",
+ "platform_wrapper_unittest.cc",
+ ]
+ }
+
+ deps = [
+ ":test_utils",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core:embedder_internal",
+ "//mojo/core/embedder",
+ "//mojo/core/ports:tests",
+ "//mojo/core/test:run_all_unittests",
+ "//mojo/core/test:test_support",
+ "//mojo/public/cpp/system",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/mojo/core/broker_win.cc b/mojo/core/broker_win.cc
new file mode 100644
index 0000000000..3ebc8839ce
--- /dev/null
+++ b/mojo/core/broker_win.cc
@@ -0,0 +1,162 @@
+// Copyright 2016 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 <windows.h>
+
+#include <limits>
+#include <utility>
+
+#include "base/debug/alias.h"
+#include "base/memory/platform_shared_memory_region.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_piece.h"
+#include "mojo/core/broker.h"
+#include "mojo/core/broker_messages.h"
+#include "mojo/core/channel.h"
+#include "mojo/core/platform_handle_utils.h"
+#include "mojo/public/cpp/platform/named_platform_channel.h"
+
+namespace mojo {
+namespace core {
+
+namespace {
+
+// 256 bytes should be enough for anyone!
+const size_t kMaxBrokerMessageSize = 256;
+
+bool TakeHandlesFromBrokerMessage(Channel::Message* message,
+ size_t num_handles,
+ PlatformHandle* out_handles) {
+ if (message->num_handles() != num_handles) {
+ DLOG(ERROR) << "Received unexpected number of handles in broker message";
+ return false;
+ }
+
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
+ DCHECK_EQ(handles.size(), num_handles);
+ DCHECK(out_handles);
+
+ for (size_t i = 0; i < num_handles; ++i)
+ out_handles[i] = handles[i].TakeHandle();
+ return true;
+}
+
+Channel::MessagePtr WaitForBrokerMessage(HANDLE pipe_handle,
+ BrokerMessageType expected_type) {
+ char buffer[kMaxBrokerMessageSize];
+ DWORD bytes_read = 0;
+ BOOL result = ::ReadFile(pipe_handle, buffer, kMaxBrokerMessageSize,
+ &bytes_read, nullptr);
+ if (!result) {
+ // The pipe may be broken if the browser side has been closed, e.g. during
+ // browser shutdown. In that case the ReadFile call will fail and we
+ // shouldn't continue waiting.
+ PLOG(ERROR) << "Error reading broker pipe";
+ return nullptr;
+ }
+
+ Channel::MessagePtr message =
+ Channel::Message::Deserialize(buffer, static_cast<size_t>(bytes_read));
+ if (!message || message->payload_size() < sizeof(BrokerMessageHeader)) {
+ LOG(ERROR) << "Invalid broker message";
+
+ base::debug::Alias(&buffer[0]);
+ base::debug::Alias(&bytes_read);
+ CHECK(false);
+ return nullptr;
+ }
+
+ const BrokerMessageHeader* header =
+ reinterpret_cast<const BrokerMessageHeader*>(message->payload());
+ if (header->type != expected_type) {
+ LOG(ERROR) << "Unexpected broker message type";
+
+ base::debug::Alias(&buffer[0]);
+ base::debug::Alias(&bytes_read);
+ CHECK(false);
+ return nullptr;
+ }
+
+ return message;
+}
+
+} // namespace
+
+Broker::Broker(PlatformHandle handle) : sync_channel_(std::move(handle)) {
+ CHECK(sync_channel_.is_valid());
+ Channel::MessagePtr message = WaitForBrokerMessage(
+ sync_channel_.GetHandle().Get(), BrokerMessageType::INIT);
+
+ // If we fail to read a message (broken pipe), just return early. The inviter
+ // handle will be null and callers must handle this gracefully.
+ if (!message)
+ return;
+
+ PlatformHandle endpoint_handle;
+ if (TakeHandlesFromBrokerMessage(message.get(), 1, &endpoint_handle)) {
+ inviter_endpoint_ = PlatformChannelEndpoint(std::move(endpoint_handle));
+ } else {
+ // If the message has no handles, we expect it to carry pipe name instead.
+ const BrokerMessageHeader* header =
+ static_cast<const BrokerMessageHeader*>(message->payload());
+ CHECK_GE(message->payload_size(),
+ sizeof(BrokerMessageHeader) + sizeof(InitData));
+ const InitData* data = reinterpret_cast<const InitData*>(header + 1);
+ CHECK_EQ(message->payload_size(),
+ sizeof(BrokerMessageHeader) + sizeof(InitData) +
+ data->pipe_name_length * sizeof(base::char16));
+ const base::char16* name_data =
+ reinterpret_cast<const base::char16*>(data + 1);
+ CHECK(data->pipe_name_length);
+ inviter_endpoint_ = NamedPlatformChannel::ConnectToServer(
+ base::StringPiece16(name_data, data->pipe_name_length).as_string());
+ }
+}
+
+Broker::~Broker() {}
+
+PlatformChannelEndpoint Broker::GetInviterEndpoint() {
+ return std::move(inviter_endpoint_);
+}
+
+base::WritableSharedMemoryRegion Broker::GetWritableSharedMemoryRegion(
+ size_t num_bytes) {
+ base::AutoLock lock(lock_);
+ BufferRequestData* buffer_request;
+ Channel::MessagePtr out_message = CreateBrokerMessage(
+ BrokerMessageType::BUFFER_REQUEST, 0, 0, &buffer_request);
+ buffer_request->size = base::checked_cast<uint32_t>(num_bytes);
+ DWORD bytes_written = 0;
+ BOOL result =
+ ::WriteFile(sync_channel_.GetHandle().Get(), out_message->data(),
+ static_cast<DWORD>(out_message->data_num_bytes()),
+ &bytes_written, nullptr);
+ if (!result ||
+ static_cast<size_t>(bytes_written) != out_message->data_num_bytes()) {
+ PLOG(ERROR) << "Error sending sync broker message";
+ return base::WritableSharedMemoryRegion();
+ }
+
+ PlatformHandle handle;
+ Channel::MessagePtr response = WaitForBrokerMessage(
+ sync_channel_.GetHandle().Get(), BrokerMessageType::BUFFER_RESPONSE);
+ if (response && TakeHandlesFromBrokerMessage(response.get(), 1, &handle)) {
+ BufferResponseData* data;
+ if (!GetBrokerMessageData(response.get(), &data))
+ return base::WritableSharedMemoryRegion();
+ return base::WritableSharedMemoryRegion::Deserialize(
+ base::subtle::PlatformSharedMemoryRegion::Take(
+ CreateSharedMemoryRegionHandleFromPlatformHandles(std::move(handle),
+ PlatformHandle()),
+ base::subtle::PlatformSharedMemoryRegion::Mode::kWritable,
+ num_bytes,
+ base::UnguessableToken::Deserialize(data->guid_high,
+ data->guid_low)));
+ }
+
+ return base::WritableSharedMemoryRegion();
+}
+
+} // namespace core
+} // namespace mojo
diff --git a/mojo/core/channel_fuchsia.cc b/mojo/core/channel_fuchsia.cc
new file mode 100644
index 0000000000..4386b200b8
--- /dev/null
+++ b/mojo/core/channel_fuchsia.cc
@@ -0,0 +1,466 @@
+// Copyright 2017 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 "mojo/core/channel.h"
+
+#include <lib/fdio/limits.h>
+#include <lib/fdio/util.h>
+#include <lib/zx/channel.h>
+#include <lib/zx/handle.h>
+#include <zircon/processargs.h>
+#include <zircon/status.h>
+#include <zircon/syscalls.h>
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/containers/circular_deque.h"
+#include "base/files/scoped_file.h"
+#include "base/fuchsia/fuchsia_logging.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/message_loop/message_pump_for_io.h"
+#include "base/stl_util.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
+#include "mojo/core/platform_handle_in_transit.h"
+
+namespace mojo {
+namespace core {
+
+namespace {
+
+const size_t kMaxBatchReadCapacity = 256 * 1024;
+
+bool UnwrapPlatformHandle(PlatformHandleInTransit handle,
+ Channel::Message::HandleInfoEntry* info_out,
+ std::vector<PlatformHandleInTransit>* handles_out) {
+ DCHECK(handle.handle().is_valid());
+
+ if (!handle.handle().is_valid_fd()) {
+ *info_out = {0u, 0u};
+ handles_out->emplace_back(std::move(handle));
+ return true;
+ }
+
+ // Each FDIO file descriptor is implemented using one or more native resources
+ // and can be un-wrapped into a set of |handle| and |info| pairs, with |info|
+ // consisting of an FDIO-defined type & arguments (see zircon/processargs.h).
+ //
+ // We try to transfer the FD, but if that fails (for example if the file has
+ // already been dup()d into another FD) we may need to clone.
+ zx_handle_t handles[FDIO_MAX_HANDLES] = {};
+ uint32_t info[FDIO_MAX_HANDLES] = {};
+ zx_status_t result =
+ fdio_transfer_fd(handle.handle().GetFD().get(), 0, handles, info);
+ if (result > 0) {
+ // On success, the fd in |handle| has been transferred and is no longer
+ // valid. Release from the PlatformHandle to avoid close()ing an invalid
+ // an invalid handle.
+ handle.CompleteTransit();
+ } else if (result == ZX_ERR_UNAVAILABLE) {
+ // No luck, try cloning instead.
+ result = fdio_clone_fd(handle.handle().GetFD().get(), 0, handles, info);
+ }
+
+ if (result <= 0) {
+ ZX_DLOG(ERROR, result) << "fdio_transfer_fd("
+ << handle.handle().GetFD().get() << ")";
+ return false;
+ }
+ DCHECK_LE(result, FDIO_MAX_HANDLES);
+
+ // We assume here that only the |PA_HND_TYPE| of the |info| really matters,
+ // and that that is the same for all the underlying handles.
+ *info_out = {PA_HND_TYPE(info[0]), result};
+ for (int i = 0; i < result; ++i) {
+ DCHECK_EQ(PA_HND_TYPE(info[0]), PA_HND_TYPE(info[i]));
+ DCHECK_EQ(0u, PA_HND_SUBTYPE(info[i]));
+ handles_out->emplace_back(
+ PlatformHandleInTransit(PlatformHandle(zx::handle(handles[i]))));
+ }
+
+ return true;
+}
+
+PlatformHandle WrapPlatformHandles(Channel::Message::HandleInfoEntry info,
+ base::circular_deque<zx::handle>* handles) {
+ PlatformHandle out_handle;
+ if (!info.type) {
+ out_handle = PlatformHandle(std::move(handles->front()));
+ handles->pop_front();
+ } else {
+ if (info.count > FDIO_MAX_HANDLES)
+ return PlatformHandle();
+
+ // Fetch the required number of handles from |handles| and set up type info.
+ zx_handle_t fd_handles[FDIO_MAX_HANDLES] = {};
+ uint32_t fd_infos[FDIO_MAX_HANDLES] = {};
+ for (int i = 0; i < info.count; ++i) {
+ fd_handles[i] = (*handles)[i].get();
+ fd_infos[i] = PA_HND(info.type, 0);
+ }
+
+ // Try to wrap the handles into an FDIO file descriptor.
+ base::ScopedFD out_fd;
+ zx_status_t result =
+ fdio_create_fd(fd_handles, fd_infos, info.count, out_fd.receive());
+ if (result != ZX_OK) {
+ ZX_DLOG(ERROR, result) << "fdio_create_fd";
+ return PlatformHandle();
+ }
+
+ // The handles are owned by FDIO now, so |release()| them before removing
+ // the entries from |handles|.
+ for (int i = 0; i < info.count; ++i) {
+ ignore_result(handles->front().release());
+ handles->pop_front();
+ }
+
+ out_handle = PlatformHandle(std::move(out_fd));
+ }
+ return out_handle;
+}
+
+// A view over a Channel::Message object. The write queue uses these since
+// large messages may need to be sent in chunks.
+class MessageView {
+ public:
+ // Owns |message|. |offset| indexes the first unsent byte in the message.
+ MessageView(Channel::MessagePtr message, size_t offset)
+ : message_(std::move(message)),
+ offset_(offset),
+ handles_(message_->TakeHandlesForTransport()) {
+ DCHECK_GT(message_->data_num_bytes(), offset_);
+ }
+
+ MessageView(MessageView&& other) { *this = std::move(other); }
+
+ MessageView& operator=(MessageView&& other) {
+ message_ = std::move(other.message_);
+ offset_ = other.offset_;
+ handles_ = std::move(other.handles_);
+ return *this;
+ }
+
+ ~MessageView() {}
+
+ const void* data() const {
+ return static_cast<const char*>(message_->data()) + offset_;
+ }
+
+ size_t data_num_bytes() const { return message_->data_num_bytes() - offset_; }
+
+ size_t data_offset() const { return offset_; }
+ void advance_data_offset(size_t num_bytes) {
+ DCHECK_GT(message_->data_num_bytes(), offset_ + num_bytes);
+ offset_ += num_bytes;
+ }
+
+ std::vector<PlatformHandleInTransit> TakeHandles() {
+ if (handles_.empty())
+ return std::vector<PlatformHandleInTransit>();
+
+ // We can only pass Fuchsia handles via IPC, so unwrap any FDIO file-
+ // descriptors in |handles_| into the underlying handles, and serialize the
+ // metadata, if any, into the extra header.
+ auto* handles_info = reinterpret_cast<Channel::Message::HandleInfoEntry*>(
+ message_->mutable_extra_header());
+ memset(handles_info, 0, message_->extra_header_size());
+
+ std::vector<PlatformHandleInTransit> in_handles = std::move(handles_);
+ handles_.reserve(in_handles.size());
+ for (size_t i = 0; i < in_handles.size(); i++) {
+ if (!UnwrapPlatformHandle(std::move(in_handles[i]), &handles_info[i],
+ &handles_))
+ return std::vector<PlatformHandleInTransit>();
+ }
+ return std::move(handles_);
+ }
+
+ private:
+ Channel::MessagePtr message_;
+ size_t offset_;
+ std::vector<PlatformHandleInTransit> handles_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageView);
+};
+
+class ChannelFuchsia : public Channel,
+ public base::MessageLoopCurrent::DestructionObserver,
+ public base::MessagePumpForIO::ZxHandleWatcher {
+ public:
+ ChannelFuchsia(Delegate* delegate,
+ ConnectionParams connection_params,
+ scoped_refptr<base::TaskRunner> io_task_runner)
+ : Channel(delegate),
+ self_(this),
+ handle_(
+ connection_params.TakeEndpoint().TakePlatformHandle().TakeHandle()),
+ io_task_runner_(io_task_runner) {
+ CHECK(handle_.is_valid());
+ }
+
+ void Start() override {
+ if (io_task_runner_->RunsTasksInCurrentSequence()) {
+ StartOnIOThread();
+ } else {
+ io_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ChannelFuchsia::StartOnIOThread, this));
+ }
+ }
+
+ void ShutDownImpl() override {
+ // Always shut down asynchronously when called through the public interface.
+ io_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ChannelFuchsia::ShutDownOnIOThread, this));
+ }
+
+ void Write(MessagePtr message) override {
+ bool write_error = false;
+ {
+ base::AutoLock lock(write_lock_);
+ if (reject_writes_)
+ return;
+ if (!WriteNoLock(MessageView(std::move(message), 0)))
+ reject_writes_ = write_error = true;
+ }
+ if (write_error) {
+ // Do not synchronously invoke OnWriteError(). Write() may have been
+ // called by the delegate and we don't want to re-enter it.
+ io_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ChannelFuchsia::OnWriteError, this,
+ Error::kDisconnected));
+ }
+ }
+
+ void LeakHandle() override {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ leak_handle_ = true;
+ }
+
+ bool GetReadPlatformHandles(const void* payload,
+ size_t payload_size,
+ size_t num_handles,
+ const void* extra_header,
+ size_t extra_header_size,
+ std::vector<PlatformHandle>* handles,
+ bool* deferred) override {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ if (num_handles > std::numeric_limits<uint16_t>::max())
+ return false;
+
+ // Locate the handle info and verify there is enough of it.
+ if (!extra_header)
+ return false;
+ const auto* handles_info =
+ reinterpret_cast<const Channel::Message::HandleInfoEntry*>(
+ extra_header);
+ size_t handles_info_size = sizeof(handles_info[0]) * num_handles;
+ if (handles_info_size > extra_header_size)
+ return false;
+
+ // Some caller-supplied handles may be FDIO file-descriptors, which were
+ // un-wrapped to more than one native platform resource handle for transfer.
+ // We may therefore need to expect more than |num_handles| handles to have
+ // been accumulated in |incoming_handles_|, based on the handle info.
+ size_t num_raw_handles = 0u;
+ for (size_t i = 0; i < num_handles; ++i)
+ num_raw_handles += handles_info[i].type ? handles_info[i].count : 1;
+
+ // If there are too few handles then we're not ready yet, so return true
+ // indicating things are OK, but leave |handles| empty.
+ if (incoming_handles_.size() < num_raw_handles)
+ return true;
+
+ handles->reserve(num_handles);
+ for (size_t i = 0; i < num_handles; ++i) {
+ handles->emplace_back(
+ WrapPlatformHandles(handles_info[i], &incoming_handles_));
+ }
+ return true;
+ }
+
+ private:
+ ~ChannelFuchsia() override { DCHECK(!read_watch_); }
+
+ void StartOnIOThread() {
+ DCHECK(!read_watch_);
+
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+
+ read_watch_.reset(
+ new base::MessagePumpForIO::ZxHandleWatchController(FROM_HERE));
+ base::MessageLoopCurrentForIO::Get()->WatchZxHandle(
+ handle_.get(), true /* persistent */,
+ ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, read_watch_.get(), this);
+ }
+
+ void ShutDownOnIOThread() {
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+
+ read_watch_.reset();
+ if (leak_handle_)
+ ignore_result(handle_.release());
+ handle_.reset();
+
+ // May destroy the |this| if it was the last reference.
+ self_ = nullptr;
+ }
+
+ // base::MessageLoopCurrent::DestructionObserver:
+ void WillDestroyCurrentMessageLoop() override {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ if (self_)
+ ShutDownOnIOThread();
+ }
+
+ // base::MessagePumpForIO::ZxHandleWatcher:
+ void OnZxHandleSignalled(zx_handle_t handle, zx_signals_t signals) override {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ CHECK_EQ(handle, handle_.get());
+ DCHECK((ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED) & signals);
+
+ // We always try to read message(s), even if ZX_CHANNEL_PEER_CLOSED, since
+ // the peer may have closed while messages were still unread, in the pipe.
+
+ bool validation_error = false;
+ bool read_error = false;
+ size_t next_read_size = 0;
+ size_t buffer_capacity = 0;
+ size_t total_bytes_read = 0;
+ do {
+ buffer_capacity = next_read_size;
+ char* buffer = GetReadBuffer(&buffer_capacity);
+ DCHECK_GT(buffer_capacity, 0u);
+
+ uint32_t bytes_read = 0;
+ uint32_t handles_read = 0;
+ zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES] = {};
+
+ zx_status_t read_result =
+ handle_.read(0, buffer, buffer_capacity, &bytes_read, handles,
+ base::size(handles), &handles_read);
+ if (read_result == ZX_OK) {
+ for (size_t i = 0; i < handles_read; ++i) {
+ incoming_handles_.emplace_back(handles[i]);
+ }
+ total_bytes_read += bytes_read;
+ if (!OnReadComplete(bytes_read, &next_read_size)) {
+ read_error = true;
+ validation_error = true;
+ break;
+ }
+ } else if (read_result == ZX_ERR_BUFFER_TOO_SMALL) {
+ DCHECK_LE(handles_read, base::size(handles));
+ next_read_size = bytes_read;
+ } else if (read_result == ZX_ERR_SHOULD_WAIT) {
+ break;
+ } else {
+ ZX_DLOG_IF(ERROR, read_result != ZX_ERR_PEER_CLOSED, read_result)
+ << "zx_channel_read";
+ read_error = true;
+ break;
+ }
+ } while (total_bytes_read < kMaxBatchReadCapacity && next_read_size > 0);
+ if (read_error) {
+ // Stop receiving read notifications.
+ read_watch_.reset();
+ if (validation_error)
+ OnError(Error::kReceivedMalformedData);
+ else
+ OnError(Error::kDisconnected);
+ }
+ }
+
+ // Attempts to write a message directly to the channel. If the full message
+ // cannot be written, it's queued and a wait is initiated to write the message
+ // ASAP on the I/O thread.
+ bool WriteNoLock(MessageView message_view) {
+ uint32_t write_bytes = 0;
+ do {
+ message_view.advance_data_offset(write_bytes);
+
+ std::vector<PlatformHandleInTransit> outgoing_handles =
+ message_view.TakeHandles();
+ zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES] = {};
+ size_t handles_count = outgoing_handles.size();
+
+ DCHECK_LE(handles_count, base::size(handles));
+ for (size_t i = 0; i < handles_count; ++i) {
+ DCHECK(outgoing_handles[i].handle().is_valid());
+ handles[i] = outgoing_handles[i].handle().GetHandle().get();
+ }
+
+ write_bytes = std::min(message_view.data_num_bytes(),
+ static_cast<size_t>(ZX_CHANNEL_MAX_MSG_BYTES));
+ zx_status_t result = handle_.write(0, message_view.data(), write_bytes,
+ handles, handles_count);
+ // zx_channel_write() consumes |handles| whether or not it succeeds, so
+ // release() our copies now, to avoid them being double-closed.
+ for (auto& outgoing_handle : outgoing_handles)
+ outgoing_handle.CompleteTransit();
+
+ if (result != ZX_OK) {
+ // TODO(fuchsia): Handle ZX_ERR_SHOULD_WAIT flow-control errors, once
+ // the platform starts generating them. See https://crbug.com/754084.
+ ZX_DLOG_IF(ERROR, result != ZX_ERR_PEER_CLOSED, result)
+ << "WriteNoLock(zx_channel_write)";
+ return false;
+ }
+
+ } while (write_bytes < message_view.data_num_bytes());
+
+ return true;
+ }
+
+ void OnWriteError(Error error) {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(reject_writes_);
+
+ if (error == Error::kDisconnected) {
+ // If we can't write because the pipe is disconnected then continue
+ // reading to fetch any in-flight messages, relying on end-of-stream to
+ // signal the actual disconnection.
+ if (read_watch_) {
+ // TODO: When we add flow-control for writes, we also need to reset the
+ // write-watcher here.
+ return;
+ }
+ }
+
+ OnError(error);
+ }
+
+ // Keeps the Channel alive at least until explicit shutdown on the IO thread.
+ scoped_refptr<Channel> self_;
+
+ zx::channel handle_;
+ scoped_refptr<base::TaskRunner> io_task_runner_;
+
+ // These members are only used on the IO thread.
+ std::unique_ptr<base::MessagePumpForIO::ZxHandleWatchController> read_watch_;
+ base::circular_deque<zx::handle> incoming_handles_;
+ bool leak_handle_ = false;
+
+ base::Lock write_lock_;
+ bool reject_writes_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ChannelFuchsia);
+};
+
+} // namespace
+
+// static
+scoped_refptr<Channel> Channel::Create(
+ Delegate* delegate,
+ ConnectionParams connection_params,
+ scoped_refptr<base::TaskRunner> io_task_runner) {
+ return new ChannelFuchsia(delegate, std::move(connection_params),
+ std::move(io_task_runner));
+}
+
+} // namespace core
+} // namespace mojo
diff --git a/mojo/core/channel_win.cc b/mojo/core/channel_win.cc
new file mode 100644
index 0000000000..30a14867be
--- /dev/null
+++ b/mojo/core/channel_win.cc
@@ -0,0 +1,377 @@
+// Copyright 2016 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 "mojo/core/channel.h"
+
+#include <stdint.h>
+#include <windows.h>
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+
+#include "base/bind.h"
+#include "base/containers/queue.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/message_loop/message_pump_for_io.h"
+#include "base/process/process_handle.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/win_util.h"
+
+namespace mojo {
+namespace core {
+
+namespace {
+
+class ChannelWin : public Channel,
+ public base::MessageLoopCurrent::DestructionObserver,
+ public base::MessagePumpForIO::IOHandler {
+ public:
+ ChannelWin(Delegate* delegate,
+ ConnectionParams connection_params,
+ scoped_refptr<base::TaskRunner> io_task_runner)
+ : Channel(delegate), self_(this), io_task_runner_(io_task_runner) {
+ if (connection_params.server_endpoint().is_valid()) {
+ handle_ = connection_params.TakeServerEndpoint()
+ .TakePlatformHandle()
+ .TakeHandle();
+ needs_connection_ = true;
+ } else {
+ handle_ =
+ connection_params.TakeEndpoint().TakePlatformHandle().TakeHandle();
+ }
+
+ CHECK(handle_.IsValid());
+ }
+
+ void Start() override {
+ io_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ChannelWin::StartOnIOThread, this));
+ }
+
+ void ShutDownImpl() override {
+ // Always shut down asynchronously when called through the public interface.
+ io_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&ChannelWin::ShutDownOnIOThread, this));
+ }
+
+ void Write(MessagePtr message) override {
+ if (remote_process().is_valid()) {
+ // If we know the remote process handle, we transfer all outgoing handles
+ // to the process now rewriting them in the message.
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
+ for (auto& handle : handles) {
+ if (handle.handle().is_valid())
+ handle.TransferToProcess(remote_process().Clone());
+ }
+ message->SetHandles(std::move(handles));
+ }
+
+ bool write_error = false;
+ {
+ base::AutoLock lock(write_lock_);
+ if (reject_writes_)
+ return;
+
+ bool write_now = !delay_writes_ && outgoing_messages_.empty();
+ outgoing_messages_.emplace_back(std::move(message));
+ if (write_now && !WriteNoLock(outgoing_messages_.front()))
+ reject_writes_ = write_error = true;
+ }
+ if (write_error) {
+ // Do not synchronously invoke OnWriteError(). Write() may have been
+ // called by the delegate and we don't want to re-enter it.
+ io_task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(&ChannelWin::OnWriteError, this,
+ Error::kDisconnected));
+ }
+ }
+
+ void LeakHandle() override {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ leak_handle_ = true;
+ }
+
+ bool GetReadPlatformHandles(const void* payload,
+ size_t payload_size,
+ size_t num_handles,
+ const void* extra_header,
+ size_t extra_header_size,
+ std::vector<PlatformHandle>* handles,
+ bool* deferred) override {
+ DCHECK(extra_header);
+ if (num_handles > std::numeric_limits<uint16_t>::max())
+ return false;
+ using HandleEntry = Channel::Message::HandleEntry;
+ size_t handles_size = sizeof(HandleEntry) * num_handles;
+ if (handles_size > extra_header_size)
+ return false;
+ handles->reserve(num_handles);
+ const HandleEntry* extra_header_handles =
+ reinterpret_cast<const HandleEntry*>(extra_header);
+ for (size_t i = 0; i < num_handles; i++) {
+ HANDLE handle_value =
+ base::win::Uint32ToHandle(extra_header_handles[i].handle);
+ if (remote_process().is_valid()) {
+ // If we know the remote process's handle, we assume it doesn't know
+ // ours; that means any handle values still belong to that process, and
+ // we need to transfer them to this process.
+ handle_value = PlatformHandleInTransit::TakeIncomingRemoteHandle(
+ handle_value, remote_process().get())
+ .ReleaseHandle();
+ }
+ handles->emplace_back(base::win::ScopedHandle(std::move(handle_value)));
+ }
+ return true;
+ }
+
+ private:
+ // May run on any thread.
+ ~ChannelWin() override {}
+
+ void StartOnIOThread() {
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
+ base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(handle_.Get(),
+ this);
+
+ if (needs_connection_) {
+ BOOL ok = ::ConnectNamedPipe(handle_.Get(), &connect_context_.overlapped);
+ if (ok) {
+ PLOG(ERROR) << "Unexpected success while waiting for pipe connection";
+ OnError(Error::kConnectionFailed);
+ return;
+ }
+
+ const DWORD err = GetLastError();
+ switch (err) {
+ case ERROR_PIPE_CONNECTED:
+ break;
+ case ERROR_IO_PENDING:
+ is_connect_pending_ = true;
+ AddRef();
+ return;
+ case ERROR_NO_DATA:
+ default:
+ OnError(Error::kConnectionFailed);
+ return;
+ }
+ }
+
+ // Now that we have registered our IOHandler, we can start writing.
+ {
+ base::AutoLock lock(write_lock_);
+ if (delay_writes_) {
+ delay_writes_ = false;
+ WriteNextNoLock();
+ }
+ }
+
+ // Keep this alive in case we synchronously run shutdown, via OnError(),
+ // as a result of a ReadFile() failure on the channel.
+ scoped_refptr<ChannelWin> keep_alive(this);
+ ReadMore(0);
+ }
+
+ void ShutDownOnIOThread() {
+ base::MessageLoopCurrent::Get()->RemoveDestructionObserver(this);
+
+ // TODO(https://crbug.com/583525): This function is expected to be called
+ // once, and |handle_| should be valid at this point.
+ CHECK(handle_.IsValid());
+ CancelIo(handle_.Get());
+ if (leak_handle_)
+ ignore_result(handle_.Take());
+ else
+ handle_.Close();
+
+ // Allow |this| to be destroyed as soon as no IO is pending.
+ self_ = nullptr;
+ }
+
+ // base::MessageLoopCurrent::DestructionObserver:
+ void WillDestroyCurrentMessageLoop() override {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ if (self_)
+ ShutDownOnIOThread();
+ }
+
+ // base::MessageLoop::IOHandler:
+ void OnIOCompleted(base::MessagePumpForIO::IOContext* context,
+ DWORD bytes_transfered,
+ DWORD error) override {
+ if (error != ERROR_SUCCESS) {
+ if (context == &write_context_) {
+ {
+ base::AutoLock lock(write_lock_);
+ reject_writes_ = true;
+ }
+ OnWriteError(Error::kDisconnected);
+ } else {
+ OnError(Error::kDisconnected);
+ }
+ } else if (context == &connect_context_) {
+ DCHECK(is_connect_pending_);
+ is_connect_pending_ = false;
+ ReadMore(0);
+
+ base::AutoLock lock(write_lock_);
+ if (delay_writes_) {
+ delay_writes_ = false;
+ WriteNextNoLock();
+ }
+ } else if (context == &read_context_) {
+ OnReadDone(static_cast<size_t>(bytes_transfered));
+ } else {
+ CHECK(context == &write_context_);
+ OnWriteDone(static_cast<size_t>(bytes_transfered));
+ }
+ Release();
+ }
+
+ void OnReadDone(size_t bytes_read) {
+ DCHECK(is_read_pending_);
+ is_read_pending_ = false;
+
+ if (bytes_read > 0) {
+ size_t next_read_size = 0;
+ if (OnReadComplete(bytes_read, &next_read_size)) {
+ ReadMore(next_read_size);
+ } else {
+ OnError(Error::kReceivedMalformedData);
+ }
+ } else if (bytes_read == 0) {
+ OnError(Error::kDisconnected);
+ }
+ }
+
+ void OnWriteDone(size_t bytes_written) {
+ if (bytes_written == 0)
+ return;
+
+ bool write_error = false;
+ {
+ base::AutoLock lock(write_lock_);
+
+ DCHECK(is_write_pending_);
+ is_write_pending_ = false;
+ DCHECK(!outgoing_messages_.empty());
+
+ Channel::MessagePtr message = std::move(outgoing_messages_.front());
+ outgoing_messages_.pop_front();
+
+ // Invalidate all the scoped handles so we don't attempt to close them.
+ std::vector<PlatformHandleInTransit> handles = message->TakeHandles();
+ for (auto& handle : handles)
+ handle.CompleteTransit();
+
+ // Overlapped WriteFile() to a pipe should always fully complete.
+ if (message->data_num_bytes() != bytes_written)
+ reject_writes_ = write_error = true;
+ else if (!WriteNextNoLock())
+ reject_writes_ = write_error = true;
+ }
+ if (write_error)
+ OnWriteError(Error::kDisconnected);
+ }
+
+ void ReadMore(size_t next_read_size_hint) {
+ DCHECK(!is_read_pending_);
+
+ size_t buffer_capacity = next_read_size_hint;
+ char* buffer = GetReadBuffer(&buffer_capacity);
+ DCHECK_GT(buffer_capacity, 0u);
+
+ BOOL ok =
+ ::ReadFile(handle_.Get(), buffer, static_cast<DWORD>(buffer_capacity),
+ NULL, &read_context_.overlapped);
+ if (ok || GetLastError() == ERROR_IO_PENDING) {
+ is_read_pending_ = true;
+ AddRef();
+ } else {
+ OnError(Error::kDisconnected);
+ }
+ }
+
+ // Attempts to write a message directly to the channel. If the full message
+ // cannot be written, it's queued and a wait is initiated to write the message
+ // ASAP on the I/O thread.
+ bool WriteNoLock(const Channel::MessagePtr& message) {
+ BOOL ok = WriteFile(handle_.Get(), message->data(),
+ static_cast<DWORD>(message->data_num_bytes()), NULL,
+ &write_context_.overlapped);
+ if (ok || GetLastError() == ERROR_IO_PENDING) {
+ is_write_pending_ = true;
+ AddRef();
+ return true;
+ }
+ return false;
+ }
+
+ bool WriteNextNoLock() {
+ if (outgoing_messages_.empty())
+ return true;
+ return WriteNoLock(outgoing_messages_.front());
+ }
+
+ void OnWriteError(Error error) {
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
+ DCHECK(reject_writes_);
+
+ if (error == Error::kDisconnected) {
+ // If we can't write because the pipe is disconnected then continue
+ // reading to fetch any in-flight messages, relying on end-of-stream to
+ // signal the actual disconnection.
+ if (is_read_pending_ || is_connect_pending_)
+ return;
+ }
+
+ OnError(error);
+ }
+
+ // Keeps the Channel alive at least until explicit shutdown on the IO thread.
+ scoped_refptr<Channel> self_;
+
+ // The pipe handle this Channel uses for communication.
+ base::win::ScopedHandle handle_;
+
+ // Indicates whether |handle_| must wait for a connection.
+ bool needs_connection_ = false;
+
+ const scoped_refptr<base::TaskRunner> io_task_runner_;
+
+ base::MessagePumpForIO::IOContext connect_context_;
+ base::MessagePumpForIO::IOContext read_context_;
+ bool is_connect_pending_ = false;
+ bool is_read_pending_ = false;
+
+ // Protects all fields potentially accessed on multiple threads via Write().
+ base::Lock write_lock_;
+ base::MessagePumpForIO::IOContext write_context_;
+ base::circular_deque<Channel::MessagePtr> outgoing_messages_;
+ bool delay_writes_ = true;
+ bool reject_writes_ = false;
+ bool is_write_pending_ = false;
+
+ bool leak_handle_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(ChannelWin);
+};
+
+} // namespace
+
+// static
+scoped_refptr<Channel> Channel::Create(
+ Delegate* delegate,
+ ConnectionParams connection_params,
+ scoped_refptr<base::TaskRunner> io_task_runner) {
+ return new ChannelWin(delegate, std::move(connection_params), io_task_runner);
+}
+
+} // namespace core
+} // namespace mojo
diff --git a/mojo/core/embedder/BUILD.gn b/mojo/core/embedder/BUILD.gn
new file mode 100644
index 0000000000..47f1c39016
--- /dev/null
+++ b/mojo/core/embedder/BUILD.gn
@@ -0,0 +1,29 @@
+# Copyright 2018 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.
+
+component("embedder") {
+ output_name = "mojo_core_embedder"
+
+ public = [
+ "configuration.h",
+ "embedder.h",
+ "scoped_ipc_support.h",
+ ]
+
+ sources = [
+ "embedder.cc",
+ "scoped_ipc_support.cc",
+ ]
+
+ defines = [ "IS_MOJO_CORE_EMBEDDER_IMPL" ]
+
+ public_deps = [
+ "//base",
+ ]
+
+ deps = [
+ "//mojo/core:embedder_internal",
+ "//mojo/public/c/system",
+ ]
+}
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
index 56b67464fa..fc65c4d5b6 100644
--- a/mojo/core/node_controller.cc
+++ b/mojo/core/node_controller.cc
@@ -933,8 +933,11 @@ void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
// Feed the broker any pending invitees of our own.
while (!pending_broker_clients.empty()) {
const ports::NodeName& invitee_name = pending_broker_clients.front();
- auto it = peers_.find(invitee_name);
- if (it != peers_.end()) {
+ auto it = pending_invitations_.find(invitee_name);
+ // If for any reason we don't have a pending invitation for the invitee,
+ // there's nothing left to do: we've already swapped the relevant state into
+ // the stack.
+ if (it != pending_invitations_.end()) {
broker->AddBrokerClient(invitee_name,
it->second->CloneRemoteProcessHandle());
}
diff --git a/mojo/core/ports/BUILD.gn b/mojo/core/ports/BUILD.gn
new file mode 100644
index 0000000000..68dce3f8eb
--- /dev/null
+++ b/mojo/core/ports/BUILD.gn
@@ -0,0 +1,59 @@
+# Copyright 2016 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.
+
+import("//testing/test.gni")
+
+component("ports") {
+ output_name = "mojo_core_ports"
+
+ sources = [
+ "event.cc",
+ "event.h",
+ "message_filter.h",
+ "message_queue.cc",
+ "message_queue.h",
+ "name.cc",
+ "name.h",
+ "node.cc",
+ "node.h",
+ "node_delegate.h",
+ "port.cc",
+ "port.h",
+ "port_locker.cc",
+ "port_locker.h",
+ "port_ref.cc",
+ "port_ref.h",
+ "user_data.h",
+ "user_message.cc",
+ "user_message.h",
+ ]
+
+ defines = [ "IS_MOJO_CORE_PORTS_IMPL" ]
+
+ public_deps = [
+ "//base",
+ ]
+
+ if (!is_nacl) {
+ deps = [
+ "//crypto",
+ ]
+ }
+}
+
+source_set("tests") {
+ testonly = true
+
+ sources = [
+ "name_unittest.cc",
+ "ports_unittest.cc",
+ ]
+
+ deps = [
+ ":ports",
+ "//base",
+ "//base/test:test_support",
+ "//testing/gtest",
+ ]
+}
diff --git a/mojo/core/test/BUILD.gn b/mojo/core/test/BUILD.gn
new file mode 100644
index 0000000000..6fad6fec71
--- /dev/null
+++ b/mojo/core/test/BUILD.gn
@@ -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.
+
+static_library("test_support") {
+ testonly = true
+ sources = [
+ "mojo_test_base.cc",
+ "mojo_test_base.h",
+ "test_utils.h",
+ "test_utils_win.cc",
+ ]
+
+ if (!is_ios) {
+ sources += [
+ "multiprocess_test_helper.cc",
+ "multiprocess_test_helper.h",
+ ]
+ }
+
+ if (is_fuchsia || is_posix) {
+ sources += [ "test_utils.cc" ]
+ }
+
+ public_deps = [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/public/cpp/system",
+ "//testing/gtest",
+ ]
+}
+
+source_set("run_all_unittests") {
+ testonly = true
+ sources = [
+ "run_all_unittests.cc",
+ ]
+
+ deps = [
+ ":test_support",
+ ":test_support_impl",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/public/c/test_support",
+ "//testing/gtest",
+ ]
+
+ if (is_linux && !is_component_build) {
+ public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+ }
+}
+
+source_set("run_all_perftests") {
+ testonly = true
+ deps = [
+ ":test_support_impl",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/core/test:test_support",
+ "//mojo/public/c/test_support",
+ ]
+
+ sources = [
+ "run_all_perftests.cc",
+ ]
+
+ if (is_linux && !is_component_build) {
+ public_configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
+ }
+}
+
+static_library("test_support_impl") {
+ testonly = true
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/public/c/test_support",
+ "//mojo/public/cpp/system",
+ ]
+
+ sources = [
+ "test_support_impl.cc",
+ "test_support_impl.h",
+ ]
+}
diff --git a/mojo/core/test/test_utils_win.cc b/mojo/core/test/test_utils_win.cc
new file mode 100644
index 0000000000..9adfb7aaa5
--- /dev/null
+++ b/mojo/core/test/test_utils_win.cc
@@ -0,0 +1,49 @@
+// 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 "mojo/core/test/test_utils.h"
+
+#include <fcntl.h>
+#include <io.h>
+#include <stddef.h>
+#include <string.h>
+#include <windows.h>
+
+namespace mojo {
+namespace core {
+namespace test {
+
+PlatformHandle PlatformHandleFromFILE(base::ScopedFILE fp) {
+ CHECK(fp);
+
+ HANDLE rv = INVALID_HANDLE_VALUE;
+ PCHECK(DuplicateHandle(
+ GetCurrentProcess(),
+ reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(fp.get()))),
+ GetCurrentProcess(), &rv, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ << "DuplicateHandle";
+ return PlatformHandle(base::win::ScopedHandle(rv));
+}
+
+base::ScopedFILE FILEFromPlatformHandle(PlatformHandle h, const char* mode) {
+ CHECK(h.is_valid());
+ // Microsoft's documentation for |_open_osfhandle()| only discusses these
+ // flags (and |_O_WTEXT|). Hmmm.
+ int flags = 0;
+ if (strchr(mode, 'a'))
+ flags |= _O_APPEND;
+ if (strchr(mode, 'r'))
+ flags |= _O_RDONLY;
+ if (strchr(mode, 't'))
+ flags |= _O_TEXT;
+ base::ScopedFILE rv(_fdopen(
+ _open_osfhandle(reinterpret_cast<intptr_t>(h.ReleaseHandle()), flags),
+ mode));
+ PCHECK(rv) << "_fdopen";
+ return rv;
+}
+
+} // namespace test
+} // namespace core
+} // namespace mojo
diff --git a/mojo/public/BUILD.gn b/mojo/public/BUILD.gn
new file mode 100644
index 0000000000..bd094c8c32
--- /dev/null
+++ b/mojo/public/BUILD.gn
@@ -0,0 +1,33 @@
+# 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.
+
+group("public") {
+ # Meta-target, don't link into production code.
+ testonly = true
+ deps = [
+ ":sdk",
+ "cpp/bindings",
+ "interfaces/bindings/tests:test_interfaces",
+ ]
+
+ if (is_android) {
+ deps += [
+ "java:bindings_java",
+ "java:system_java",
+ ]
+ }
+}
+
+group("sdk") {
+ deps = [
+ "c/system",
+ "cpp/bindings",
+ ]
+}
+
+group("fuzzers") {
+ deps = [
+ "tools/fuzzers",
+ ]
+}
diff --git a/mojo/public/c/system/BUILD.gn b/mojo/public/c/system/BUILD.gn
new file mode 100644
index 0000000000..6cc2b02a7a
--- /dev/null
+++ b/mojo/public/c/system/BUILD.gn
@@ -0,0 +1,38 @@
+# 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.
+
+component("system") {
+ output_name = "mojo_public_system"
+
+ sources = [
+ "thunks.cc",
+ ]
+
+ defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ]
+
+ public_deps = [
+ ":headers",
+ ]
+
+ deps = [
+ "//base",
+ ]
+}
+
+source_set("headers") {
+ public = [
+ "buffer.h",
+ "core.h",
+ "data_pipe.h",
+ "functions.h",
+ "invitation.h",
+ "macros.h",
+ "message_pipe.h",
+ "platform_handle.h",
+ "system_export.h",
+ "thunks.h",
+ "trap.h",
+ "types.h",
+ ]
+}
diff --git a/mojo/public/c/system/tests/BUILD.gn b/mojo/public/c/system/tests/BUILD.gn
new file mode 100644
index 0000000000..f116cc6c91
--- /dev/null
+++ b/mojo/public/c/system/tests/BUILD.gn
@@ -0,0 +1,38 @@
+# 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.
+
+source_set("tests") {
+ testonly = true
+
+ visibility = [
+ "//mojo/public/cpp/system/tests:mojo_unittests",
+ "//mojo/public/cpp/system/tests:tests",
+ ]
+
+ sources = [
+ "core_api_unittest.cc",
+ "core_unittest_pure_c.c",
+ "macros_unittest.cc",
+ ]
+
+ deps = [
+ "//mojo/public/c/system",
+ "//mojo/public/cpp/system",
+ "//testing/gtest",
+ ]
+}
+
+source_set("perftests") {
+ testonly = true
+
+ sources = [
+ "core_perftest.cc",
+ ]
+
+ deps = [
+ "//mojo/public/cpp/system",
+ "//mojo/public/cpp/test_support:test_utils",
+ "//testing/gtest",
+ ]
+}
diff --git a/mojo/public/c/test_support/BUILD.gn b/mojo/public/c/test_support/BUILD.gn
new file mode 100644
index 0000000000..e2abd5807e
--- /dev/null
+++ b/mojo/public/c/test_support/BUILD.gn
@@ -0,0 +1,15 @@
+# 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.
+
+static_library("test_support") {
+ output_name = "mojo_public_test_support"
+
+ sources = [
+ "test_support.h",
+
+ # TODO(vtl): Convert this to thunks http://crbug.com/386799
+ "../../tests/test_support_private.cc",
+ "../../tests/test_support_private.h",
+ ]
+}
diff --git a/mojo/public/cpp/base/BUILD.gn b/mojo/public/cpp/base/BUILD.gn
new file mode 100644
index 0000000000..c57ac0bf1d
--- /dev/null
+++ b/mojo/public/cpp/base/BUILD.gn
@@ -0,0 +1,85 @@
+# Copyright 2018 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+component("base") {
+ output_name = "mojo_base_lib"
+
+ sources = [
+ "big_buffer.cc",
+ "big_buffer.h",
+ ]
+
+ defines = [ "IS_MOJO_BASE_IMPL" ]
+
+ public_deps = [
+ "//base",
+ "//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/system",
+ ]
+}
+
+# Normally typemap traits sources should be build directly into mojom targets
+# via the typemap file. This target is for typemapped mojo_base types whose
+# traits are shared between chromium and blink variants.
+component("shared_typemap_traits") {
+ output_name = "mojo_base_shared_typemap_traits"
+
+ sources = [
+ "big_buffer_mojom_traits.cc",
+ "big_buffer_mojom_traits.h",
+ "file_info_mojom_traits.cc",
+ "file_info_mojom_traits.h",
+ "file_path_mojom_traits.cc",
+ "file_path_mojom_traits.h",
+ "shared_memory_mojom_traits.cc",
+ "shared_memory_mojom_traits.h",
+ "time_mojom_traits.cc",
+ "time_mojom_traits.h",
+ "values_mojom_traits.cc",
+ "values_mojom_traits.h",
+ ]
+
+ defines = [ "IS_MOJO_BASE_SHARED_TRAITS_IMPL" ]
+
+ public_deps = [
+ ":base",
+ "//base:i18n",
+ "//mojo/public/mojom/base:base_shared",
+ ]
+}
+
+source_set("tests") {
+ testonly = true
+
+ sources = [
+ "big_buffer_unittest.cc",
+ "big_string_unittest.cc",
+ "file_path_unittest.cc",
+ "file_unittest.cc",
+ "memory_allocator_dump_cross_process_uid_unittest.cc",
+ "process_id_unittest.cc",
+ "read_only_buffer_unittest.cc",
+ "ref_counted_memory_unittest.cc",
+ "shared_memory_unittest.cc",
+ "string16_unittest.cc",
+ "text_direction_unittest.cc",
+ "thread_priority_unittest.cc",
+ "time_unittest.cc",
+ "unguessable_token_unittest.cc",
+ "values_unittest.cc",
+ ]
+
+ public_deps = [
+ ":base",
+ ":shared_typemap_traits",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/public/cpp/test_support:test_utils",
+ "//mojo/public/mojom/base",
+ "//mojo/public/mojom/base:read_only_buffer",
+ "//testing/gtest",
+ ]
+}
diff --git a/mojo/public/cpp/base/logfont_win.typemap b/mojo/public/cpp/base/logfont_win.typemap
new file mode 100644
index 0000000000..daaf6fcca6
--- /dev/null
+++ b/mojo/public/cpp/base/logfont_win.typemap
@@ -0,0 +1,18 @@
+# Copyright 2017 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.
+
+mojom = "//mojo/public/mojom/base/logfont_win.mojom"
+public_headers = [
+ "//base/win/windows_full.h",
+ "//base/win/windows_types.h",
+]
+traits_headers = [ "//mojo/public/cpp/base/logfont_win_mojom_traits.h" ]
+public_deps = [
+ "//base",
+]
+sources = [
+ "//mojo/public/cpp/base/logfont_win_mojom_traits.cc",
+ "//mojo/public/cpp/base/logfont_win_mojom_traits.h",
+]
+type_mappings = [ "mojo_base.mojom.LOGFONT=::LOGFONT" ]
diff --git a/mojo/public/cpp/base/logfont_win_mojom_traits.cc b/mojo/public/cpp/base/logfont_win_mojom_traits.cc
new file mode 100644
index 0000000000..3c73701ce9
--- /dev/null
+++ b/mojo/public/cpp/base/logfont_win_mojom_traits.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 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 "mojo/public/cpp/base/logfont_win_mojom_traits.h"
+
+#include <tchar.h>
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+
+namespace mojo {
+
+// static
+base::span<const uint8_t>
+StructTraits<mojo_base::mojom::LOGFONTDataView, ::LOGFONT>::bytes(
+ const ::LOGFONT& input) {
+ return base::make_span(reinterpret_cast<const uint8_t*>(&input),
+ sizeof(::LOGFONT));
+}
+
+// static
+bool StructTraits<mojo_base::mojom::LOGFONTDataView, ::LOGFONT>::Read(
+ mojo_base::mojom::LOGFONTDataView data,
+ ::LOGFONT* out) {
+ ArrayDataView<uint8_t> bytes_view;
+ data.GetBytesDataView(&bytes_view);
+ if (bytes_view.size() != sizeof(::LOGFONT))
+ return false;
+
+ const ::LOGFONT* font = reinterpret_cast<const ::LOGFONT*>(bytes_view.data());
+ if (_tcsnlen(font->lfFaceName, LF_FACESIZE) >= LF_FACESIZE)
+ return false;
+
+ memcpy(out, font, sizeof(::LOGFONT));
+ return true;
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/base/logfont_win_mojom_traits.h b/mojo/public/cpp/base/logfont_win_mojom_traits.h
new file mode 100644
index 0000000000..09a9fbbeee
--- /dev/null
+++ b/mojo/public/cpp/base/logfont_win_mojom_traits.h
@@ -0,0 +1,30 @@
+// Copyright 2018 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.
+
+#ifndef MOJO_PUBLIC_CPP_BASE_LOGFONT_WIN_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_LOGFONT_WIN_MOJOM_TRAITS_H_
+
+#include <windows.h>
+
+#include <cstdint>
+
+#include "base/component_export.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/win/windows_types.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "mojo/public/mojom/base/logfont_win.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+ StructTraits<mojo_base::mojom::LOGFONTDataView, ::LOGFONT> {
+ static base::span<const uint8_t> bytes(const ::LOGFONT& input);
+ static bool Read(mojo_base::mojom::LOGFONTDataView data, ::LOGFONT* out);
+};
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BASE_LOGFONT_WIN_MOJOM_TRAITS_H_
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
new file mode 100644
index 0000000000..27152835ac
--- /dev/null
+++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -0,0 +1,228 @@
+# 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.
+
+import("//build/buildflag_header.gni")
+import("//build/config/nacl/config.gni")
+import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
+
+declare_args() {
+ enable_mojo_tracing = false
+}
+
+buildflag_header("mojo_buildflags") {
+ header = "mojo_buildflags.h"
+
+ flags = [ "MOJO_TRACE_ENABLED=$enable_mojo_tracing" ]
+}
+
+# Headers and sources which generated bindings can depend upon. No need for
+# other targets to depend on this directly: just use the "bindings" target.
+component("bindings_base") {
+ sources = [
+ "array_data_view.h",
+ "array_traits.h",
+ "array_traits_span.h",
+ "array_traits_stl.h",
+ "associated_group.h",
+ "associated_group_controller.h",
+ "clone_traits.h",
+ "disconnect_reason.h",
+ "enum_traits.h",
+ "equals_traits.h",
+ "interface_data_view.h",
+ "interface_id.h",
+ "lib/array_internal.cc",
+ "lib/array_internal.h",
+ "lib/array_serialization.h",
+ "lib/associated_group.cc",
+ "lib/associated_group_controller.cc",
+ "lib/bindings_internal.h",
+ "lib/buffer.cc",
+ "lib/buffer.h",
+ "lib/fixed_buffer.cc",
+ "lib/fixed_buffer.h",
+ "lib/handle_serialization.h",
+ "lib/hash_util.h",
+ "lib/map_data_internal.h",
+ "lib/map_serialization.h",
+ "lib/may_auto_lock.h",
+ "lib/message.cc",
+ "lib/message_header_validator.cc",
+ "lib/message_internal.cc",
+ "lib/message_internal.h",
+ "lib/scoped_interface_endpoint_handle.cc",
+ "lib/serialization.h",
+ "lib/serialization.h",
+ "lib/serialization_context.cc",
+ "lib/serialization_context.h",
+ "lib/serialization_forward.h",
+ "lib/serialization_util.h",
+ "lib/string_serialization.h",
+ "lib/template_util.h",
+ "lib/unserialized_message_context.cc",
+ "lib/unserialized_message_context.h",
+ "lib/validate_params.h",
+ "lib/validation_context.cc",
+ "lib/validation_context.h",
+ "lib/validation_errors.cc",
+ "lib/validation_errors.h",
+ "lib/validation_util.cc",
+ "lib/validation_util.h",
+ "map.h",
+ "map_data_view.h",
+ "map_traits.h",
+ "map_traits_flat_map.h",
+ "map_traits_stl.h",
+ "message.h",
+ "message_header_validator.h",
+ "scoped_interface_endpoint_handle.h",
+ "string_data_view.h",
+ "string_traits.h",
+ "string_traits_stl.h",
+ "string_traits_string_piece.h",
+ "struct_ptr.h",
+ "struct_traits.h",
+ "type_converter.h",
+ "union_traits.h",
+ ]
+
+ defines = [ "IS_MOJO_CPP_BINDINGS_BASE_IMPL" ]
+
+ public_deps = [
+ ":mojo_buildflags",
+ "//base",
+ "//mojo/public/cpp/system",
+ ]
+
+ if (enable_ipc_fuzzer) {
+ all_dependent_configs = [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ]
+ }
+}
+
+component("bindings") {
+ sources = [
+ "associated_binding.h",
+ "associated_binding_set.h",
+ "associated_interface_ptr.h",
+ "associated_interface_ptr_info.h",
+ "associated_interface_request.h",
+ "binding.h",
+ "binding_set.h",
+ "bindings_export.h",
+ "callback_helpers.h",
+ "connection_error_callback.h",
+ "connector.h",
+ "filter_chain.h",
+ "interface_endpoint_client.h",
+ "interface_endpoint_controller.h",
+ "interface_ptr.h",
+ "interface_ptr_info.h",
+ "interface_ptr_set.h",
+ "interface_request.h",
+ "lib/associated_binding.cc",
+ "lib/associated_interface_ptr.cc",
+ "lib/associated_interface_ptr_state.cc",
+ "lib/associated_interface_ptr_state.h",
+ "lib/binding_state.cc",
+ "lib/binding_state.h",
+ "lib/connector.cc",
+ "lib/control_message_handler.cc",
+ "lib/control_message_handler.h",
+ "lib/control_message_proxy.cc",
+ "lib/control_message_proxy.h",
+ "lib/filter_chain.cc",
+ "lib/interface_endpoint_client.cc",
+ "lib/interface_ptr_state.cc",
+ "lib/interface_ptr_state.h",
+ "lib/interface_serialization.h",
+ "lib/multiplex_router.cc",
+ "lib/multiplex_router.h",
+ "lib/native_enum_data.h",
+ "lib/native_enum_serialization.h",
+ "lib/native_struct_serialization.cc",
+ "lib/native_struct_serialization.h",
+ "lib/pipe_control_message_handler.cc",
+ "lib/pipe_control_message_proxy.cc",
+ "lib/sequence_local_sync_event_watcher.cc",
+ "lib/sync_call_restrictions.cc",
+ "lib/sync_event_watcher.cc",
+ "lib/sync_handle_registry.cc",
+ "lib/sync_handle_watcher.cc",
+ "lib/task_runner_helper.cc",
+ "lib/task_runner_helper.h",
+ "native_enum.h",
+ "pipe_control_message_handler.h",
+ "pipe_control_message_handler_delegate.h",
+ "pipe_control_message_proxy.h",
+ "raw_ptr_impl_ref_traits.h",
+ "sequence_local_sync_event_watcher.h",
+ "strong_associated_binding.h",
+ "strong_binding.h",
+ "strong_binding_set.h",
+ "sync_call_restrictions.h",
+ "sync_event_watcher.h",
+ "sync_handle_registry.h",
+ "sync_handle_watcher.h",
+ "thread_safe_interface_ptr.h",
+ "unique_ptr_impl_ref_traits.h",
+ ]
+
+ if (enable_ipc_fuzzer && !is_nacl_nonsfi) {
+ sources += [
+ "lib/message_dumper.cc",
+ "message_dumper.h",
+ ]
+ }
+
+ public_deps = [
+ ":bindings_base",
+ ":struct_traits",
+ "//base",
+ "//ipc:message_support",
+ "//ipc:param_traits",
+ "//mojo/public/cpp/system",
+ "//mojo/public/interfaces/bindings",
+ ]
+
+ deps = [
+ "//ipc:native_handle_type_converters",
+ ]
+
+ defines = [ "MOJO_CPP_BINDINGS_IMPLEMENTATION" ]
+}
+
+source_set("struct_traits") {
+ sources = [
+ "array_traits.h",
+ "enum_traits.h",
+ "lib/template_util.h",
+ "map_traits.h",
+ "string_traits.h",
+ "struct_traits.h",
+ "union_traits.h",
+ ]
+}
+
+if (!is_ios) {
+ # TODO(yzshen): crbug.com/617718 Consider moving this into blink.
+ source_set("wtf_support") {
+ sources = [
+ "array_traits_wtf_vector.h",
+ "lib/string_traits_wtf.cc",
+ "lib/wtf_clone_equals_util.h",
+ "lib/wtf_hash_util.h",
+ "lib/wtf_serialization.h",
+ "map_traits_wtf_hash_map.h",
+ "string_traits_wtf.h",
+ ]
+
+ public_deps = [
+ ":bindings",
+ "//third_party/blink/renderer/platform:platform_export",
+ "//third_party/blink/renderer/platform/wtf",
+ ]
+
+ public_configs = [ "//third_party/blink/renderer:config" ]
+ }
+}
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn
new file mode 100644
index 0000000000..82038a186d
--- /dev/null
+++ b/mojo/public/cpp/bindings/tests/BUILD.gn
@@ -0,0 +1,156 @@
+# 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.
+
+source_set("tests") {
+ testonly = true
+
+ sources = [
+ "associated_interface_unittest.cc",
+ "bind_task_runner_unittest.cc",
+ "binding_callback_unittest.cc",
+ "binding_set_unittest.cc",
+ "binding_unittest.cc",
+ "bindings_test_base.cc",
+ "bindings_test_base.h",
+ "buffer_unittest.cc",
+ "callback_helpers_unittest.cc",
+ "connector_unittest.cc",
+ "constant_unittest.cc",
+ "container_test_util.cc",
+ "container_test_util.h",
+ "data_view_unittest.cc",
+ "equals_unittest.cc",
+ "handle_passing_unittest.cc",
+ "hash_unittest.cc",
+ "interface_ptr_unittest.cc",
+ "lazy_serialization_unittest.cc",
+ "map_unittest.cc",
+ "message_queue.cc",
+ "message_queue.h",
+ "multiplex_router_unittest.cc",
+ "native_struct_unittest.cc",
+ "report_bad_message_unittest.cc",
+ "request_response_unittest.cc",
+ "router_test_util.cc",
+ "router_test_util.h",
+ "sample_service_unittest.cc",
+ "serialization_warning_unittest.cc",
+ "struct_unittest.cc",
+ "sync_handle_registry_unittest.cc",
+ "sync_method_unittest.cc",
+ "test_helpers_unittest.cc",
+ "type_conversion_unittest.cc",
+ "union_unittest.cc",
+ "validation_context_unittest.cc",
+ "validation_unittest.cc",
+ "variant_test_util.h",
+ ]
+
+ deps = [
+ ":mojo_public_bindings_test_utils",
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/system",
+ "//mojo/public/cpp/test_support:test_utils",
+ "//mojo/public/interfaces/bindings/tests:test_associated_interfaces",
+ "//mojo/public/interfaces/bindings/tests:test_export_component",
+ "//mojo/public/interfaces/bindings/tests:test_export_component2",
+ "//mojo/public/interfaces/bindings/tests:test_exported_import",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces",
+ "//mojo/public/interfaces/bindings/tests:test_struct_traits_interfaces",
+ "//testing/gtest",
+ ]
+
+ data = [
+ "//mojo/public/interfaces/bindings/tests/data/validation/",
+ ]
+
+ if (is_ios) {
+ assert_no_deps = [ "//third_party/WebKit/*" ]
+ } else {
+ sources += [
+ "pickle_unittest.cc",
+ "struct_traits_unittest.cc",
+ ]
+
+ deps += [
+ "//mojo/public/cpp/bindings/tests:struct_with_traits_impl",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces_blink",
+ ]
+ }
+}
+
+if (!is_ios) {
+ source_set("for_blink_tests") {
+ testonly = true
+
+ sources = [
+ "container_test_util.cc",
+ "container_test_util.h",
+ "variant_test_util.h",
+ "wtf_hash_unittest.cc",
+ "wtf_map_unittest.cc",
+ "wtf_types_unittest.cc",
+ ]
+
+ deps = [
+ "//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/system",
+ "//mojo/public/interfaces/bindings/tests:test_export_blink_component",
+ "//mojo/public/interfaces/bindings/tests:test_exported_import_blink",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces_blink",
+ "//mojo/public/interfaces/bindings/tests:test_wtf_types",
+ "//mojo/public/interfaces/bindings/tests:test_wtf_types_blink",
+ "//testing/gtest",
+ ]
+ }
+}
+
+source_set("struct_with_traits_impl") {
+ sources = [
+ "struct_with_traits_impl.cc",
+ "struct_with_traits_impl.h",
+ ]
+
+ deps = [
+ "//base",
+ "//mojo/public/cpp/system:system",
+ ]
+}
+
+source_set("perftests") {
+ testonly = true
+
+ sources = [
+ "bindings_perftest.cc",
+ ]
+
+ if (!is_ios) {
+ sources += [ "e2e_perftest.cc" ]
+ }
+
+ deps = [
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/core/test:test_support",
+ "//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/system",
+ "//mojo/public/cpp/test_support:test_utils",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces",
+ "//testing/gtest",
+ ]
+}
+
+source_set("mojo_public_bindings_test_utils") {
+ sources = [
+ "validation_test_input_parser.cc",
+ "validation_test_input_parser.h",
+ ]
+
+ deps = [
+ "//mojo/public/c/system",
+ ]
+}
diff --git a/mojo/public/cpp/platform/BUILD.gn b/mojo/public/cpp/platform/BUILD.gn
new file mode 100644
index 0000000000..b0aa90ef37
--- /dev/null
+++ b/mojo/public/cpp/platform/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright 2018 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.
+
+import("//build/config/nacl/config.gni")
+
+component("platform") {
+ output_name = "mojo_cpp_platform"
+
+ public = [
+ "named_platform_channel.h",
+ "platform_channel.h",
+ "platform_channel_endpoint.h",
+ "platform_channel_server_endpoint.h",
+ "platform_handle.h",
+ ]
+
+ sources = [
+ "named_platform_channel.cc",
+ "named_platform_channel_win.cc",
+ "platform_channel.cc",
+ "platform_channel_endpoint.cc",
+ "platform_channel_server_endpoint.cc",
+ "platform_handle.cc",
+ ]
+
+ if (is_posix && (!is_nacl || is_nacl_nonsfi)) {
+ public += [ "socket_utils_posix.h" ]
+ sources += [ "socket_utils_posix.cc" ]
+ }
+
+ public_deps = [
+ "//base",
+ "//mojo/public/c/system:headers",
+ ]
+
+ if (is_posix && (!is_nacl && !is_fuchsia)) {
+ sources += [ "named_platform_channel_posix.cc" ]
+ }
+
+ if (is_fuchsia) {
+ sources += [ "named_platform_channel_fuchsia.cc" ]
+ public_deps += [
+ "//third_party/fuchsia-sdk:fdio",
+ "//third_party/fuchsia-sdk:zx",
+ ]
+ }
+
+ defines = [ "IS_MOJO_CPP_PLATFORM_IMPL" ]
+}
diff --git a/mojo/public/cpp/platform/named_platform_channel_fuchsia.cc b/mojo/public/cpp/platform/named_platform_channel_fuchsia.cc
new file mode 100644
index 0000000000..44ae4af368
--- /dev/null
+++ b/mojo/public/cpp/platform/named_platform_channel_fuchsia.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 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 "mojo/public/cpp/platform/named_platform_channel.h"
+
+namespace mojo {
+
+// static
+PlatformChannelServerEndpoint NamedPlatformChannel::CreateServerEndpoint(
+ const Options& options,
+ ServerName* server_name) {
+ // TODO(https://crbug.com/754038): Implement, or remove dependencies.
+ NOTREACHED();
+ return {};
+}
+
+// static
+PlatformChannelEndpoint NamedPlatformChannel::CreateClientEndpoint(
+ const ServerName& server_name) {
+ // TODO(https://crbug.com/754038): Implement, or remove dependencies.
+ NOTREACHED();
+ return {};
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/platform/named_platform_channel_win.cc b/mojo/public/cpp/platform/named_platform_channel_win.cc
new file mode 100644
index 0000000000..9c329bd6d8
--- /dev/null
+++ b/mojo/public/cpp/platform/named_platform_channel_win.cc
@@ -0,0 +1,110 @@
+// Copyright 2018 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 "mojo/public/cpp/platform/named_platform_channel.h"
+
+#include <windows.h>
+#include <memory>
+
+// NOTE: This needs to be included *after* windows.h.
+#include <sddl.h>
+
+#include "base/rand_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
+
+namespace mojo {
+
+namespace {
+
+// A DACL to grant:
+// GA = Generic All
+// access to:
+// SY = LOCAL_SYSTEM
+// BA = BUILTIN_ADMINISTRATORS
+// OW = OWNER_RIGHTS
+constexpr base::char16 kDefaultSecurityDescriptor[] =
+ L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;OW)";
+
+NamedPlatformChannel::ServerName GenerateRandomServerName() {
+ return base::UTF8ToUTF16(
+ base::StringPrintf("%lu.%lu.%I64u", ::GetCurrentProcessId(),
+ ::GetCurrentThreadId(), base::RandUint64()));
+}
+
+base::string16 GetPipeNameFromServerName(
+ const NamedPlatformChannel::ServerName& server_name) {
+ return L"\\\\.\\pipe\\mojo." + server_name;
+}
+
+} // namespace
+
+// static
+PlatformChannelServerEndpoint NamedPlatformChannel::CreateServerEndpoint(
+ const Options& options,
+ ServerName* server_name) {
+ ServerName name = options.server_name;
+ if (name.empty())
+ name = GenerateRandomServerName();
+
+ PSECURITY_DESCRIPTOR security_desc = nullptr;
+ ULONG security_desc_len = 0;
+ PCHECK(::ConvertStringSecurityDescriptorToSecurityDescriptor(
+ options.security_descriptor.empty() ? kDefaultSecurityDescriptor
+ : options.security_descriptor.c_str(),
+ SDDL_REVISION_1, &security_desc, &security_desc_len));
+ std::unique_ptr<void, decltype(::LocalFree)*> p(security_desc, ::LocalFree);
+ SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES),
+ security_desc, FALSE};
+
+ const DWORD kOpenMode = options.enforce_uniqueness
+ ? PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
+ FILE_FLAG_FIRST_PIPE_INSTANCE
+ : PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED;
+ const DWORD kPipeMode =
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS;
+
+ base::string16 pipe_name = GetPipeNameFromServerName(name);
+ PlatformHandle handle(base::win::ScopedHandle(::CreateNamedPipeW(
+ pipe_name.c_str(), kOpenMode, kPipeMode,
+ options.enforce_uniqueness ? 1 : 255, // Max instances.
+ 4096, // Out buffer size.
+ 4096, // In buffer size.
+ 5000, // Timeout in milliseconds.
+ &security_attributes)));
+
+ *server_name = name;
+ return PlatformChannelServerEndpoint(std::move(handle));
+}
+
+// static
+PlatformChannelEndpoint NamedPlatformChannel::CreateClientEndpoint(
+ const ServerName& server_name) {
+ base::string16 pipe_name = GetPipeNameFromServerName(server_name);
+
+ // Note: This may block.
+ if (!::WaitNamedPipeW(pipe_name.c_str(), NMPWAIT_USE_DEFAULT_WAIT))
+ return PlatformChannelEndpoint();
+
+ const DWORD kDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ // The SECURITY_ANONYMOUS flag means that the server side cannot impersonate
+ // the client.
+ const DWORD kFlags =
+ SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED;
+ PlatformHandle handle(base::win::ScopedHandle(
+ ::CreateFileW(pipe_name.c_str(), kDesiredAccess, 0, nullptr,
+ OPEN_EXISTING, kFlags, nullptr)));
+
+ // The server may have stopped accepting a connection between the
+ // WaitNamedPipe() and CreateFile(). If this occurs, an invalid handle is
+ // returned.
+ DPLOG_IF(ERROR, !handle.is_valid())
+ << "Named pipe " << pipe_name
+ << " could not be opened after WaitNamedPipe succeeded";
+ return PlatformChannelEndpoint(std::move(handle));
+}
+
+} // namespace mojo
diff --git a/mojo/public/cpp/platform/tests/BUILD.gn b/mojo/public/cpp/platform/tests/BUILD.gn
new file mode 100644
index 0000000000..d90e9f6155
--- /dev/null
+++ b/mojo/public/cpp/platform/tests/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2018 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.
+
+source_set("tests") {
+ testonly = true
+
+ sources = [
+ "platform_handle_unittest.cc",
+ ]
+
+ deps = [
+ "//base",
+ "//mojo/public/c/system",
+ "//mojo/public/cpp/platform",
+ "//mojo/public/cpp/system",
+ "//testing/gtest",
+ ]
+}
diff --git a/mojo/public/cpp/system/BUILD.gn b/mojo/public/cpp/system/BUILD.gn
new file mode 100644
index 0000000000..155ac14ab3
--- /dev/null
+++ b/mojo/public/cpp/system/BUILD.gn
@@ -0,0 +1,75 @@
+# 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.
+
+# Deletes libsystem.dylib from the build dir, since it shadows
+# /usr/lib/libSystem.dylib on macOS.
+# TODO(thakis): Remove this after a while.
+action("clean_up_old_dylib") {
+ script = "//build/rm.py"
+ stamp = "$target_gen_dir/clean_up_stamp"
+ outputs = [
+ stamp,
+ ]
+ args = [
+ "--stamp",
+ rebase_path(stamp, root_build_dir),
+ "-f",
+ "libsystem.dylib",
+ ]
+}
+
+component("system") {
+ output_name = "mojo_public_system_cpp"
+
+ sources = [
+ "buffer.cc",
+ "buffer.h",
+ "core.h",
+ "data_pipe.h",
+ "data_pipe_drainer.cc",
+ "data_pipe_drainer.h",
+ "data_pipe_utils.cc",
+ "data_pipe_utils.h",
+ "file_data_pipe_producer.cc",
+ "file_data_pipe_producer.h",
+ "functions.h",
+ "handle.h",
+ "handle_signal_tracker.cc",
+ "handle_signal_tracker.h",
+ "handle_signals_state.h",
+ "invitation.cc",
+ "invitation.h",
+ "isolated_connection.cc",
+ "isolated_connection.h",
+ "message.h",
+ "message_pipe.cc",
+ "message_pipe.h",
+ "platform_handle.cc",
+ "platform_handle.h",
+ "scope_to_message_pipe.cc",
+ "scope_to_message_pipe.h",
+ "simple_watcher.cc",
+ "simple_watcher.h",
+ "string_data_pipe_producer.cc",
+ "string_data_pipe_producer.h",
+ "system_export.h",
+ "trap.cc",
+ "trap.h",
+ "wait.cc",
+ "wait.h",
+ "wait_set.cc",
+ "wait_set.h",
+ ]
+
+ public_deps = [
+ "//base",
+ "//mojo/public/c/system",
+ "//mojo/public/cpp/platform",
+ ]
+ deps = [
+ ":clean_up_old_dylib",
+ ]
+
+ defines = [ "MOJO_CPP_SYSTEM_IMPLEMENTATION" ]
+}
diff --git a/mojo/public/cpp/system/tests/BUILD.gn b/mojo/public/cpp/system/tests/BUILD.gn
new file mode 100644
index 0000000000..c08f3c1099
--- /dev/null
+++ b/mojo/public/cpp/system/tests/BUILD.gn
@@ -0,0 +1,35 @@
+# 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.
+
+source_set("tests") {
+ testonly = true
+
+ sources = [
+ "core_unittest.cc",
+ "data_pipe_drainer_unittest.cc",
+ "file_data_pipe_producer_unittest.cc",
+ "handle_signal_tracker_unittest.cc",
+ "handle_signals_state_unittest.cc",
+ "scope_to_message_pipe_unittest.cc",
+ "simple_watcher_unittest.cc",
+ "string_data_pipe_producer_unittest.cc",
+ "wait_set_unittest.cc",
+ "wait_unittest.cc",
+ ]
+
+ if (!is_ios) {
+ sources += [ "invitation_unittest.cc" ]
+ }
+
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/test:test_support",
+ "//mojo/public/c/system/tests",
+ "//mojo/public/cpp/platform",
+ "//mojo/public/cpp/system",
+ "//mojo/public/cpp/test_support:test_utils",
+ "//testing/gtest",
+ ]
+}
diff --git a/mojo/public/cpp/test_support/BUILD.gn b/mojo/public/cpp/test_support/BUILD.gn
new file mode 100644
index 0000000000..3312a371ba
--- /dev/null
+++ b/mojo/public/cpp/test_support/BUILD.gn
@@ -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.
+
+static_library("test_utils") {
+ testonly = true
+
+ sources = [
+ "lib/test_support.cc",
+ "lib/test_utils.cc",
+ "test_utils.h",
+ ]
+
+ deps = [
+ "//mojo/public/c/test_support",
+ "//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/system",
+ "//testing/gtest",
+ ]
+}
diff --git a/mojo/public/interfaces/BUILD.gn b/mojo/public/interfaces/BUILD.gn
new file mode 100644
index 0000000000..fb11ec2250
--- /dev/null
+++ b/mojo/public/interfaces/BUILD.gn
@@ -0,0 +1,9 @@
+# Copyright 2015 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.
+
+group("interfaces") {
+ deps = [
+ "bindings",
+ ]
+}
diff --git a/mojo/public/interfaces/bindings/BUILD.gn b/mojo/public/interfaces/bindings/BUILD.gn
new file mode 100644
index 0000000000..eca88c6c9e
--- /dev/null
+++ b/mojo/public/interfaces/bindings/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright 2015 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.
+
+import("../../tools/bindings/mojom.gni")
+
+mojom_component("bindings") {
+ output_prefix = "mojo_mojom_bindings"
+ macro_prefix = "MOJO_MOJOM_BINDINGS"
+
+ visibility = [
+ "//mojo/public/cpp/bindings",
+ "//ipc:mojom",
+ ]
+
+ sources = [
+ "interface_control_messages.mojom",
+ "native_struct.mojom",
+ "pipe_control_messages.mojom",
+ ]
+
+ disallow_native_types = true
+ disallow_interfaces = true
+}
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn
new file mode 100644
index 0000000000..939c837c0f
--- /dev/null
+++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -0,0 +1,266 @@
+# 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.
+
+import("../../../tools/bindings/mojom.gni")
+
+group("test_data_deps") {
+ testonly = true
+ data_deps = [
+ ":test_interfaces_js_data_deps",
+ ":test_associated_interfaces_js_data_deps",
+ ":validation_test_data",
+ ":validation_test_data_list",
+ ]
+}
+
+copy("validation_test_data") {
+ testonly = true
+ sources = [
+ "data/validation",
+ ]
+ outputs = [
+ "$root_gen_dir/layout_test_data/{{source_root_relative_dir}}/{{source_file_part}}",
+ ]
+}
+
+action_foreach("validation_test_data_list") {
+ testonly = true
+ script = "//mojo/public/tools/bindings/gen_data_files_list.py"
+ inputs = mojom_generator_sources
+ sources = [
+ "data/validation",
+ ]
+ outputs = [
+ "$root_gen_dir/layout_test_data/{{source_root_relative_dir}}/{{source_file_part}}_index.txt",
+ ]
+ args = [
+ "-d",
+ rebase_path(sources[0], root_build_dir),
+ "-o",
+ rebase_path(outputs[0], root_build_dir),
+ ]
+}
+
+mojom("test_interfaces") {
+ testonly = true
+ sources = [
+ "math_calculator.mojom",
+ "no_module.mojom",
+ "ping_service.mojom",
+ "rect.mojom",
+ "regression_tests.mojom",
+ "sample_factory.mojom",
+ "sample_interfaces.mojom",
+ "sample_service.mojom",
+ "scoping.mojom",
+ "serialization_test_structs.mojom",
+ "test_bad_messages.mojom",
+ "test_constants.mojom",
+ "test_data_view.mojom",
+ "test_name_generator.mojom",
+ "test_native_types.mojom",
+ "test_structs.mojom",
+ "test_sync_methods.mojom",
+ "test_unions.mojom",
+ "validation_test_interfaces.mojom",
+ ]
+ public_deps = [
+ ":echo",
+ ":test_mojom_import",
+ ":test_mojom_import2",
+ ]
+
+ # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
+ use_once_callback = false
+
+ support_lazy_serialization = true
+
+ # Validation tests require precise message content matching, so we avoid
+ # scrambling message IDs for test interfaces.
+ scramble_message_ids = false
+}
+
+component("test_export_component") {
+ testonly = true
+ deps = [
+ ":test_export",
+ ]
+}
+
+if (!is_ios) {
+ component("test_export_blink_component") {
+ testonly = true
+ deps = [
+ ":test_export_blink",
+ ]
+ }
+}
+
+mojom("test_export") {
+ testonly = true
+ sources = [
+ "test_export.mojom",
+ ]
+ export_class_attribute = "MOJO_TEST_EXPORT"
+ export_define = "MOJO_TEST_IMPLEMENTATION=1"
+ export_header = "mojo/public/cpp/bindings/tests/mojo_test_export.h"
+ if (!is_ios) {
+ export_class_attribute_blink = "MOJO_TEST_BLINK_EXPORT"
+ export_define_blink = "MOJO_TEST_BLINK_IMPLEMENTATION=1"
+ export_header_blink =
+ "mojo/public/cpp/bindings/tests/mojo_test_blink_export.h"
+ }
+ visibility = [ ":test_export_component" ]
+ if (!is_ios) {
+ visibility_blink = [ ":test_export_blink_component" ]
+ }
+}
+
+mojom("test_exported_import") {
+ testonly = true
+ sources = [
+ "test_import.mojom",
+ ]
+ public_deps = [
+ ":test_export",
+ ]
+
+ overridden_deps = [ ":test_export" ]
+ component_deps = [ ":test_export_component" ]
+ if (!is_ios) {
+ overridden_deps_blink = [ ":test_export" ]
+ component_deps_blink = [ ":test_export_blink_component" ]
+ }
+}
+
+# Used to test that it is okay to call mojom::Foo::Serialize()/Deserialize()
+# even if the mojom target is linked into another component.
+#
+# We don't use |test_export_component| for this test because
+# //mojo/public/cpp/bindings/tests depends on both |test_export_component| and
+# |test_exported_import| and therefore actually get the shared cpp sources of
+# test_export.mojom from |test_exported_import|.
+component("test_export_component2") {
+ testonly = true
+ public_deps = [
+ ":test_export2",
+ ]
+}
+
+mojom("test_export2") {
+ testonly = true
+ sources = [
+ "test_export2.mojom",
+ ]
+ export_class_attribute = "MOJO_TEST_EXPORT"
+ export_define = "MOJO_TEST_IMPLEMENTATION=1"
+ export_header = "mojo/public/cpp/bindings/tests/mojo_test_export.h"
+ visibility = [ ":test_export_component2" ]
+}
+
+mojom("test_mojom_import") {
+ testonly = true
+ sources = [
+ "sample_import.mojom",
+ ]
+}
+
+mojom("test_mojom_import_wrapper") {
+ testonly = true
+ public_deps = [
+ ":test_mojom_import",
+ ]
+}
+
+mojom("test_mojom_import_wrapper_wrapper") {
+ testonly = true
+ public_deps = [
+ ":test_mojom_import_wrapper",
+ ]
+}
+
+mojom("test_mojom_import2") {
+ testonly = true
+ sources = [
+ "sample_import2.mojom",
+ ]
+ public_deps = [
+ ":test_mojom_import",
+ ":test_mojom_import_wrapper_wrapper",
+ ]
+}
+
+mojom("test_struct_traits_interfaces") {
+ testonly = true
+ sources = [
+ "struct_with_traits.mojom",
+ ]
+
+ # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
+ use_once_callback = false
+
+ support_lazy_serialization = true
+}
+
+mojom("test_associated_interfaces") {
+ # These files are not included in the test_interfaces target because
+ # associated interfaces are not supported by all bindings languages yet.
+ testonly = true
+ sources = [
+ "test_associated_interfaces.mojom",
+ "validation_test_associated_interfaces.mojom",
+ ]
+
+ public_deps = [
+ ":test_interfaces",
+ ]
+
+ # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
+ use_once_callback = false
+
+ # Validation tests require precise message content matching, so we avoid
+ # scrambling message IDs for test interfaces.
+ scramble_message_ids = false
+}
+
+mojom("versioning_test_service_interfaces") {
+ testonly = true
+ sources = [
+ "versioning_test_service.mojom",
+ ]
+}
+
+mojom("versioning_test_client_interfaces") {
+ testonly = true
+ sources = [
+ "versioning_test_client.mojom",
+ ]
+}
+
+mojom("test_wtf_types") {
+ testonly = true
+
+ sources = [
+ "test_wtf_types.mojom",
+ ]
+
+ # TODO(crbug.com/714018): Convert the implementation to use OnceCallback.
+ use_once_callback = false
+}
+
+mojom("test_no_sources") {
+ testonly = true
+
+ public_deps = [
+ ":test_interfaces",
+ ]
+}
+
+mojom("echo") {
+ testonly = true
+ sources = [
+ "echo.mojom",
+ "echo_import/echo_import.mojom",
+ ]
+}
diff --git a/mojo/public/java/BUILD.gn b/mojo/public/java/BUILD.gn
new file mode 100644
index 0000000000..c6159ab2e8
--- /dev/null
+++ b/mojo/public/java/BUILD.gn
@@ -0,0 +1,79 @@
+# 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.
+
+import("//build/config/android/rules.gni")
+
+android_library("system_java") {
+ java_files = [
+ "system/src/org/chromium/mojo/system/Core.java",
+ "system/src/org/chromium/mojo/system/DataPipe.java",
+ "system/src/org/chromium/mojo/system/Flags.java",
+ "system/src/org/chromium/mojo/system/Handle.java",
+ "system/src/org/chromium/mojo/system/InvalidHandle.java",
+ "system/src/org/chromium/mojo/system/MessagePipeHandle.java",
+ "system/src/org/chromium/mojo/system/MojoException.java",
+ "system/src/org/chromium/mojo/system/MojoResult.java",
+ "system/src/org/chromium/mojo/system/Pair.java",
+ "system/src/org/chromium/mojo/system/ResultAnd.java",
+ "system/src/org/chromium/mojo/system/SharedBufferHandle.java",
+ "system/src/org/chromium/mojo/system/UntypedHandle.java",
+ "system/src/org/chromium/mojo/system/RunLoop.java",
+ "system/src/org/chromium/mojo/system/Watcher.java",
+ ]
+
+ deps = [
+ "//base:base_java",
+ ]
+}
+
+android_library("bindings_java") {
+ java_files = [
+ "bindings/src/org/chromium/mojo/bindings/AssociatedInterfaceNotSupported.java",
+ "bindings/src/org/chromium/mojo/bindings/AssociatedInterfaceRequestNotSupported.java",
+ "bindings/src/org/chromium/mojo/bindings/AutoCloseableRouter.java",
+ "bindings/src/org/chromium/mojo/bindings/BindingsHelper.java",
+ "bindings/src/org/chromium/mojo/bindings/Callbacks.java",
+ "bindings/src/org/chromium/mojo/bindings/ConnectionErrorHandler.java",
+ "bindings/src/org/chromium/mojo/bindings/Connector.java",
+ "bindings/src/org/chromium/mojo/bindings/DataHeader.java",
+ "bindings/src/org/chromium/mojo/bindings/Decoder.java",
+ "bindings/src/org/chromium/mojo/bindings/DelegatingConnectionErrorHandler.java",
+ "bindings/src/org/chromium/mojo/bindings/DeserializationException.java",
+ "bindings/src/org/chromium/mojo/bindings/Encoder.java",
+ "bindings/src/org/chromium/mojo/bindings/ExceptionHandler.java",
+ "bindings/src/org/chromium/mojo/bindings/ExecutorFactory.java",
+ "bindings/src/org/chromium/mojo/bindings/HandleOwner.java",
+ "bindings/src/org/chromium/mojo/bindings/InterfaceControlMessagesHelper.java",
+ "bindings/src/org/chromium/mojo/bindings/Interface.java",
+ "bindings/src/org/chromium/mojo/bindings/InterfaceRequest.java",
+ "bindings/src/org/chromium/mojo/bindings/MessageHeader.java",
+ "bindings/src/org/chromium/mojo/bindings/Message.java",
+ "bindings/src/org/chromium/mojo/bindings/MessageReceiver.java",
+ "bindings/src/org/chromium/mojo/bindings/MessageReceiverWithResponder.java",
+ "bindings/src/org/chromium/mojo/bindings/RouterImpl.java",
+ "bindings/src/org/chromium/mojo/bindings/Router.java",
+ "bindings/src/org/chromium/mojo/bindings/SerializationException.java",
+ "bindings/src/org/chromium/mojo/bindings/ServiceMessage.java",
+ "bindings/src/org/chromium/mojo/bindings/SideEffectFreeCloseable.java",
+ "bindings/src/org/chromium/mojo/bindings/Struct.java",
+ "bindings/src/org/chromium/mojo/bindings/Union.java",
+ ]
+
+ deps = [
+ ":system_java",
+ "//base:base_java",
+ ]
+
+ srcjar_deps = [ "../interfaces/bindings:bindings_java_sources" ]
+}
+
+android_library("base_java") {
+ java_files = [ "base/src/org/chromium/mojo_base/BigBufferUtil.java" ]
+
+ deps = [
+ ":system_java",
+ "//mojo/public/java/system:system_impl_java",
+ "//mojo/public/mojom/base:base_java",
+ ]
+}
diff --git a/mojo/public/java/system/BUILD.gn b/mojo/public/java/system/BUILD.gn
new file mode 100644
index 0000000000..0025f5588d
--- /dev/null
+++ b/mojo/public/java/system/BUILD.gn
@@ -0,0 +1,177 @@
+# 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.
+
+import("//build/config/android/rules.gni")
+
+group("system") {
+ testonly = true
+ deps = [
+ ":mojo_javatests",
+ ":mojo_test_apk",
+ ":system_impl_java",
+ ]
+}
+
+generate_jni("jni_headers") {
+ sources = [
+ "javatests/src/org/chromium/mojo/MojoTestRule.java",
+ "javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java",
+ ]
+ public_deps = [
+ ":system_impl_java_jni_headers",
+ ]
+
+ jni_package = "mojo"
+}
+
+generate_jni("system_impl_java_jni_headers") {
+ sources = [
+ "src/org/chromium/mojo/system/impl/BaseRunLoop.java",
+ "src/org/chromium/mojo/system/impl/CoreImpl.java",
+ "src/org/chromium/mojo/system/impl/WatcherImpl.java",
+ ]
+
+ jni_package = "mojo"
+}
+
+source_set("native_support") {
+ sources = [
+ "base_run_loop.cc",
+ "core_impl.cc",
+ "watcher_impl.cc",
+ ]
+
+ deps = [
+ ":system_impl_java_jni_headers",
+ "//base",
+ "//mojo/public/c/system",
+ "//mojo/public/cpp/system",
+ ]
+}
+
+android_library("system_impl_java") {
+ java_files = [
+ "src/org/chromium/mojo/system/impl/BaseRunLoop.java",
+ "src/org/chromium/mojo/system/impl/CoreImpl.java",
+ "src/org/chromium/mojo/system/impl/DataPipeConsumerHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/DataPipeProducerHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/HandleBase.java",
+ "src/org/chromium/mojo/system/impl/MessagePipeHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/SharedBufferHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/UntypedHandleImpl.java",
+ "src/org/chromium/mojo/system/impl/WatcherImpl.java",
+ ]
+
+ deps = [
+ "//base:base_java",
+ "//mojo/public/java:system_java",
+ ]
+}
+
+# Targets should also depend on :test_support for the native side.
+android_library("test_support_java") {
+ testonly = true
+ java_files = [ "javatests/src/org/chromium/mojo/MojoTestRule.java" ]
+ deps = [
+ "//base:base_java",
+ "//third_party/junit",
+ ]
+}
+
+source_set("test_support") {
+ testonly = true
+ sources = [
+ "javatests/mojo_test_rule.cc",
+ ]
+ deps = [
+ ":jni_headers",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ ]
+ defines = [ "UNIT_TEST" ]
+}
+
+android_library("mojo_javatests") {
+ testonly = true
+ java_files = [
+ "javatests/src/org/chromium/mojo/HandleMock.java",
+ "javatests/src/org/chromium/mojo/TestUtils.java",
+ "javatests/src/org/chromium/mojo/bindings/BindingsHelperTest.java",
+ "javatests/src/org/chromium/mojo/bindings/BindingsTest.java",
+ "javatests/src/org/chromium/mojo/bindings/BindingsTestUtils.java",
+ "javatests/src/org/chromium/mojo/bindings/BindingsVersioningTest.java",
+ "javatests/src/org/chromium/mojo/bindings/CallbacksTest.java",
+ "javatests/src/org/chromium/mojo/bindings/ConnectorTest.java",
+ "javatests/src/org/chromium/mojo/bindings/ExecutorFactoryTest.java",
+ "javatests/src/org/chromium/mojo/bindings/InterfacesTest.java",
+ "javatests/src/org/chromium/mojo/bindings/MessageHeaderTest.java",
+ "javatests/src/org/chromium/mojo/bindings/NameGeneratorTest.java",
+ "javatests/src/org/chromium/mojo/bindings/ReadAndDispatchMessageTest.java",
+ "javatests/src/org/chromium/mojo/bindings/RouterTest.java",
+ "javatests/src/org/chromium/mojo/bindings/SerializationTest.java",
+ "javatests/src/org/chromium/mojo/bindings/test/mojom/mojo/IntegrationTestInterfaceTestHelper.java",
+ "javatests/src/org/chromium/mojo/bindings/ValidationTest.java",
+ "javatests/src/org/chromium/mojo/bindings/ValidationTestUtil.java",
+ "javatests/src/org/chromium/mojo/bindings/ValidationTestUtilTest.java",
+ "javatests/src/org/chromium/mojo/system/impl/CoreImplTest.java",
+ "javatests/src/org/chromium/mojo/system/impl/WatcherImplTest.java",
+ ]
+
+ deps = [
+ ":system_impl_java",
+ ":test_support_java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces_java",
+ "//mojo/public/interfaces/bindings/tests:test_mojom_import2_java",
+ "//mojo/public/interfaces/bindings/tests:test_mojom_import_java",
+ "//mojo/public/java:bindings_java",
+ "//mojo/public/java:system_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/junit",
+ ]
+
+ data = [
+ "//mojo/public/interfaces/bindings/tests/data/validation/",
+ ]
+}
+
+shared_library("mojo_java_unittests") {
+ testonly = true
+
+ sources = [
+ "javatests/init_library.cc",
+ "javatests/validation_test_util.cc",
+ ]
+
+ deps = [
+ ":jni_headers",
+ ":native_support",
+ ":system_impl_java_jni_headers",
+ ":test_support",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/core/embedder",
+ "//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils",
+ "//mojo/public/cpp/test_support:test_utils",
+ ]
+ defines = [ "UNIT_TEST" ]
+ configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
+ configs += [ "//build/config/android:hide_all_but_jni" ]
+}
+
+instrumentation_test_apk("mojo_test_apk") {
+ deps = [
+ ":mojo_javatests",
+ ":system_impl_java",
+ "//base:base_java",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces",
+ "//mojo/public/java:bindings_java",
+ "//third_party/android_support_test_runner:runner_java",
+ ]
+ shared_libraries = [ ":mojo_java_unittests" ]
+ apk_name = "MojoTest"
+ android_manifest = "javatests/AndroidManifest.xml"
+}
diff --git a/mojo/public/js/BUILD.gn b/mojo/public/js/BUILD.gn
new file mode 100644
index 0000000000..d6b97bda6b
--- /dev/null
+++ b/mojo/public/js/BUILD.gn
@@ -0,0 +1,72 @@
+# 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.
+
+import("//tools/grit/grit_rule.gni")
+
+interfaces_bindings_gen_dir = "$root_gen_dir/mojo/public/interfaces/bindings"
+
+action("bindings") {
+ bindings_js_files = [
+ # This must be the first file in the list, because it initializes global
+ # variable |mojo| that the others need to refer to.
+ "base.js",
+
+ "bindings.js",
+ "interface_types.js",
+ "lib/buffer.js",
+ "lib/codec.js",
+ "lib/connector.js",
+ "lib/control_message_handler.js",
+ "lib/control_message_proxy.js",
+ "lib/interface_endpoint_client.js",
+ "lib/interface_endpoint_handle.js",
+ "lib/pipe_control_message_handler.js",
+ "lib/pipe_control_message_proxy.js",
+ "lib/router.js",
+ "lib/unicode.js",
+ "lib/validator.js",
+
+ # These two needs to refer to codec.js.
+ "$interfaces_bindings_gen_dir/interface_control_messages.mojom.js",
+ "$interfaces_bindings_gen_dir/pipe_control_messages.mojom.js",
+ ]
+ compiled_file = "$target_gen_dir/mojo_bindings.js"
+
+ # TODO(yzshen): Eventually we would like to use Closure Compiler to minify the
+ # bindings instead of simply concatenating the files.
+ script = "//v8/tools/concatenate-files.py"
+
+ sources = bindings_js_files
+ outputs = [
+ compiled_file,
+ ]
+
+ args = rebase_path(bindings_js_files, root_build_dir)
+ args += [ rebase_path(compiled_file, root_build_dir) ]
+
+ deps = [
+ "//mojo/public/interfaces/bindings:bindings_js__generator",
+ ]
+}
+
+grit("resources") {
+ source = "mojo_bindings_resources.grd"
+
+ # The .grd contains references to generated files.
+ source_is_generated = true
+
+ outputs = [
+ "grit/mojo_bindings_resources.h",
+ "grit/mojo_bindings_resources_map.cc",
+ "grit/mojo_bindings_resources_map.h",
+ "mojo_bindings_resources.pak",
+ ]
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+ deps = [
+ ":bindings",
+ ]
+}
diff --git a/mojo/public/mojom/base/BUILD.gn b/mojo/public/mojom/base/BUILD.gn
new file mode 100644
index 0000000000..807d4b91be
--- /dev/null
+++ b/mojo/public/mojom/base/BUILD.gn
@@ -0,0 +1,45 @@
+# Copyright 2018 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom_component("base") {
+ sources = [
+ "big_buffer.mojom",
+ "big_string.mojom",
+ "file.mojom",
+ "file_error.mojom",
+ "file_info.mojom",
+ "file_path.mojom",
+ "memory_allocator_dump_cross_process_uid.mojom",
+ "process_id.mojom",
+ "ref_counted_memory.mojom",
+ "shared_memory.mojom",
+ "string16.mojom",
+ "text_direction.mojom",
+ "thread_priority.mojom",
+ "time.mojom",
+ "unguessable_token.mojom",
+ "values.mojom",
+ ]
+
+ if (is_win) {
+ sources += [ "logfont_win.mojom" ]
+ }
+ enabled_features = []
+ if (is_win) {
+ enabled_features += [ "file_path_is_string16" ]
+ } else {
+ enabled_features += [ "file_path_is_string" ]
+ }
+
+ output_prefix = "mojo_base_mojom"
+ macro_prefix = "MOJO_BASE_MOJOM"
+}
+
+mojom("read_only_buffer") {
+ sources = [
+ "read_only_buffer.mojom",
+ ]
+}
diff --git a/ipc/constants.mojom b/mojo/public/mojom/base/logfont_win.mojom
index 502187f2e2..27922b8478 100644
--- a/ipc/constants.mojom
+++ b/mojo/public/mojom/base/logfont_win.mojom
@@ -2,7 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module IPC.mojom;
+module mojo_base.mojom;
-// NOTE: This MUST match the value of MSG_ROUTING_NONE in src/ipc/ipc_message.h.
-const int32 kRoutingIdNone = -2;
+// Native Windows struct. Its typemap only exists for windows builds.
+[EnableIf=is_win]
+struct LOGFONT {
+ array<uint8> bytes;
+};
diff --git a/mojo/public/tools/bindings/BUILD.gn b/mojo/public/tools/bindings/BUILD.gn
new file mode 100644
index 0000000000..4979617303
--- /dev/null
+++ b/mojo/public/tools/bindings/BUILD.gn
@@ -0,0 +1,86 @@
+# Copyright 2016 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+import("//third_party/jinja2/jinja2.gni")
+
+action("precompile_templates") {
+ sources = mojom_generator_sources
+ sources += [
+ "$mojom_generator_root/generators/cpp_templates/enum_macros.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/enum_serialization_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/interface_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/interface_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/interface_macros.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/interface_proxy_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/interface_request_validator_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/interface_response_validator_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/interface_stub_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module-shared-internal.h.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module-shared-message-ids.h.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module-shared.cc.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module-shared.h.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module.cc.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/module.h.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_data_view_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_data_view_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_macros.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_serialization_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_traits_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_traits_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/struct_unserialized_message_context.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_data_view_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_data_view_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_serialization_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_traits_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/union_traits_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/validation_macros.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/wrapper_class_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/wrapper_class_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/wrapper_class_template_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/wrapper_union_class_declaration.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/wrapper_union_class_definition.tmpl",
+ "$mojom_generator_root/generators/cpp_templates/wrapper_union_class_template_definition.tmpl",
+ "$mojom_generator_root/generators/java_templates/constant_definition.tmpl",
+ "$mojom_generator_root/generators/java_templates/constants.java.tmpl",
+ "$mojom_generator_root/generators/java_templates/data_types_definition.tmpl",
+ "$mojom_generator_root/generators/java_templates/enum.java.tmpl",
+ "$mojom_generator_root/generators/java_templates/enum_definition.tmpl",
+ "$mojom_generator_root/generators/java_templates/header.java.tmpl",
+ "$mojom_generator_root/generators/java_templates/interface.java.tmpl",
+ "$mojom_generator_root/generators/java_templates/interface_definition.tmpl",
+ "$mojom_generator_root/generators/java_templates/interface_internal.java.tmpl",
+ "$mojom_generator_root/generators/java_templates/struct.java.tmpl",
+ "$mojom_generator_root/generators/java_templates/union.java.tmpl",
+ "$mojom_generator_root/generators/js_templates/enum_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/externs/interface_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/externs/module.externs.tmpl",
+ "$mojom_generator_root/generators/js_templates/externs/struct_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/fuzzing.tmpl",
+ "$mojom_generator_root/generators/js_templates/interface_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/module.amd.tmpl",
+ "$mojom_generator_root/generators/js_templates/module_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/struct_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/union_definition.tmpl",
+ "$mojom_generator_root/generators/js_templates/validation_macros.tmpl",
+ ]
+ script = mojom_generator_script
+
+ inputs = jinja2_sources
+ outputs = [
+ "$target_gen_dir/cpp_templates.zip",
+ "$target_gen_dir/java_templates.zip",
+ "$target_gen_dir/js_templates.zip",
+ ]
+ args = [
+ "--use_bundled_pylibs",
+ "precompile",
+ "-o",
+ rebase_path(target_gen_dir, root_build_dir),
+ ]
+}
diff --git a/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl b/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl
index 568db8eb31..7af57bd968 100644
--- a/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/java_templates/data_types_definition.tmpl
@@ -100,8 +100,8 @@ if ({{variable}} != null) {
{%- else %}
{
{%- endif %}
- for (int i{{level+1}} = 0; i{{level+1}} < {{variable}}.length; ++i{{level+1}}) {
- {{kind.kind|java_class_for_enum}}.validate({{variable}}[i{{level+1}}]);
+ for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) {
+ {{kind.kind|java_class_for_enum}}.validate({{variable}}[i{{level}}]);
}
}
{%- elif kind|is_enum_kind %}
diff --git a/mojo/public/tools/fuzzers/BUILD.gn b/mojo/public/tools/fuzzers/BUILD.gn
new file mode 100644
index 0000000000..69531552db
--- /dev/null
+++ b/mojo/public/tools/fuzzers/BUILD.gn
@@ -0,0 +1,67 @@
+# Copyright 2017 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.
+
+# Mojo fuzzing tools
+
+import("//build/config/features.gni")
+import("//mojo/public/tools/bindings/mojom.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
+import("//third_party/protobuf/proto_library.gni")
+
+# mojo/public BUILD depends on this target. Needed for package discovery
+group("fuzzers") {
+}
+
+mojom("fuzz_mojom") {
+ sources = [
+ "fuzz.mojom",
+ ]
+}
+
+fuzzer_test("mojo_parse_message_fuzzer") {
+ sources = [
+ "fuzz_impl.cc",
+ "mojo_parse_message_fuzzer.cc",
+ ]
+ deps = [
+ ":fuzz_mojom",
+ "//mojo/core/embedder",
+ ]
+ seed_corpus = "//mojo/public/tools/fuzzers/message_corpus"
+}
+
+# MessageDumper is not meant to work on Windows.
+if (!is_win) {
+ executable("mojo_fuzzer_message_dump") {
+ sources = [
+ "fuzz_impl.cc",
+ "mojo_fuzzer_message_dump.cc",
+ ]
+ deps = [
+ ":fuzz_mojom",
+ "//base",
+ "//mojo/core/embedder",
+ ]
+ }
+}
+
+fuzzer_test("mojo_parse_message_proto_fuzzer") {
+ sources = [
+ "fuzz_impl.cc",
+ "mojo_parse_message_proto_fuzzer.cc",
+ ]
+ deps = [
+ ":fuzz_mojom",
+ ":mojo_fuzzer_proto",
+ "//mojo/core/embedder",
+ "//third_party/libprotobuf-mutator",
+ ]
+ seed_corpus = "//mojo/public/tools/fuzzers/mojo_parse_message_proto_corpus"
+}
+
+proto_library("mojo_fuzzer_proto") {
+ sources = [
+ "mojo_fuzzer.proto",
+ ]
+}
diff --git a/soong/Android.bp b/soong/Android.bp
index 35fa5fb47c..7230b812d2 100644
--- a/soong/Android.bp
+++ b/soong/Android.bp
@@ -1,12 +1,3 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "external_libchrome_license"
- // to get the below license kinds:
- // SPDX-license-identifier-BSD
- default_applicable_licenses: ["external_libchrome_license"],
-}
-
bootstrap_go_package {
name: "soong-libchrome",
pkgPath: "android/soong/external/libchrome",
diff --git a/testing/empty_main.cc b/testing/empty_main.cc
deleted file mode 100644
index 759687fa2e..0000000000
--- a/testing/empty_main.cc
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018 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.
-
-// Used by bots that want to check that compiler command lines still work.
-int main(int argc, char** argv) {
- return 0;
-}
diff --git a/testing/gmock_mutant.h b/testing/gmock_mutant.h
deleted file mode 100644
index 2a41cf54da..0000000000
--- a/testing/gmock_mutant.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef TESTING_GMOCK_MUTANT_H_
-#define TESTING_GMOCK_MUTANT_H_
-
-// The intention of this file is to make possible using GMock actions in
-// all of its syntactic beauty.
-//
-//
-// Sample usage with gMock:
-//
-// struct Mock : public ObjectDelegate {
-// MOCK_METHOD2(string, OnRequest(int n, const string& request));
-// MOCK_METHOD1(void, OnQuit(int exit_code));
-// MOCK_METHOD2(void, LogMessage(int level, const string& message));
-//
-// string HandleFlowers(const string& reply, int n, const string& request) {
-// string result = SStringPrintf("In request of %d %s ", n, request);
-// for (int i = 0; i < n; ++i) result.append(reply)
-// return result;
-// }
-//
-// void DoLogMessage(int level, const string& message) {
-// }
-//
-// void QuitMessageLoop(int seconds) {
-// base::MessageLoop* loop = base::MessageLoop::current();
-// loop->PostDelayedTask(FROM_HERE,
-// base::MessageLoop::QuitWhenIdleClosure(),
-// 1000 * seconds);
-// }
-// };
-//
-// Mock mock;
-// // Will invoke mock.HandleFlowers("orchids", n, request)
-// // "orchids" is a pre-bound argument, and <n> and <request> are call-time
-// // arguments - they are not known until the OnRequest mock is invoked.
-// EXPECT_CALL(mock, OnRequest(Ge(5), base::StartsWith("flower"))
-// .Times(1)
-// .WillOnce(Invoke(CreateFunctor(
-// &Mock::HandleFlowers, base::Unretained(&mock), string("orchids"))));
-//
-//
-// // No pre-bound arguments, two call-time arguments passed
-// // directly to DoLogMessage
-// EXPECT_CALL(mock, OnLogMessage(_, _))
-// .Times(AnyNumber())
-// .WillAlways(Invoke(CreateFunctor(
-// &Mock::DoLogMessage, base::Unretained(&mock))));
-//
-//
-// // In this case we have a single pre-bound argument - 3. We ignore
-// // all of the arguments of OnQuit.
-// EXCEPT_CALL(mock, OnQuit(_))
-// .Times(1)
-// .WillOnce(InvokeWithoutArgs(CreateFunctor(
-// &Mock::QuitMessageLoop, base::Unretained(&mock), 3)));
-//
-// MessageLoop loop;
-// loop.Run();
-//
-//
-// // Here is another example of how we can set an action that invokes
-// // method of an object that is not yet created.
-// struct Mock : public ObjectDelegate {
-// MOCK_METHOD1(void, DemiurgeCreated(Demiurge*));
-// MOCK_METHOD2(void, OnRequest(int count, const string&));
-//
-// void StoreDemiurge(Demiurge* w) {
-// demiurge_ = w;
-// }
-//
-// Demiurge* demiurge;
-// }
-//
-// EXPECT_CALL(mock, DemiurgeCreated(_)).Times(1)
-// .WillOnce(Invoke(CreateFunctor(
-// &Mock::StoreDemiurge, base::Unretained(&mock))));
-//
-// EXPECT_CALL(mock, OnRequest(_, StrEq("Moby Dick")))
-// .Times(AnyNumber())
-// .WillAlways(WithArgs<0>(Invoke(CreateFunctor(
-// &Demiurge::DecreaseMonsters, base::Unretained(&mock->demiurge_)))));
-//
-
-#include "base/bind.h"
-
-namespace testing {
-
-template <typename Signature>
-class CallbackToFunctorHelper;
-
-template <typename R, typename... Args>
-class CallbackToFunctorHelper<R(Args...)> {
- public:
- explicit CallbackToFunctorHelper(const base::Callback<R(Args...)>& cb)
- : cb_(cb) {}
-
- template <typename... RunArgs>
- R operator()(RunArgs&&... args) {
- return cb_.Run(std::forward<RunArgs>(args)...);
- }
-
- private:
- base::Callback<R(Args...)> cb_;
-};
-
-template <typename Signature>
-CallbackToFunctorHelper<Signature>
-CallbackToFunctor(const base::Callback<Signature>& cb) {
- return CallbackToFunctorHelper<Signature>(cb);
-}
-
-template <typename Functor>
-CallbackToFunctorHelper<typename Functor::RunType> CreateFunctor(
- Functor functor) {
- return CallbackToFunctor(functor);
-}
-
-template <typename Functor, typename... BoundArgs>
-CallbackToFunctorHelper<base::MakeUnboundRunType<Functor, BoundArgs...>>
-CreateFunctor(Functor functor, const BoundArgs&... args) {
- return CallbackToFunctor(base::Bind(functor, args...));
-}
-
-} // namespace testing
-
-#endif // TESTING_GMOCK_MUTANT_H_
diff --git a/third_party/ashmem/ashmem.h b/third_party/ashmem/ashmem.h
index 7a26a18ae3..3ef9f73c80 100644
--- a/third_party/ashmem/ashmem.h
+++ b/third_party/ashmem/ashmem.h
@@ -15,18 +15,3 @@
// third_party/ashmem is Android shared memory. Instead of clone it here,
// use cutils/ashmem.h directly.
#include <cutils/ashmem.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-inline int ashmem_get_prot_region(int fd) {
- int ret = ashmem_valid(fd);
- if (ret < 0)
- return ret;
- return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_PROT_MASK));
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/ui/gfx/geometry/angle_conversions.h b/ui/gfx/geometry/angle_conversions.h
deleted file mode 100644
index 68e9209f72..0000000000
--- a/ui/gfx/geometry/angle_conversions.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef UI_GFX_GEOMETRY_ANGLE_CONVERSIONS_H_
-#define UI_GFX_GEOMETRY_ANGLE_CONVERSIONS_H_
-
-#include "base/numerics/math_constants.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-GFX_EXPORT constexpr double DegToRad(double deg) {
- return deg * base::kPiDouble / 180.0;
-}
-GFX_EXPORT constexpr float DegToRad(float deg) {
- return deg * base::kPiFloat / 180.0f;
-}
-
-GFX_EXPORT constexpr double RadToDeg(double rad) {
- return rad * 180.0 / base::kPiDouble;
-}
-GFX_EXPORT constexpr float RadToDeg(float rad) {
- return rad * 180.0f / base::kPiFloat;
-}
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_ANGLE_CONVERSIONS_H_
diff --git a/ui/gfx/geometry/axis_transform2d.cc b/ui/gfx/geometry/axis_transform2d.cc
deleted file mode 100644
index 5b7d86a450..0000000000
--- a/ui/gfx/geometry/axis_transform2d.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2013 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 "ui/gfx/geometry/axis_transform2d.h"
-
-#include "base/strings/stringprintf.h"
-
-namespace gfx {
-
-std::string AxisTransform2d::ToString() const {
- return base::StringPrintf("[%f, %s]", scale_,
- translation_.ToString().c_str());
-}
-
-} // namespace gfx \ No newline at end of file
diff --git a/ui/gfx/geometry/axis_transform2d.h b/ui/gfx/geometry/axis_transform2d.h
deleted file mode 100644
index 1829bf60fc..0000000000
--- a/ui/gfx/geometry/axis_transform2d.h
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2017 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.
-
-#ifndef UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
-#define UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
-
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/geometry/vector2d_f.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-// This class implements the subset of 2D linear transforms that only
-// translation and uniform scaling are allowed.
-// Internally this is stored as a scalar pre-scale factor, and a vector
-// for post-translation. The class constructor and member accessor follows
-// the same convention.
-class GFX_EXPORT AxisTransform2d {
- public:
- constexpr AxisTransform2d() = default;
- constexpr AxisTransform2d(float scale, const Vector2dF& translation)
- : scale_(scale), translation_(translation) {}
-
- bool operator==(const AxisTransform2d& other) const {
- return scale_ == other.scale_ && translation_ == other.translation_;
- }
- bool operator!=(const AxisTransform2d& other) const {
- return !(*this == other);
- }
-
- void PreScale(float scale) { scale_ *= scale; }
- void PostScale(float scale) {
- scale_ *= scale;
- translation_.Scale(scale);
- }
- void PreTranslate(const Vector2dF& translation) {
- translation_ += ScaleVector2d(translation, scale_);
- }
- void PostTranslate(const Vector2dF& translation) {
- translation_ += translation;
- }
-
- void PreConcat(const AxisTransform2d& pre) {
- PreTranslate(pre.translation_);
- PreScale(pre.scale_);
- }
- void PostConcat(const AxisTransform2d& post) {
- PostScale(post.scale_);
- PostTranslate(post.translation_);
- }
-
- void Invert() {
- DCHECK(scale_);
- scale_ = 1.f / scale_;
- translation_.Scale(-scale_);
- }
-
- PointF MapPoint(const PointF& p) const {
- return ScalePoint(p, scale_) + translation_;
- }
- PointF InverseMapPoint(const PointF& p) const {
- return ScalePoint(p - translation_, 1.f / scale_);
- }
-
- RectF MapRect(const RectF& r) const {
- DCHECK(scale_ >= 0.f);
- return ScaleRect(r, scale_) + translation_;
- }
- RectF InverseMapRect(const RectF& r) const {
- DCHECK(scale_ > 0.f);
- return ScaleRect(r - translation_, 1.f / scale_);
- }
-
- float scale() const { return scale_; }
- const Vector2dF& translation() const { return translation_; }
-
- std::string ToString() const;
-
- private:
- // Scale is applied before translation, i.e.
- // this->Transform(p) == scale_ * p + translation_
- float scale_ = 1.f;
- Vector2dF translation_;
-};
-
-static inline AxisTransform2d PreScaleAxisTransform2d(const AxisTransform2d& t,
- float scale) {
- AxisTransform2d result(t);
- result.PreScale(scale);
- return result;
-}
-
-static inline AxisTransform2d PostScaleAxisTransform2d(const AxisTransform2d& t,
- float scale) {
- AxisTransform2d result(t);
- result.PostScale(scale);
- return result;
-}
-
-static inline AxisTransform2d PreTranslateAxisTransform2d(
- const AxisTransform2d& t,
- const Vector2dF& translation) {
- AxisTransform2d result(t);
- result.PreTranslate(translation);
- return result;
-}
-
-static inline AxisTransform2d PostTranslateAxisTransform2d(
- const AxisTransform2d& t,
- const Vector2dF& translation) {
- AxisTransform2d result(t);
- result.PostTranslate(translation);
- return result;
-}
-
-static inline AxisTransform2d ConcatAxisTransform2d(
- const AxisTransform2d& post,
- const AxisTransform2d& pre) {
- AxisTransform2d result(post);
- result.PreConcat(pre);
- return result;
-}
-
-static inline AxisTransform2d InvertAxisTransform2d(const AxisTransform2d& t) {
- AxisTransform2d result = t;
- result.Invert();
- return result;
-}
-
-// This is declared here for use in gtest-based unit tests but is defined in
-// the //ui/gfx:test_support target. Depend on that to use this in your unit
-// test. This should not be used in production code - call ToString() instead.
-void PrintTo(const AxisTransform2d&, ::std::ostream* os);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
diff --git a/ui/gfx/geometry/axis_transform2d_unittest.cc b/ui/gfx/geometry/axis_transform2d_unittest.cc
deleted file mode 100644
index b132c69635..0000000000
--- a/ui/gfx/geometry/axis_transform2d_unittest.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2017 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 "ui/gfx/geometry/axis_transform2d.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/test/gfx_util.h"
-
-namespace gfx {
-namespace {
-
-TEST(AxisTransform2dTest, Mapping) {
- AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
-
- PointF p(150.f, 100.f);
- EXPECT_EQ(PointF(191.25f, 180.f), t.MapPoint(p));
- EXPECT_POINTF_EQ(PointF(117.f, 36.f), t.InverseMapPoint(p));
-
- RectF r(150.f, 100.f, 22.5f, 37.5f);
- EXPECT_EQ(RectF(191.25f, 180.f, 28.125f, 46.875f), t.MapRect(r));
- EXPECT_RECTF_EQ(RectF(117.f, 36.f, 18.f, 30.f), t.InverseMapRect(r));
-}
-
-TEST(AxisTransform2dTest, Scaling) {
- {
- AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
- EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(3.75f, 55.f)),
- PreScaleAxisTransform2d(t, 1.25));
- t.PreScale(1.25);
- EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(3.75f, 55.f)), t);
- }
-
- {
- AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
- EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(4.6875f, 68.75f)),
- PostScaleAxisTransform2d(t, 1.25));
- t.PostScale(1.25);
- EXPECT_EQ(AxisTransform2d(1.5625f, Vector2dF(4.6875f, 68.75f)), t);
- }
-}
-
-TEST(AxisTransform2dTest, Translating) {
- Vector2dF tr(3.f, -5.f);
- {
- AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
- EXPECT_EQ(AxisTransform2d(1.25f, Vector2dF(7.5f, 48.75f)),
- PreTranslateAxisTransform2d(t, tr));
- t.PreTranslate(tr);
- EXPECT_EQ(AxisTransform2d(1.25f, Vector2dF(7.5f, 48.75f)), t);
- }
-
- {
- AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
- EXPECT_EQ(AxisTransform2d(1.25f, Vector2dF(6.75f, 50.f)),
- PostTranslateAxisTransform2d(t, tr));
- t.PostTranslate(tr);
- EXPECT_EQ(AxisTransform2d(1.25f, Vector2dF(6.75f, 50.f)), t);
- }
-}
-
-TEST(AxisTransform2dTest, Concat) {
- AxisTransform2d pre(1.25f, Vector2dF(3.75f, 55.f));
- AxisTransform2d post(0.5f, Vector2dF(10.f, 5.f));
- AxisTransform2d expectation(0.625f, Vector2dF(11.875f, 32.5f));
- EXPECT_EQ(expectation, ConcatAxisTransform2d(post, pre));
-
- AxisTransform2d post_concat = pre;
- post_concat.PostConcat(post);
- EXPECT_EQ(expectation, post_concat);
-
- AxisTransform2d pre_concat = post;
- pre_concat.PreConcat(pre);
- EXPECT_EQ(expectation, pre_concat);
-}
-
-TEST(AxisTransform2dTest, Inverse) {
- AxisTransform2d t(1.25f, Vector2dF(3.75f, 55.f));
- AxisTransform2d inv_inplace = t;
- inv_inplace.Invert();
- AxisTransform2d inv_out_of_place = InvertAxisTransform2d(t);
-
- EXPECT_AXIS_TRANSFORM2D_EQ(inv_inplace, inv_out_of_place);
- EXPECT_AXIS_TRANSFORM2D_EQ(AxisTransform2d(),
- ConcatAxisTransform2d(t, inv_inplace));
- EXPECT_AXIS_TRANSFORM2D_EQ(AxisTransform2d(),
- ConcatAxisTransform2d(inv_inplace, t));
-}
-
-} // namespace
-} // namespace gfx
diff --git a/ui/gfx/geometry/box_f.cc b/ui/gfx/geometry/box_f.cc
deleted file mode 100644
index 674bb509c8..0000000000
--- a/ui/gfx/geometry/box_f.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2013 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 "ui/gfx/geometry/box_f.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/strings/stringprintf.h"
-
-namespace gfx {
-
-std::string BoxF::ToString() const {
- return base::StringPrintf("%s %fx%fx%f",
- origin().ToString().c_str(),
- width_,
- height_,
- depth_);
-}
-
-bool BoxF::IsEmpty() const {
- return (width_ == 0 && height_ == 0) ||
- (width_ == 0 && depth_ == 0) ||
- (height_ == 0 && depth_ == 0);
-}
-
-void BoxF::ExpandTo(const Point3F& min, const Point3F& max) {
- DCHECK_LE(min.x(), max.x());
- DCHECK_LE(min.y(), max.y());
- DCHECK_LE(min.z(), max.z());
-
- float min_x = std::min(x(), min.x());
- float min_y = std::min(y(), min.y());
- float min_z = std::min(z(), min.z());
- float max_x = std::max(right(), max.x());
- float max_y = std::max(bottom(), max.y());
- float max_z = std::max(front(), max.z());
-
- origin_.SetPoint(min_x, min_y, min_z);
- width_ = max_x - min_x;
- height_ = max_y - min_y;
- depth_ = max_z - min_z;
-}
-
-void BoxF::Union(const BoxF& box) {
- if (IsEmpty()) {
- *this = box;
- return;
- }
- if (box.IsEmpty())
- return;
- ExpandTo(box);
-}
-
-void BoxF::ExpandTo(const Point3F& point) {
- ExpandTo(point, point);
-}
-
-void BoxF::ExpandTo(const BoxF& box) {
- ExpandTo(box.origin(), gfx::Point3F(box.right(), box.bottom(), box.front()));
-}
-
-BoxF UnionBoxes(const BoxF& a, const BoxF& b) {
- BoxF result = a;
- result.Union(b);
- return result;
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/box_f.h b/ui/gfx/geometry/box_f.h
deleted file mode 100644
index b4d9eff1c0..0000000000
--- a/ui/gfx/geometry/box_f.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef UI_GFX_GEOMETRY_BOX_F_H_
-#define UI_GFX_GEOMETRY_BOX_F_H_
-
-#include <iosfwd>
-#include <string>
-
-#include "ui/gfx/geometry/point3_f.h"
-#include "ui/gfx/geometry/vector3d_f.h"
-
-namespace gfx {
-
-// A 3d version of gfx::RectF, with the positive z-axis pointed towards
-// the camera.
-class GFX_EXPORT BoxF {
- public:
- constexpr BoxF() : BoxF(0, 0, 0) {}
- constexpr BoxF(float width, float height, float depth)
- : BoxF(0, 0, 0, width, height, depth) {}
- constexpr BoxF(float x,
- float y,
- float z,
- float width,
- float height,
- float depth)
- : BoxF(Point3F(x, y, z), width, height, depth) {}
- constexpr BoxF(const Point3F& origin, float width, float height, float depth)
- : origin_(origin),
- width_(width >= 0 ? width : 0),
- height_(height >= 0 ? height : 0),
- depth_(depth >= 0 ? depth : 0) {}
-
- // Scales all three axes by the given scale.
- void Scale(float scale) {
- Scale(scale, scale, scale);
- }
-
- // Scales each axis by the corresponding given scale.
- void Scale(float x_scale, float y_scale, float z_scale) {
- origin_.Scale(x_scale, y_scale, z_scale);
- set_size(width_ * x_scale, height_ * y_scale, depth_ * z_scale);
- }
-
- // Moves the box by the specified distance in each dimension.
- void operator+=(const Vector3dF& offset) {
- origin_ += offset;
- }
-
- // Returns true if the box has no interior points.
- bool IsEmpty() const;
-
- // Computes the union of this box with the given box. The union is the
- // smallest box that contains both boxes.
- void Union(const BoxF& box);
-
- std::string ToString() const;
-
- constexpr float x() const { return origin_.x(); }
- void set_x(float x) { origin_.set_x(x); }
-
- constexpr float y() const { return origin_.y(); }
- void set_y(float y) { origin_.set_y(y); }
-
- constexpr float z() const { return origin_.z(); }
- void set_z(float z) { origin_.set_z(z); }
-
- constexpr float width() const { return width_; }
- void set_width(float width) { width_ = width < 0 ? 0 : width; }
-
- constexpr float height() const { return height_; }
- void set_height(float height) { height_ = height < 0 ? 0 : height; }
-
- constexpr float depth() const { return depth_; }
- void set_depth(float depth) { depth_ = depth < 0 ? 0 : depth; }
-
- constexpr float right() const { return x() + width(); }
- constexpr float bottom() const { return y() + height(); }
- constexpr float front() const { return z() + depth(); }
-
- void set_size(float width, float height, float depth) {
- width_ = width < 0 ? 0 : width;
- height_ = height < 0 ? 0 : height;
- depth_ = depth < 0 ? 0 : depth;
- }
-
- constexpr const Point3F& origin() const { return origin_; }
- void set_origin(const Point3F& origin) { origin_ = origin; }
-
- // Expands |this| to contain the given point, if necessary. Please note, even
- // if |this| is empty, after the function |this| will continue to contain its
- // |origin_|.
- void ExpandTo(const Point3F& point);
-
- // Expands |this| to contain the given box, if necessary. Please note, even
- // if |this| is empty, after the function |this| will continue to contain its
- // |origin_|.
- void ExpandTo(const BoxF& box);
-
- private:
- // Expands the box to contain the two given points. It is required that each
- // component of |min| is less than or equal to the corresponding component in
- // |max|. Precisely, what this function does is ensure that after the function
- // completes, |this| contains origin_, min, max, and origin_ + (width_,
- // height_, depth_), even if the box is empty. Emptiness checks are handled in
- // the public function Union.
- void ExpandTo(const Point3F& min, const Point3F& max);
-
- Point3F origin_;
- float width_;
- float height_;
- float depth_;
-};
-
-GFX_EXPORT BoxF UnionBoxes(const BoxF& a, const BoxF& b);
-
-inline BoxF ScaleBox(const BoxF& b,
- float x_scale,
- float y_scale,
- float z_scale) {
- return BoxF(b.x() * x_scale,
- b.y() * y_scale,
- b.z() * z_scale,
- b.width() * x_scale,
- b.height() * y_scale,
- b.depth() * z_scale);
-}
-
-inline BoxF ScaleBox(const BoxF& b, float scale) {
- return ScaleBox(b, scale, scale, scale);
-}
-
-inline bool operator==(const BoxF& a, const BoxF& b) {
- return a.origin() == b.origin() && a.width() == b.width() &&
- a.height() == b.height() && a.depth() == b.depth();
-}
-
-inline bool operator!=(const BoxF& a, const BoxF& b) {
- return !(a == b);
-}
-
-inline BoxF operator+(const BoxF& b, const Vector3dF& v) {
- return BoxF(b.x() + v.x(),
- b.y() + v.y(),
- b.z() + v.z(),
- b.width(),
- b.height(),
- b.depth());
-}
-
-// This is declared here for use in gtest-based unit tests but is defined in
-// the //ui/gfx:test_support target. Depend on that to use this in your unit
-// test. This should not be used in production code - call ToString() instead.
-void PrintTo(const BoxF& box, ::std::ostream* os);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_BOX_F_H_
diff --git a/ui/gfx/geometry/box_unittest.cc b/ui/gfx/geometry/box_unittest.cc
deleted file mode 100644
index 990fccc249..0000000000
--- a/ui/gfx/geometry/box_unittest.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2013 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 "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/box_f.h"
-
-namespace gfx {
-
-TEST(BoxTest, Constructors) {
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).ToString(),
- BoxF().ToString());
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, -3.f, -5.f, -7.f).ToString(),
- BoxF().ToString());
-
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 3.f, 5.f, 7.f).ToString(),
- BoxF(3.f, 5.f, 7.f).ToString());
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).ToString(),
- BoxF(-3.f, -5.f, -7.f).ToString());
-
- EXPECT_EQ(BoxF(2.f, 4.f, 6.f, 3.f, 5.f, 7.f).ToString(),
- BoxF(Point3F(2.f, 4.f, 6.f), 3.f, 5.f, 7.f).ToString());
- EXPECT_EQ(BoxF(2.f, 4.f, 6.f, 0.f, 0.f, 0.f).ToString(),
- BoxF(Point3F(2.f, 4.f, 6.f), -3.f, -5.f, -7.f).ToString());
-}
-
-TEST(BoxTest, IsEmpty) {
- EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 0.f).IsEmpty());
- EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 0.f, 0.f).IsEmpty());
-
- EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 2.f, 0.f, 0.f).IsEmpty());
- EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 2.f, 0.f, 0.f).IsEmpty());
- EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 2.f, 0.f).IsEmpty());
- EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 2.f, 0.f).IsEmpty());
- EXPECT_TRUE(BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 2.f).IsEmpty());
- EXPECT_TRUE(BoxF(1.f, 2.f, 3.f, 0.f, 0.f, 2.f).IsEmpty());
-
- EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 0.f, 2.f, 2.f).IsEmpty());
- EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 0.f, 2.f, 2.f).IsEmpty());
- EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 0.f, 2.f).IsEmpty());
- EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 0.f, 2.f).IsEmpty());
- EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 2.f, 0.f).IsEmpty());
- EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 2.f, 0.f).IsEmpty());
-
- EXPECT_FALSE(BoxF(0.f, 0.f, 0.f, 2.f, 2.f, 2.f).IsEmpty());
- EXPECT_FALSE(BoxF(1.f, 2.f, 3.f, 2.f, 2.f, 2.f).IsEmpty());
-}
-
-TEST(BoxTest, Union) {
- BoxF empty_box;
- BoxF box1(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
- BoxF box2(0.f, 0.f, 0.f, 4.f, 6.f, 8.f);
- BoxF box3(3.f, 4.f, 5.f, 6.f, 4.f, 0.f);
-
- EXPECT_EQ(empty_box.ToString(), UnionBoxes(empty_box, empty_box).ToString());
- EXPECT_EQ(box1.ToString(), UnionBoxes(empty_box, box1).ToString());
- EXPECT_EQ(box1.ToString(), UnionBoxes(box1, empty_box).ToString());
- EXPECT_EQ(box2.ToString(), UnionBoxes(empty_box, box2).ToString());
- EXPECT_EQ(box2.ToString(), UnionBoxes(box2, empty_box).ToString());
- EXPECT_EQ(box3.ToString(), UnionBoxes(empty_box, box3).ToString());
- EXPECT_EQ(box3.ToString(), UnionBoxes(box3, empty_box).ToString());
-
- // box_1 is contained in box_2
- EXPECT_EQ(box2.ToString(), UnionBoxes(box1, box2).ToString());
- EXPECT_EQ(box2.ToString(), UnionBoxes(box2, box1).ToString());
-
- // box_1 and box_3 are disjoint
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 5.f).ToString(),
- UnionBoxes(box1, box3).ToString());
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 5.f).ToString(),
- UnionBoxes(box3, box1).ToString());
-
- // box_2 and box_3 intersect, but neither contains the other
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 8.f).ToString(),
- UnionBoxes(box2, box3).ToString());
- EXPECT_EQ(BoxF(0.f, 0.f, 0.f, 9.f, 8.f, 8.f).ToString(),
- UnionBoxes(box3, box2).ToString());
-}
-
-TEST(BoxTest, ExpandTo) {
- BoxF box1;
- BoxF box2(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
- BoxF box3(1.f, 1.f, 1.f, 0.f, 0.f, 0.f);
-
- Point3F point1(0.5f, 0.5f, 0.5f);
- Point3F point2(-0.5f, -0.5f, -0.5f);
-
- BoxF expected1_1(0.f, 0.f, 0.f, 0.5f, 0.5f, 0.5f);
- BoxF expected1_2(-0.5f, -0.5f, -0.5f, 1.f, 1.f, 1.f);
-
- BoxF expected2_1 = box2;
- BoxF expected2_2(-0.5f, -0.5f, -0.5f, 1.5f, 1.5f, 1.5f);
-
- BoxF expected3_1(0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f);
- BoxF expected3_2(-0.5f, -0.5f, -0.5f, 1.5f, 1.5f, 1.5f);
-
- box1.ExpandTo(point1);
- EXPECT_EQ(expected1_1.ToString(), box1.ToString());
- box1.ExpandTo(point2);
- EXPECT_EQ(expected1_2.ToString(), box1.ToString());
-
- box2.ExpandTo(point1);
- EXPECT_EQ(expected2_1.ToString(), box2.ToString());
- box2.ExpandTo(point2);
- EXPECT_EQ(expected2_2.ToString(), box2.ToString());
-
- box3.ExpandTo(point1);
- EXPECT_EQ(expected3_1.ToString(), box3.ToString());
- box3.ExpandTo(point2);
- EXPECT_EQ(expected3_2.ToString(), box3.ToString());
-}
-
-TEST(BoxTest, Scale) {
- BoxF box1(2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
-
- EXPECT_EQ(BoxF().ToString(), ScaleBox(box1, 0.f).ToString());
- EXPECT_EQ(box1.ToString(), ScaleBox(box1, 1.f).ToString());
- EXPECT_EQ(BoxF(4.f, 12.f, 24.f, 10.f, 24.f, 42.f).ToString(),
- ScaleBox(box1, 2.f, 4.f, 6.f).ToString());
-
- BoxF box2 = box1;
- box2.Scale(0.f);
- EXPECT_EQ(BoxF().ToString(), box2.ToString());
-
- box2 = box1;
- box2.Scale(1.f);
- EXPECT_EQ(box1.ToString(), box2.ToString());
-
- box2.Scale(2.f, 4.f, 6.f);
- EXPECT_EQ(BoxF(4.f, 12.f, 24.f, 10.f, 24.f, 42.f).ToString(),
- box2.ToString());
-}
-
-TEST(BoxTest, Equals) {
- EXPECT_TRUE(BoxF() == BoxF());
- EXPECT_TRUE(BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f) ==
- BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f));
- EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 1.f));
- EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 0.f, 1.f, 0.f));
- EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 0.f, 1.f, 0.f, 0.f));
- EXPECT_FALSE(BoxF() == BoxF(0.f, 0.f, 1.f, 0.f, 0.f, 0.f));
- EXPECT_FALSE(BoxF() == BoxF(0.f, 1.f, 0.f, 0.f, 0.f, 0.f));
- EXPECT_FALSE(BoxF() == BoxF(1.f, 0.f, 0.f, 0.f, 0.f, 0.f));
-}
-
-TEST(BoxTest, NotEquals) {
- EXPECT_FALSE(BoxF() != BoxF());
- EXPECT_FALSE(BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f) !=
- BoxF(2.f, 3.f, 4.f, 6.f, 8.f, 10.f));
- EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 0.f, 0.f, 1.f));
- EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 0.f, 1.f, 0.f));
- EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 0.f, 1.f, 0.f, 0.f));
- EXPECT_TRUE(BoxF() != BoxF(0.f, 0.f, 1.f, 0.f, 0.f, 0.f));
- EXPECT_TRUE(BoxF() != BoxF(0.f, 1.f, 0.f, 0.f, 0.f, 0.f));
- EXPECT_TRUE(BoxF() != BoxF(1.f, 0.f, 0.f, 0.f, 0.f, 0.f));
-}
-
-
-TEST(BoxTest, Offset) {
- BoxF box1(2.f, 3.f, 4.f, 5.f, 6.f, 7.f);
-
- EXPECT_EQ(box1.ToString(), (box1 + Vector3dF(0.f, 0.f, 0.f)).ToString());
- EXPECT_EQ(BoxF(3.f, 1.f, 0.f, 5.f, 6.f, 7.f).ToString(),
- (box1 + Vector3dF(1.f, -2.f, -4.f)).ToString());
-
- BoxF box2 = box1;
- box2 += Vector3dF(0.f, 0.f, 0.f);
- EXPECT_EQ(box1.ToString(), box2.ToString());
-
- box2 += Vector3dF(1.f, -2.f, -4.f);
- EXPECT_EQ(BoxF(3.f, 1.f, 0.f, 5.f, 6.f, 7.f).ToString(),
- box2.ToString());
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/cubic_bezier.cc b/ui/gfx/geometry/cubic_bezier.cc
deleted file mode 100644
index e42d893d7f..0000000000
--- a/ui/gfx/geometry/cubic_bezier.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-// 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 "ui/gfx/geometry/cubic_bezier.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/logging.h"
-
-namespace gfx {
-
-static const double kBezierEpsilon = 1e-7;
-
-CubicBezier::CubicBezier(double p1x, double p1y, double p2x, double p2y) {
- InitCoefficients(p1x, p1y, p2x, p2y);
- InitGradients(p1x, p1y, p2x, p2y);
- InitRange(p1y, p2y);
-}
-
-CubicBezier::CubicBezier(const CubicBezier& other) = default;
-
-void CubicBezier::InitCoefficients(double p1x,
- double p1y,
- double p2x,
- double p2y) {
- // Calculate the polynomial coefficients, implicit first and last control
- // points are (0,0) and (1,1).
- cx_ = 3.0 * p1x;
- bx_ = 3.0 * (p2x - p1x) - cx_;
- ax_ = 1.0 - cx_ - bx_;
-
- cy_ = 3.0 * p1y;
- by_ = 3.0 * (p2y - p1y) - cy_;
- ay_ = 1.0 - cy_ - by_;
-}
-
-void CubicBezier::InitGradients(double p1x,
- double p1y,
- double p2x,
- double p2y) {
- // End-point gradients are used to calculate timing function results
- // outside the range [0, 1].
- //
- // There are three possibilities for the gradient at each end:
- // (1) the closest control point is not horizontally coincident with regard to
- // (0, 0) or (1, 1). In this case the line between the end point and
- // the control point is tangent to the bezier at the end point.
- // (2) the closest control point is coincident with the end point. In
- // this case the line between the end point and the far control
- // point is tangent to the bezier at the end point.
- // (3) the closest control point is horizontally coincident with the end
- // point, but vertically distinct. In this case the gradient at the
- // end point is Infinite. However, this causes issues when
- // interpolating. As a result, we break down to a simple case of
- // 0 gradient under these conditions.
-
- if (p1x > 0)
- start_gradient_ = p1y / p1x;
- else if (!p1y && p2x > 0)
- start_gradient_ = p2y / p2x;
- else
- start_gradient_ = 0;
-
- if (p2x < 1)
- end_gradient_ = (p2y - 1) / (p2x - 1);
- else if (p2x == 1 && p1x < 1)
- end_gradient_ = (p1y - 1) / (p1x - 1);
- else
- end_gradient_ = 0;
-}
-
-// This works by taking taking the derivative of the cubic bezier, on the y
-// axis. We can then solve for where the derivative is zero to find the min
-// and max distance along the line. We the have to solve those in terms of time
-// rather than distance on the x-axis
-void CubicBezier::InitRange(double p1y, double p2y) {
- range_min_ = 0;
- range_max_ = 1;
- if (0 <= p1y && p1y < 1 && 0 <= p2y && p2y <= 1)
- return;
-
- const double epsilon = kBezierEpsilon;
-
- // Represent the function's derivative in the form at^2 + bt + c
- // as in sampleCurveDerivativeY.
- // (Technically this is (dy/dt)*(1/3), which is suitable for finding zeros
- // but does not actually give the slope of the curve.)
- const double a = 3.0 * ay_;
- const double b = 2.0 * by_;
- const double c = cy_;
-
- // Check if the derivative is constant.
- if (std::abs(a) < epsilon && std::abs(b) < epsilon)
- return;
-
- // Zeros of the function's derivative.
- double t1 = 0;
- double t2 = 0;
-
- if (std::abs(a) < epsilon) {
- // The function's derivative is linear.
- t1 = -c / b;
- } else {
- // The function's derivative is a quadratic. We find the zeros of this
- // quadratic using the quadratic formula.
- double discriminant = b * b - 4 * a * c;
- if (discriminant < 0)
- return;
- double discriminant_sqrt = sqrt(discriminant);
- t1 = (-b + discriminant_sqrt) / (2 * a);
- t2 = (-b - discriminant_sqrt) / (2 * a);
- }
-
- double sol1 = 0;
- double sol2 = 0;
-
- // If the solution is in the range [0,1] then we include it, otherwise we
- // ignore it.
-
- // An interesting fact about these beziers is that they are only
- // actually evaluated in [0,1]. After that we take the tangent at that point
- // and linearly project it out.
- if (0 < t1 && t1 < 1)
- sol1 = SampleCurveY(t1);
-
- if (0 < t2 && t2 < 1)
- sol2 = SampleCurveY(t2);
-
- range_min_ = std::min(std::min(range_min_, sol1), sol2);
- range_max_ = std::max(std::max(range_max_, sol1), sol2);
-}
-
-double CubicBezier::GetDefaultEpsilon() {
- return kBezierEpsilon;
-}
-
-double CubicBezier::SolveCurveX(double x, double epsilon) const {
- DCHECK_GE(x, 0.0);
- DCHECK_LE(x, 1.0);
-
- double t0;
- double t1;
- double t2;
- double x2;
- double d2;
- int i;
-
- // First try a few iterations of Newton's method -- normally very fast.
- for (t2 = x, i = 0; i < 8; i++) {
- x2 = SampleCurveX(t2) - x;
- if (fabs(x2) < epsilon)
- return t2;
- d2 = SampleCurveDerivativeX(t2);
- if (fabs(d2) < 1e-6)
- break;
- t2 = t2 - x2 / d2;
- }
-
- // Fall back to the bisection method for reliability.
- t0 = 0.0;
- t1 = 1.0;
- t2 = x;
-
- while (t0 < t1) {
- x2 = SampleCurveX(t2);
- if (fabs(x2 - x) < epsilon)
- return t2;
- if (x > x2)
- t0 = t2;
- else
- t1 = t2;
- t2 = (t1 - t0) * .5 + t0;
- }
-
- // Failure.
- return t2;
-}
-
-double CubicBezier::Solve(double x) const {
- return SolveWithEpsilon(x, kBezierEpsilon);
-}
-
-double CubicBezier::SlopeWithEpsilon(double x, double epsilon) const {
- x = std::min(std::max(x, 0.0), 1.0);
- double t = SolveCurveX(x, epsilon);
- double dx = SampleCurveDerivativeX(t);
- double dy = SampleCurveDerivativeY(t);
- return dy / dx;
-}
-
-double CubicBezier::Slope(double x) const {
- return SlopeWithEpsilon(x, kBezierEpsilon);
-}
-
-double CubicBezier::GetX1() const {
- return cx_ / 3.0;
-}
-
-double CubicBezier::GetY1() const {
- return cy_ / 3.0;
-}
-
-double CubicBezier::GetX2() const {
- return (bx_ + cx_) / 3.0 + GetX1();
-}
-
-double CubicBezier::GetY2() const {
- return (by_ + cy_) / 3.0 + GetY1();
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/cubic_bezier.h b/ui/gfx/geometry/cubic_bezier.h
deleted file mode 100644
index 013123999c..0000000000
--- a/ui/gfx/geometry/cubic_bezier.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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.
-
-#ifndef UI_GFX_GEOMETRY_CUBIC_BEZIER_H_
-#define UI_GFX_GEOMETRY_CUBIC_BEZIER_H_
-
-#include "base/macros.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-class GFX_EXPORT CubicBezier {
- public:
- CubicBezier(double p1x, double p1y, double p2x, double p2y);
- CubicBezier(const CubicBezier& other);
-
- double SampleCurveX(double t) const {
- // `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
- return ((ax_ * t + bx_) * t + cx_) * t;
- }
-
- double SampleCurveY(double t) const {
- return ((ay_ * t + by_) * t + cy_) * t;
- }
-
- double SampleCurveDerivativeX(double t) const {
- return (3.0 * ax_ * t + 2.0 * bx_) * t + cx_;
- }
-
- double SampleCurveDerivativeY(double t) const {
- return (3.0 * ay_ * t + 2.0 * by_) * t + cy_;
- }
-
- static double GetDefaultEpsilon();
-
- // Given an x value, find a parametric value it came from.
- // x must be in [0, 1] range. Doesn't use gradients.
- double SolveCurveX(double x, double epsilon) const;
-
- // Evaluates y at the given x with default epsilon.
- double Solve(double x) const;
- // Evaluates y at the given x. The epsilon parameter provides a hint as to the
- // required accuracy and is not guaranteed. Uses gradients if x is
- // out of [0, 1] range.
- double SolveWithEpsilon(double x, double epsilon) const {
- if (x < 0.0)
- return 0.0 + start_gradient_ * x;
- if (x > 1.0)
- return 1.0 + end_gradient_ * (x - 1.0);
- return SampleCurveY(SolveCurveX(x, epsilon));
- }
-
- // Returns an approximation of dy/dx at the given x with default epsilon.
- double Slope(double x) const;
- // Returns an approximation of dy/dx at the given x.
- // Clamps x to range [0, 1].
- double SlopeWithEpsilon(double x, double epsilon) const;
-
- // These getters are used rarely. We reverse compute them from coefficients.
- // See CubicBezier::InitCoefficients. The speed has been traded for memory.
- double GetX1() const;
- double GetY1() const;
- double GetX2() const;
- double GetY2() const;
-
- // Gets the bezier's minimum y value in the interval [0, 1].
- double range_min() const { return range_min_; }
- // Gets the bezier's maximum y value in the interval [0, 1].
- double range_max() const { return range_max_; }
-
- private:
- void InitCoefficients(double p1x, double p1y, double p2x, double p2y);
- void InitGradients(double p1x, double p1y, double p2x, double p2y);
- void InitRange(double p1y, double p2y);
-
- double ax_;
- double bx_;
- double cx_;
-
- double ay_;
- double by_;
- double cy_;
-
- double start_gradient_;
- double end_gradient_;
-
- double range_min_;
- double range_max_;
-
- DISALLOW_ASSIGN(CubicBezier);
-};
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_CUBIC_BEZIER_H_
diff --git a/ui/gfx/geometry/cubic_bezier_unittest.cc b/ui/gfx/geometry/cubic_bezier_unittest.cc
deleted file mode 100644
index 74ccb6d414..0000000000
--- a/ui/gfx/geometry/cubic_bezier_unittest.cc
+++ /dev/null
@@ -1,230 +0,0 @@
-// 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 "ui/gfx/geometry/cubic_bezier.h"
-
-#include <memory>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace gfx {
-namespace {
-
-TEST(CubicBezierTest, Basic) {
- CubicBezier function(0.25, 0.0, 0.75, 1.0);
-
- double epsilon = 0.00015;
-
- EXPECT_NEAR(function.Solve(0), 0, epsilon);
- EXPECT_NEAR(function.Solve(0.05), 0.01136, epsilon);
- EXPECT_NEAR(function.Solve(0.1), 0.03978, epsilon);
- EXPECT_NEAR(function.Solve(0.15), 0.079780, epsilon);
- EXPECT_NEAR(function.Solve(0.2), 0.12803, epsilon);
- EXPECT_NEAR(function.Solve(0.25), 0.18235, epsilon);
- EXPECT_NEAR(function.Solve(0.3), 0.24115, epsilon);
- EXPECT_NEAR(function.Solve(0.35), 0.30323, epsilon);
- EXPECT_NEAR(function.Solve(0.4), 0.36761, epsilon);
- EXPECT_NEAR(function.Solve(0.45), 0.43345, epsilon);
- EXPECT_NEAR(function.Solve(0.5), 0.5, epsilon);
- EXPECT_NEAR(function.Solve(0.6), 0.63238, epsilon);
- EXPECT_NEAR(function.Solve(0.65), 0.69676, epsilon);
- EXPECT_NEAR(function.Solve(0.7), 0.75884, epsilon);
- EXPECT_NEAR(function.Solve(0.75), 0.81764, epsilon);
- EXPECT_NEAR(function.Solve(0.8), 0.87196, epsilon);
- EXPECT_NEAR(function.Solve(0.85), 0.92021, epsilon);
- EXPECT_NEAR(function.Solve(0.9), 0.96021, epsilon);
- EXPECT_NEAR(function.Solve(0.95), 0.98863, epsilon);
- EXPECT_NEAR(function.Solve(1), 1, epsilon);
-
- CubicBezier basic_use(0.5, 1.0, 0.5, 1.0);
- EXPECT_EQ(0.875, basic_use.Solve(0.5));
-
- CubicBezier overshoot(0.5, 2.0, 0.5, 2.0);
- EXPECT_EQ(1.625, overshoot.Solve(0.5));
-
- CubicBezier undershoot(0.5, -1.0, 0.5, -1.0);
- EXPECT_EQ(-0.625, undershoot.Solve(0.5));
-}
-
-// Tests that solving the bezier works with knots with y not in (0, 1).
-TEST(CubicBezierTest, UnclampedYValues) {
- CubicBezier function(0.5, -1.0, 0.5, 2.0);
-
- double epsilon = 0.00015;
-
- EXPECT_NEAR(function.Solve(0.0), 0.0, epsilon);
- EXPECT_NEAR(function.Solve(0.05), -0.08954, epsilon);
- EXPECT_NEAR(function.Solve(0.1), -0.15613, epsilon);
- EXPECT_NEAR(function.Solve(0.15), -0.19641, epsilon);
- EXPECT_NEAR(function.Solve(0.2), -0.20651, epsilon);
- EXPECT_NEAR(function.Solve(0.25), -0.18232, epsilon);
- EXPECT_NEAR(function.Solve(0.3), -0.11992, epsilon);
- EXPECT_NEAR(function.Solve(0.35), -0.01672, epsilon);
- EXPECT_NEAR(function.Solve(0.4), 0.12660, epsilon);
- EXPECT_NEAR(function.Solve(0.45), 0.30349, epsilon);
- EXPECT_NEAR(function.Solve(0.5), 0.50000, epsilon);
- EXPECT_NEAR(function.Solve(0.55), 0.69651, epsilon);
- EXPECT_NEAR(function.Solve(0.6), 0.87340, epsilon);
- EXPECT_NEAR(function.Solve(0.65), 1.01672, epsilon);
- EXPECT_NEAR(function.Solve(0.7), 1.11992, epsilon);
- EXPECT_NEAR(function.Solve(0.75), 1.18232, epsilon);
- EXPECT_NEAR(function.Solve(0.8), 1.20651, epsilon);
- EXPECT_NEAR(function.Solve(0.85), 1.19641, epsilon);
- EXPECT_NEAR(function.Solve(0.9), 1.15613, epsilon);
- EXPECT_NEAR(function.Solve(0.95), 1.08954, epsilon);
- EXPECT_NEAR(function.Solve(1.0), 1.0, epsilon);
-}
-
-TEST(CubicBezierTest, Range) {
- double epsilon = 0.00015;
-
- // Derivative is a constant.
- std::unique_ptr<CubicBezier> function(
- new CubicBezier(0.25, (1.0 / 3.0), 0.75, (2.0 / 3.0)));
- EXPECT_EQ(0, function->range_min());
- EXPECT_EQ(1, function->range_max());
-
- // Derivative is linear.
- function.reset(new CubicBezier(0.25, -0.5, 0.75, (-1.0 / 6.0)));
- EXPECT_NEAR(function->range_min(), -0.225, epsilon);
- EXPECT_EQ(1, function->range_max());
-
- // Derivative has no real roots.
- function.reset(new CubicBezier(0.25, 0.25, 0.75, 0.5));
- EXPECT_EQ(0, function->range_min());
- EXPECT_EQ(1, function->range_max());
-
- // Derivative has exactly one real root.
- function.reset(new CubicBezier(0.0, 1.0, 1.0, 0.0));
- EXPECT_EQ(0, function->range_min());
- EXPECT_EQ(1, function->range_max());
-
- // Derivative has one root < 0 and one root > 1.
- function.reset(new CubicBezier(0.25, 0.1, 0.75, 0.9));
- EXPECT_EQ(0, function->range_min());
- EXPECT_EQ(1, function->range_max());
-
- // Derivative has two roots in [0,1].
- function.reset(new CubicBezier(0.25, 2.5, 0.75, 0.5));
- EXPECT_EQ(0, function->range_min());
- EXPECT_NEAR(function->range_max(), 1.28818, epsilon);
- function.reset(new CubicBezier(0.25, 0.5, 0.75, -1.5));
- EXPECT_NEAR(function->range_min(), -0.28818, epsilon);
- EXPECT_EQ(1, function->range_max());
-
- // Derivative has one root < 0 and one root in [0,1].
- function.reset(new CubicBezier(0.25, 0.1, 0.75, 1.5));
- EXPECT_EQ(0, function->range_min());
- EXPECT_NEAR(function->range_max(), 1.10755, epsilon);
-
- // Derivative has one root in [0,1] and one root > 1.
- function.reset(new CubicBezier(0.25, -0.5, 0.75, 0.9));
- EXPECT_NEAR(function->range_min(), -0.10755, epsilon);
- EXPECT_EQ(1, function->range_max());
-
- // Derivative has two roots < 0.
- function.reset(new CubicBezier(0.25, 0.3, 0.75, 0.633));
- EXPECT_EQ(0, function->range_min());
- EXPECT_EQ(1, function->range_max());
-
- // Derivative has two roots > 1.
- function.reset(new CubicBezier(0.25, 0.367, 0.75, 0.7));
- EXPECT_EQ(0.f, function->range_min());
- EXPECT_EQ(1.f, function->range_max());
-}
-
-TEST(CubicBezierTest, Slope) {
- CubicBezier function(0.25, 0.0, 0.75, 1.0);
-
- double epsilon = 0.00015;
-
- EXPECT_NEAR(function.Slope(-0.1), 0, epsilon);
- EXPECT_NEAR(function.Slope(0), 0, epsilon);
- EXPECT_NEAR(function.Slope(0.05), 0.42170, epsilon);
- EXPECT_NEAR(function.Slope(0.1), 0.69778, epsilon);
- EXPECT_NEAR(function.Slope(0.15), 0.89121, epsilon);
- EXPECT_NEAR(function.Slope(0.2), 1.03184, epsilon);
- EXPECT_NEAR(function.Slope(0.25), 1.13576, epsilon);
- EXPECT_NEAR(function.Slope(0.3), 1.21239, epsilon);
- EXPECT_NEAR(function.Slope(0.35), 1.26751, epsilon);
- EXPECT_NEAR(function.Slope(0.4), 1.30474, epsilon);
- EXPECT_NEAR(function.Slope(0.45), 1.32628, epsilon);
- EXPECT_NEAR(function.Slope(0.5), 1.33333, epsilon);
- EXPECT_NEAR(function.Slope(0.55), 1.32628, epsilon);
- EXPECT_NEAR(function.Slope(0.6), 1.30474, epsilon);
- EXPECT_NEAR(function.Slope(0.65), 1.26751, epsilon);
- EXPECT_NEAR(function.Slope(0.7), 1.21239, epsilon);
- EXPECT_NEAR(function.Slope(0.75), 1.13576, epsilon);
- EXPECT_NEAR(function.Slope(0.8), 1.03184, epsilon);
- EXPECT_NEAR(function.Slope(0.85), 0.89121, epsilon);
- EXPECT_NEAR(function.Slope(0.9), 0.69778, epsilon);
- EXPECT_NEAR(function.Slope(0.95), 0.42170, epsilon);
- EXPECT_NEAR(function.Slope(1), 0, epsilon);
- EXPECT_NEAR(function.Slope(1.1), 0, epsilon);
-}
-
-TEST(CubicBezierTest, InputOutOfRange) {
- CubicBezier simple(0.5, 1.0, 0.5, 1.0);
- EXPECT_EQ(-2.0, simple.Solve(-1.0));
- EXPECT_EQ(1.0, simple.Solve(2.0));
-
- CubicBezier at_edge_of_range(0.5, 1.0, 0.5, 1.0);
- EXPECT_EQ(0.0, at_edge_of_range.Solve(0.0));
- EXPECT_EQ(1.0, at_edge_of_range.Solve(1.0));
-
- CubicBezier large_epsilon(0.5, 1.0, 0.5, 1.0);
- EXPECT_EQ(-2.0, large_epsilon.SolveWithEpsilon(-1.0, 1.0));
- EXPECT_EQ(1.0, large_epsilon.SolveWithEpsilon(2.0, 1.0));
-
- CubicBezier coincident_endpoints(0.0, 0.0, 1.0, 1.0);
- EXPECT_EQ(-1.0, coincident_endpoints.Solve(-1.0));
- EXPECT_EQ(2.0, coincident_endpoints.Solve(2.0));
-
- CubicBezier vertical_gradient(0.0, 1.0, 1.0, 0.0);
- EXPECT_EQ(0.0, vertical_gradient.Solve(-1.0));
- EXPECT_EQ(1.0, vertical_gradient.Solve(2.0));
-
- CubicBezier distinct_endpoints(0.1, 0.2, 0.8, 0.8);
- EXPECT_EQ(-2.0, distinct_endpoints.Solve(-1.0));
- EXPECT_EQ(2.0, distinct_endpoints.Solve(2.0));
-
- CubicBezier coincident_endpoint(0.0, 0.0, 0.8, 0.8);
- EXPECT_EQ(-1.0, coincident_endpoint.Solve(-1.0));
- EXPECT_EQ(2.0, coincident_endpoint.Solve(2.0));
-
- CubicBezier three_coincident_points(0.0, 0.0, 0.0, 0.0);
- EXPECT_EQ(0, three_coincident_points.Solve(-1.0));
- EXPECT_EQ(2.0, three_coincident_points.Solve(2.0));
-}
-
-TEST(CubicBezierTest, GetPoints) {
- double epsilon = 0.00015;
-
- CubicBezier cubic1(0.1, 0.2, 0.8, 0.9);
- EXPECT_NEAR(0.1, cubic1.GetX1(), epsilon);
- EXPECT_NEAR(0.2, cubic1.GetY1(), epsilon);
- EXPECT_NEAR(0.8, cubic1.GetX2(), epsilon);
- EXPECT_NEAR(0.9, cubic1.GetY2(), epsilon);
-
- CubicBezier cubic_zero(0, 0, 0, 0);
- EXPECT_NEAR(0, cubic_zero.GetX1(), epsilon);
- EXPECT_NEAR(0, cubic_zero.GetY1(), epsilon);
- EXPECT_NEAR(0, cubic_zero.GetX2(), epsilon);
- EXPECT_NEAR(0, cubic_zero.GetY2(), epsilon);
-
- CubicBezier cubic_one(1, 1, 1, 1);
- EXPECT_NEAR(1, cubic_one.GetX1(), epsilon);
- EXPECT_NEAR(1, cubic_one.GetY1(), epsilon);
- EXPECT_NEAR(1, cubic_one.GetX2(), epsilon);
- EXPECT_NEAR(1, cubic_one.GetY2(), epsilon);
-
- CubicBezier cubic_oor(-0.5, -1.5, 1.5, -1.6);
- EXPECT_NEAR(-0.5, cubic_oor.GetX1(), epsilon);
- EXPECT_NEAR(-1.5, cubic_oor.GetY1(), epsilon);
- EXPECT_NEAR(1.5, cubic_oor.GetX2(), epsilon);
- EXPECT_NEAR(-1.6, cubic_oor.GetY2(), epsilon);
-}
-
-} // namespace
-} // namespace gfx
diff --git a/ui/gfx/geometry/dip_util.cc b/ui/gfx/geometry/dip_util.cc
deleted file mode 100644
index db8e1be5d5..0000000000
--- a/ui/gfx/geometry/dip_util.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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 "ui/gfx/geometry/dip_util.h"
-
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/geometry/size_conversions.h"
-
-namespace gfx {
-
-Insets ConvertInsetsToDIP(float scale_factor,
- const gfx::Insets& insets_in_pixel) {
- if (scale_factor == 1.f)
- return insets_in_pixel;
- return insets_in_pixel.Scale(1.f / scale_factor);
-}
-
-Point ConvertPointToDIP(float scale_factor, const Point& point_in_pixel) {
- if (scale_factor == 1.f)
- return point_in_pixel;
- return ScaleToFlooredPoint(point_in_pixel, 1.f / scale_factor);
-}
-
-PointF ConvertPointToDIP(float scale_factor, const PointF& point_in_pixel) {
- if (scale_factor == 1.f)
- return point_in_pixel;
- return ScalePoint(point_in_pixel, 1.f / scale_factor);
-}
-
-Size ConvertSizeToDIP(float scale_factor, const Size& size_in_pixel) {
- if (scale_factor == 1.f)
- return size_in_pixel;
- return ScaleToFlooredSize(size_in_pixel, 1.f / scale_factor);
-}
-
-Rect ConvertRectToDIP(float scale_factor, const Rect& rect_in_pixel) {
- if (scale_factor == 1.f)
- return rect_in_pixel;
- return ToFlooredRectDeprecated(
- ScaleRect(RectF(rect_in_pixel), 1.f / scale_factor));
-}
-
-Insets ConvertInsetsToPixel(float scale_factor,
- const gfx::Insets& insets_in_dip) {
- if (scale_factor == 1.f)
- return insets_in_dip;
- return insets_in_dip.Scale(scale_factor);
-}
-
-Point ConvertPointToPixel(float scale_factor, const Point& point_in_dip) {
- if (scale_factor == 1.f)
- return point_in_dip;
- return ScaleToFlooredPoint(point_in_dip, scale_factor);
-}
-
-PointF ConvertPointToPixel(float scale_factor, const PointF& point_in_dip) {
- if (scale_factor == 1.f)
- return point_in_dip;
- return ScalePoint(point_in_dip, scale_factor);
-}
-
-Size ConvertSizeToPixel(float scale_factor, const Size& size_in_dip) {
- if (scale_factor == 1.f)
- return size_in_dip;
- return ScaleToFlooredSize(size_in_dip, scale_factor);
-}
-
-Rect ConvertRectToPixel(float scale_factor, const Rect& rect_in_dip) {
- // Use ToEnclosingRect() to ensure we paint all the possible pixels
- // touched. ToEnclosingRect() floors the origin, and ceils the max
- // coordinate. To do otherwise (such as flooring the size) potentially
- // results in rounding down and not drawing all the pixels that are
- // touched.
- if (scale_factor == 1.f)
- return rect_in_dip;
- return ToEnclosingRect(
- RectF(ScalePoint(gfx::PointF(rect_in_dip.origin()), scale_factor),
- ScaleSize(gfx::SizeF(rect_in_dip.size()), scale_factor)));
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/dip_util.h b/ui/gfx/geometry/dip_util.h
deleted file mode 100644
index e88d49b007..0000000000
--- a/ui/gfx/geometry/dip_util.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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.
-
-#ifndef UI_GFX_GEOMETRY_DIP_UTIL_H_
-#define UI_GFX_GEOMETRY_DIP_UTIL_H_
-
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-class Insets;
-class Point;
-class PointF;
-class Rect;
-class Size;
-
-GFX_EXPORT gfx::Insets ConvertInsetsToDIP(float scale_factor,
- const gfx::Insets& insets_in_pixel);
-GFX_EXPORT gfx::Point ConvertPointToDIP(float scale_factor,
- const gfx::Point& point_in_pixel);
-GFX_EXPORT gfx::PointF ConvertPointToDIP(float scale_factor,
- const gfx::PointF& point_in_pixel);
-GFX_EXPORT gfx::Size ConvertSizeToDIP(float scale_factor,
- const gfx::Size& size_in_pixel);
-GFX_EXPORT gfx::Rect ConvertRectToDIP(float scale_factor,
- const gfx::Rect& rect_in_pixel);
-
-GFX_EXPORT gfx::Insets ConvertInsetsToPixel(float scale_factor,
- const gfx::Insets& insets_in_dip);
-GFX_EXPORT gfx::Point ConvertPointToPixel(float scale_factor,
- const gfx::Point& point_in_dip);
-GFX_EXPORT gfx::PointF ConvertPointToPixel(float scale_factor,
- const gfx::PointF& point_in_dip);
-GFX_EXPORT gfx::Size ConvertSizeToPixel(float scale_factor,
- const gfx::Size& size_in_dip);
-GFX_EXPORT gfx::Rect ConvertRectToPixel(float scale_factor,
- const gfx::Rect& rect_in_dip);
-} // gfx
-
-#endif // UI_GFX_GEOMETRY_DIP_UTIL_H_
diff --git a/ui/gfx/geometry/insets_unittest.cc b/ui/gfx/geometry/insets_unittest.cc
deleted file mode 100644
index 6f607d9173..0000000000
--- a/ui/gfx/geometry/insets_unittest.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2009 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 "ui/gfx/geometry/insets.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/insets_f.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/vector2d.h"
-
-TEST(InsetsTest, InsetsDefault) {
- gfx::Insets insets;
- EXPECT_EQ(0, insets.top());
- EXPECT_EQ(0, insets.left());
- EXPECT_EQ(0, insets.bottom());
- EXPECT_EQ(0, insets.right());
- EXPECT_EQ(0, insets.width());
- EXPECT_EQ(0, insets.height());
- EXPECT_TRUE(insets.IsEmpty());
-}
-
-TEST(InsetsTest, Insets) {
- gfx::Insets insets(1, 2, 3, 4);
- EXPECT_EQ(1, insets.top());
- EXPECT_EQ(2, insets.left());
- EXPECT_EQ(3, insets.bottom());
- EXPECT_EQ(4, insets.right());
- EXPECT_EQ(6, insets.width()); // Left + right.
- EXPECT_EQ(4, insets.height()); // Top + bottom.
- EXPECT_FALSE(insets.IsEmpty());
-}
-
-TEST(InsetsTest, Set) {
- gfx::Insets insets;
- insets.Set(1, 2, 3, 4);
- EXPECT_EQ(1, insets.top());
- EXPECT_EQ(2, insets.left());
- EXPECT_EQ(3, insets.bottom());
- EXPECT_EQ(4, insets.right());
-}
-
-TEST(InsetsTest, Operators) {
- gfx::Insets insets;
- insets.Set(1, 2, 3, 4);
- insets += gfx::Insets(5, 6, 7, 8);
- EXPECT_EQ(6, insets.top());
- EXPECT_EQ(8, insets.left());
- EXPECT_EQ(10, insets.bottom());
- EXPECT_EQ(12, insets.right());
-
- insets -= gfx::Insets(-1, 0, 1, 2);
- EXPECT_EQ(7, insets.top());
- EXPECT_EQ(8, insets.left());
- EXPECT_EQ(9, insets.bottom());
- EXPECT_EQ(10, insets.right());
-
- insets = gfx::Insets(10, 10, 10, 10) + gfx::Insets(5, 5, 0, -20);
- EXPECT_EQ(15, insets.top());
- EXPECT_EQ(15, insets.left());
- EXPECT_EQ(10, insets.bottom());
- EXPECT_EQ(-10, insets.right());
-
- insets = gfx::Insets(10, 10, 10, 10) - gfx::Insets(5, 5, 0, -20);
- EXPECT_EQ(5, insets.top());
- EXPECT_EQ(5, insets.left());
- EXPECT_EQ(10, insets.bottom());
- EXPECT_EQ(30, insets.right());
-}
-
-TEST(InsetsFTest, Operators) {
- gfx::InsetsF insets;
- insets.Set(1.f, 2.5f, 3.3f, 4.1f);
- insets += gfx::InsetsF(5.8f, 6.7f, 7.6f, 8.5f);
- EXPECT_FLOAT_EQ(6.8f, insets.top());
- EXPECT_FLOAT_EQ(9.2f, insets.left());
- EXPECT_FLOAT_EQ(10.9f, insets.bottom());
- EXPECT_FLOAT_EQ(12.6f, insets.right());
-
- insets -= gfx::InsetsF(-1.f, 0, 1.1f, 2.2f);
- EXPECT_FLOAT_EQ(7.8f, insets.top());
- EXPECT_FLOAT_EQ(9.2f, insets.left());
- EXPECT_FLOAT_EQ(9.8f, insets.bottom());
- EXPECT_FLOAT_EQ(10.4f, insets.right());
-
- insets = gfx::InsetsF(10, 10.1f, 10.01f, 10.001f) +
- gfx::InsetsF(5.5f, 5.f, 0, -20.2f);
- EXPECT_FLOAT_EQ(15.5f, insets.top());
- EXPECT_FLOAT_EQ(15.1f, insets.left());
- EXPECT_FLOAT_EQ(10.01f, insets.bottom());
- EXPECT_FLOAT_EQ(-10.199f, insets.right());
-
- insets = gfx::InsetsF(10, 10.1f, 10.01f, 10.001f) -
- gfx::InsetsF(5.5f, 5.f, 0, -20.2f);
- EXPECT_FLOAT_EQ(4.5f, insets.top());
- EXPECT_FLOAT_EQ(5.1f, insets.left());
- EXPECT_FLOAT_EQ(10.01f, insets.bottom());
- EXPECT_FLOAT_EQ(30.201f, insets.right());
-}
-
-TEST(InsetsTest, Equality) {
- gfx::Insets insets1;
- insets1.Set(1, 2, 3, 4);
- gfx::Insets insets2;
- // Test operator== and operator!=.
- EXPECT_FALSE(insets1 == insets2);
- EXPECT_TRUE(insets1 != insets2);
-
- insets2.Set(1, 2, 3, 4);
- EXPECT_TRUE(insets1 == insets2);
- EXPECT_FALSE(insets1 != insets2);
-}
-
-TEST(InsetsTest, ToString) {
- gfx::Insets insets(1, 2, 3, 4);
- EXPECT_EQ("1,2,3,4", insets.ToString());
-}
-
-TEST(InsetsTest, Offset) {
- const gfx::Insets insets(1, 2, 3, 4);
- const gfx::Rect rect(5, 6, 7, 8);
- const gfx::Vector2d vector(9, 10);
-
- // Whether you inset then offset the rect, offset then inset the rect, or
- // offset the insets then apply to the rect, the outcome should be the same.
- gfx::Rect inset_first = rect;
- inset_first.Inset(insets);
- inset_first.Offset(vector);
-
- gfx::Rect offset_first = rect;
- offset_first.Offset(vector);
- offset_first.Inset(insets);
-
- gfx::Rect inset_by_offset = rect;
- inset_by_offset.Inset(insets.Offset(vector));
-
- EXPECT_EQ(inset_first, offset_first);
- EXPECT_EQ(inset_by_offset, inset_first);
-}
diff --git a/ui/gfx/geometry/matrix3_f.cc b/ui/gfx/geometry/matrix3_f.cc
deleted file mode 100644
index 1420ee539d..0000000000
--- a/ui/gfx/geometry/matrix3_f.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright (c) 2013 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 "ui/gfx/geometry/matrix3_f.h"
-
-#include <algorithm>
-#include <cmath>
-#include <limits>
-
-#include "base/numerics/math_constants.h"
-#include "base/strings/stringprintf.h"
-
-namespace {
-
-// This is only to make accessing indices self-explanatory.
-enum MatrixCoordinates {
- M00,
- M01,
- M02,
- M10,
- M11,
- M12,
- M20,
- M21,
- M22,
- M_END
-};
-
-template<typename T>
-double Determinant3x3(T data[M_END]) {
- // This routine is separated from the Matrix3F::Determinant because in
- // computing inverse we do want higher precision afforded by the explicit
- // use of 'double'.
- return
- static_cast<double>(data[M00]) * (
- static_cast<double>(data[M11]) * data[M22] -
- static_cast<double>(data[M12]) * data[M21]) +
- static_cast<double>(data[M01]) * (
- static_cast<double>(data[M12]) * data[M20] -
- static_cast<double>(data[M10]) * data[M22]) +
- static_cast<double>(data[M02]) * (
- static_cast<double>(data[M10]) * data[M21] -
- static_cast<double>(data[M11]) * data[M20]);
-}
-
-} // namespace
-
-namespace gfx {
-
-Matrix3F::Matrix3F() {
-}
-
-Matrix3F::~Matrix3F() {
-}
-
-// static
-Matrix3F Matrix3F::Zeros() {
- Matrix3F matrix;
- matrix.set(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
- return matrix;
-}
-
-// static
-Matrix3F Matrix3F::Ones() {
- Matrix3F matrix;
- matrix.set(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
- return matrix;
-}
-
-// static
-Matrix3F Matrix3F::Identity() {
- Matrix3F matrix;
- matrix.set(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
- return matrix;
-}
-
-// static
-Matrix3F Matrix3F::FromOuterProduct(const Vector3dF& a, const Vector3dF& bt) {
- Matrix3F matrix;
- matrix.set(a.x() * bt.x(), a.x() * bt.y(), a.x() * bt.z(),
- a.y() * bt.x(), a.y() * bt.y(), a.y() * bt.z(),
- a.z() * bt.x(), a.z() * bt.y(), a.z() * bt.z());
- return matrix;
-}
-
-bool Matrix3F::IsEqual(const Matrix3F& rhs) const {
- return 0 == memcmp(data_, rhs.data_, sizeof(data_));
-}
-
-bool Matrix3F::IsNear(const Matrix3F& rhs, float precision) const {
- DCHECK(precision >= 0);
- for (int i = 0; i < M_END; ++i) {
- if (std::abs(data_[i] - rhs.data_[i]) > precision)
- return false;
- }
- return true;
-}
-
-Matrix3F Matrix3F::Add(const Matrix3F& rhs) const {
- Matrix3F result;
- for (int i = 0; i < M_END; ++i)
- result.data_[i] = data_[i] + rhs.data_[i];
- return result;
-}
-
-Matrix3F Matrix3F::Subtract(const Matrix3F& rhs) const {
- Matrix3F result;
- for (int i = 0; i < M_END; ++i)
- result.data_[i] = data_[i] - rhs.data_[i];
- return result;
-}
-
-Matrix3F Matrix3F::Inverse() const {
- Matrix3F inverse = Matrix3F::Zeros();
- double determinant = Determinant3x3(data_);
- if (std::numeric_limits<float>::epsilon() > std::abs(determinant))
- return inverse; // Singular matrix. Return Zeros().
-
- inverse.set(
- static_cast<float>((data_[M11] * data_[M22] - data_[M12] * data_[M21]) /
- determinant),
- static_cast<float>((data_[M02] * data_[M21] - data_[M01] * data_[M22]) /
- determinant),
- static_cast<float>((data_[M01] * data_[M12] - data_[M02] * data_[M11]) /
- determinant),
- static_cast<float>((data_[M12] * data_[M20] - data_[M10] * data_[M22]) /
- determinant),
- static_cast<float>((data_[M00] * data_[M22] - data_[M02] * data_[M20]) /
- determinant),
- static_cast<float>((data_[M02] * data_[M10] - data_[M00] * data_[M12]) /
- determinant),
- static_cast<float>((data_[M10] * data_[M21] - data_[M11] * data_[M20]) /
- determinant),
- static_cast<float>((data_[M01] * data_[M20] - data_[M00] * data_[M21]) /
- determinant),
- static_cast<float>((data_[M00] * data_[M11] - data_[M01] * data_[M10]) /
- determinant));
- return inverse;
-}
-
-Matrix3F Matrix3F::Transpose() const {
- Matrix3F transpose;
- transpose.set(data_[M00], data_[M10], data_[M20], data_[M01], data_[M11],
- data_[M21], data_[M02], data_[M12], data_[M22]);
- return transpose;
-}
-
-float Matrix3F::Determinant() const {
- return static_cast<float>(Determinant3x3(data_));
-}
-
-Vector3dF Matrix3F::SolveEigenproblem(Matrix3F* eigenvectors) const {
- // The matrix must be symmetric.
- const float epsilon = std::numeric_limits<float>::epsilon();
- if (std::abs(data_[M01] - data_[M10]) > epsilon ||
- std::abs(data_[M02] - data_[M20]) > epsilon ||
- std::abs(data_[M12] - data_[M21]) > epsilon) {
- NOTREACHED();
- return Vector3dF();
- }
-
- float eigenvalues[3];
- float p =
- data_[M01] * data_[M01] +
- data_[M02] * data_[M02] +
- data_[M12] * data_[M12];
-
- bool diagonal = std::abs(p) < epsilon;
- if (diagonal) {
- eigenvalues[0] = data_[M00];
- eigenvalues[1] = data_[M11];
- eigenvalues[2] = data_[M22];
- } else {
- float q = Trace() / 3.0f;
- p = (data_[M00] - q) * (data_[M00] - q) +
- (data_[M11] - q) * (data_[M11] - q) +
- (data_[M22] - q) * (data_[M22] - q) +
- 2 * p;
- p = std::sqrt(p / 6);
-
- // The computation below puts B as (A - qI) / p, where A is *this.
- Matrix3F matrix_b(*this);
- matrix_b.data_[M00] -= q;
- matrix_b.data_[M11] -= q;
- matrix_b.data_[M22] -= q;
- for (int i = 0; i < M_END; ++i)
- matrix_b.data_[i] /= p;
-
- double half_det_b = Determinant3x3(matrix_b.data_) / 2.0;
- // half_det_b should be in <-1, 1>, but beware of rounding error.
- double phi = 0.0f;
- if (half_det_b <= -1.0)
- phi = base::kPiDouble / 3;
- else if (half_det_b < 1.0)
- phi = acos(half_det_b) / 3;
-
- eigenvalues[0] = q + 2 * p * static_cast<float>(cos(phi));
- eigenvalues[2] =
- q + 2 * p * static_cast<float>(cos(phi + 2.0 * base::kPiDouble / 3.0));
- eigenvalues[1] = 3 * q - eigenvalues[0] - eigenvalues[2];
- }
-
- // Put eigenvalues in the descending order.
- int indices[3] = {0, 1, 2};
- if (eigenvalues[2] > eigenvalues[1]) {
- std::swap(eigenvalues[2], eigenvalues[1]);
- std::swap(indices[2], indices[1]);
- }
-
- if (eigenvalues[1] > eigenvalues[0]) {
- std::swap(eigenvalues[1], eigenvalues[0]);
- std::swap(indices[1], indices[0]);
- }
-
- if (eigenvalues[2] > eigenvalues[1]) {
- std::swap(eigenvalues[2], eigenvalues[1]);
- std::swap(indices[2], indices[1]);
- }
-
- if (eigenvectors != NULL && diagonal) {
- // Eigenvectors are e-vectors, just need to be sorted accordingly.
- *eigenvectors = Zeros();
- for (int i = 0; i < 3; ++i)
- eigenvectors->set(indices[i], i, 1.0f);
- } else if (eigenvectors != NULL) {
- // Consult the following for a detailed discussion:
- // Joachim Kopp
- // Numerical diagonalization of hermitian 3x3 matrices
- // arXiv.org preprint: physics/0610206
- // Int. J. Mod. Phys. C19 (2008) 523-548
-
- // TODO(motek): expand to handle correctly negative and multiple
- // eigenvalues.
- for (int i = 0; i < 3; ++i) {
- float l = eigenvalues[i];
- // B = A - l * I
- Matrix3F matrix_b(*this);
- matrix_b.data_[M00] -= l;
- matrix_b.data_[M11] -= l;
- matrix_b.data_[M22] -= l;
- Vector3dF e1 = CrossProduct(matrix_b.get_column(0),
- matrix_b.get_column(1));
- Vector3dF e2 = CrossProduct(matrix_b.get_column(1),
- matrix_b.get_column(2));
- Vector3dF e3 = CrossProduct(matrix_b.get_column(2),
- matrix_b.get_column(0));
-
- // e1, e2 and e3 should point in the same direction.
- if (DotProduct(e1, e2) < 0)
- e2 = -e2;
-
- if (DotProduct(e1, e3) < 0)
- e3 = -e3;
-
- Vector3dF eigvec = e1 + e2 + e3;
- // Normalize.
- eigvec.Scale(1.0f / eigvec.Length());
- eigenvectors->set_column(i, eigvec);
- }
- }
-
- return Vector3dF(eigenvalues[0], eigenvalues[1], eigenvalues[2]);
-}
-
-Matrix3F MatrixProduct(const Matrix3F& lhs, const Matrix3F& rhs) {
- Matrix3F result = Matrix3F::Zeros();
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++) {
- result.set(i, j, DotProduct(lhs.get_row(i), rhs.get_column(j)));
- }
- }
- return result;
-}
-
-Vector3dF MatrixProduct(const Matrix3F& lhs, const Vector3dF& rhs) {
- return Vector3dF(DotProduct(lhs.get_row(0), rhs),
- DotProduct(lhs.get_row(1), rhs),
- DotProduct(lhs.get_row(2), rhs));
-}
-
-std::string Matrix3F::ToString() const {
- return base::StringPrintf(
- "[[%+0.4f, %+0.4f, %+0.4f],"
- " [%+0.4f, %+0.4f, %+0.4f],"
- " [%+0.4f, %+0.4f, %+0.4f]]",
- data_[M00], data_[M01], data_[M02], data_[M10], data_[M11], data_[M12],
- data_[M20], data_[M21], data_[M22]);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/matrix3_f.h b/ui/gfx/geometry/matrix3_f.h
deleted file mode 100644
index 7fab2e3e7c..0000000000
--- a/ui/gfx/geometry/matrix3_f.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2013 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.
-
-#ifndef UI_GFX_GEOMETRY_MATRIX3_F_H_
-#define UI_GFX_GEOMETRY_MATRIX3_F_H_
-
-#include "base/logging.h"
-#include "ui/gfx/geometry/vector3d_f.h"
-
-namespace gfx {
-
-class GFX_EXPORT Matrix3F {
- public:
- ~Matrix3F();
-
- static Matrix3F Zeros();
- static Matrix3F Ones();
- static Matrix3F Identity();
- static Matrix3F FromOuterProduct(const Vector3dF& a, const Vector3dF& bt);
-
- bool IsEqual(const Matrix3F& rhs) const;
-
- // Element-wise comparison with given precision.
- bool IsNear(const Matrix3F& rhs, float precision) const;
-
- float get(int i, int j) const {
- return data_[MatrixToArrayCoords(i, j)];
- }
-
- void set(int i, int j, float v) {
- data_[MatrixToArrayCoords(i, j)] = v;
- }
-
- void set(float m00, float m01, float m02,
- float m10, float m11, float m12,
- float m20, float m21, float m22) {
- data_[0] = m00;
- data_[1] = m01;
- data_[2] = m02;
- data_[3] = m10;
- data_[4] = m11;
- data_[5] = m12;
- data_[6] = m20;
- data_[7] = m21;
- data_[8] = m22;
- }
-
- Vector3dF get_row(int i) const {
- return Vector3dF(data_[MatrixToArrayCoords(i, 0)],
- data_[MatrixToArrayCoords(i, 1)],
- data_[MatrixToArrayCoords(i, 2)]);
- }
-
- Vector3dF get_column(int i) const {
- return Vector3dF(
- data_[MatrixToArrayCoords(0, i)],
- data_[MatrixToArrayCoords(1, i)],
- data_[MatrixToArrayCoords(2, i)]);
- }
-
- void set_column(int i, const Vector3dF& c) {
- data_[MatrixToArrayCoords(0, i)] = c.x();
- data_[MatrixToArrayCoords(1, i)] = c.y();
- data_[MatrixToArrayCoords(2, i)] = c.z();
- }
-
- // Produces a new matrix by adding the elements of |rhs| to this matrix
- Matrix3F Add(const Matrix3F& rhs) const;
- // Produces a new matrix by subtracting elements of |rhs| from this matrix.
- Matrix3F Subtract(const Matrix3F& rhs) const;
-
- // Returns an inverse of this if the matrix is non-singular, zero (== Zero())
- // otherwise.
- Matrix3F Inverse() const;
-
- // Returns a transpose of this matrix.
- Matrix3F Transpose() const;
-
- // Value of the determinant of the matrix.
- float Determinant() const;
-
- // Trace (sum of diagonal elements) of the matrix.
- float Trace() const {
- return data_[MatrixToArrayCoords(0, 0)] +
- data_[MatrixToArrayCoords(1, 1)] +
- data_[MatrixToArrayCoords(2, 2)];
- }
-
- // Compute eigenvalues and (optionally) normalized eigenvectors of
- // a positive defnite matrix *this. Eigenvectors are computed only if
- // non-null |eigenvectors| matrix is passed. If it is NULL, the routine
- // will not attempt to compute eigenvectors but will still return eigenvalues
- // if they can be computed.
- // If eigenvalues cannot be computed (the matrix does not meet constraints)
- // the 0-vector is returned. Note that to retrieve eigenvalues, the matrix
- // only needs to be symmetric while eigenvectors require it to be
- // positive-definite. Passing a non-positive definite matrix will result in
- // NaNs in vectors which cannot be computed.
- // Eigenvectors are placed as column in |eigenvectors| in order corresponding
- // to eigenvalues.
- Vector3dF SolveEigenproblem(Matrix3F* eigenvectors) const;
-
- std::string ToString() const;
-
- private:
- Matrix3F(); // Uninitialized default.
-
- static int MatrixToArrayCoords(int i, int j) {
- DCHECK(i >= 0 && i < 3);
- DCHECK(j >= 0 && j < 3);
- return i * 3 + j;
- }
-
- float data_[9];
-};
-
-inline bool operator==(const Matrix3F& lhs, const Matrix3F& rhs) {
- return lhs.IsEqual(rhs);
-}
-
-// Matrix addition. Produces a new matrix by adding the corresponding elements
-// together.
-inline Matrix3F operator+(const Matrix3F& lhs, const Matrix3F& rhs) {
- return lhs.Add(rhs);
-}
-
-// Matrix subtraction. Produces a new matrix by subtracting elements of rhs
-// from corresponding elements of lhs.
-inline Matrix3F operator-(const Matrix3F& lhs, const Matrix3F& rhs) {
- return lhs.Subtract(rhs);
-}
-
-GFX_EXPORT Matrix3F MatrixProduct(const Matrix3F& lhs, const Matrix3F& rhs);
-GFX_EXPORT Vector3dF MatrixProduct(const Matrix3F& lhs, const Vector3dF& rhs);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_MATRIX3_F_H_
diff --git a/ui/gfx/geometry/matrix3_unittest.cc b/ui/gfx/geometry/matrix3_unittest.cc
deleted file mode 100644
index 27e9182f94..0000000000
--- a/ui/gfx/geometry/matrix3_unittest.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2013 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 <cmath>
-#include <limits>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/matrix3_f.h"
-
-namespace gfx {
-namespace {
-
-TEST(Matrix3fTest, Constructors) {
- Matrix3F zeros = Matrix3F::Zeros();
- Matrix3F ones = Matrix3F::Ones();
- Matrix3F identity = Matrix3F::Identity();
-
- Matrix3F product_ones = Matrix3F::FromOuterProduct(
- Vector3dF(1.0f, 1.0f, 1.0f), Vector3dF(1.0f, 1.0f, 1.0f));
- Matrix3F product_zeros = Matrix3F::FromOuterProduct(
- Vector3dF(1.0f, 1.0f, 1.0f), Vector3dF(0.0f, 0.0f, 0.0f));
- EXPECT_EQ(ones, product_ones);
- EXPECT_EQ(zeros, product_zeros);
-
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j)
- EXPECT_EQ(i == j ? 1.0f : 0.0f, identity.get(i, j));
- }
-}
-
-TEST(Matrix3fTest, DataAccess) {
- Matrix3F matrix = Matrix3F::Ones();
- Matrix3F identity = Matrix3F::Identity();
-
- EXPECT_EQ(Vector3dF(0.0f, 1.0f, 0.0f), identity.get_column(1));
- EXPECT_EQ(Vector3dF(0.0f, 1.0f, 0.0f), identity.get_row(1));
- matrix.set(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
- EXPECT_EQ(Vector3dF(2.0f, 5.0f, 8.0f), matrix.get_column(2));
- EXPECT_EQ(Vector3dF(6.0f, 7.0f, 8.0f), matrix.get_row(2));
- matrix.set_column(0, Vector3dF(0.1f, 0.2f, 0.3f));
- matrix.set_column(0, Vector3dF(0.1f, 0.2f, 0.3f));
- EXPECT_EQ(Vector3dF(0.1f, 0.2f, 0.3f), matrix.get_column(0));
- EXPECT_EQ(Vector3dF(0.1f, 1.0f, 2.0f), matrix.get_row(0));
-
- EXPECT_EQ(0.1f, matrix.get(0, 0));
- EXPECT_EQ(5.0f, matrix.get(1, 2));
-}
-
-TEST(Matrix3fTest, Determinant) {
- EXPECT_EQ(1.0f, Matrix3F::Identity().Determinant());
- EXPECT_EQ(0.0f, Matrix3F::Zeros().Determinant());
- EXPECT_EQ(0.0f, Matrix3F::Ones().Determinant());
-
- // Now for something non-trivial...
- Matrix3F matrix = Matrix3F::Zeros();
- matrix.set(0, 5, 6, 8, 7, 0, 1, 9, 0);
- EXPECT_EQ(390.0f, matrix.Determinant());
- matrix.set(2, 0, 3 * matrix.get(0, 0));
- matrix.set(2, 1, 3 * matrix.get(0, 1));
- matrix.set(2, 2, 3 * matrix.get(0, 2));
- EXPECT_EQ(0, matrix.Determinant());
-
- matrix.set(0.57f, 0.205f, 0.942f,
- 0.314f, 0.845f, 0.826f,
- 0.131f, 0.025f, 0.962f);
- EXPECT_NEAR(0.3149f, matrix.Determinant(), 0.0001f);
-}
-
-TEST(Matrix3fTest, Inverse) {
- Matrix3F identity = Matrix3F::Identity();
- Matrix3F inv_identity = identity.Inverse();
- EXPECT_EQ(identity, inv_identity);
-
- Matrix3F singular = Matrix3F::Zeros();
- singular.set(1.0f, 3.0f, 4.0f,
- 2.0f, 11.0f, 5.0f,
- 0.5f, 1.5f, 2.0f);
- EXPECT_EQ(0, singular.Determinant());
- EXPECT_EQ(Matrix3F::Zeros(), singular.Inverse());
-
- Matrix3F regular = Matrix3F::Zeros();
- regular.set(0.57f, 0.205f, 0.942f,
- 0.314f, 0.845f, 0.826f,
- 0.131f, 0.025f, 0.962f);
- Matrix3F inv_regular = regular.Inverse();
- regular.set(2.51540616f, -0.55138018f, -1.98968043f,
- -0.61552266f, 1.34920184f, -0.55573636f,
- -0.32653861f, 0.04002158f, 1.32488726f);
- EXPECT_TRUE(regular.IsNear(inv_regular, 0.00001f));
-}
-
-TEST(Matrix3fTest, Transpose) {
- Matrix3F matrix = Matrix3F::Zeros();
-
- matrix.set(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
-
- Matrix3F transpose = matrix.Transpose();
- EXPECT_EQ(Vector3dF(0.0f, 1.0f, 2.0f), transpose.get_column(0));
- EXPECT_EQ(Vector3dF(3.0f, 4.0f, 5.0f), transpose.get_column(1));
- EXPECT_EQ(Vector3dF(6.0f, 7.0f, 8.0f), transpose.get_column(2));
-
- EXPECT_TRUE(matrix.IsEqual(transpose.Transpose()));
-}
-
-TEST(Matrix3fTest, EigenvectorsIdentity) {
- // This block tests the trivial case of eigenvalues of the identity matrix.
- Matrix3F identity = Matrix3F::Identity();
- Vector3dF eigenvals = identity.SolveEigenproblem(NULL);
- EXPECT_EQ(Vector3dF(1.0f, 1.0f, 1.0f), eigenvals);
-}
-
-TEST(Matrix3fTest, EigenvectorsDiagonal) {
- // This block tests the another trivial case of eigenvalues of a diagonal
- // matrix. Here we expect values to be sorted.
- Matrix3F matrix = Matrix3F::Zeros();
- matrix.set(0, 0, 1.0f);
- matrix.set(1, 1, -2.5f);
- matrix.set(2, 2, 3.14f);
- Matrix3F eigenvectors = Matrix3F::Zeros();
- Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors);
- EXPECT_EQ(Vector3dF(3.14f, 1.0f, -2.5f), eigenvals);
-
- EXPECT_EQ(Vector3dF(0.0f, 0.0f, 1.0f), eigenvectors.get_column(0));
- EXPECT_EQ(Vector3dF(1.0f, 0.0f, 0.0f), eigenvectors.get_column(1));
- EXPECT_EQ(Vector3dF(0.0f, 1.0f, 0.0f), eigenvectors.get_column(2));
-}
-
-TEST(Matrix3fTest, EigenvectorsNiceNotPositive) {
- // This block tests computation of eigenvectors of a matrix where nice
- // round values are expected.
- Matrix3F matrix = Matrix3F::Zeros();
- // This is not a positive-definite matrix but eigenvalues and the first
- // eigenvector should nonetheless be computed correctly.
- matrix.set(3, 2, 4, 2, 0, 2, 4, 2, 3);
- Matrix3F eigenvectors = Matrix3F::Zeros();
- Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors);
- EXPECT_EQ(Vector3dF(8.0f, -1.0f, -1.0f), eigenvals);
-
- Vector3dF expected_principal(0.66666667f, 0.33333333f, 0.66666667f);
- EXPECT_NEAR(0.0f,
- (expected_principal - eigenvectors.get_column(0)).Length(),
- 0.000001f);
-}
-
-TEST(Matrix3fTest, EigenvectorsPositiveDefinite) {
- // This block tests computation of eigenvectors of a matrix where output
- // is not as nice as above, but it actually meets the definition.
- Matrix3F matrix = Matrix3F::Zeros();
- Matrix3F eigenvectors = Matrix3F::Zeros();
- Matrix3F expected_eigenvectors = Matrix3F::Zeros();
- matrix.set(1, -1, 2, -1, 4, 5, 2, 5, 0);
- Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors);
- Vector3dF expected_eigv(7.3996266f, 1.91197255f, -4.31159915f);
- expected_eigv -= eigenvals;
- EXPECT_NEAR(0, expected_eigv.LengthSquared(), 0.00001f);
- expected_eigenvectors.set(0.04926317f, -0.92135662f, -0.38558414f,
- 0.82134249f, 0.25703273f, -0.50924521f,
- 0.56830419f, -0.2916096f, 0.76941158f);
- EXPECT_TRUE(expected_eigenvectors.IsNear(eigenvectors, 0.00001f));
-}
-
-TEST(Matrix3fTest, Operators) {
- Matrix3F matrix1 = Matrix3F::Zeros();
- matrix1.set(1, 2, 3, 4, 5, 6, 7, 8, 9);
- EXPECT_EQ(matrix1 + Matrix3F::Zeros(), matrix1);
-
- Matrix3F matrix2 = Matrix3F::Zeros();
- matrix2.set(-1, -2, -3, -4, -5, -6, -7, -8, -9);
- EXPECT_EQ(matrix1 + matrix2, Matrix3F::Zeros());
-
- EXPECT_EQ(Matrix3F::Zeros() - matrix1, matrix2);
-
- Matrix3F result = Matrix3F::Zeros();
- result.set(2, 4, 6, 8, 10, 12, 14, 16, 18);
- EXPECT_EQ(matrix1 - matrix2, result);
- result.set(-2, -4, -6, -8, -10, -12, -14, -16, -18);
- EXPECT_EQ(matrix2 - matrix1, result);
-}
-
-} // namespace
-} // namespace gfx
diff --git a/ui/gfx/geometry/mojo/BUILD.gn b/ui/gfx/geometry/mojo/BUILD.gn
new file mode 100644
index 0000000000..2d0e1efbcf
--- /dev/null
+++ b/ui/gfx/geometry/mojo/BUILD.gn
@@ -0,0 +1,51 @@
+# Copyright 2016 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+# This target does NOT depend on skia. One can depend on this target to avoid
+# picking up a dependency on skia.
+mojom("mojo") {
+ sources = [
+ "geometry.mojom",
+ ]
+
+ check_includes_blink = false
+}
+
+mojom("test_interfaces") {
+ sources = [
+ "geometry_traits_test_service.mojom",
+ ]
+
+ public_deps = [
+ ":mojo",
+ ]
+}
+
+source_set("unit_test") {
+ testonly = true
+
+ sources = [
+ "geometry_struct_traits_unittest.cc",
+ ]
+
+ deps = [
+ ":test_interfaces",
+ "//base",
+ "//mojo/public/cpp/bindings",
+ "//testing/gtest",
+ "//ui/gfx/geometry",
+ ]
+}
+
+source_set("struct_traits") {
+ sources = [
+ "geometry_struct_traits.h",
+ ]
+ public_deps = [
+ ":mojo_shared_cpp_sources",
+ "//ui/gfx/geometry",
+ ]
+}
diff --git a/ui/gfx/geometry/point3_f.cc b/ui/gfx/geometry/point3_f.cc
deleted file mode 100644
index 465376e55e..0000000000
--- a/ui/gfx/geometry/point3_f.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 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.
-
-#include "ui/gfx/geometry/point3_f.h"
-
-#include "base/strings/stringprintf.h"
-
-namespace gfx {
-
-std::string Point3F::ToString() const {
- return base::StringPrintf("%f,%f,%f", x_, y_, z_);
-}
-
-Point3F operator+(const Point3F& lhs, const Vector3dF& rhs) {
- float x = lhs.x() + rhs.x();
- float y = lhs.y() + rhs.y();
- float z = lhs.z() + rhs.z();
- return Point3F(x, y, z);
-}
-
-// Subtract a vector from a point, producing a new point offset by the vector's
-// inverse.
-Point3F operator-(const Point3F& lhs, const Vector3dF& rhs) {
- float x = lhs.x() - rhs.x();
- float y = lhs.y() - rhs.y();
- float z = lhs.z() - rhs.z();
- return Point3F(x, y, z);
-}
-
-// Subtract one point from another, producing a vector that represents the
-// distances between the two points along each axis.
-Vector3dF operator-(const Point3F& lhs, const Point3F& rhs) {
- float x = lhs.x() - rhs.x();
- float y = lhs.y() - rhs.y();
- float z = lhs.z() - rhs.z();
- return Vector3dF(x, y, z);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/point3_f.h b/ui/gfx/geometry/point3_f.h
deleted file mode 100644
index 15a560c497..0000000000
--- a/ui/gfx/geometry/point3_f.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2011 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.
-
-#ifndef UI_GFX_GEOMETRY_POINT3_F_H_
-#define UI_GFX_GEOMETRY_POINT3_F_H_
-
-#include <iosfwd>
-#include <string>
-
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/vector3d_f.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-// A point has an x, y and z coordinate.
-class GFX_EXPORT Point3F {
- public:
- constexpr Point3F() : x_(0), y_(0), z_(0) {}
- constexpr Point3F(float x, float y, float z) : x_(x), y_(y), z_(z) {}
-
- constexpr explicit Point3F(const PointF& point)
- : x_(point.x()), y_(point.y()), z_(0) {}
-
- void Scale(float scale) {
- Scale(scale, scale, scale);
- }
-
- void Scale(float x_scale, float y_scale, float z_scale) {
- SetPoint(x() * x_scale, y() * y_scale, z() * z_scale);
- }
-
- constexpr float x() const { return x_; }
- constexpr float y() const { return y_; }
- constexpr float z() const { return z_; }
-
- void set_x(float x) { x_ = x; }
- void set_y(float y) { y_ = y; }
- void set_z(float z) { z_ = z; }
-
- void SetPoint(float x, float y, float z) {
- x_ = x;
- y_ = y;
- z_ = z;
- }
-
- // Offset the point by the given vector.
- void operator+=(const Vector3dF& v) {
- x_ += v.x();
- y_ += v.y();
- z_ += v.z();
- }
-
- // Offset the point by the given vector's inverse.
- void operator-=(const Vector3dF& v) {
- x_ -= v.x();
- y_ -= v.y();
- z_ -= v.z();
- }
-
- // Returns the squared euclidean distance between two points.
- float SquaredDistanceTo(const Point3F& other) const {
- float dx = x_ - other.x_;
- float dy = y_ - other.y_;
- float dz = z_ - other.z_;
- return dx * dx + dy * dy + dz * dz;
- }
-
- PointF AsPointF() const { return PointF(x_, y_); }
-
- // Returns a string representation of 3d point.
- std::string ToString() const;
-
- private:
- float x_;
- float y_;
- float z_;
-
- // copy/assign are allowed.
-};
-
-inline bool operator==(const Point3F& lhs, const Point3F& rhs) {
- return lhs.x() == rhs.x() && lhs.y() == rhs.y() && lhs.z() == rhs.z();
-}
-
-inline bool operator!=(const Point3F& lhs, const Point3F& rhs) {
- return !(lhs == rhs);
-}
-
-// Add a vector to a point, producing a new point offset by the vector.
-GFX_EXPORT Point3F operator+(const Point3F& lhs, const Vector3dF& rhs);
-
-// Subtract a vector from a point, producing a new point offset by the vector's
-// inverse.
-GFX_EXPORT Point3F operator-(const Point3F& lhs, const Vector3dF& rhs);
-
-// Subtract one point from another, producing a vector that represents the
-// distances between the two points along each axis.
-GFX_EXPORT Vector3dF operator-(const Point3F& lhs, const Point3F& rhs);
-
-inline Point3F PointAtOffsetFromOrigin(const Vector3dF& offset) {
- return Point3F(offset.x(), offset.y(), offset.z());
-}
-
-inline Point3F ScalePoint(const Point3F& p,
- float x_scale,
- float y_scale,
- float z_scale) {
- return Point3F(p.x() * x_scale, p.y() * y_scale, p.z() * z_scale);
-}
-
-inline Point3F ScalePoint(const Point3F& p, const Vector3dF& v) {
- return Point3F(p.x() * v.x(), p.y() * v.y(), p.z() * v.z());
-}
-
-inline Point3F ScalePoint(const Point3F& p, float scale) {
- return ScalePoint(p, scale, scale, scale);
-}
-
-// This is declared here for use in gtest-based unit tests but is defined in
-// the //ui/gfx:test_support target. Depend on that to use this in your unit
-// test. This should not be used in production code - call ToString() instead.
-void PrintTo(const Point3F& point, ::std::ostream* os);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_POINT3_F_H_
diff --git a/ui/gfx/geometry/point3_unittest.cc b/ui/gfx/geometry/point3_unittest.cc
deleted file mode 100644
index 999b1f43c8..0000000000
--- a/ui/gfx/geometry/point3_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 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.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/point3_f.h"
-
-namespace gfx {
-
-TEST(Point3Test, VectorArithmetic) {
- gfx::Point3F a(1.6f, 5.1f, 3.2f);
- gfx::Vector3dF v1(3.1f, -3.2f, 9.3f);
- gfx::Vector3dF v2(-8.1f, 1.2f, 3.3f);
-
- static const struct {
- gfx::Point3F expected;
- gfx::Point3F actual;
- } tests[] = {
- { gfx::Point3F(4.7f, 1.9f, 12.5f), a + v1 },
- { gfx::Point3F(-1.5f, 8.3f, -6.1f), a - v1 },
- { a, a - v1 + v1 },
- { a, a + v1 - v1 },
- { a, a + gfx::Vector3dF() },
- { gfx::Point3F(12.8f, 0.7f, 9.2f), a + v1 - v2 },
- { gfx::Point3F(-9.6f, 9.5f, -2.8f), a - v1 + v2 }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i)
- EXPECT_EQ(tests[i].expected.ToString(),
- tests[i].actual.ToString());
-
- a += v1;
- EXPECT_EQ(Point3F(4.7f, 1.9f, 12.5f).ToString(), a.ToString());
-
- a -= v2;
- EXPECT_EQ(Point3F(12.8f, 0.7f, 9.2f).ToString(), a.ToString());
-}
-
-TEST(Point3Test, VectorFromPoints) {
- gfx::Point3F a(1.6f, 5.2f, 3.2f);
- gfx::Vector3dF v1(3.1f, -3.2f, 9.3f);
-
- gfx::Point3F b(a + v1);
- EXPECT_EQ((b - a).ToString(), v1.ToString());
-}
-
-TEST(Point3Test, Scale) {
- EXPECT_EQ(Point3F().ToString(), ScalePoint(Point3F(), 2.f).ToString());
- EXPECT_EQ(Point3F().ToString(),
- ScalePoint(Point3F(), 2.f, 2.f, 2.f).ToString());
-
- EXPECT_EQ(Point3F(2.f, -2.f, 4.f).ToString(),
- ScalePoint(Point3F(1.f, -1.f, 2.f), 2.f).ToString());
- EXPECT_EQ(Point3F(2.f, -3.f, 8.f).ToString(),
- ScalePoint(Point3F(1.f, -1.f, 2.f), 2.f, 3.f, 4.f).ToString());
-
- Point3F zero;
- zero.Scale(2.f);
- zero.Scale(6.f, 3.f, 1.5f);
- EXPECT_EQ(Point3F().ToString(), zero.ToString());
-
- Point3F point(1.f, -1.f, 2.f);
- point.Scale(2.f);
- point.Scale(6.f, 3.f, 1.5f);
- EXPECT_EQ(Point3F(12.f, -6.f, 6.f).ToString(), point.ToString());
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/point_unittest.cc b/ui/gfx/geometry/point_unittest.cc
deleted file mode 100644
index b453dd7684..0000000000
--- a/ui/gfx/geometry/point_unittest.cc
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright (c) 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.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/point_f.h"
-
-namespace gfx {
-
-TEST(PointTest, ToPointF) {
- // Check that explicit conversion from integer to float compiles.
- Point a(10, 20);
- PointF b = PointF(a);
-
- EXPECT_EQ(static_cast<float>(a.x()), b.x());
- EXPECT_EQ(static_cast<float>(a.y()), b.y());
-}
-
-TEST(PointTest, IsOrigin) {
- EXPECT_FALSE(Point(1, 0).IsOrigin());
- EXPECT_FALSE(Point(0, 1).IsOrigin());
- EXPECT_FALSE(Point(1, 2).IsOrigin());
- EXPECT_FALSE(Point(-1, 0).IsOrigin());
- EXPECT_FALSE(Point(0, -1).IsOrigin());
- EXPECT_FALSE(Point(-1, -2).IsOrigin());
- EXPECT_TRUE(Point(0, 0).IsOrigin());
-
- EXPECT_FALSE(PointF(0.1f, 0).IsOrigin());
- EXPECT_FALSE(PointF(0, 0.1f).IsOrigin());
- EXPECT_FALSE(PointF(0.1f, 2).IsOrigin());
- EXPECT_FALSE(PointF(-0.1f, 0).IsOrigin());
- EXPECT_FALSE(PointF(0, -0.1f).IsOrigin());
- EXPECT_FALSE(PointF(-0.1f, -2).IsOrigin());
- EXPECT_TRUE(PointF(0, 0).IsOrigin());
-}
-
-TEST(PointTest, VectorArithmetic) {
- Point a(1, 5);
- Vector2d v1(3, -3);
- Vector2d v2(-8, 1);
-
- static const struct {
- Point expected;
- Point actual;
- } tests[] = {
- { Point(4, 2), a + v1 },
- { Point(-2, 8), a - v1 },
- { a, a - v1 + v1 },
- { a, a + v1 - v1 },
- { a, a + Vector2d() },
- { Point(12, 1), a + v1 - v2 },
- { Point(-10, 9), a - v1 + v2 }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i)
- EXPECT_EQ(tests[i].expected.ToString(), tests[i].actual.ToString());
-}
-
-TEST(PointTest, OffsetFromPoint) {
- Point a(1, 5);
- Point b(-20, 8);
- EXPECT_EQ(Vector2d(-20 - 1, 8 - 5).ToString(), (b - a).ToString());
-}
-
-TEST(PointTest, ToRoundedPoint) {
- EXPECT_EQ(Point(0, 0), ToRoundedPoint(PointF(0, 0)));
- EXPECT_EQ(Point(0, 0), ToRoundedPoint(PointF(0.0001f, 0.0001f)));
- EXPECT_EQ(Point(0, 0), ToRoundedPoint(PointF(0.4999f, 0.4999f)));
- EXPECT_EQ(Point(1, 1), ToRoundedPoint(PointF(0.5f, 0.5f)));
- EXPECT_EQ(Point(1, 1), ToRoundedPoint(PointF(0.9999f, 0.9999f)));
-
- EXPECT_EQ(Point(10, 10), ToRoundedPoint(PointF(10, 10)));
- EXPECT_EQ(Point(10, 10), ToRoundedPoint(PointF(10.0001f, 10.0001f)));
- EXPECT_EQ(Point(10, 10), ToRoundedPoint(PointF(10.4999f, 10.4999f)));
- EXPECT_EQ(Point(11, 11), ToRoundedPoint(PointF(10.5f, 10.5f)));
- EXPECT_EQ(Point(11, 11), ToRoundedPoint(PointF(10.9999f, 10.9999f)));
-
- EXPECT_EQ(Point(-10, -10), ToRoundedPoint(PointF(-10, -10)));
- EXPECT_EQ(Point(-10, -10), ToRoundedPoint(PointF(-10.0001f, -10.0001f)));
- EXPECT_EQ(Point(-10, -10), ToRoundedPoint(PointF(-10.4999f, -10.4999f)));
- EXPECT_EQ(Point(-11, -11), ToRoundedPoint(PointF(-10.5f, -10.5f)));
- EXPECT_EQ(Point(-11, -11), ToRoundedPoint(PointF(-10.9999f, -10.9999f)));
-}
-
-TEST(PointTest, Scale) {
- EXPECT_EQ(PointF().ToString(), ScalePoint(PointF(), 2).ToString());
- EXPECT_EQ(PointF().ToString(), ScalePoint(PointF(), 2, 2).ToString());
-
- EXPECT_EQ(PointF(2, -2).ToString(), ScalePoint(PointF(1, -1), 2).ToString());
- EXPECT_EQ(PointF(2, -2).ToString(),
- ScalePoint(PointF(1, -1), 2, 2).ToString());
-
- PointF zero;
- PointF one(1, -1);
-
- zero.Scale(2);
- zero.Scale(3, 1.5);
-
- one.Scale(2);
- one.Scale(3, 1.5);
-
- EXPECT_EQ(PointF().ToString(), zero.ToString());
- EXPECT_EQ(PointF(6, -3).ToString(), one.ToString());
-}
-
-TEST(PointTest, ClampPoint) {
- Point a;
-
- a = Point(3, 5);
- EXPECT_EQ(Point(3, 5).ToString(), a.ToString());
- a.SetToMax(Point(2, 4));
- EXPECT_EQ(Point(3, 5).ToString(), a.ToString());
- a.SetToMax(Point(3, 5));
- EXPECT_EQ(Point(3, 5).ToString(), a.ToString());
- a.SetToMax(Point(4, 2));
- EXPECT_EQ(Point(4, 5).ToString(), a.ToString());
- a.SetToMax(Point(8, 10));
- EXPECT_EQ(Point(8, 10).ToString(), a.ToString());
-
- a.SetToMin(Point(9, 11));
- EXPECT_EQ(Point(8, 10).ToString(), a.ToString());
- a.SetToMin(Point(8, 10));
- EXPECT_EQ(Point(8, 10).ToString(), a.ToString());
- a.SetToMin(Point(11, 9));
- EXPECT_EQ(Point(8, 9).ToString(), a.ToString());
- a.SetToMin(Point(7, 11));
- EXPECT_EQ(Point(7, 9).ToString(), a.ToString());
- a.SetToMin(Point(3, 5));
- EXPECT_EQ(Point(3, 5).ToString(), a.ToString());
-}
-
-TEST(PointTest, ClampPointF) {
- PointF a;
-
- a = PointF(3.5f, 5.5f);
- EXPECT_EQ(PointF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(PointF(2.5f, 4.5f));
- EXPECT_EQ(PointF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(PointF(3.5f, 5.5f));
- EXPECT_EQ(PointF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(PointF(4.5f, 2.5f));
- EXPECT_EQ(PointF(4.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(PointF(8.5f, 10.5f));
- EXPECT_EQ(PointF(8.5f, 10.5f).ToString(), a.ToString());
-
- a.SetToMin(PointF(9.5f, 11.5f));
- EXPECT_EQ(PointF(8.5f, 10.5f).ToString(), a.ToString());
- a.SetToMin(PointF(8.5f, 10.5f));
- EXPECT_EQ(PointF(8.5f, 10.5f).ToString(), a.ToString());
- a.SetToMin(PointF(11.5f, 9.5f));
- EXPECT_EQ(PointF(8.5f, 9.5f).ToString(), a.ToString());
- a.SetToMin(PointF(7.5f, 11.5f));
- EXPECT_EQ(PointF(7.5f, 9.5f).ToString(), a.ToString());
- a.SetToMin(PointF(3.5f, 5.5f));
- EXPECT_EQ(PointF(3.5f, 5.5f).ToString(), a.ToString());
-}
-
-TEST(PointTest, Offset) {
- Point test(3, 4);
- test.Offset(5, -8);
- EXPECT_EQ(test, Point(8, -4));
-}
-
-TEST(PointTest, VectorMath) {
- Point test = Point(3, 4);
- test += Vector2d(5, -8);
- EXPECT_EQ(test, Point(8, -4));
-
- Point test2 = Point(3, 4);
- test2 -= Vector2d(5, -8);
- EXPECT_EQ(test2, Point(-2, 12));
-}
-
-TEST(PointTest, IntegerOverflow) {
- int int_max = std::numeric_limits<int>::max();
- int int_min = std::numeric_limits<int>::min();
-
- Point max_point(int_max, int_max);
- Point min_point(int_min, int_min);
- Point test;
-
- test = Point();
- test.Offset(int_max, int_max);
- EXPECT_EQ(test, max_point);
-
- test = Point();
- test.Offset(int_min, int_min);
- EXPECT_EQ(test, min_point);
-
- test = Point(10, 20);
- test.Offset(int_max, int_max);
- EXPECT_EQ(test, max_point);
-
- test = Point(-10, -20);
- test.Offset(int_min, int_min);
- EXPECT_EQ(test, min_point);
-
- test = Point();
- test += Vector2d(int_max, int_max);
- EXPECT_EQ(test, max_point);
-
- test = Point();
- test += Vector2d(int_min, int_min);
- EXPECT_EQ(test, min_point);
-
- test = Point(10, 20);
- test += Vector2d(int_max, int_max);
- EXPECT_EQ(test, max_point);
-
- test = Point(-10, -20);
- test += Vector2d(int_min, int_min);
- EXPECT_EQ(test, min_point);
-
- test = Point();
- test -= Vector2d(int_max, int_max);
- EXPECT_EQ(test, Point(-int_max, -int_max));
-
- test = Point();
- test -= Vector2d(int_min, int_min);
- EXPECT_EQ(test, max_point);
-
- test = Point(10, 20);
- test -= Vector2d(int_min, int_min);
- EXPECT_EQ(test, max_point);
-
- test = Point(-10, -20);
- test -= Vector2d(int_max, int_max);
- EXPECT_EQ(test, min_point);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/quad_f.cc b/ui/gfx/geometry/quad_f.cc
deleted file mode 100644
index 8ed8b91700..0000000000
--- a/ui/gfx/geometry/quad_f.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 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.
-
-#include "ui/gfx/geometry/quad_f.h"
-
-#include <limits>
-
-#include "base/strings/stringprintf.h"
-
-namespace gfx {
-
-void QuadF::operator=(const RectF& rect) {
- p1_ = PointF(rect.x(), rect.y());
- p2_ = PointF(rect.right(), rect.y());
- p3_ = PointF(rect.right(), rect.bottom());
- p4_ = PointF(rect.x(), rect.bottom());
-}
-
-std::string QuadF::ToString() const {
- return base::StringPrintf("%s;%s;%s;%s",
- p1_.ToString().c_str(),
- p2_.ToString().c_str(),
- p3_.ToString().c_str(),
- p4_.ToString().c_str());
-}
-
-static inline bool WithinEpsilon(float a, float b) {
- return std::abs(a - b) < std::numeric_limits<float>::epsilon();
-}
-
-bool QuadF::IsRectilinear() const {
- return
- (WithinEpsilon(p1_.x(), p2_.x()) && WithinEpsilon(p2_.y(), p3_.y()) &&
- WithinEpsilon(p3_.x(), p4_.x()) && WithinEpsilon(p4_.y(), p1_.y())) ||
- (WithinEpsilon(p1_.y(), p2_.y()) && WithinEpsilon(p2_.x(), p3_.x()) &&
- WithinEpsilon(p3_.y(), p4_.y()) && WithinEpsilon(p4_.x(), p1_.x()));
-}
-
-bool QuadF::IsCounterClockwise() const {
- // This math computes the signed area of the quad. Positive area
- // indicates the quad is clockwise; negative area indicates the quad is
- // counter-clockwise. Note carefully: this is backwards from conventional
- // math because our geometric space uses screen coordiantes with y-axis
- // pointing downards.
- // Reference: http://mathworld.wolfram.com/PolygonArea.html.
- // The equation can be written:
- // Signed area = determinant1 + determinant2 + determinant3 + determinant4
- // In practise, Refactoring the computation of adding determinants so that
- // reducing the number of operations. The equation is:
- // Signed area = element1 + element2 - element3 - element4
-
- float p24 = p2_.y() - p4_.y();
- float p31 = p3_.y() - p1_.y();
-
- // Up-cast to double so this cannot overflow.
- double element1 = static_cast<double>(p1_.x()) * p24;
- double element2 = static_cast<double>(p2_.x()) * p31;
- double element3 = static_cast<double>(p3_.x()) * p24;
- double element4 = static_cast<double>(p4_.x()) * p31;
-
- return element1 + element2 < element3 + element4;
-}
-
-static inline bool PointIsInTriangle(const PointF& point,
- const PointF& r1,
- const PointF& r2,
- const PointF& r3) {
- // Compute the barycentric coordinates (u, v, w) of |point| relative to the
- // triangle (r1, r2, r3) by the solving the system of equations:
- // 1) point = u * r1 + v * r2 + w * r3
- // 2) u + v + w = 1
- // This algorithm comes from Christer Ericson's Real-Time Collision Detection.
-
- Vector2dF r31 = r1 - r3;
- Vector2dF r32 = r2 - r3;
- Vector2dF r3p = point - r3;
-
- // Promote to doubles so all the math below is done with doubles, because
- // otherwise it gets incorrect results on arm64.
- double r31x = r31.x();
- double r31y = r31.y();
- double r32x = r32.x();
- double r32y = r32.y();
-
- double denom = r32y * r31x - r32x * r31y;
- double u = (r32y * r3p.x() - r32x * r3p.y()) / denom;
- double v = (r31x * r3p.y() - r31y * r3p.x()) / denom;
- double w = 1.0 - u - v;
-
- // Use the barycentric coordinates to test if |point| is inside the
- // triangle (r1, r2, r2).
- return (u >= 0) && (v >= 0) && (w >= 0);
-}
-
-bool QuadF::Contains(const PointF& point) const {
- return PointIsInTriangle(point, p1_, p2_, p3_)
- || PointIsInTriangle(point, p1_, p3_, p4_);
-}
-
-void QuadF::Scale(float x_scale, float y_scale) {
- p1_.Scale(x_scale, y_scale);
- p2_.Scale(x_scale, y_scale);
- p3_.Scale(x_scale, y_scale);
- p4_.Scale(x_scale, y_scale);
-}
-
-void QuadF::operator+=(const Vector2dF& rhs) {
- p1_ += rhs;
- p2_ += rhs;
- p3_ += rhs;
- p4_ += rhs;
-}
-
-void QuadF::operator-=(const Vector2dF& rhs) {
- p1_ -= rhs;
- p2_ -= rhs;
- p3_ -= rhs;
- p4_ -= rhs;
-}
-
-QuadF operator+(const QuadF& lhs, const Vector2dF& rhs) {
- QuadF result = lhs;
- result += rhs;
- return result;
-}
-
-QuadF operator-(const QuadF& lhs, const Vector2dF& rhs) {
- QuadF result = lhs;
- result -= rhs;
- return result;
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/quad_f.h b/ui/gfx/geometry/quad_f.h
deleted file mode 100644
index 8e45b3e2de..0000000000
--- a/ui/gfx/geometry/quad_f.h
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef UI_GFX_GEOMETRY_QUAD_F_H_
-#define UI_GFX_GEOMETRY_QUAD_F_H_
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <cmath>
-#include <iosfwd>
-#include <string>
-
-#include "base/logging.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-// A Quad is defined by four corners, allowing it to have edges that are not
-// axis-aligned, unlike a Rect.
-class GFX_EXPORT QuadF {
- public:
- constexpr QuadF() = default;
- constexpr QuadF(const PointF& p1,
- const PointF& p2,
- const PointF& p3,
- const PointF& p4)
- : p1_(p1), p2_(p2), p3_(p3), p4_(p4) {}
-
- constexpr explicit QuadF(const RectF& rect)
- : p1_(rect.x(), rect.y()),
- p2_(rect.right(), rect.y()),
- p3_(rect.right(), rect.bottom()),
- p4_(rect.x(), rect.bottom()) {}
-
- void operator=(const RectF& rect);
-
- void set_p1(const PointF& p) { p1_ = p; }
- void set_p2(const PointF& p) { p2_ = p; }
- void set_p3(const PointF& p) { p3_ = p; }
- void set_p4(const PointF& p) { p4_ = p; }
-
- constexpr const PointF& p1() const { return p1_; }
- constexpr const PointF& p2() const { return p2_; }
- constexpr const PointF& p3() const { return p3_; }
- constexpr const PointF& p4() const { return p4_; }
-
- // Returns true if the quad is an axis-aligned rectangle.
- bool IsRectilinear() const;
-
- // Returns true if the points of the quad are in counter-clockwise order. This
- // assumes that the quad is convex, and that no three points are collinear.
- bool IsCounterClockwise() const;
-
- // Returns true if the |point| is contained within the quad, or lies on on
- // edge of the quad. This assumes that the quad is convex.
- bool Contains(const gfx::PointF& point) const;
-
- // Returns a rectangle that bounds the four points of the quad. The points of
- // the quad may lie on the right/bottom edge of the resulting rectangle,
- // rather than being strictly inside it.
- RectF BoundingBox() const {
- float rl = std::min(std::min(p1_.x(), p2_.x()), std::min(p3_.x(), p4_.x()));
- float rr = std::max(std::max(p1_.x(), p2_.x()), std::max(p3_.x(), p4_.x()));
- float rt = std::min(std::min(p1_.y(), p2_.y()), std::min(p3_.y(), p4_.y()));
- float rb = std::max(std::max(p1_.y(), p2_.y()), std::max(p3_.y(), p4_.y()));
- return RectF(rl, rt, rr - rl, rb - rt);
- }
-
- // Realigns the corners in the quad by rotating them n corners to the right.
- void Realign(size_t times) {
- DCHECK_LE(times, 4u);
- for (size_t i = 0; i < times; ++i) {
- PointF temp = p1_;
- p1_ = p2_;
- p2_ = p3_;
- p3_ = p4_;
- p4_ = temp;
- }
- }
-
- // Add a vector to the quad, offseting each point in the quad by the vector.
- void operator+=(const Vector2dF& rhs);
- // Subtract a vector from the quad, offseting each point in the quad by the
- // inverse of the vector.
- void operator-=(const Vector2dF& rhs);
-
- // Scale each point in the quad by the |scale| factor.
- void Scale(float scale) { Scale(scale, scale); }
-
- // Scale each point in the quad by the scale factors along each axis.
- void Scale(float x_scale, float y_scale);
-
- // Returns a string representation of quad.
- std::string ToString() const;
-
- private:
- PointF p1_;
- PointF p2_;
- PointF p3_;
- PointF p4_;
-};
-
-inline bool operator==(const QuadF& lhs, const QuadF& rhs) {
- return
- lhs.p1() == rhs.p1() && lhs.p2() == rhs.p2() &&
- lhs.p3() == rhs.p3() && lhs.p4() == rhs.p4();
-}
-
-inline bool operator!=(const QuadF& lhs, const QuadF& rhs) {
- return !(lhs == rhs);
-}
-
-// Add a vector to a quad, offseting each point in the quad by the vector.
-GFX_EXPORT QuadF operator+(const QuadF& lhs, const Vector2dF& rhs);
-// Subtract a vector from a quad, offseting each point in the quad by the
-// inverse of the vector.
-GFX_EXPORT QuadF operator-(const QuadF& lhs, const Vector2dF& rhs);
-
-// This is declared here for use in gtest-based unit tests but is defined in
-// the //ui/gfx:test_support target. Depend on that to use this in your unit
-// test. This should not be used in production code - call ToString() instead.
-void PrintTo(const QuadF& quad, ::std::ostream* os);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_QUAD_F_H_
diff --git a/ui/gfx/geometry/quad_unittest.cc b/ui/gfx/geometry/quad_unittest.cc
deleted file mode 100644
index 2731583aab..0000000000
--- a/ui/gfx/geometry/quad_unittest.cc
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright (c) 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.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/quad_f.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace gfx {
-
-TEST(QuadTest, Construction) {
- // Verify constructors.
- PointF a(1, 1);
- PointF b(2, 1);
- PointF c(2, 2);
- PointF d(1, 2);
- PointF e;
- QuadF q1;
- QuadF q2(e, e, e, e);
- QuadF q3(a, b, c, d);
- QuadF q4(BoundingRect(a, c));
- EXPECT_EQ(q1, q2);
- EXPECT_EQ(q3, q4);
-
- // Verify getters.
- EXPECT_EQ(q3.p1(), a);
- EXPECT_EQ(q3.p2(), b);
- EXPECT_EQ(q3.p3(), c);
- EXPECT_EQ(q3.p4(), d);
-
- // Verify setters.
- q3.set_p1(b);
- q3.set_p2(c);
- q3.set_p3(d);
- q3.set_p4(a);
- EXPECT_EQ(q3.p1(), b);
- EXPECT_EQ(q3.p2(), c);
- EXPECT_EQ(q3.p3(), d);
- EXPECT_EQ(q3.p4(), a);
-
- // Verify operator=(Rect)
- EXPECT_NE(q1, q4);
- q1 = BoundingRect(a, c);
- EXPECT_EQ(q1, q4);
-
- // Verify operator=(Quad)
- EXPECT_NE(q1, q3);
- q1 = q3;
- EXPECT_EQ(q1, q3);
-}
-
-TEST(QuadTest, AddingVectors) {
- PointF a(1, 1);
- PointF b(2, 1);
- PointF c(2, 2);
- PointF d(1, 2);
- Vector2dF v(3.5f, -2.5f);
-
- QuadF q1(a, b, c, d);
- QuadF added = q1 + v;
- q1 += v;
- QuadF expected1(PointF(4.5f, -1.5f),
- PointF(5.5f, -1.5f),
- PointF(5.5f, -0.5f),
- PointF(4.5f, -0.5f));
- EXPECT_EQ(expected1, added);
- EXPECT_EQ(expected1, q1);
-
- QuadF q2(a, b, c, d);
- QuadF subtracted = q2 - v;
- q2 -= v;
- QuadF expected2(PointF(-2.5f, 3.5f),
- PointF(-1.5f, 3.5f),
- PointF(-1.5f, 4.5f),
- PointF(-2.5f, 4.5f));
- EXPECT_EQ(expected2, subtracted);
- EXPECT_EQ(expected2, q2);
-
- QuadF q3(a, b, c, d);
- q3 += v;
- q3 -= v;
- EXPECT_EQ(QuadF(a, b, c, d), q3);
- EXPECT_EQ(q3, (q3 + v - v));
-}
-
-TEST(QuadTest, IsRectilinear) {
- PointF a(1, 1);
- PointF b(2, 1);
- PointF c(2, 2);
- PointF d(1, 2);
- Vector2dF v(3.5f, -2.5f);
-
- EXPECT_TRUE(QuadF().IsRectilinear());
- EXPECT_TRUE(QuadF(a, b, c, d).IsRectilinear());
- EXPECT_TRUE((QuadF(a, b, c, d) + v).IsRectilinear());
-
- float epsilon = std::numeric_limits<float>::epsilon();
- PointF a2(1 + epsilon / 2, 1 + epsilon / 2);
- PointF b2(2 + epsilon / 2, 1 + epsilon / 2);
- PointF c2(2 + epsilon / 2, 2 + epsilon / 2);
- PointF d2(1 + epsilon / 2, 2 + epsilon / 2);
- EXPECT_TRUE(QuadF(a2, b, c, d).IsRectilinear());
- EXPECT_TRUE((QuadF(a2, b, c, d) + v).IsRectilinear());
- EXPECT_TRUE(QuadF(a, b2, c, d).IsRectilinear());
- EXPECT_TRUE((QuadF(a, b2, c, d) + v).IsRectilinear());
- EXPECT_TRUE(QuadF(a, b, c2, d).IsRectilinear());
- EXPECT_TRUE((QuadF(a, b, c2, d) + v).IsRectilinear());
- EXPECT_TRUE(QuadF(a, b, c, d2).IsRectilinear());
- EXPECT_TRUE((QuadF(a, b, c, d2) + v).IsRectilinear());
-
- struct {
- PointF a_off, b_off, c_off, d_off;
- } tests[] = {
- {
- PointF(1, 1.00001f),
- PointF(2, 1.00001f),
- PointF(2, 2.00001f),
- PointF(1, 2.00001f)
- },
- {
- PointF(1.00001f, 1),
- PointF(2.00001f, 1),
- PointF(2.00001f, 2),
- PointF(1.00001f, 2)
- },
- {
- PointF(1.00001f, 1.00001f),
- PointF(2.00001f, 1.00001f),
- PointF(2.00001f, 2.00001f),
- PointF(1.00001f, 2.00001f)
- },
- {
- PointF(1, 0.99999f),
- PointF(2, 0.99999f),
- PointF(2, 1.99999f),
- PointF(1, 1.99999f)
- },
- {
- PointF(0.99999f, 1),
- PointF(1.99999f, 1),
- PointF(1.99999f, 2),
- PointF(0.99999f, 2)
- },
- {
- PointF(0.99999f, 0.99999f),
- PointF(1.99999f, 0.99999f),
- PointF(1.99999f, 1.99999f),
- PointF(0.99999f, 1.99999f)
- }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- PointF a_off = tests[i].a_off;
- PointF b_off = tests[i].b_off;
- PointF c_off = tests[i].c_off;
- PointF d_off = tests[i].d_off;
-
- EXPECT_FALSE(QuadF(a_off, b, c, d).IsRectilinear());
- EXPECT_FALSE((QuadF(a_off, b, c, d) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a, b_off, c, d).IsRectilinear());
- EXPECT_FALSE((QuadF(a, b_off, c, d) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a, b, c_off, d).IsRectilinear());
- EXPECT_FALSE((QuadF(a, b, c_off, d) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a, b, c, d_off).IsRectilinear());
- EXPECT_FALSE((QuadF(a, b, c, d_off) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a_off, b, c_off, d).IsRectilinear());
- EXPECT_FALSE((QuadF(a_off, b, c_off, d) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a, b_off, c, d_off).IsRectilinear());
- EXPECT_FALSE((QuadF(a, b_off, c, d_off) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a, b_off, c_off, d_off).IsRectilinear());
- EXPECT_FALSE((QuadF(a, b_off, c_off, d_off) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a_off, b, c_off, d_off).IsRectilinear());
- EXPECT_FALSE((QuadF(a_off, b, c_off, d_off) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a_off, b_off, c, d_off).IsRectilinear());
- EXPECT_FALSE((QuadF(a_off, b_off, c, d_off) + v).IsRectilinear());
- EXPECT_FALSE(QuadF(a_off, b_off, c_off, d).IsRectilinear());
- EXPECT_FALSE((QuadF(a_off, b_off, c_off, d) + v).IsRectilinear());
- EXPECT_TRUE(QuadF(a_off, b_off, c_off, d_off).IsRectilinear());
- EXPECT_TRUE((QuadF(a_off, b_off, c_off, d_off) + v).IsRectilinear());
- }
-}
-
-TEST(QuadTest, IsCounterClockwise) {
- PointF a1(1, 1);
- PointF b1(2, 1);
- PointF c1(2, 2);
- PointF d1(1, 2);
- EXPECT_FALSE(QuadF(a1, b1, c1, d1).IsCounterClockwise());
- EXPECT_FALSE(QuadF(b1, c1, d1, a1).IsCounterClockwise());
- EXPECT_TRUE(QuadF(a1, d1, c1, b1).IsCounterClockwise());
- EXPECT_TRUE(QuadF(c1, b1, a1, d1).IsCounterClockwise());
-
- // Slightly more complicated quads should work just as easily.
- PointF a2(1.3f, 1.4f);
- PointF b2(-0.7f, 4.9f);
- PointF c2(1.8f, 6.2f);
- PointF d2(2.1f, 1.6f);
- EXPECT_TRUE(QuadF(a2, b2, c2, d2).IsCounterClockwise());
- EXPECT_TRUE(QuadF(b2, c2, d2, a2).IsCounterClockwise());
- EXPECT_FALSE(QuadF(a2, d2, c2, b2).IsCounterClockwise());
- EXPECT_FALSE(QuadF(c2, b2, a2, d2).IsCounterClockwise());
-
- // Quads with 3 collinear points should work correctly, too.
- PointF a3(0, 0);
- PointF b3(1, 0);
- PointF c3(2, 0);
- PointF d3(1, 1);
- EXPECT_FALSE(QuadF(a3, b3, c3, d3).IsCounterClockwise());
- EXPECT_FALSE(QuadF(b3, c3, d3, a3).IsCounterClockwise());
- EXPECT_TRUE(QuadF(a3, d3, c3, b3).IsCounterClockwise());
- // The next expectation in particular would fail for an implementation
- // that incorrectly uses only a cross product of the first 3 vertices.
- EXPECT_TRUE(QuadF(c3, b3, a3, d3).IsCounterClockwise());
-
- // Non-convex quads should work correctly, too.
- PointF a4(0, 0);
- PointF b4(1, 1);
- PointF c4(2, 0);
- PointF d4(1, 3);
- EXPECT_FALSE(QuadF(a4, b4, c4, d4).IsCounterClockwise());
- EXPECT_FALSE(QuadF(b4, c4, d4, a4).IsCounterClockwise());
- EXPECT_TRUE(QuadF(a4, d4, c4, b4).IsCounterClockwise());
- EXPECT_TRUE(QuadF(c4, b4, a4, d4).IsCounterClockwise());
-
- // A quad with huge coordinates should not fail this check due to
- // single-precision overflow.
- PointF a5(1e30f, 1e30f);
- PointF b5(1e35f, 1e30f);
- PointF c5(1e35f, 1e35f);
- PointF d5(1e30f, 1e35f);
- EXPECT_FALSE(QuadF(a5, b5, c5, d5).IsCounterClockwise());
- EXPECT_FALSE(QuadF(b5, c5, d5, a5).IsCounterClockwise());
- EXPECT_TRUE(QuadF(a5, d5, c5, b5).IsCounterClockwise());
- EXPECT_TRUE(QuadF(c5, b5, a5, d5).IsCounterClockwise());
-}
-
-TEST(QuadTest, BoundingBox) {
- RectF r(3.2f, 5.4f, 7.007f, 12.01f);
- EXPECT_EQ(r, QuadF(r).BoundingBox());
-
- PointF a(1.3f, 1.4f);
- PointF b(-0.7f, 4.9f);
- PointF c(1.8f, 6.2f);
- PointF d(2.1f, 1.6f);
- float left = -0.7f;
- float top = 1.4f;
- float right = 2.1f;
- float bottom = 6.2f;
- EXPECT_EQ(RectF(left, top, right - left, bottom - top),
- QuadF(a, b, c, d).BoundingBox());
-}
-
-TEST(QuadTest, ContainsPoint) {
- PointF a(1.3f, 1.4f);
- PointF b(-0.8f, 4.4f);
- PointF c(1.8f, 6.1f);
- PointF d(2.1f, 1.6f);
-
- Vector2dF epsilon_x(2 * std::numeric_limits<float>::epsilon(), 0);
- Vector2dF epsilon_y(0, 2 * std::numeric_limits<float>::epsilon());
-
- Vector2dF ac_center = c - a;
- ac_center.Scale(0.5f);
- Vector2dF bd_center = d - b;
- bd_center.Scale(0.5f);
-
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(a + ac_center));
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(b + bd_center));
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(c - ac_center));
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(d - bd_center));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - ac_center));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - bd_center));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + ac_center));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + bd_center));
-
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(a));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - epsilon_x));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - epsilon_y));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(a + epsilon_x));
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(a + epsilon_y));
-
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(b));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - epsilon_x));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - epsilon_y));
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(b + epsilon_x));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(b + epsilon_y));
-
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(c));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(c - epsilon_x));
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(c - epsilon_y));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + epsilon_x));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + epsilon_y));
-
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(d));
- EXPECT_TRUE(QuadF(a, b, c, d).Contains(d - epsilon_x));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(d - epsilon_y));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + epsilon_x));
- EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + epsilon_y));
-
- // Test a simple square.
- PointF s1(-1, -1);
- PointF s2(1, -1);
- PointF s3(1, 1);
- PointF s4(-1, 1);
- // Top edge.
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, -1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0.0f, -1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.0f)));
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, -1.0f)));
- // Bottom edge.
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, 1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0.0f, 1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.0f)));
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, 1.0f)));
- // Left edge.
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.1f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 0.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.0f)));
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.1f)));
- // Right edge.
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.1f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 0.0f)));
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.0f)));
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.1f)));
- // Centered inside.
- EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0, 0)));
- // Centered outside.
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, 0)));
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, 0)));
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(0, -1.1f)));
- EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(0, 1.1f)));
-}
-
-TEST(QuadTest, Scale) {
- PointF a(1.3f, 1.4f);
- PointF b(-0.8f, 4.4f);
- PointF c(1.8f, 6.1f);
- PointF d(2.1f, 1.6f);
- QuadF q1(a, b, c, d);
- q1.Scale(1.5f);
-
- PointF a_scaled = ScalePoint(a, 1.5f);
- PointF b_scaled = ScalePoint(b, 1.5f);
- PointF c_scaled = ScalePoint(c, 1.5f);
- PointF d_scaled = ScalePoint(d, 1.5f);
- EXPECT_EQ(q1, QuadF(a_scaled, b_scaled, c_scaled, d_scaled));
-
- QuadF q2;
- q2.Scale(1.5f);
- EXPECT_EQ(q2, q2);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/quaternion.cc b/ui/gfx/geometry/quaternion.cc
deleted file mode 100644
index f2be00b857..0000000000
--- a/ui/gfx/geometry/quaternion.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2017 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 "ui/gfx/geometry/quaternion.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/numerics/math_constants.h"
-#include "base/strings/stringprintf.h"
-#include "ui/gfx/geometry/vector3d_f.h"
-
-namespace gfx {
-
-namespace {
-
-const double kEpsilon = 1e-5;
-
-} // namespace
-
-Quaternion::Quaternion(const Vector3dF& axis, double theta) {
- // Rotation angle is the product of |angle| and the magnitude of |axis|.
- double length = axis.Length();
- if (std::abs(length) < kEpsilon)
- return;
-
- Vector3dF normalized = axis;
- normalized.Scale(1.0 / length);
-
- theta *= 0.5;
- double s = sin(theta);
- x_ = normalized.x() * s;
- y_ = normalized.y() * s;
- z_ = normalized.z() * s;
- w_ = cos(theta);
-}
-
-Quaternion::Quaternion(const Vector3dF& from, const Vector3dF& to) {
- double dot = gfx::DotProduct(from, to);
- double norm = sqrt(from.LengthSquared() * to.LengthSquared());
- double real = norm + dot;
- gfx::Vector3dF axis;
- if (real < kEpsilon * norm) {
- real = 0.0f;
- axis = std::abs(from.x()) > std::abs(from.z())
- ? gfx::Vector3dF{-from.y(), from.x(), 0.0}
- : gfx::Vector3dF{0.0, -from.z(), from.y()};
- } else {
- axis = gfx::CrossProduct(from, to);
- }
- x_ = axis.x();
- y_ = axis.y();
- z_ = axis.z();
- w_ = real;
- *this = this->Normalized();
-}
-
-// Taken from http://www.w3.org/TR/css3-transforms/.
-Quaternion Quaternion::Slerp(const Quaternion& q, double t) const {
- double dot = x_ * q.x_ + y_ * q.y_ + z_ * q.z_ + w_ * q.w_;
-
- // Clamp dot to -1.0 <= dot <= 1.0.
- dot = std::min(std::max(dot, -1.0), 1.0);
-
- // Quaternions are facing the same direction.
- if (std::abs(dot - 1.0) < kEpsilon || std::abs(dot + 1.0) < kEpsilon)
- return *this;
-
- double denom = std::sqrt(1.0 - dot * dot);
- double theta = std::acos(dot);
- double w = std::sin(t * theta) * (1.0 / denom);
-
- double s1 = std::cos(t * theta) - dot * w;
- double s2 = w;
-
- return (s1 * *this) + (s2 * q);
-}
-
-Quaternion Quaternion::Lerp(const Quaternion& q, double t) const {
- return (((1.0 - t) * *this) + (t * q)).Normalized();
-}
-
-double Quaternion::Length() const {
- return x_ * x_ + y_ * y_ + z_ * z_ + w_ * w_;
-}
-
-Quaternion Quaternion::Normalized() const {
- double length = Length();
- if (length < kEpsilon)
- return *this;
- return *this / sqrt(length);
-}
-
-std::string Quaternion::ToString() const {
- // q = (con(abs(v_theta)/2), v_theta/abs(v_theta) * sin(abs(v_theta)/2))
- float abs_theta = acos(w_) * 2;
- float scale = 1. / sin(abs_theta * .5);
- gfx::Vector3dF v(x_, y_, z_);
- v.Scale(scale);
- return base::StringPrintf("[%f %f %f %f], v:", x_, y_, z_, w_) +
- v.ToString() +
- base::StringPrintf(", θ:%fπ", abs_theta / base::kPiFloat);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/quaternion.h b/ui/gfx/geometry/quaternion.h
deleted file mode 100644
index 7f65b796e6..0000000000
--- a/ui/gfx/geometry/quaternion.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef UI_GFX_GEOMETRY_QUATERNION_
-#define UI_GFX_GEOMETRY_QUATERNION_
-
-#include <string>
-
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-class Vector3dF;
-
-class GFX_EXPORT Quaternion {
- public:
- constexpr Quaternion() = default;
- constexpr Quaternion(double x, double y, double z, double w)
- : x_(x), y_(y), z_(z), w_(w) {}
- Quaternion(const Vector3dF& axis, double angle);
-
- // Constructs a quaternion representing a rotation between |from| and |to|.
- Quaternion(const Vector3dF& from, const Vector3dF& to);
-
- constexpr double x() const { return x_; }
- void set_x(double x) { x_ = x; }
-
- constexpr double y() const { return y_; }
- void set_y(double y) { y_ = y; }
-
- constexpr double z() const { return z_; }
- void set_z(double z) { z_ = z; }
-
- constexpr double w() const { return w_; }
- void set_w(double w) { w_ = w; }
-
- Quaternion operator+(const Quaternion& q) const {
- return {q.x_ + x_, q.y_ + y_, q.z_ + z_, q.w_ + w_};
- }
-
- Quaternion operator*(const Quaternion& q) const {
- return {w_ * q.x_ + x_ * q.w_ + y_ * q.z_ - z_ * q.y_,
- w_ * q.y_ - x_ * q.z_ + y_ * q.w_ + z_ * q.x_,
- w_ * q.z_ + x_ * q.y_ - y_ * q.x_ + z_ * q.w_,
- w_ * q.w_ - x_ * q.x_ - y_ * q.y_ - z_ * q.z_};
- }
-
- Quaternion inverse() const { return {-x_, -y_, -z_, w_}; }
-
- // Blends with the given quaternion, |q|, via spherical linear interpolation.
- // Values of |t| in the range [0, 1] will interpolate between |this| and |q|,
- // and values outside that range will extrapolate beyond in either direction.
- Quaternion Slerp(const Quaternion& q, double t) const;
-
- // Blends with the given quaternion, |q|, via linear interpolation. This is
- // rarely what you want. Use only if you know what you're doing.
- // Values of |t| in the range [0, 1] will interpolate between |this| and |q|,
- // and values outside that range will extrapolate beyond in either direction.
- Quaternion Lerp(const Quaternion& q, double t) const;
-
- double Length() const;
-
- Quaternion Normalized() const;
-
- std::string ToString() const;
-
- private:
- double x_ = 0.0;
- double y_ = 0.0;
- double z_ = 0.0;
- double w_ = 1.0;
-};
-
-// |s| is an arbitrary, real constant.
-inline Quaternion operator*(const Quaternion& q, double s) {
- return Quaternion(q.x() * s, q.y() * s, q.z() * s, q.w() * s);
-}
-
-// |s| is an arbitrary, real constant.
-inline Quaternion operator*(double s, const Quaternion& q) {
- return Quaternion(q.x() * s, q.y() * s, q.z() * s, q.w() * s);
-}
-
-// |s| is an arbitrary, real constant.
-inline Quaternion operator/(const Quaternion& q, double s) {
- double inv = 1.0 / s;
- return q * inv;
-}
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_QUATERNION_
diff --git a/ui/gfx/geometry/quaternion_unittest.cc b/ui/gfx/geometry/quaternion_unittest.cc
deleted file mode 100644
index 5c8fa9b8ae..0000000000
--- a/ui/gfx/geometry/quaternion_unittest.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2017 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.
-
-#define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first.
-
-#include <cmath>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/quaternion.h"
-#include "ui/gfx/geometry/vector3d_f.h"
-
-namespace gfx {
-
-namespace {
-
-const double kEpsilon = 1e-7;
-
-void CompareQuaternions(const Quaternion& a, const Quaternion& b) {
- EXPECT_FLOAT_EQ(a.x(), b.x());
- EXPECT_FLOAT_EQ(a.y(), b.y());
- EXPECT_FLOAT_EQ(a.z(), b.z());
- EXPECT_FLOAT_EQ(a.w(), b.w());
-}
-
-} // namespace
-
-TEST(QuatTest, DefaultConstruction) {
- CompareQuaternions(Quaternion(0, 0, 0, 1), Quaternion());
-}
-
-TEST(QuatTest, AxisAngleCommon) {
- double radians = 0.5;
- Quaternion q(Vector3dF(1, 0, 0), radians);
- CompareQuaternions(
- Quaternion(std::sin(radians / 2), 0, 0, std::cos(radians / 2)), q);
-}
-
-TEST(QuatTest, VectorToVectorRotation) {
- Quaternion q(Vector3dF(1.0f, 0.0f, 0.0f), Vector3dF(0.0f, 1.0f, 0.0f));
- Quaternion r(Vector3dF(0.0f, 0.0f, 1.0f), M_PI_2);
-
- EXPECT_FLOAT_EQ(r.x(), q.x());
- EXPECT_FLOAT_EQ(r.y(), q.y());
- EXPECT_FLOAT_EQ(r.z(), q.z());
- EXPECT_FLOAT_EQ(r.w(), q.w());
-}
-
-TEST(QuatTest, AxisAngleWithZeroLengthAxis) {
- Quaternion q(Vector3dF(0, 0, 0), 0.5);
- // If the axis of zero length, we should assume the default values.
- CompareQuaternions(q, Quaternion());
-}
-
-TEST(QuatTest, Addition) {
- double values[] = {0, 1, 100};
- for (size_t i = 0; i < arraysize(values); ++i) {
- float t = values[i];
- Quaternion a(t, 2 * t, 3 * t, 4 * t);
- Quaternion b(5 * t, 4 * t, 3 * t, 2 * t);
- Quaternion sum = a + b;
- CompareQuaternions(Quaternion(t, t, t, t) * 6, sum);
- }
-}
-
-TEST(QuatTest, Multiplication) {
- struct {
- Quaternion a;
- Quaternion b;
- Quaternion expected;
- } cases[] = {
- {Quaternion(1, 0, 0, 0), Quaternion(1, 0, 0, 0), Quaternion(0, 0, 0, -1)},
- {Quaternion(0, 1, 0, 0), Quaternion(0, 1, 0, 0), Quaternion(0, 0, 0, -1)},
- {Quaternion(0, 0, 1, 0), Quaternion(0, 0, 1, 0), Quaternion(0, 0, 0, -1)},
- {Quaternion(0, 0, 0, 1), Quaternion(0, 0, 0, 1), Quaternion(0, 0, 0, 1)},
- {Quaternion(1, 2, 3, 4), Quaternion(5, 6, 7, 8),
- Quaternion(24, 48, 48, -6)},
- {Quaternion(5, 6, 7, 8), Quaternion(1, 2, 3, 4),
- Quaternion(32, 32, 56, -6)},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- Quaternion product = cases[i].a * cases[i].b;
- CompareQuaternions(cases[i].expected, product);
- }
-}
-
-TEST(QuatTest, Scaling) {
- double values[] = {0, 10, 100};
- for (size_t i = 0; i < arraysize(values); ++i) {
- double s = values[i];
- Quaternion q(1, 2, 3, 4);
- Quaternion expected(s, 2 * s, 3 * s, 4 * s);
- CompareQuaternions(expected, q * s);
- CompareQuaternions(expected, s * q);
- if (s > 0)
- CompareQuaternions(expected, q / (1 / s));
- }
-}
-
-TEST(QuatTest, Normalization) {
- Quaternion q(1, -1, 1, -1);
- EXPECT_NEAR(q.Length(), 4, kEpsilon);
-
- q = q.Normalized();
-
- EXPECT_NEAR(q.Length(), 1, kEpsilon);
- EXPECT_NEAR(q.x(), 0.5, kEpsilon);
- EXPECT_NEAR(q.y(), -0.5, kEpsilon);
- EXPECT_NEAR(q.z(), 0.5, kEpsilon);
- EXPECT_NEAR(q.w(), -0.5, kEpsilon);
-}
-
-TEST(QuatTest, Lerp) {
- for (size_t i = 1; i < 100; ++i) {
- Quaternion a(0, 0, 0, 0);
- Quaternion b(1, 2, 3, 4);
- float t = static_cast<float>(i) / 100.0f;
- Quaternion interpolated = a.Lerp(b, t);
- double s = 1.0 / sqrt(30.0);
- CompareQuaternions(Quaternion(1, 2, 3, 4) * s, interpolated);
- }
-
- Quaternion a(4, 3, 2, 1);
- Quaternion b(1, 2, 3, 4);
- CompareQuaternions(a.Normalized(), a.Lerp(b, 0));
- CompareQuaternions(b.Normalized(), a.Lerp(b, 1));
- CompareQuaternions(Quaternion(1, 1, 1, 1).Normalized(), a.Lerp(b, 0.5));
-}
-
-TEST(QuatTest, Slerp) {
- Vector3dF axis(1, 1, 1);
- double start_radians = -0.5;
- double stop_radians = 0.5;
- Quaternion start(axis, start_radians);
- Quaternion stop(axis, stop_radians);
-
- for (size_t i = 0; i < 100; ++i) {
- float t = static_cast<float>(i) / 100.0f;
- double radians = (1.0 - t) * start_radians + t * stop_radians;
- Quaternion expected(axis, radians);
- Quaternion interpolated = start.Slerp(stop, t);
- EXPECT_NEAR(expected.x(), interpolated.x(), kEpsilon);
- EXPECT_NEAR(expected.y(), interpolated.y(), kEpsilon);
- EXPECT_NEAR(expected.z(), interpolated.z(), kEpsilon);
- EXPECT_NEAR(expected.w(), interpolated.w(), kEpsilon);
- }
-}
-
-TEST(QuatTest, SlerpOppositeAngles) {
- Vector3dF axis(1, 1, 1);
- double start_radians = -M_PI_2;
- double stop_radians = M_PI_2;
- Quaternion start(axis, start_radians);
- Quaternion stop(axis, stop_radians);
-
- // When quaternions are pointed in the fully opposite direction, this is
- // ambiguous, so we rotate as per https://www.w3.org/TR/css-transforms-1/
- Quaternion expected(axis, 0);
-
- Quaternion interpolated = start.Slerp(stop, 0.5f);
- EXPECT_NEAR(expected.x(), interpolated.x(), kEpsilon);
- EXPECT_NEAR(expected.y(), interpolated.y(), kEpsilon);
- EXPECT_NEAR(expected.z(), interpolated.z(), kEpsilon);
- EXPECT_NEAR(expected.w(), interpolated.w(), kEpsilon);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/rect_conversions.cc b/ui/gfx/geometry/rect_conversions.cc
deleted file mode 100644
index 3a5b2dcead..0000000000
--- a/ui/gfx/geometry/rect_conversions.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 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.
-
-#include "ui/gfx/geometry/rect_conversions.h"
-
-#include <algorithm>
-#include <cmath>
-
-#include "base/logging.h"
-#include "ui/gfx/geometry/safe_integer_conversions.h"
-
-namespace gfx {
-
-Rect ToEnclosingRect(const RectF& r) {
- int left = ToFlooredInt(r.x());
- int right = r.width() ? ToCeiledInt(r.right()) : left;
- int top = ToFlooredInt(r.y());
- int bottom = r.height() ? ToCeiledInt(r.bottom()) : top;
-
- Rect result;
- result.SetByBounds(left, top, right, bottom);
- return result;
-}
-
-Rect ToEnclosedRect(const RectF& rect) {
- Rect result;
- result.SetByBounds(ToCeiledInt(rect.x()), ToCeiledInt(rect.y()),
- ToFlooredInt(rect.right()), ToFlooredInt(rect.bottom()));
- return result;
-}
-
-Rect ToNearestRect(const RectF& rect) {
- float float_min_x = rect.x();
- float float_min_y = rect.y();
- float float_max_x = rect.right();
- float float_max_y = rect.bottom();
-
- int min_x = ToRoundedInt(float_min_x);
- int min_y = ToRoundedInt(float_min_y);
- int max_x = ToRoundedInt(float_max_x);
- int max_y = ToRoundedInt(float_max_y);
-
- // If these DCHECKs fail, you're using the wrong method, consider using
- // ToEnclosingRect or ToEnclosedRect instead.
- DCHECK(std::abs(min_x - float_min_x) < 0.01f);
- DCHECK(std::abs(min_y - float_min_y) < 0.01f);
- DCHECK(std::abs(max_x - float_max_x) < 0.01f);
- DCHECK(std::abs(max_y - float_max_y) < 0.01f);
-
- Rect result;
- result.SetByBounds(min_x, min_y, max_x, max_y);
-
- return result;
-}
-
-bool IsNearestRectWithinDistance(const gfx::RectF& rect, float distance) {
- float float_min_x = rect.x();
- float float_min_y = rect.y();
- float float_max_x = rect.right();
- float float_max_y = rect.bottom();
-
- int min_x = ToRoundedInt(float_min_x);
- int min_y = ToRoundedInt(float_min_y);
- int max_x = ToRoundedInt(float_max_x);
- int max_y = ToRoundedInt(float_max_y);
-
- return
- (std::abs(min_x - float_min_x) < distance) &&
- (std::abs(min_y - float_min_y) < distance) &&
- (std::abs(max_x - float_max_x) < distance) &&
- (std::abs(max_y - float_max_y) < distance);
-}
-
-Rect ToFlooredRectDeprecated(const RectF& rect) {
- return Rect(ToFlooredInt(rect.x()),
- ToFlooredInt(rect.y()),
- ToFlooredInt(rect.width()),
- ToFlooredInt(rect.height()));
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/rect_conversions.h b/ui/gfx/geometry/rect_conversions.h
deleted file mode 100644
index 617074abee..0000000000
--- a/ui/gfx/geometry/rect_conversions.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef UI_GFX_GEOMETRY_RECT_CONVERSIONS_H_
-#define UI_GFX_GEOMETRY_RECT_CONVERSIONS_H_
-
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace gfx {
-
-// Returns the smallest Rect that encloses the given RectF.
-GFX_EXPORT Rect ToEnclosingRect(const RectF& rect);
-
-// Returns the largest Rect that is enclosed by the given RectF.
-GFX_EXPORT Rect ToEnclosedRect(const RectF& rect);
-
-// Returns the Rect after snapping the corners of the RectF to an integer grid.
-// This should only be used when the RectF you provide is expected to be an
-// integer rect with floating point error. If it is an arbitrary RectF, then
-// you should use a different method.
-GFX_EXPORT Rect ToNearestRect(const RectF& rect);
-
-// Returns true if the Rect produced after snapping the corners of the RectF
-// to an integer grid is withing |distance|.
-GFX_EXPORT bool IsNearestRectWithinDistance(
- const gfx::RectF& rect, float distance);
-
-// Returns a Rect obtained by flooring the values of the given RectF.
-// Please prefer the previous two functions in new code.
-GFX_EXPORT Rect ToFlooredRectDeprecated(const RectF& rect);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_RECT_CONVERSIONS_H_
diff --git a/ui/gfx/geometry/rect_unittest.cc b/ui/gfx/geometry/rect_unittest.cc
deleted file mode 100644
index aaa533bfcd..0000000000
--- a/ui/gfx/geometry/rect_unittest.cc
+++ /dev/null
@@ -1,1141 +0,0 @@
-// Copyright (c) 2013 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 <limits>
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/test/gfx_util.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace gfx {
-
-TEST(RectTest, Contains) {
- static const struct ContainsCase {
- int rect_x;
- int rect_y;
- int rect_width;
- int rect_height;
- int point_x;
- int point_y;
- bool contained;
- } contains_cases[] = {
- {0, 0, 10, 10, 0, 0, true},
- {0, 0, 10, 10, 5, 5, true},
- {0, 0, 10, 10, 9, 9, true},
- {0, 0, 10, 10, 5, 10, false},
- {0, 0, 10, 10, 10, 5, false},
- {0, 0, 10, 10, -1, -1, false},
- {0, 0, 10, 10, 50, 50, false},
- #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
- {0, 0, -10, -10, 0, 0, false},
- #endif
- };
- for (size_t i = 0; i < arraysize(contains_cases); ++i) {
- const ContainsCase& value = contains_cases[i];
- Rect rect(value.rect_x, value.rect_y, value.rect_width, value.rect_height);
- EXPECT_EQ(value.contained, rect.Contains(value.point_x, value.point_y));
- }
-}
-
-TEST(RectTest, Intersects) {
- static const struct {
- int x1; // rect 1
- int y1;
- int w1;
- int h1;
- int x2; // rect 2
- int y2;
- int w2;
- int h2;
- bool intersects;
- } tests[] = {
- { 0, 0, 0, 0, 0, 0, 0, 0, false },
- { 0, 0, 0, 0, -10, -10, 20, 20, false },
- { -10, 0, 0, 20, 0, -10, 20, 0, false },
- { 0, 0, 10, 10, 0, 0, 10, 10, true },
- { 0, 0, 10, 10, 10, 10, 10, 10, false },
- { 10, 10, 10, 10, 0, 0, 10, 10, false },
- { 10, 10, 10, 10, 5, 5, 10, 10, true },
- { 10, 10, 10, 10, 15, 15, 10, 10, true },
- { 10, 10, 10, 10, 20, 15, 10, 10, false },
- { 10, 10, 10, 10, 21, 15, 10, 10, false }
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
- Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
- EXPECT_EQ(tests[i].intersects, r1.Intersects(r2));
- EXPECT_EQ(tests[i].intersects, r2.Intersects(r1));
- }
-}
-
-TEST(RectTest, Intersect) {
- static const struct {
- int x1; // rect 1
- int y1;
- int w1;
- int h1;
- int x2; // rect 2
- int y2;
- int w2;
- int h2;
- int x3; // rect 3: the union of rects 1 and 2
- int y3;
- int w3;
- int h3;
- } tests[] = {
- { 0, 0, 0, 0, // zeros
- 0, 0, 0, 0,
- 0, 0, 0, 0 },
- { 0, 0, 4, 4, // equal
- 0, 0, 4, 4,
- 0, 0, 4, 4 },
- { 0, 0, 4, 4, // neighboring
- 4, 4, 4, 4,
- 0, 0, 0, 0 },
- { 0, 0, 4, 4, // overlapping corners
- 2, 2, 4, 4,
- 2, 2, 2, 2 },
- { 0, 0, 4, 4, // T junction
- 3, 1, 4, 2,
- 3, 1, 1, 2 },
- { 3, 0, 2, 2, // gap
- 0, 0, 2, 2,
- 0, 0, 0, 0 }
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
- Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
- Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
- Rect ir = IntersectRects(r1, r2);
- EXPECT_EQ(r3.x(), ir.x());
- EXPECT_EQ(r3.y(), ir.y());
- EXPECT_EQ(r3.width(), ir.width());
- EXPECT_EQ(r3.height(), ir.height());
- }
-}
-
-TEST(RectTest, Union) {
- static const struct Test {
- int x1; // rect 1
- int y1;
- int w1;
- int h1;
- int x2; // rect 2
- int y2;
- int w2;
- int h2;
- int x3; // rect 3: the union of rects 1 and 2
- int y3;
- int w3;
- int h3;
- } tests[] = {
- { 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0 },
- { 0, 0, 4, 4,
- 0, 0, 4, 4,
- 0, 0, 4, 4 },
- { 0, 0, 4, 4,
- 4, 4, 4, 4,
- 0, 0, 8, 8 },
- { 0, 0, 4, 4,
- 0, 5, 4, 4,
- 0, 0, 4, 9 },
- { 0, 0, 2, 2,
- 3, 3, 2, 2,
- 0, 0, 5, 5 },
- { 3, 3, 2, 2, // reverse r1 and r2 from previous test
- 0, 0, 2, 2,
- 0, 0, 5, 5 },
- { 0, 0, 0, 0, // union with empty rect
- 2, 2, 2, 2,
- 2, 2, 2, 2 }
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
- Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
- Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
- Rect u = UnionRects(r1, r2);
- EXPECT_EQ(r3.x(), u.x());
- EXPECT_EQ(r3.y(), u.y());
- EXPECT_EQ(r3.width(), u.width());
- EXPECT_EQ(r3.height(), u.height());
- }
-}
-
-TEST(RectTest, Equals) {
- ASSERT_TRUE(Rect(0, 0, 0, 0) == Rect(0, 0, 0, 0));
- ASSERT_TRUE(Rect(1, 2, 3, 4) == Rect(1, 2, 3, 4));
- ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 0, 0, 1));
- ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 0, 1, 0));
- ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(0, 1, 0, 0));
- ASSERT_FALSE(Rect(0, 0, 0, 0) == Rect(1, 0, 0, 0));
-}
-
-TEST(RectTest, AdjustToFit) {
- static const struct Test {
- int x1; // source
- int y1;
- int w1;
- int h1;
- int x2; // target
- int y2;
- int w2;
- int h2;
- int x3; // rect 3: results of invoking AdjustToFit
- int y3;
- int w3;
- int h3;
- } tests[] = {
- { 0, 0, 2, 2,
- 0, 0, 2, 2,
- 0, 0, 2, 2 },
- { 2, 2, 3, 3,
- 0, 0, 4, 4,
- 1, 1, 3, 3 },
- { -1, -1, 5, 5,
- 0, 0, 4, 4,
- 0, 0, 4, 4 },
- { 2, 2, 4, 4,
- 0, 0, 3, 3,
- 0, 0, 3, 3 },
- { 2, 2, 1, 1,
- 0, 0, 3, 3,
- 2, 2, 1, 1 }
- };
- for (size_t i = 0; i < arraysize(tests); ++i) {
- Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
- Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
- Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
- Rect u = r1;
- u.AdjustToFit(r2);
- EXPECT_EQ(r3.x(), u.x());
- EXPECT_EQ(r3.y(), u.y());
- EXPECT_EQ(r3.width(), u.width());
- EXPECT_EQ(r3.height(), u.height());
- }
-}
-
-TEST(RectTest, Subtract) {
- Rect result;
-
- // Matching
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(10, 10, 20, 20));
- EXPECT_EQ(Rect(0, 0, 0, 0), result);
-
- // Contains
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(5, 5, 30, 30));
- EXPECT_EQ(Rect(0, 0, 0, 0), result);
-
- // No intersection
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(30, 30, 30, 30));
- EXPECT_EQ(Rect(10, 10, 20, 20), result);
-
- // Not a complete intersection in either direction
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(15, 15, 20, 20));
- EXPECT_EQ(Rect(10, 10, 20, 20), result);
-
- // Complete intersection in the x-direction, top edge is fully covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(10, 15, 20, 20));
- EXPECT_EQ(Rect(10, 10, 20, 5), result);
-
- // Complete intersection in the x-direction, top edge is fully covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(5, 15, 30, 20));
- EXPECT_EQ(Rect(10, 10, 20, 5), result);
-
- // Complete intersection in the x-direction, bottom edge is fully covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(5, 5, 30, 20));
- EXPECT_EQ(Rect(10, 25, 20, 5), result);
-
- // Complete intersection in the x-direction, none of the edges is fully
- // covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(5, 15, 30, 1));
- EXPECT_EQ(Rect(10, 10, 20, 20), result);
-
- // Complete intersection in the y-direction, left edge is fully covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(10, 10, 10, 30));
- EXPECT_EQ(Rect(20, 10, 10, 20), result);
-
- // Complete intersection in the y-direction, left edge is fully covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(5, 5, 20, 30));
- EXPECT_EQ(Rect(25, 10, 5, 20), result);
-
- // Complete intersection in the y-direction, right edge is fully covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(20, 5, 20, 30));
- EXPECT_EQ(Rect(10, 10, 10, 20), result);
-
- // Complete intersection in the y-direction, none of the edges is fully
- // covered.
- result = Rect(10, 10, 20, 20);
- result.Subtract(Rect(15, 5, 1, 30));
- EXPECT_EQ(Rect(10, 10, 20, 20), result);
-}
-
-TEST(RectTest, IsEmpty) {
- EXPECT_TRUE(Rect(0, 0, 0, 0).IsEmpty());
- EXPECT_TRUE(Rect(0, 0, 0, 0).size().IsEmpty());
- EXPECT_TRUE(Rect(0, 0, 10, 0).IsEmpty());
- EXPECT_TRUE(Rect(0, 0, 10, 0).size().IsEmpty());
- EXPECT_TRUE(Rect(0, 0, 0, 10).IsEmpty());
- EXPECT_TRUE(Rect(0, 0, 0, 10).size().IsEmpty());
- EXPECT_FALSE(Rect(0, 0, 10, 10).IsEmpty());
- EXPECT_FALSE(Rect(0, 0, 10, 10).size().IsEmpty());
-}
-
-TEST(RectTest, SplitVertically) {
- Rect left_half, right_half;
-
- // Splitting when origin is (0, 0).
- Rect(0, 0, 20, 20).SplitVertically(&left_half, &right_half);
- EXPECT_TRUE(left_half == Rect(0, 0, 10, 20));
- EXPECT_TRUE(right_half == Rect(10, 0, 10, 20));
-
- // Splitting when origin is arbitrary.
- Rect(10, 10, 20, 10).SplitVertically(&left_half, &right_half);
- EXPECT_TRUE(left_half == Rect(10, 10, 10, 10));
- EXPECT_TRUE(right_half == Rect(20, 10, 10, 10));
-
- // Splitting a rectangle of zero width.
- Rect(10, 10, 0, 10).SplitVertically(&left_half, &right_half);
- EXPECT_TRUE(left_half == Rect(10, 10, 0, 10));
- EXPECT_TRUE(right_half == Rect(10, 10, 0, 10));
-
- // Splitting a rectangle of odd width.
- Rect(10, 10, 5, 10).SplitVertically(&left_half, &right_half);
- EXPECT_TRUE(left_half == Rect(10, 10, 2, 10));
- EXPECT_TRUE(right_half == Rect(12, 10, 3, 10));
-}
-
-TEST(RectTest, CenterPoint) {
- Point center;
-
- // When origin is (0, 0).
- center = Rect(0, 0, 20, 20).CenterPoint();
- EXPECT_TRUE(center == Point(10, 10));
-
- // When origin is even.
- center = Rect(10, 10, 20, 20).CenterPoint();
- EXPECT_TRUE(center == Point(20, 20));
-
- // When origin is odd.
- center = Rect(11, 11, 20, 20).CenterPoint();
- EXPECT_TRUE(center == Point(21, 21));
-
- // When 0 width or height.
- center = Rect(10, 10, 0, 20).CenterPoint();
- EXPECT_TRUE(center == Point(10, 20));
- center = Rect(10, 10, 20, 0).CenterPoint();
- EXPECT_TRUE(center == Point(20, 10));
-
- // When an odd size.
- center = Rect(10, 10, 21, 21).CenterPoint();
- EXPECT_TRUE(center == Point(20, 20));
-
- // When an odd size and position.
- center = Rect(11, 11, 21, 21).CenterPoint();
- EXPECT_TRUE(center == Point(21, 21));
-}
-
-TEST(RectTest, CenterPointF) {
- PointF center;
-
- // When origin is (0, 0).
- center = RectF(0, 0, 20, 20).CenterPoint();
- EXPECT_TRUE(center == PointF(10, 10));
-
- // When origin is even.
- center = RectF(10, 10, 20, 20).CenterPoint();
- EXPECT_TRUE(center == PointF(20, 20));
-
- // When origin is odd.
- center = RectF(11, 11, 20, 20).CenterPoint();
- EXPECT_TRUE(center == PointF(21, 21));
-
- // When 0 width or height.
- center = RectF(10, 10, 0, 20).CenterPoint();
- EXPECT_TRUE(center == PointF(10, 20));
- center = RectF(10, 10, 20, 0).CenterPoint();
- EXPECT_TRUE(center == PointF(20, 10));
-
- // When an odd size.
- center = RectF(10, 10, 21, 21).CenterPoint();
- EXPECT_TRUE(center == PointF(20.5f, 20.5f));
-
- // When an odd size and position.
- center = RectF(11, 11, 21, 21).CenterPoint();
- EXPECT_TRUE(center == PointF(21.5f, 21.5f));
-}
-
-TEST(RectTest, SharesEdgeWith) {
- Rect r(2, 3, 4, 5);
-
- // Must be non-overlapping
- EXPECT_FALSE(r.SharesEdgeWith(r));
-
- Rect just_above(2, 1, 4, 2);
- Rect just_below(2, 8, 4, 2);
- Rect just_left(0, 3, 2, 5);
- Rect just_right(6, 3, 2, 5);
-
- EXPECT_TRUE(r.SharesEdgeWith(just_above));
- EXPECT_TRUE(r.SharesEdgeWith(just_below));
- EXPECT_TRUE(r.SharesEdgeWith(just_left));
- EXPECT_TRUE(r.SharesEdgeWith(just_right));
-
- // Wrong placement
- Rect same_height_no_edge(0, 0, 1, 5);
- Rect same_width_no_edge(0, 0, 4, 1);
-
- EXPECT_FALSE(r.SharesEdgeWith(same_height_no_edge));
- EXPECT_FALSE(r.SharesEdgeWith(same_width_no_edge));
-
- Rect just_above_no_edge(2, 1, 5, 2); // too wide
- Rect just_below_no_edge(2, 8, 3, 2); // too narrow
- Rect just_left_no_edge(0, 3, 2, 6); // too tall
- Rect just_right_no_edge(6, 3, 2, 4); // too short
-
- EXPECT_FALSE(r.SharesEdgeWith(just_above_no_edge));
- EXPECT_FALSE(r.SharesEdgeWith(just_below_no_edge));
- EXPECT_FALSE(r.SharesEdgeWith(just_left_no_edge));
- EXPECT_FALSE(r.SharesEdgeWith(just_right_no_edge));
-}
-
-// Similar to EXPECT_FLOAT_EQ, but lets NaN equal NaN
-#define EXPECT_FLOAT_AND_NAN_EQ(a, b) \
- { if (a == a || b == b) { EXPECT_FLOAT_EQ(a, b); } }
-
-TEST(RectTest, ScaleRect) {
- static const struct Test {
- int x1; // source
- int y1;
- int w1;
- int h1;
- float scale;
- float x2; // target
- float y2;
- float w2;
- float h2;
- } tests[] = {
- { 3, 3, 3, 3,
- 1.5f,
- 4.5f, 4.5f, 4.5f, 4.5f },
- { 3, 3, 3, 3,
- 0.0f,
- 0.0f, 0.0f, 0.0f, 0.0f },
- { 3, 3, 3, 3,
- std::numeric_limits<float>::quiet_NaN(),
- std::numeric_limits<float>::quiet_NaN(),
- std::numeric_limits<float>::quiet_NaN(),
- std::numeric_limits<float>::quiet_NaN(),
- std::numeric_limits<float>::quiet_NaN() },
- { 3, 3, 3, 3,
- std::numeric_limits<float>::max(),
- std::numeric_limits<float>::max(),
- std::numeric_limits<float>::max(),
- std::numeric_limits<float>::max(),
- std::numeric_limits<float>::max() }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
- RectF r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
-
- RectF scaled = ScaleRect(r1, tests[i].scale);
- EXPECT_FLOAT_AND_NAN_EQ(r2.x(), scaled.x());
- EXPECT_FLOAT_AND_NAN_EQ(r2.y(), scaled.y());
- EXPECT_FLOAT_AND_NAN_EQ(r2.width(), scaled.width());
- EXPECT_FLOAT_AND_NAN_EQ(r2.height(), scaled.height());
- }
-}
-
-TEST(RectTest, ToEnclosedRect) {
- static const int max_int = std::numeric_limits<int>::max();
- static const int min_int = std::numeric_limits<int>::min();
- static const float max_float = std::numeric_limits<float>::max();
- static const float max_int_f = static_cast<float>(max_int);
- static const float min_int_f = static_cast<float>(min_int);
-
- static const struct Test {
- struct {
- float x;
- float y;
- float width;
- float height;
- } in;
- struct {
- int x;
- int y;
- int width;
- int height;
- } expected;
- } tests[] = {
- {{0.0f, 0.0f, 0.0f, 0.0f}, {0, 0, 0, 0}},
- {{-1.5f, -1.5f, 3.0f, 3.0f}, {-1, -1, 2, 2}},
- {{-1.5f, -1.5f, 3.5f, 3.5f}, {-1, -1, 3, 3}},
- {{max_float, max_float, 2.0f, 2.0f}, {max_int, max_int, 0, 0}},
- {{0.0f, 0.0f, max_float, max_float}, {0, 0, max_int, max_int}},
- {{20000.5f, 20000.5f, 0.5f, 0.5f}, {20001, 20001, 0, 0}},
- {{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}}};
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- RectF source(tests[i].in.x, tests[i].in.y, tests[i].in.width,
- tests[i].in.height);
- Rect enclosed = ToEnclosedRect(source);
-
- EXPECT_EQ(tests[i].expected.x, enclosed.x());
- EXPECT_EQ(tests[i].expected.y, enclosed.y());
- EXPECT_EQ(tests[i].expected.width, enclosed.width());
- EXPECT_EQ(tests[i].expected.height, enclosed.height());
- }
-
- {
- RectF source(min_int_f, min_int_f, max_int_f * 3.f, max_int_f * 3.f);
- Rect enclosed = ToEnclosedRect(source);
-
- // That rect can't be represented, but it should be big.
- EXPECT_EQ(max_int, enclosed.width());
- EXPECT_EQ(max_int, enclosed.height());
- // It should include some axis near the global origin.
- EXPECT_GT(1, enclosed.x());
- EXPECT_GT(1, enclosed.y());
- // And it should not cause computation issues for itself.
- EXPECT_LT(0, enclosed.right());
- EXPECT_LT(0, enclosed.bottom());
- }
-}
-
-TEST(RectTest, ToEnclosingRect) {
- static const int max_int = std::numeric_limits<int>::max();
- static const int min_int = std::numeric_limits<int>::min();
- static const float max_float = std::numeric_limits<float>::max();
- static const float epsilon_float = std::numeric_limits<float>::epsilon();
- static const float max_int_f = static_cast<float>(max_int);
- static const float min_int_f = static_cast<float>(min_int);
- static const struct Test {
- struct {
- float x;
- float y;
- float width;
- float height;
- } in;
- struct {
- int x;
- int y;
- int width;
- int height;
- } expected;
- } tests[] = {
- {{0.0f, 0.0f, 0.0f, 0.0f}, {0, 0, 0, 0}},
- {{5.5f, 5.5f, 0.0f, 0.0f}, {5, 5, 0, 0}},
- {{3.5f, 2.5f, epsilon_float, -0.0f}, {3, 2, 0, 0}},
- {{3.5f, 2.5f, 0.f, 0.001f}, {3, 2, 0, 1}},
- {{-1.5f, -1.5f, 3.0f, 3.0f}, {-2, -2, 4, 4}},
- {{-1.5f, -1.5f, 3.5f, 3.5f}, {-2, -2, 4, 4}},
- {{max_float, max_float, 2.0f, 2.0f}, {max_int, max_int, 0, 0}},
- {{0.0f, 0.0f, max_float, max_float}, {0, 0, max_int, max_int}},
- {{20000.5f, 20000.5f, 0.5f, 0.5f}, {20000, 20000, 1, 1}},
- {{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}},
- {{-0.5f, -0.5f, 22777712.f, 1.f}, {-1, -1, 22777713, 2}}};
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- RectF source(tests[i].in.x, tests[i].in.y, tests[i].in.width,
- tests[i].in.height);
-
- Rect enclosing = ToEnclosingRect(source);
- EXPECT_EQ(tests[i].expected.x, enclosing.x());
- EXPECT_EQ(tests[i].expected.y, enclosing.y());
- EXPECT_EQ(tests[i].expected.width, enclosing.width());
- EXPECT_EQ(tests[i].expected.height, enclosing.height());
- }
-
- {
- RectF source(min_int_f, min_int_f, max_int_f * 3.f, max_int_f * 3.f);
- Rect enclosing = ToEnclosingRect(source);
-
- // That rect can't be represented, but it should be big.
- EXPECT_EQ(max_int, enclosing.width());
- EXPECT_EQ(max_int, enclosing.height());
- // It should include some axis near the global origin.
- EXPECT_GT(1, enclosing.x());
- EXPECT_GT(1, enclosing.y());
- // And it should cause computation issues for itself.
- EXPECT_LT(0, enclosing.right());
- EXPECT_LT(0, enclosing.bottom());
- }
-}
-
-TEST(RectTest, ToNearestRect) {
- Rect rect;
- EXPECT_EQ(rect, ToNearestRect(RectF(rect)));
-
- rect = Rect(-1, -1, 3, 3);
- EXPECT_EQ(rect, ToNearestRect(RectF(rect)));
-
- RectF rectf(-1.00001f, -0.999999f, 3.0000001f, 2.999999f);
- EXPECT_EQ(rect, ToNearestRect(rectf));
-}
-
-TEST(RectTest, ToFlooredRect) {
- static const struct Test {
- float x1; // source
- float y1;
- float w1;
- float h1;
- int x2; // target
- int y2;
- int w2;
- int h2;
- } tests [] = {
- { 0.0f, 0.0f, 0.0f, 0.0f,
- 0, 0, 0, 0 },
- { -1.5f, -1.5f, 3.0f, 3.0f,
- -2, -2, 3, 3 },
- { -1.5f, -1.5f, 3.5f, 3.5f,
- -2, -2, 3, 3 },
- { 20000.5f, 20000.5f, 0.5f, 0.5f,
- 20000, 20000, 0, 0 },
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
- Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
-
- Rect floored = ToFlooredRectDeprecated(r1);
- EXPECT_FLOAT_EQ(r2.x(), floored.x());
- EXPECT_FLOAT_EQ(r2.y(), floored.y());
- EXPECT_FLOAT_EQ(r2.width(), floored.width());
- EXPECT_FLOAT_EQ(r2.height(), floored.height());
- }
-}
-
-TEST(RectTest, ScaleToEnclosedRect) {
- static const struct Test {
- Rect input_rect;
- float input_scale;
- Rect expected_rect;
- } tests[] = {
- {
- Rect(),
- 5.f,
- Rect(),
- }, {
- Rect(1, 1, 1, 1),
- 5.f,
- Rect(5, 5, 5, 5),
- }, {
- Rect(-1, -1, 0, 0),
- 5.f,
- Rect(-5, -5, 0, 0),
- }, {
- Rect(1, -1, 0, 1),
- 5.f,
- Rect(5, -5, 0, 5),
- }, {
- Rect(-1, 1, 1, 0),
- 5.f,
- Rect(-5, 5, 5, 0),
- }, {
- Rect(1, 2, 3, 4),
- 1.5f,
- Rect(2, 3, 4, 6),
- }, {
- Rect(-1, -2, 0, 0),
- 1.5f,
- Rect(-1, -3, 0, 0),
- }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- Rect result = ScaleToEnclosedRect(tests[i].input_rect,
- tests[i].input_scale);
- EXPECT_EQ(tests[i].expected_rect, result);
- }
-}
-
-TEST(RectTest, ScaleToEnclosingRect) {
- static const struct Test {
- Rect input_rect;
- float input_scale;
- Rect expected_rect;
- } tests[] = {
- {
- Rect(),
- 5.f,
- Rect(),
- }, {
- Rect(1, 1, 1, 1),
- 5.f,
- Rect(5, 5, 5, 5),
- }, {
- Rect(-1, -1, 0, 0),
- 5.f,
- Rect(-5, -5, 0, 0),
- }, {
- Rect(1, -1, 0, 1),
- 5.f,
- Rect(5, -5, 0, 5),
- }, {
- Rect(-1, 1, 1, 0),
- 5.f,
- Rect(-5, 5, 5, 0),
- }, {
- Rect(1, 2, 3, 4),
- 1.5f,
- Rect(1, 3, 5, 6),
- }, {
- Rect(-1, -2, 0, 0),
- 1.5f,
- Rect(-2, -3, 0, 0),
- }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- Rect result =
- ScaleToEnclosingRect(tests[i].input_rect, tests[i].input_scale);
- EXPECT_EQ(tests[i].expected_rect, result);
- Rect result_safe =
- ScaleToEnclosingRectSafe(tests[i].input_rect, tests[i].input_scale);
- EXPECT_EQ(tests[i].expected_rect, result_safe);
- }
-}
-
-#if defined(OS_WIN)
-TEST(RectTest, ConstructAndAssign) {
- const RECT rect_1 = { 0, 0, 10, 10 };
- const RECT rect_2 = { 0, 0, -10, -10 };
- Rect test1(rect_1);
- Rect test2(rect_2);
-}
-#endif
-
-TEST(RectTest, ToRectF) {
- // Check that explicit conversion from integer to float compiles.
- Rect a(10, 20, 30, 40);
- RectF b(10, 20, 30, 40);
-
- RectF c = RectF(a);
- EXPECT_EQ(b, c);
-}
-
-TEST(RectTest, BoundingRect) {
- struct {
- Point a;
- Point b;
- Rect expected;
- } int_tests[] = {
- // If point B dominates A, then A should be the origin.
- { Point(4, 6), Point(4, 6), Rect(4, 6, 0, 0) },
- { Point(4, 6), Point(8, 6), Rect(4, 6, 4, 0) },
- { Point(4, 6), Point(4, 9), Rect(4, 6, 0, 3) },
- { Point(4, 6), Point(8, 9), Rect(4, 6, 4, 3) },
- // If point A dominates B, then B should be the origin.
- { Point(4, 6), Point(4, 6), Rect(4, 6, 0, 0) },
- { Point(8, 6), Point(4, 6), Rect(4, 6, 4, 0) },
- { Point(4, 9), Point(4, 6), Rect(4, 6, 0, 3) },
- { Point(8, 9), Point(4, 6), Rect(4, 6, 4, 3) },
- // If neither point dominates, then the origin is a combination of the two.
- { Point(4, 6), Point(6, 4), Rect(4, 4, 2, 2) },
- { Point(-4, -6), Point(-6, -4), Rect(-6, -6, 2, 2) },
- { Point(-4, 6), Point(6, -4), Rect(-4, -4, 10, 10) },
- };
-
- for (size_t i = 0; i < arraysize(int_tests); ++i) {
- Rect actual = BoundingRect(int_tests[i].a, int_tests[i].b);
- EXPECT_EQ(int_tests[i].expected, actual);
- }
-
- struct {
- PointF a;
- PointF b;
- RectF expected;
- } float_tests[] = {
- // If point B dominates A, then A should be the origin.
- { PointF(4.2f, 6.8f), PointF(4.2f, 6.8f),
- RectF(4.2f, 6.8f, 0, 0) },
- { PointF(4.2f, 6.8f), PointF(8.5f, 6.8f),
- RectF(4.2f, 6.8f, 4.3f, 0) },
- { PointF(4.2f, 6.8f), PointF(4.2f, 9.3f),
- RectF(4.2f, 6.8f, 0, 2.5f) },
- { PointF(4.2f, 6.8f), PointF(8.5f, 9.3f),
- RectF(4.2f, 6.8f, 4.3f, 2.5f) },
- // If point A dominates B, then B should be the origin.
- { PointF(4.2f, 6.8f), PointF(4.2f, 6.8f),
- RectF(4.2f, 6.8f, 0, 0) },
- { PointF(8.5f, 6.8f), PointF(4.2f, 6.8f),
- RectF(4.2f, 6.8f, 4.3f, 0) },
- { PointF(4.2f, 9.3f), PointF(4.2f, 6.8f),
- RectF(4.2f, 6.8f, 0, 2.5f) },
- { PointF(8.5f, 9.3f), PointF(4.2f, 6.8f),
- RectF(4.2f, 6.8f, 4.3f, 2.5f) },
- // If neither point dominates, then the origin is a combination of the two.
- { PointF(4.2f, 6.8f), PointF(6.8f, 4.2f),
- RectF(4.2f, 4.2f, 2.6f, 2.6f) },
- { PointF(-4.2f, -6.8f), PointF(-6.8f, -4.2f),
- RectF(-6.8f, -6.8f, 2.6f, 2.6f) },
- { PointF(-4.2f, 6.8f), PointF(6.8f, -4.2f),
- RectF(-4.2f, -4.2f, 11.0f, 11.0f) }
- };
-
- for (size_t i = 0; i < arraysize(float_tests); ++i) {
- RectF actual = BoundingRect(float_tests[i].a, float_tests[i].b);
- EXPECT_RECTF_EQ(float_tests[i].expected, actual);
- }
-}
-
-TEST(RectTest, IsExpressibleAsRect) {
- EXPECT_TRUE(RectF().IsExpressibleAsRect());
-
- float min = std::numeric_limits<int>::min();
- float max = std::numeric_limits<int>::max();
- float infinity = std::numeric_limits<float>::infinity();
-
- EXPECT_TRUE(RectF(
- min + 200, min + 200, max - 200, max - 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(
- min - 200, min + 200, max + 200, max + 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(
- min + 200 , min - 200, max + 200, max + 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(
- min + 200, min + 200, max + 200, max - 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(
- min + 200, min + 200, max - 200, max + 200).IsExpressibleAsRect());
-
- EXPECT_TRUE(RectF(0, 0, max - 200, max - 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(200, 0, max + 200, max - 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(0, 200, max - 200, max + 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(0, 0, max + 200, max - 200).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(0, 0, max - 200, max + 200).IsExpressibleAsRect());
-
- EXPECT_FALSE(RectF(infinity, 0, 1, 1).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(0, infinity, 1, 1).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(0, 0, infinity, 1).IsExpressibleAsRect());
- EXPECT_FALSE(RectF(0, 0, 1, infinity).IsExpressibleAsRect());
-}
-
-TEST(RectTest, Offset) {
- Rect i(1, 2, 3, 4);
-
- EXPECT_EQ(Rect(2, 1, 3, 4), (i + Vector2d(1, -1)));
- EXPECT_EQ(Rect(2, 1, 3, 4), (Vector2d(1, -1) + i));
- i += Vector2d(1, -1);
- EXPECT_EQ(Rect(2, 1, 3, 4), i);
- EXPECT_EQ(Rect(1, 2, 3, 4), (i - Vector2d(1, -1)));
- i -= Vector2d(1, -1);
- EXPECT_EQ(Rect(1, 2, 3, 4), i);
-
- RectF f(1.1f, 2.2f, 3.3f, 4.4f);
- EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f), (f + Vector2dF(1.1f, -1.1f)));
- EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f), (Vector2dF(1.1f, -1.1f) + f));
- f += Vector2dF(1.1f, -1.1f);
- EXPECT_EQ(RectF(2.2f, 1.1f, 3.3f, 4.4f), f);
- EXPECT_EQ(RectF(1.1f, 2.2f, 3.3f, 4.4f), (f - Vector2dF(1.1f, -1.1f)));
- f -= Vector2dF(1.1f, -1.1f);
- EXPECT_EQ(RectF(1.1f, 2.2f, 3.3f, 4.4f), f);
-}
-
-TEST(RectTest, Corners) {
- Rect i(1, 2, 3, 4);
- RectF f(1.1f, 2.1f, 3.1f, 4.1f);
-
- EXPECT_EQ(Point(1, 2), i.origin());
- EXPECT_EQ(Point(4, 2), i.top_right());
- EXPECT_EQ(Point(1, 6), i.bottom_left());
- EXPECT_EQ(Point(4, 6), i.bottom_right());
-
- EXPECT_EQ(PointF(1.1f, 2.1f), f.origin());
- EXPECT_EQ(PointF(4.2f, 2.1f), f.top_right());
- EXPECT_EQ(PointF(1.1f, 6.2f), f.bottom_left());
- EXPECT_EQ(PointF(4.2f, 6.2f), f.bottom_right());
-}
-
-TEST(RectTest, ManhattanDistanceToPoint) {
- Rect i(1, 2, 3, 4);
- EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(1, 2)));
- EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(4, 6)));
- EXPECT_EQ(0, i.ManhattanDistanceToPoint(Point(2, 4)));
- EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(0, 0)));
- EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(2, 0)));
- EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 0)));
- EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(5, 4)));
- EXPECT_EQ(3, i.ManhattanDistanceToPoint(Point(5, 8)));
- EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(3, 8)));
- EXPECT_EQ(2, i.ManhattanDistanceToPoint(Point(0, 7)));
- EXPECT_EQ(1, i.ManhattanDistanceToPoint(Point(0, 3)));
-
- RectF f(1.1f, 2.1f, 3.1f, 4.1f);
- EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(1.1f, 2.1f)));
- EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(4.2f, 6.f)));
- EXPECT_FLOAT_EQ(0.f, f.ManhattanDistanceToPoint(PointF(2.f, 4.f)));
- EXPECT_FLOAT_EQ(3.2f, f.ManhattanDistanceToPoint(PointF(0.f, 0.f)));
- EXPECT_FLOAT_EQ(2.1f, f.ManhattanDistanceToPoint(PointF(2.f, 0.f)));
- EXPECT_FLOAT_EQ(2.9f, f.ManhattanDistanceToPoint(PointF(5.f, 0.f)));
- EXPECT_FLOAT_EQ(.8f, f.ManhattanDistanceToPoint(PointF(5.f, 4.f)));
- EXPECT_FLOAT_EQ(2.6f, f.ManhattanDistanceToPoint(PointF(5.f, 8.f)));
- EXPECT_FLOAT_EQ(1.8f, f.ManhattanDistanceToPoint(PointF(3.f, 8.f)));
- EXPECT_FLOAT_EQ(1.9f, f.ManhattanDistanceToPoint(PointF(0.f, 7.f)));
- EXPECT_FLOAT_EQ(1.1f, f.ManhattanDistanceToPoint(PointF(0.f, 3.f)));
-}
-
-TEST(RectTest, ManhattanInternalDistance) {
- Rect i(0, 0, 400, 400);
- EXPECT_EQ(0, i.ManhattanInternalDistance(gfx::Rect(-1, 0, 2, 1)));
- EXPECT_EQ(1, i.ManhattanInternalDistance(gfx::Rect(400, 0, 1, 400)));
- EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-100, -100, 100, 100)));
- EXPECT_EQ(2, i.ManhattanInternalDistance(gfx::Rect(-101, 100, 100, 100)));
- EXPECT_EQ(4, i.ManhattanInternalDistance(gfx::Rect(-101, -101, 100, 100)));
- EXPECT_EQ(435, i.ManhattanInternalDistance(gfx::Rect(630, 603, 100, 100)));
-
- RectF f(0.0f, 0.0f, 400.0f, 400.0f);
- static const float kEpsilon = std::numeric_limits<float>::epsilon();
-
- EXPECT_FLOAT_EQ(
- 0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 2.0f, 1.0f)));
- EXPECT_FLOAT_EQ(
- kEpsilon,
- f.ManhattanInternalDistance(gfx::RectF(400.0f, 0.0f, 1.0f, 400.0f)));
- EXPECT_FLOAT_EQ(2.0f * kEpsilon,
- f.ManhattanInternalDistance(
- gfx::RectF(-100.0f, -100.0f, 100.0f, 100.0f)));
- EXPECT_FLOAT_EQ(
- 1.0f + kEpsilon,
- f.ManhattanInternalDistance(gfx::RectF(-101.0f, 100.0f, 100.0f, 100.0f)));
- EXPECT_FLOAT_EQ(2.0f + 2.0f * kEpsilon,
- f.ManhattanInternalDistance(
- gfx::RectF(-101.0f, -101.0f, 100.0f, 100.0f)));
- EXPECT_FLOAT_EQ(
- 433.0f + 2.0f * kEpsilon,
- f.ManhattanInternalDistance(gfx::RectF(630.0f, 603.0f, 100.0f, 100.0f)));
-
- EXPECT_FLOAT_EQ(
- 0.0f, f.ManhattanInternalDistance(gfx::RectF(-1.0f, 0.0f, 1.1f, 1.0f)));
- EXPECT_FLOAT_EQ(
- 0.1f + kEpsilon,
- f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.4f, 1.0f)));
- EXPECT_FLOAT_EQ(
- kEpsilon,
- f.ManhattanInternalDistance(gfx::RectF(-1.5f, 0.0f, 1.5f, 1.0f)));
-}
-
-TEST(RectTest, IntegerOverflow) {
- int limit = std::numeric_limits<int>::max();
- int min_limit = std::numeric_limits<int>::min();
- int expected = 10;
- int large_number = limit - expected;
-
- Rect height_overflow(0, large_number, 100, 100);
- EXPECT_EQ(large_number, height_overflow.y());
- EXPECT_EQ(expected, height_overflow.height());
-
- Rect width_overflow(large_number, 0, 100, 100);
- EXPECT_EQ(large_number, width_overflow.x());
- EXPECT_EQ(expected, width_overflow.width());
-
- Rect size_height_overflow(Point(0, large_number), Size(100, 100));
- EXPECT_EQ(large_number, size_height_overflow.y());
- EXPECT_EQ(expected, size_height_overflow.height());
-
- Rect size_width_overflow(Point(large_number, 0), Size(100, 100));
- EXPECT_EQ(large_number, size_width_overflow.x());
- EXPECT_EQ(expected, size_width_overflow.width());
-
- Rect set_height_overflow(0, large_number, 100, 5);
- EXPECT_EQ(5, set_height_overflow.height());
- set_height_overflow.set_height(100);
- EXPECT_EQ(expected, set_height_overflow.height());
-
- Rect set_y_overflow(100, 100, 100, 100);
- EXPECT_EQ(100, set_y_overflow.height());
- set_y_overflow.set_y(large_number);
- EXPECT_EQ(expected, set_y_overflow.height());
-
- Rect set_width_overflow(large_number, 0, 5, 100);
- EXPECT_EQ(5, set_width_overflow.width());
- set_width_overflow.set_width(100);
- EXPECT_EQ(expected, set_width_overflow.width());
-
- Rect set_x_overflow(100, 100, 100, 100);
- EXPECT_EQ(100, set_x_overflow.width());
- set_x_overflow.set_x(large_number);
- EXPECT_EQ(expected, set_x_overflow.width());
-
- Point large_offset(large_number, large_number);
- Size size(100, 100);
- Size expected_size(10, 10);
-
- Rect set_origin_overflow(100, 100, 100, 100);
- EXPECT_EQ(size, set_origin_overflow.size());
- set_origin_overflow.set_origin(large_offset);
- EXPECT_EQ(large_offset, set_origin_overflow.origin());
- EXPECT_EQ(expected_size, set_origin_overflow.size());
-
- Rect set_size_overflow(large_number, large_number, 5, 5);
- EXPECT_EQ(Size(5, 5), set_size_overflow.size());
- set_size_overflow.set_size(size);
- EXPECT_EQ(large_offset, set_size_overflow.origin());
- EXPECT_EQ(expected_size, set_size_overflow.size());
-
- Rect set_rect_overflow;
- set_rect_overflow.SetRect(large_number, large_number, 100, 100);
- EXPECT_EQ(large_offset, set_rect_overflow.origin());
- EXPECT_EQ(expected_size, set_rect_overflow.size());
-
- // Insetting an empty rect, but the total inset (left + right) could overflow.
- Rect inset_overflow;
- inset_overflow.Inset(large_number, large_number, 100, 100);
- EXPECT_EQ(large_offset, inset_overflow.origin());
- EXPECT_EQ(gfx::Size(), inset_overflow.size());
-
- // Insetting where the total inset (width - left - right) could overflow.
- // Also, this insetting by the min limit in all directions cannot
- // represent width() without overflow, so that will also clamp.
- Rect inset_overflow2;
- inset_overflow2.Inset(min_limit, min_limit, min_limit, min_limit);
- EXPECT_EQ(inset_overflow2, gfx::Rect(min_limit, min_limit, limit, limit));
-
- // Insetting where the width shouldn't change, but if the insets operations
- // clamped in the wrong order, e.g. ((width - left) - right) vs (width - (left
- // + right)) then this will not work properly. This is the proper order,
- // as if left + right overflows, the width cannot be decreased by more than
- // max int anyway. Additionally, if left + right underflows, it cannot be
- // increased by more then max int.
- Rect inset_overflow3(0, 0, limit, limit);
- inset_overflow3.Inset(-100, -100, 100, 100);
- EXPECT_EQ(inset_overflow3, gfx::Rect(-100, -100, limit, limit));
-
- Rect inset_overflow4(-1000, -1000, limit, limit);
- inset_overflow4.Inset(100, 100, -100, -100);
- EXPECT_EQ(inset_overflow4, gfx::Rect(-900, -900, limit, limit));
-
- Rect offset_overflow(0, 0, 100, 100);
- offset_overflow.Offset(large_number, large_number);
- EXPECT_EQ(large_offset, offset_overflow.origin());
- EXPECT_EQ(expected_size, offset_overflow.size());
-
- Rect operator_overflow(0, 0, 100, 100);
- operator_overflow += Vector2d(large_number, large_number);
- EXPECT_EQ(large_offset, operator_overflow.origin());
- EXPECT_EQ(expected_size, operator_overflow.size());
-
- Rect origin_maxint(limit, limit, limit, limit);
- EXPECT_EQ(origin_maxint, Rect(gfx::Point(limit, limit), gfx::Size()));
-
- // Expect a rect at the origin and a rect whose right/bottom is maxint
- // create a rect that extends from 0..maxint in both extents.
- {
- Rect origin_small(0, 0, 100, 100);
- Rect big_clamped(50, 50, limit, limit);
- EXPECT_EQ(big_clamped.right(), limit);
-
- Rect unioned = UnionRects(origin_small, big_clamped);
- Rect rect_limit(0, 0, limit, limit);
- EXPECT_EQ(unioned, rect_limit);
- }
-
- // Expect a rect that would overflow width (but not right) to be clamped
- // and to have maxint extents after unioning.
- {
- Rect small(-500, -400, 100, 100);
- Rect big(-400, -500, limit, limit);
- // Technically, this should be limit + 100 width, but will clamp to maxint.
- EXPECT_EQ(UnionRects(small, big), Rect(-500, -500, limit, limit));
- }
-
- // Expect a rect that would overflow right *and* width to be clamped.
- {
- Rect clamped(500, 500, limit, limit);
- Rect positive_origin(100, 100, 500, 500);
-
- // Ideally, this should be (100, 100, limit + 400, limit + 400).
- // However, width overflows and would be clamped to limit, but right
- // overflows too and so will be clamped to limit - 100.
- Rect expected(100, 100, limit - 100, limit - 100);
- EXPECT_EQ(UnionRects(clamped, positive_origin), expected);
- }
-
- // Unioning a left=minint rect with a right=maxint rect.
- // We can't represent both ends of the spectrum in the same rect.
- // Make sure we keep the most useful area.
- {
- int part_limit = min_limit / 3;
- Rect left_minint(min_limit, min_limit, 1, 1);
- Rect right_maxint(limit - 1, limit - 1, limit, limit);
- Rect expected(part_limit, part_limit, 2 * part_limit, 2 * part_limit);
- Rect result = UnionRects(left_minint, right_maxint);
-
- // The result should be maximally big.
- EXPECT_EQ(limit, result.height());
- EXPECT_EQ(limit, result.width());
-
- // The result should include the area near the origin.
- EXPECT_GT(-part_limit, result.x());
- EXPECT_LT(part_limit, result.right());
- EXPECT_GT(-part_limit, result.y());
- EXPECT_LT(part_limit, result.bottom());
-
- // More succinctly, but harder to read in the results.
- EXPECT_TRUE(UnionRects(left_minint, right_maxint).Contains(expected));
- }
-}
-
-TEST(RectTest, ScaleToEnclosingRectSafe) {
- const int max_int = std::numeric_limits<int>::max();
- const int min_int = std::numeric_limits<int>::min();
-
- Rect xy_underflow(-100000, -123456, 10, 20);
- EXPECT_EQ(ScaleToEnclosingRectSafe(xy_underflow, 100000, 100000),
- Rect(min_int, min_int, 1000000, 2000000));
-
- // A location overflow means that width/right and bottom/top also
- // overflow so need to be clamped.
- Rect xy_overflow(100000, 123456, 10, 20);
- EXPECT_EQ(ScaleToEnclosingRectSafe(xy_overflow, 100000, 100000),
- Rect(max_int, max_int, 0, 0));
-
- // In practice all rects are clamped to 0 width / 0 height so
- // negative sizes don't matter, but try this for the sake of testing.
- Rect size_underflow(-1, -2, 100000, 100000);
- EXPECT_EQ(ScaleToEnclosingRectSafe(size_underflow, -100000, -100000),
- Rect(100000, 200000, 0, 0));
-
- Rect size_overflow(-1, -2, 123456, 234567);
- EXPECT_EQ(ScaleToEnclosingRectSafe(size_overflow, 100000, 100000),
- Rect(-100000, -200000, max_int, max_int));
- // Verify width/right gets clamped properly too if x/y positive.
- Rect size_overflow2(1, 2, 123456, 234567);
- EXPECT_EQ(ScaleToEnclosingRectSafe(size_overflow2, 100000, 100000),
- Rect(100000, 200000, max_int - 100000, max_int - 200000));
-
- Rect max_rect(max_int, max_int, max_int, max_int);
- EXPECT_EQ(ScaleToEnclosingRectSafe(max_rect, max_int, max_int),
- Rect(max_int, max_int, 0, 0));
-
- Rect min_rect(min_int, min_int, max_int, max_int);
- // Min rect can't be scaled up any further in any dimension.
- EXPECT_EQ(ScaleToEnclosingRectSafe(min_rect, 2, 3.5), min_rect);
- EXPECT_EQ(ScaleToEnclosingRectSafe(min_rect, max_int, max_int), min_rect);
- // Min rect scaled by min is an empty rect at (max, max)
- EXPECT_EQ(ScaleToEnclosingRectSafe(min_rect, min_int, min_int), max_rect);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/safe_integer_conversions_unittest.cc b/ui/gfx/geometry/safe_integer_conversions_unittest.cc
deleted file mode 100644
index 91bdbb8d35..0000000000
--- a/ui/gfx/geometry/safe_integer_conversions_unittest.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 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.
-
-#include "ui/gfx/geometry/safe_integer_conversions.h"
-
-#include <limits>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace gfx {
-
-TEST(SafeIntegerConversions, ToFlooredInt) {
- float max = std::numeric_limits<int>::max();
- float min = std::numeric_limits<int>::min();
- float infinity = std::numeric_limits<float>::infinity();
-
- int int_max = std::numeric_limits<int>::max();
- int int_min = std::numeric_limits<int>::min();
-
- EXPECT_EQ(int_max, ToFlooredInt(infinity));
- EXPECT_EQ(int_max, ToFlooredInt(max));
- EXPECT_EQ(int_max, ToFlooredInt(max + 100));
-
- EXPECT_EQ(-101, ToFlooredInt(-100.5f));
- EXPECT_EQ(0, ToFlooredInt(0.f));
- EXPECT_EQ(100, ToFlooredInt(100.5f));
-
- EXPECT_EQ(int_min, ToFlooredInt(-infinity));
- EXPECT_EQ(int_min, ToFlooredInt(min));
- EXPECT_EQ(int_min, ToFlooredInt(min - 100));
-}
-
-TEST(SafeIntegerConversions, ToCeiledInt) {
- float max = std::numeric_limits<int>::max();
- float min = std::numeric_limits<int>::min();
- float infinity = std::numeric_limits<float>::infinity();
-
- int int_max = std::numeric_limits<int>::max();
- int int_min = std::numeric_limits<int>::min();
-
- EXPECT_EQ(int_max, ToCeiledInt(infinity));
- EXPECT_EQ(int_max, ToCeiledInt(max));
- EXPECT_EQ(int_max, ToCeiledInt(max + 100));
-
- EXPECT_EQ(-100, ToCeiledInt(-100.5f));
- EXPECT_EQ(0, ToCeiledInt(0.f));
- EXPECT_EQ(101, ToCeiledInt(100.5f));
-
- EXPECT_EQ(int_min, ToCeiledInt(-infinity));
- EXPECT_EQ(int_min, ToCeiledInt(min));
- EXPECT_EQ(int_min, ToCeiledInt(min - 100));
-}
-
-TEST(SafeIntegerConversions, ToRoundedInt) {
- float max = std::numeric_limits<int>::max();
- float min = std::numeric_limits<int>::min();
- float infinity = std::numeric_limits<float>::infinity();
-
- int int_max = std::numeric_limits<int>::max();
- int int_min = std::numeric_limits<int>::min();
-
- EXPECT_EQ(int_max, ToRoundedInt(infinity));
- EXPECT_EQ(int_max, ToRoundedInt(max));
- EXPECT_EQ(int_max, ToRoundedInt(max + 100));
-
- EXPECT_EQ(-100, ToRoundedInt(-100.1f));
- EXPECT_EQ(-101, ToRoundedInt(-100.5f));
- EXPECT_EQ(-101, ToRoundedInt(-100.9f));
- EXPECT_EQ(0, ToRoundedInt(0.f));
- EXPECT_EQ(100, ToRoundedInt(100.1f));
- EXPECT_EQ(101, ToRoundedInt(100.5f));
- EXPECT_EQ(101, ToRoundedInt(100.9f));
-
- EXPECT_EQ(int_min, ToRoundedInt(-infinity));
- EXPECT_EQ(int_min, ToRoundedInt(min));
- EXPECT_EQ(int_min, ToRoundedInt(min - 100));
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/scroll_offset_unittest.cc b/ui/gfx/geometry/scroll_offset_unittest.cc
deleted file mode 100644
index 782fdf4c10..0000000000
--- a/ui/gfx/geometry/scroll_offset_unittest.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// 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 <stddef.h>
-
-#include <cmath>
-#include <limits>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/scroll_offset.h"
-
-namespace gfx {
-
-TEST(ScrollOffsetTest, IsZero) {
- ScrollOffset zero(0, 0);
- ScrollOffset nonzero(0.1f, -0.1f);
-
- EXPECT_TRUE(zero.IsZero());
- EXPECT_FALSE(nonzero.IsZero());
-}
-
-TEST(ScrollOffsetTest, Add) {
- ScrollOffset f1(3.1f, 5.1f);
- ScrollOffset f2(4.3f, -1.3f);
-
- const struct {
- ScrollOffset expected;
- ScrollOffset actual;
- } scroll_offset_tests[] = {
- { ScrollOffset(3.1f, 5.1f), f1 + ScrollOffset() },
- { ScrollOffset(3.1f + 4.3f, 5.1f - 1.3f), f1 + f2 },
- { ScrollOffset(3.1f - 4.3f, 5.1f + 1.3f), f1 - f2 }
- };
-
- for (size_t i = 0; i < arraysize(scroll_offset_tests); ++i)
- EXPECT_EQ(scroll_offset_tests[i].expected.ToString(),
- scroll_offset_tests[i].actual.ToString());
-}
-
-TEST(ScrollOffsetTest, Negative) {
- const struct {
- ScrollOffset expected;
- ScrollOffset actual;
- } scroll_offset_tests[] = {
- { ScrollOffset(-0.3f, -0.3f), -ScrollOffset(0.3f, 0.3f) },
- { ScrollOffset(0.3f, 0.3f), -ScrollOffset(-0.3f, -0.3f) },
- { ScrollOffset(-0.3f, 0.3f), -ScrollOffset(0.3f, -0.3f) },
- { ScrollOffset(0.3f, -0.3f), -ScrollOffset(-0.3f, 0.3f) }
- };
-
- for (size_t i = 0; i < arraysize(scroll_offset_tests); ++i)
- EXPECT_EQ(scroll_offset_tests[i].expected.ToString(),
- scroll_offset_tests[i].actual.ToString());
-}
-
-TEST(ScrollOffsetTest, Scale) {
- float float_values[][4] = {
- { 4.5f, 1.2f, 3.3f, 5.6f },
- { 4.5f, -1.2f, 3.3f, 5.6f },
- { 4.5f, 1.2f, 3.3f, -5.6f },
- { 4.5f, 1.2f, -3.3f, -5.6f },
- { -4.5f, 1.2f, 3.3f, 5.6f },
- { -4.5f, 1.2f, 0, 5.6f },
- { -4.5f, 1.2f, 3.3f, 0 },
- { 4.5f, 0, 3.3f, 5.6f },
- { 0, 1.2f, 3.3f, 5.6f }
- };
-
- for (size_t i = 0; i < arraysize(float_values); ++i) {
- ScrollOffset v(float_values[i][0], float_values[i][1]);
- v.Scale(float_values[i][2], float_values[i][3]);
- EXPECT_EQ(v.x(), float_values[i][0] * float_values[i][2]);
- EXPECT_EQ(v.y(), float_values[i][1] * float_values[i][3]);
- }
-
- float single_values[][3] = {
- { 4.5f, 1.2f, 3.3f },
- { 4.5f, -1.2f, 3.3f },
- { 4.5f, 1.2f, 3.3f },
- { 4.5f, 1.2f, -3.3f },
- { -4.5f, 1.2f, 3.3f },
- { -4.5f, 1.2f, 0 },
- { -4.5f, 1.2f, 3.3f },
- { 4.5f, 0, 3.3f },
- { 0, 1.2f, 3.3f }
- };
-
- for (size_t i = 0; i < arraysize(single_values); ++i) {
- ScrollOffset v(single_values[i][0], single_values[i][1]);
- v.Scale(single_values[i][2]);
- EXPECT_EQ(v.x(), single_values[i][0] * single_values[i][2]);
- EXPECT_EQ(v.y(), single_values[i][1] * single_values[i][2]);
- }
-}
-
-TEST(ScrollOffsetTest, ClampScrollOffset) {
- ScrollOffset a;
-
- a = ScrollOffset(3.5, 5.5);
- EXPECT_EQ(ScrollOffset(3.5, 5.5).ToString(), a.ToString());
- a.SetToMax(ScrollOffset(2.5, 4.5));
- EXPECT_EQ(ScrollOffset(3.5, 5.5).ToString(), a.ToString());
- a.SetToMax(ScrollOffset(3.5, 5.5));
- EXPECT_EQ(ScrollOffset(3.5, 5.5).ToString(), a.ToString());
- a.SetToMax(ScrollOffset(4.5, 2.5));
- EXPECT_EQ(ScrollOffset(4.5, 5.5).ToString(), a.ToString());
- a.SetToMax(ScrollOffset(8.5, 10.5));
- EXPECT_EQ(ScrollOffset(8.5, 10.5).ToString(), a.ToString());
-
- a.SetToMin(ScrollOffset(9.5, 11.5));
- EXPECT_EQ(ScrollOffset(8.5, 10.5).ToString(), a.ToString());
- a.SetToMin(ScrollOffset(8.5, 10.5));
- EXPECT_EQ(ScrollOffset(8.5, 10.5).ToString(), a.ToString());
- a.SetToMin(ScrollOffset(11.5, 9.5));
- EXPECT_EQ(ScrollOffset(8.5, 9.5).ToString(), a.ToString());
- a.SetToMin(ScrollOffset(7.5, 11.5));
- EXPECT_EQ(ScrollOffset(7.5, 9.5).ToString(), a.ToString());
- a.SetToMin(ScrollOffset(3.5, 5.5));
- EXPECT_EQ(ScrollOffset(3.5, 5.5).ToString(), a.ToString());
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/size_unittest.cc b/ui/gfx/geometry/size_unittest.cc
deleted file mode 100644
index ab4a831768..0000000000
--- a/ui/gfx/geometry/size_unittest.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright (c) 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.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/geometry/size_conversions.h"
-#include "ui/gfx/geometry/size_f.h"
-
-namespace gfx {
-
-namespace {
-
-int TestSizeF(const SizeF& s) {
- return s.width();
-}
-
-} // namespace
-
-TEST(SizeTest, ToSizeF) {
- // Check that explicit conversion from integer to float compiles.
- Size a(10, 20);
- float width = TestSizeF(gfx::SizeF(a));
- EXPECT_EQ(width, a.width());
-
- SizeF b(10, 20);
-
- EXPECT_EQ(b, gfx::SizeF(a));
-}
-
-TEST(SizeTest, ToFlooredSize) {
- EXPECT_EQ(Size(0, 0), ToFlooredSize(SizeF(0, 0)));
- EXPECT_EQ(Size(0, 0), ToFlooredSize(SizeF(0.0001f, 0.0001f)));
- EXPECT_EQ(Size(0, 0), ToFlooredSize(SizeF(0.4999f, 0.4999f)));
- EXPECT_EQ(Size(0, 0), ToFlooredSize(SizeF(0.5f, 0.5f)));
- EXPECT_EQ(Size(0, 0), ToFlooredSize(SizeF(0.9999f, 0.9999f)));
-
- EXPECT_EQ(Size(10, 10), ToFlooredSize(SizeF(10, 10)));
- EXPECT_EQ(Size(10, 10), ToFlooredSize(SizeF(10.0001f, 10.0001f)));
- EXPECT_EQ(Size(10, 10), ToFlooredSize(SizeF(10.4999f, 10.4999f)));
- EXPECT_EQ(Size(10, 10), ToFlooredSize(SizeF(10.5f, 10.5f)));
- EXPECT_EQ(Size(10, 10), ToFlooredSize(SizeF(10.9999f, 10.9999f)));
-}
-
-TEST(SizeTest, ToCeiledSize) {
- EXPECT_EQ(Size(0, 0), ToCeiledSize(SizeF(0, 0)));
- EXPECT_EQ(Size(1, 1), ToCeiledSize(SizeF(0.0001f, 0.0001f)));
- EXPECT_EQ(Size(1, 1), ToCeiledSize(SizeF(0.4999f, 0.4999f)));
- EXPECT_EQ(Size(1, 1), ToCeiledSize(SizeF(0.5f, 0.5f)));
- EXPECT_EQ(Size(1, 1), ToCeiledSize(SizeF(0.9999f, 0.9999f)));
-
- EXPECT_EQ(Size(10, 10), ToCeiledSize(SizeF(10, 10)));
- EXPECT_EQ(Size(11, 11), ToCeiledSize(SizeF(10.0001f, 10.0001f)));
- EXPECT_EQ(Size(11, 11), ToCeiledSize(SizeF(10.4999f, 10.4999f)));
- EXPECT_EQ(Size(11, 11), ToCeiledSize(SizeF(10.5f, 10.5f)));
- EXPECT_EQ(Size(11, 11), ToCeiledSize(SizeF(10.9999f, 10.9999f)));
-}
-
-TEST(SizeTest, ToRoundedSize) {
- EXPECT_EQ(Size(0, 0), ToRoundedSize(SizeF(0, 0)));
- EXPECT_EQ(Size(0, 0), ToRoundedSize(SizeF(0.0001f, 0.0001f)));
- EXPECT_EQ(Size(0, 0), ToRoundedSize(SizeF(0.4999f, 0.4999f)));
- EXPECT_EQ(Size(1, 1), ToRoundedSize(SizeF(0.5f, 0.5f)));
- EXPECT_EQ(Size(1, 1), ToRoundedSize(SizeF(0.9999f, 0.9999f)));
-
- EXPECT_EQ(Size(10, 10), ToRoundedSize(SizeF(10, 10)));
- EXPECT_EQ(Size(10, 10), ToRoundedSize(SizeF(10.0001f, 10.0001f)));
- EXPECT_EQ(Size(10, 10), ToRoundedSize(SizeF(10.4999f, 10.4999f)));
- EXPECT_EQ(Size(11, 11), ToRoundedSize(SizeF(10.5f, 10.5f)));
- EXPECT_EQ(Size(11, 11), ToRoundedSize(SizeF(10.9999f, 10.9999f)));
-}
-
-TEST(SizeTest, ClampSize) {
- Size a;
-
- a = Size(3, 5);
- EXPECT_EQ(Size(3, 5).ToString(), a.ToString());
- a.SetToMax(Size(2, 4));
- EXPECT_EQ(Size(3, 5).ToString(), a.ToString());
- a.SetToMax(Size(3, 5));
- EXPECT_EQ(Size(3, 5).ToString(), a.ToString());
- a.SetToMax(Size(4, 2));
- EXPECT_EQ(Size(4, 5).ToString(), a.ToString());
- a.SetToMax(Size(8, 10));
- EXPECT_EQ(Size(8, 10).ToString(), a.ToString());
-
- a.SetToMin(Size(9, 11));
- EXPECT_EQ(Size(8, 10).ToString(), a.ToString());
- a.SetToMin(Size(8, 10));
- EXPECT_EQ(Size(8, 10).ToString(), a.ToString());
- a.SetToMin(Size(11, 9));
- EXPECT_EQ(Size(8, 9).ToString(), a.ToString());
- a.SetToMin(Size(7, 11));
- EXPECT_EQ(Size(7, 9).ToString(), a.ToString());
- a.SetToMin(Size(3, 5));
- EXPECT_EQ(Size(3, 5).ToString(), a.ToString());
-}
-
-TEST(SizeTest, ClampSizeF) {
- SizeF a;
-
- a = SizeF(3.5f, 5.5f);
- EXPECT_EQ(SizeF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(SizeF(2.5f, 4.5f));
- EXPECT_EQ(SizeF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(SizeF(3.5f, 5.5f));
- EXPECT_EQ(SizeF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(SizeF(4.5f, 2.5f));
- EXPECT_EQ(SizeF(4.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(SizeF(8.5f, 10.5f));
- EXPECT_EQ(SizeF(8.5f, 10.5f).ToString(), a.ToString());
-
- a.SetToMin(SizeF(9.5f, 11.5f));
- EXPECT_EQ(SizeF(8.5f, 10.5f).ToString(), a.ToString());
- a.SetToMin(SizeF(8.5f, 10.5f));
- EXPECT_EQ(SizeF(8.5f, 10.5f).ToString(), a.ToString());
- a.SetToMin(SizeF(11.5f, 9.5f));
- EXPECT_EQ(SizeF(8.5f, 9.5f).ToString(), a.ToString());
- a.SetToMin(SizeF(7.5f, 11.5f));
- EXPECT_EQ(SizeF(7.5f, 9.5f).ToString(), a.ToString());
- a.SetToMin(SizeF(3.5f, 5.5f));
- EXPECT_EQ(SizeF(3.5f, 5.5f).ToString(), a.ToString());
-}
-
-TEST(SizeTest, Enlarge) {
- Size test(3, 4);
- test.Enlarge(5, -8);
- EXPECT_EQ(test, Size(8, -4));
-}
-
-TEST(SizeTest, IntegerOverflow) {
- int int_max = std::numeric_limits<int>::max();
- int int_min = std::numeric_limits<int>::min();
-
- Size max_size(int_max, int_max);
- Size min_size(int_min, int_min);
- Size test;
-
- test = Size();
- test.Enlarge(int_max, int_max);
- EXPECT_EQ(test, max_size);
-
- test = Size();
- test.Enlarge(int_min, int_min);
- EXPECT_EQ(test, min_size);
-
- test = Size(10, 20);
- test.Enlarge(int_max, int_max);
- EXPECT_EQ(test, max_size);
-
- test = Size(-10, -20);
- test.Enlarge(int_min, int_min);
- EXPECT_EQ(test, min_size);
-}
-
-// This checks that we set IsEmpty appropriately.
-TEST(SizeTest, TrivialDimensionTests) {
- const float clearly_trivial = SizeF::kTrivial / 2.f;
- const float massize_dimension = 4e13f;
-
- // First, using the constructor.
- EXPECT_TRUE(SizeF(clearly_trivial, 1.f).IsEmpty());
- EXPECT_TRUE(SizeF(.01f, clearly_trivial).IsEmpty());
- EXPECT_TRUE(SizeF(0.f, 0.f).IsEmpty());
- EXPECT_FALSE(SizeF(.01f, .01f).IsEmpty());
-
- // Then use the setter.
- SizeF test(2.f, 1.f);
- EXPECT_FALSE(test.IsEmpty());
-
- test.SetSize(clearly_trivial, 1.f);
- EXPECT_TRUE(test.IsEmpty());
-
- test.SetSize(.01f, clearly_trivial);
- EXPECT_TRUE(test.IsEmpty());
-
- test.SetSize(0.f, 0.f);
- EXPECT_TRUE(test.IsEmpty());
-
- test.SetSize(.01f, .01f);
- EXPECT_FALSE(test.IsEmpty());
-
- // Now just one dimension at a time.
- test.set_width(clearly_trivial);
- EXPECT_TRUE(test.IsEmpty());
-
- test.set_width(massize_dimension);
- test.set_height(clearly_trivial);
- EXPECT_TRUE(test.IsEmpty());
-
- test.set_width(clearly_trivial);
- test.set_height(massize_dimension);
- EXPECT_TRUE(test.IsEmpty());
-
- test.set_width(2.f);
- EXPECT_FALSE(test.IsEmpty());
-}
-
-// These are the ramifications of the decision to keep the recorded size
-// at zero for trivial sizes.
-TEST(SizeTest, ClampsToZero) {
- const float clearly_trivial = SizeF::kTrivial / 2.f;
- const float nearly_trivial = SizeF::kTrivial * 1.5f;
-
- SizeF test(clearly_trivial, 1.f);
-
- EXPECT_FLOAT_EQ(0.f, test.width());
- EXPECT_FLOAT_EQ(1.f, test.height());
-
- test.SetSize(.01f, clearly_trivial);
-
- EXPECT_FLOAT_EQ(.01f, test.width());
- EXPECT_FLOAT_EQ(0.f, test.height());
-
- test.SetSize(nearly_trivial, nearly_trivial);
-
- EXPECT_FLOAT_EQ(nearly_trivial, test.width());
- EXPECT_FLOAT_EQ(nearly_trivial, test.height());
-
- test.Scale(0.5f);
-
- EXPECT_FLOAT_EQ(0.f, test.width());
- EXPECT_FLOAT_EQ(0.f, test.height());
-
- test.SetSize(0.f, 0.f);
- test.Enlarge(clearly_trivial, clearly_trivial);
- test.Enlarge(clearly_trivial, clearly_trivial);
- test.Enlarge(clearly_trivial, clearly_trivial);
-
- EXPECT_EQ(SizeF(0.f, 0.f), test);
-}
-
-// These make sure the constructor and setter have the same effect on the
-// boundary case. This claims to know the boundary, but not which way it goes.
-TEST(SizeTest, ConsistentClamping) {
- SizeF resized;
-
- resized.SetSize(SizeF::kTrivial, 0.f);
- EXPECT_EQ(SizeF(SizeF::kTrivial, 0.f), resized);
-
- resized.SetSize(0.f, SizeF::kTrivial);
- EXPECT_EQ(SizeF(0.f, SizeF::kTrivial), resized);
-}
-
-// Let's make sure we don't unexpectedly grow the struct by adding constants.
-// Also, if some platform packs floats inefficiently, it would be worth noting.
-TEST(SizeTest, StaysSmall) {
- EXPECT_EQ(2 * sizeof(float), sizeof(SizeF));
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/test/rect_test_util.cc b/ui/gfx/geometry/test/rect_test_util.cc
deleted file mode 100644
index bcc943b7fc..0000000000
--- a/ui/gfx/geometry/test/rect_test_util.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 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 "ui/gfx/geometry/test/rect_test_util.h"
-
-namespace gfx {
-namespace test {
-
-testing::AssertionResult RectContains(const gfx::Rect& outer_rect,
- const gfx::Rect& inner_rect) {
- if (outer_rect.Contains(inner_rect)) {
- return testing::AssertionSuccess()
- << "outer_rect (" << outer_rect.ToString()
- << ") does contain inner_rect (" << inner_rect.ToString() << ")";
- }
- return testing::AssertionFailure() << "outer_rect (" << outer_rect.ToString()
- << ") does not contain inner_rect ("
- << inner_rect.ToString() << ")";
-}
-
-} // namespace test
-} // namespace gfx
diff --git a/ui/gfx/geometry/test/rect_test_util.h b/ui/gfx/geometry/test/rect_test_util.h
deleted file mode 100644
index 857dd210b1..0000000000
--- a/ui/gfx/geometry/test/rect_test_util.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 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.
-
-#ifndef UI_GFX_GEOMETRY_TEST_RECT_TEST_UTIL_H_
-#define UI_GFX_GEOMETRY_TEST_RECT_TEST_UTIL_H_
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-namespace test {
-
-testing::AssertionResult RectContains(const gfx::Rect& outer_rect,
- const gfx::Rect& inner_rect);
-
-} // namespace test
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_TEST_RECT_TEST_UTIL_H_
diff --git a/ui/gfx/geometry/vector2d_conversions.cc b/ui/gfx/geometry/vector2d_conversions.cc
deleted file mode 100644
index dceb69e2ff..0000000000
--- a/ui/gfx/geometry/vector2d_conversions.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 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.
-
-#include "ui/gfx/geometry/vector2d_conversions.h"
-
-#include "ui/gfx/geometry/safe_integer_conversions.h"
-
-namespace gfx {
-
-Vector2d ToFlooredVector2d(const Vector2dF& vector2d) {
- int x = ToFlooredInt(vector2d.x());
- int y = ToFlooredInt(vector2d.y());
- return Vector2d(x, y);
-}
-
-Vector2d ToCeiledVector2d(const Vector2dF& vector2d) {
- int x = ToCeiledInt(vector2d.x());
- int y = ToCeiledInt(vector2d.y());
- return Vector2d(x, y);
-}
-
-Vector2d ToRoundedVector2d(const Vector2dF& vector2d) {
- int x = ToRoundedInt(vector2d.x());
- int y = ToRoundedInt(vector2d.y());
- return Vector2d(x, y);
-}
-
-} // namespace gfx
-
diff --git a/ui/gfx/geometry/vector2d_conversions.h b/ui/gfx/geometry/vector2d_conversions.h
deleted file mode 100644
index f4e16ae4be..0000000000
--- a/ui/gfx/geometry/vector2d_conversions.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 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.
-
-#ifndef UI_GFX_GEOMETRY_VECTOR2D_CONVERSIONS_H_
-#define UI_GFX_GEOMETRY_VECTOR2D_CONVERSIONS_H_
-
-#include "ui/gfx/geometry/vector2d.h"
-#include "ui/gfx/geometry/vector2d_f.h"
-
-namespace gfx {
-
-// Returns a Vector2d with each component from the input Vector2dF floored.
-GFX_EXPORT Vector2d ToFlooredVector2d(const Vector2dF& vector2d);
-
-// Returns a Vector2d with each component from the input Vector2dF ceiled.
-GFX_EXPORT Vector2d ToCeiledVector2d(const Vector2dF& vector2d);
-
-// Returns a Vector2d with each component from the input Vector2dF rounded.
-GFX_EXPORT Vector2d ToRoundedVector2d(const Vector2dF& vector2d);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_VECTOR2D_CONVERSIONS_H_
diff --git a/ui/gfx/geometry/vector2d_unittest.cc b/ui/gfx/geometry/vector2d_unittest.cc
deleted file mode 100644
index 4bdf24cba4..0000000000
--- a/ui/gfx/geometry/vector2d_unittest.cc
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright (c) 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.
-
-#include <stddef.h>
-
-#include <cmath>
-#include <limits>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/vector2d.h"
-#include "ui/gfx/geometry/vector2d_f.h"
-
-namespace gfx {
-
-TEST(Vector2dTest, ConversionToFloat) {
- Vector2d i(3, 4);
- Vector2dF f = i;
- EXPECT_EQ(i, f);
-}
-
-TEST(Vector2dTest, IsZero) {
- Vector2d int_zero(0, 0);
- Vector2d int_nonzero(2, -2);
- Vector2dF float_zero(0, 0);
- Vector2dF float_nonzero(0.1f, -0.1f);
-
- EXPECT_TRUE(int_zero.IsZero());
- EXPECT_FALSE(int_nonzero.IsZero());
- EXPECT_TRUE(float_zero.IsZero());
- EXPECT_FALSE(float_nonzero.IsZero());
-}
-
-TEST(Vector2dTest, Add) {
- Vector2d i1(3, 5);
- Vector2d i2(4, -1);
-
- const struct {
- Vector2d expected;
- Vector2d actual;
- } int_tests[] = {
- { Vector2d(3, 5), i1 + Vector2d() },
- { Vector2d(3 + 4, 5 - 1), i1 + i2 },
- { Vector2d(3 - 4, 5 + 1), i1 - i2 }
- };
-
- for (size_t i = 0; i < arraysize(int_tests); ++i)
- EXPECT_EQ(int_tests[i].expected.ToString(),
- int_tests[i].actual.ToString());
-
- Vector2dF f1(3.1f, 5.1f);
- Vector2dF f2(4.3f, -1.3f);
-
- const struct {
- Vector2dF expected;
- Vector2dF actual;
- } float_tests[] = {
- { Vector2dF(3.1F, 5.1F), f1 + Vector2d() },
- { Vector2dF(3.1F, 5.1F), f1 + Vector2dF() },
- { Vector2dF(3.1f + 4.3f, 5.1f - 1.3f), f1 + f2 },
- { Vector2dF(3.1f - 4.3f, 5.1f + 1.3f), f1 - f2 }
- };
-
- for (size_t i = 0; i < arraysize(float_tests); ++i)
- EXPECT_EQ(float_tests[i].expected.ToString(),
- float_tests[i].actual.ToString());
-}
-
-TEST(Vector2dTest, Negative) {
- const struct {
- Vector2d expected;
- Vector2d actual;
- } int_tests[] = {
- { Vector2d(0, 0), -Vector2d(0, 0) },
- { Vector2d(-3, -3), -Vector2d(3, 3) },
- { Vector2d(3, 3), -Vector2d(-3, -3) },
- { Vector2d(-3, 3), -Vector2d(3, -3) },
- { Vector2d(3, -3), -Vector2d(-3, 3) }
- };
-
- for (size_t i = 0; i < arraysize(int_tests); ++i)
- EXPECT_EQ(int_tests[i].expected.ToString(),
- int_tests[i].actual.ToString());
-
- const struct {
- Vector2dF expected;
- Vector2dF actual;
- } float_tests[] = {
- { Vector2dF(0, 0), -Vector2d(0, 0) },
- { Vector2dF(-0.3f, -0.3f), -Vector2dF(0.3f, 0.3f) },
- { Vector2dF(0.3f, 0.3f), -Vector2dF(-0.3f, -0.3f) },
- { Vector2dF(-0.3f, 0.3f), -Vector2dF(0.3f, -0.3f) },
- { Vector2dF(0.3f, -0.3f), -Vector2dF(-0.3f, 0.3f) }
- };
-
- for (size_t i = 0; i < arraysize(float_tests); ++i)
- EXPECT_EQ(float_tests[i].expected.ToString(),
- float_tests[i].actual.ToString());
-}
-
-TEST(Vector2dTest, Scale) {
- float double_values[][4] = {
- { 4.5f, 1.2f, 3.3f, 5.6f },
- { 4.5f, -1.2f, 3.3f, 5.6f },
- { 4.5f, 1.2f, 3.3f, -5.6f },
- { 4.5f, 1.2f, -3.3f, -5.6f },
- { -4.5f, 1.2f, 3.3f, 5.6f },
- { -4.5f, 1.2f, 0, 5.6f },
- { -4.5f, 1.2f, 3.3f, 0 },
- { 4.5f, 0, 3.3f, 5.6f },
- { 0, 1.2f, 3.3f, 5.6f }
- };
-
- for (size_t i = 0; i < arraysize(double_values); ++i) {
- Vector2dF v(double_values[i][0], double_values[i][1]);
- v.Scale(double_values[i][2], double_values[i][3]);
- EXPECT_EQ(v.x(), double_values[i][0] * double_values[i][2]);
- EXPECT_EQ(v.y(), double_values[i][1] * double_values[i][3]);
-
- Vector2dF v2 = ScaleVector2d(
- gfx::Vector2dF(double_values[i][0], double_values[i][1]),
- double_values[i][2], double_values[i][3]);
- EXPECT_EQ(double_values[i][0] * double_values[i][2], v2.x());
- EXPECT_EQ(double_values[i][1] * double_values[i][3], v2.y());
- }
-
- float single_values[][3] = {
- { 4.5f, 1.2f, 3.3f },
- { 4.5f, -1.2f, 3.3f },
- { 4.5f, 1.2f, 3.3f },
- { 4.5f, 1.2f, -3.3f },
- { -4.5f, 1.2f, 3.3f },
- { -4.5f, 1.2f, 0 },
- { -4.5f, 1.2f, 3.3f },
- { 4.5f, 0, 3.3f },
- { 0, 1.2f, 3.3f }
- };
-
- for (size_t i = 0; i < arraysize(single_values); ++i) {
- Vector2dF v(single_values[i][0], single_values[i][1]);
- v.Scale(single_values[i][2]);
- EXPECT_EQ(v.x(), single_values[i][0] * single_values[i][2]);
- EXPECT_EQ(v.y(), single_values[i][1] * single_values[i][2]);
-
- Vector2dF v2 = ScaleVector2d(
- gfx::Vector2dF(double_values[i][0], double_values[i][1]),
- double_values[i][2]);
- EXPECT_EQ(single_values[i][0] * single_values[i][2], v2.x());
- EXPECT_EQ(single_values[i][1] * single_values[i][2], v2.y());
- }
-}
-
-TEST(Vector2dTest, Length) {
- int int_values[][2] = {
- { 0, 0 },
- { 10, 20 },
- { 20, 10 },
- { -10, -20 },
- { -20, 10 },
- { 10, -20 },
- };
-
- for (size_t i = 0; i < arraysize(int_values); ++i) {
- int v0 = int_values[i][0];
- int v1 = int_values[i][1];
- double length_squared =
- static_cast<double>(v0) * v0 + static_cast<double>(v1) * v1;
- double length = std::sqrt(length_squared);
- Vector2d vector(v0, v1);
- EXPECT_EQ(static_cast<float>(length_squared), vector.LengthSquared());
- EXPECT_EQ(static_cast<float>(length), vector.Length());
- }
-
- float float_values[][2] = {
- { 0, 0 },
- { 10.5f, 20.5f },
- { 20.5f, 10.5f },
- { -10.5f, -20.5f },
- { -20.5f, 10.5f },
- { 10.5f, -20.5f },
- // A large vector that fails if the Length function doesn't use
- // double precision internally.
- { 1236278317862780234892374893213178027.12122348904204230f,
- 335890352589839028212313231225425134332.38123f },
- };
-
- for (size_t i = 0; i < arraysize(float_values); ++i) {
- double v0 = float_values[i][0];
- double v1 = float_values[i][1];
- double length_squared =
- static_cast<double>(v0) * v0 + static_cast<double>(v1) * v1;
- double length = std::sqrt(length_squared);
- Vector2dF vector(v0, v1);
- EXPECT_DOUBLE_EQ(length_squared, vector.LengthSquared());
- EXPECT_FLOAT_EQ(static_cast<float>(length), vector.Length());
- }
-}
-
-TEST(Vector2dTest, ClampVector2d) {
- Vector2d a;
-
- a = Vector2d(3, 5);
- EXPECT_EQ(Vector2d(3, 5).ToString(), a.ToString());
- a.SetToMax(Vector2d(2, 4));
- EXPECT_EQ(Vector2d(3, 5).ToString(), a.ToString());
- a.SetToMax(Vector2d(3, 5));
- EXPECT_EQ(Vector2d(3, 5).ToString(), a.ToString());
- a.SetToMax(Vector2d(4, 2));
- EXPECT_EQ(Vector2d(4, 5).ToString(), a.ToString());
- a.SetToMax(Vector2d(8, 10));
- EXPECT_EQ(Vector2d(8, 10).ToString(), a.ToString());
-
- a.SetToMin(Vector2d(9, 11));
- EXPECT_EQ(Vector2d(8, 10).ToString(), a.ToString());
- a.SetToMin(Vector2d(8, 10));
- EXPECT_EQ(Vector2d(8, 10).ToString(), a.ToString());
- a.SetToMin(Vector2d(11, 9));
- EXPECT_EQ(Vector2d(8, 9).ToString(), a.ToString());
- a.SetToMin(Vector2d(7, 11));
- EXPECT_EQ(Vector2d(7, 9).ToString(), a.ToString());
- a.SetToMin(Vector2d(3, 5));
- EXPECT_EQ(Vector2d(3, 5).ToString(), a.ToString());
-}
-
-TEST(Vector2dTest, ClampVector2dF) {
- Vector2dF a;
-
- a = Vector2dF(3.5f, 5.5f);
- EXPECT_EQ(Vector2dF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(Vector2dF(2.5f, 4.5f));
- EXPECT_EQ(Vector2dF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(Vector2dF(3.5f, 5.5f));
- EXPECT_EQ(Vector2dF(3.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(Vector2dF(4.5f, 2.5f));
- EXPECT_EQ(Vector2dF(4.5f, 5.5f).ToString(), a.ToString());
- a.SetToMax(Vector2dF(8.5f, 10.5f));
- EXPECT_EQ(Vector2dF(8.5f, 10.5f).ToString(), a.ToString());
-
- a.SetToMin(Vector2dF(9.5f, 11.5f));
- EXPECT_EQ(Vector2dF(8.5f, 10.5f).ToString(), a.ToString());
- a.SetToMin(Vector2dF(8.5f, 10.5f));
- EXPECT_EQ(Vector2dF(8.5f, 10.5f).ToString(), a.ToString());
- a.SetToMin(Vector2dF(11.5f, 9.5f));
- EXPECT_EQ(Vector2dF(8.5f, 9.5f).ToString(), a.ToString());
- a.SetToMin(Vector2dF(7.5f, 11.5f));
- EXPECT_EQ(Vector2dF(7.5f, 9.5f).ToString(), a.ToString());
- a.SetToMin(Vector2dF(3.5f, 5.5f));
- EXPECT_EQ(Vector2dF(3.5f, 5.5f).ToString(), a.ToString());
-}
-
-TEST(Vector2dTest, IntegerOverflow) {
- int int_max = std::numeric_limits<int>::max();
- int int_min = std::numeric_limits<int>::min();
-
- Vector2d max_vector(int_max, int_max);
- Vector2d min_vector(int_min, int_min);
- Vector2d test;
-
- test = Vector2d();
- test += Vector2d(int_max, int_max);
- EXPECT_EQ(test, max_vector);
-
- test = Vector2d();
- test += Vector2d(int_min, int_min);
- EXPECT_EQ(test, min_vector);
-
- test = Vector2d(10, 20);
- test += Vector2d(int_max, int_max);
- EXPECT_EQ(test, max_vector);
-
- test = Vector2d(-10, -20);
- test += Vector2d(int_min, int_min);
- EXPECT_EQ(test, min_vector);
-
- test = Vector2d();
- test -= Vector2d(int_max, int_max);
- EXPECT_EQ(test, Vector2d(-int_max, -int_max));
-
- test = Vector2d();
- test -= Vector2d(int_min, int_min);
- EXPECT_EQ(test, max_vector);
-
- test = Vector2d(10, 20);
- test -= Vector2d(int_min, int_min);
- EXPECT_EQ(test, max_vector);
-
- test = Vector2d(-10, -20);
- test -= Vector2d(int_max, int_max);
- EXPECT_EQ(test, min_vector);
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/vector3d_f.cc b/ui/gfx/geometry/vector3d_f.cc
deleted file mode 100644
index 749e330f27..0000000000
--- a/ui/gfx/geometry/vector3d_f.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 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.
-
-#include "ui/gfx/geometry/vector3d_f.h"
-
-#include <cmath>
-
-#include "base/strings/stringprintf.h"
-#include "ui/gfx/geometry/angle_conversions.h"
-
-namespace {
-const double kEpsilon = 1.0e-6;
-}
-
-namespace gfx {
-
-std::string Vector3dF::ToString() const {
- return base::StringPrintf("[%f %f %f]", x_, y_, z_);
-}
-
-bool Vector3dF::IsZero() const {
- return x_ == 0 && y_ == 0 && z_ == 0;
-}
-
-void Vector3dF::Add(const Vector3dF& other) {
- x_ += other.x_;
- y_ += other.y_;
- z_ += other.z_;
-}
-
-void Vector3dF::Subtract(const Vector3dF& other) {
- x_ -= other.x_;
- y_ -= other.y_;
- z_ -= other.z_;
-}
-
-double Vector3dF::LengthSquared() const {
- return static_cast<double>(x_) * x_ + static_cast<double>(y_) * y_ +
- static_cast<double>(z_) * z_;
-}
-
-float Vector3dF::Length() const {
- return static_cast<float>(std::sqrt(LengthSquared()));
-}
-
-void Vector3dF::Scale(float x_scale, float y_scale, float z_scale) {
- x_ *= x_scale;
- y_ *= y_scale;
- z_ *= z_scale;
-}
-
-void Vector3dF::Cross(const Vector3dF& other) {
- double dx = x_;
- double dy = y_;
- double dz = z_;
- float x = static_cast<float>(dy * other.z() - dz * other.y());
- float y = static_cast<float>(dz * other.x() - dx * other.z());
- float z = static_cast<float>(dx * other.y() - dy * other.x());
- x_ = x;
- y_ = y;
- z_ = z;
-}
-
-bool Vector3dF::GetNormalized(Vector3dF* out) const {
- double length_squared = LengthSquared();
- *out = *this;
- if (length_squared < kEpsilon * kEpsilon)
- return false;
- out->Scale(1 / sqrt(length_squared));
- return true;
-}
-
-float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs) {
- return lhs.x() * rhs.x() + lhs.y() * rhs.y() + lhs.z() * rhs.z();
-}
-
-Vector3dF ScaleVector3d(const Vector3dF& v,
- float x_scale,
- float y_scale,
- float z_scale) {
- Vector3dF scaled_v(v);
- scaled_v.Scale(x_scale, y_scale, z_scale);
- return scaled_v;
-}
-
-float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
- const gfx::Vector3dF& other) {
- return gfx::RadToDeg(
- std::acos(gfx::DotProduct(base, other) / base.Length() / other.Length()));
-}
-
-float ClockwiseAngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
- const gfx::Vector3dF& other,
- const gfx::Vector3dF& normal) {
- float angle = AngleBetweenVectorsInDegrees(base, other);
- gfx::Vector3dF cross(base);
- cross.Cross(other);
-
- // If the dot product of this cross product is normal, it means that the
- // shortest angle between |base| and |other| was counterclockwise with respect
- // to the surface represented by |normal| and this angle must be reversed.
- if (gfx::DotProduct(cross, normal) > 0.0f)
- angle = 360.0f - angle;
- return angle;
-}
-
-} // namespace gfx
diff --git a/ui/gfx/geometry/vector3d_f.h b/ui/gfx/geometry/vector3d_f.h
deleted file mode 100644
index 0e5e43713a..0000000000
--- a/ui/gfx/geometry/vector3d_f.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 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.
-
-// Defines a simple float vector class. This class is used to indicate a
-// distance in two dimensions between two points. Subtracting two points should
-// produce a vector, and adding a vector to a point produces the point at the
-// vector's distance from the original point.
-
-#ifndef UI_GFX_GEOMETRY_VECTOR3D_F_H_
-#define UI_GFX_GEOMETRY_VECTOR3D_F_H_
-
-#include <iosfwd>
-#include <string>
-
-#include "ui/gfx/geometry/vector2d_f.h"
-#include "ui/gfx/gfx_export.h"
-
-namespace gfx {
-
-class GFX_EXPORT Vector3dF {
- public:
- constexpr Vector3dF() : x_(0), y_(0), z_(0) {}
- constexpr Vector3dF(float x, float y, float z) : x_(x), y_(y), z_(z) {}
-
- constexpr explicit Vector3dF(const Vector2dF& other)
- : x_(other.x()), y_(other.y()), z_(0) {}
-
- constexpr float x() const { return x_; }
- void set_x(float x) { x_ = x; }
-
- constexpr float y() const { return y_; }
- void set_y(float y) { y_ = y; }
-
- constexpr float z() const { return z_; }
- void set_z(float z) { z_ = z; }
-
- // True if all components of the vector are 0.
- bool IsZero() const;
-
- // Add the components of the |other| vector to the current vector.
- void Add(const Vector3dF& other);
- // Subtract the components of the |other| vector from the current vector.
- void Subtract(const Vector3dF& other);
-
- void operator+=(const Vector3dF& other) { Add(other); }
- void operator-=(const Vector3dF& other) { Subtract(other); }
-
- void SetToMin(const Vector3dF& other) {
- x_ = x_ <= other.x_ ? x_ : other.x_;
- y_ = y_ <= other.y_ ? y_ : other.y_;
- z_ = z_ <= other.z_ ? z_ : other.z_;
- }
-
- void SetToMax(const Vector3dF& other) {
- x_ = x_ >= other.x_ ? x_ : other.x_;
- y_ = y_ >= other.y_ ? y_ : other.y_;
- z_ = z_ >= other.z_ ? z_ : other.z_;
- }
-
- // Gives the square of the diagonal length of the vector.
- double LengthSquared() const;
- // Gives the diagonal length of the vector.
- float Length() const;
-
- // Scale all components of the vector by |scale|.
- void Scale(float scale) { Scale(scale, scale, scale); }
- // Scale the each component of the vector by the given scale factors.
- void Scale(float x_scale, float y_scale, float z_scale);
-
- // Take the cross product of this vector with |other| and become the result.
- void Cross(const Vector3dF& other);
-
- // |out| is assigned a unit-length vector in the direction of |this| iff
- // this function returns true. It can return false if |this| is too short.
- bool GetNormalized(Vector3dF* out) const;
-
- std::string ToString() const;
-
- private:
- float x_;
- float y_;
- float z_;
-};
-
-inline bool operator==(const Vector3dF& lhs, const Vector3dF& rhs) {
- return lhs.x() == rhs.x() && lhs.y() == rhs.y() && lhs.z() == rhs.z();
-}
-
-inline Vector3dF operator-(const Vector3dF& v) {
- return Vector3dF(-v.x(), -v.y(), -v.z());
-}
-
-inline Vector3dF operator+(const Vector3dF& lhs, const Vector3dF& rhs) {
- Vector3dF result = lhs;
- result.Add(rhs);
- return result;
-}
-
-inline Vector3dF operator-(const Vector3dF& lhs, const Vector3dF& rhs) {
- Vector3dF result = lhs;
- result.Add(-rhs);
- return result;
-}
-
-// Return the cross product of two vectors.
-inline Vector3dF CrossProduct(const Vector3dF& lhs, const Vector3dF& rhs) {
- Vector3dF result = lhs;
- result.Cross(rhs);
- return result;
-}
-
-// Return the dot product of two vectors.
-GFX_EXPORT float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs);
-
-// Return a vector that is |v| scaled by the given scale factors along each
-// axis.
-GFX_EXPORT Vector3dF ScaleVector3d(const Vector3dF& v,
- float x_scale,
- float y_scale,
- float z_scale);
-
-// Return a vector that is |v| scaled by the components of |s|
-inline Vector3dF ScaleVector3d(const Vector3dF& v, const Vector3dF& s) {
- return ScaleVector3d(v, s.x(), s.y(), s.z());
-}
-
-// Return a vector that is |v| scaled by the given scale factor.
-inline Vector3dF ScaleVector3d(const Vector3dF& v, float scale) {
- return ScaleVector3d(v, scale, scale, scale);
-}
-
-// Returns the angle between |base| and |other| in degrees.
-GFX_EXPORT float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
- const gfx::Vector3dF& other);
-
-// Returns the clockwise angle between |base| and |other| where |normal| is the
-// normal of the virtual surface to measure clockwise according to.
-GFX_EXPORT float ClockwiseAngleBetweenVectorsInDegrees(
- const gfx::Vector3dF& base,
- const gfx::Vector3dF& other,
- const gfx::Vector3dF& normal);
-
-// This is declared here for use in gtest-based unit tests but is defined in
-// the //ui/gfx:test_support target. Depend on that to use this in your unit
-// test. This should not be used in production code - call ToString() instead.
-void PrintTo(const Vector3dF& vector, ::std::ostream* os);
-
-} // namespace gfx
-
-#endif // UI_GFX_GEOMETRY_VECTOR3D_F_H_
diff --git a/ui/gfx/geometry/vector3d_unittest.cc b/ui/gfx/geometry/vector3d_unittest.cc
deleted file mode 100644
index 12ee757346..0000000000
--- a/ui/gfx/geometry/vector3d_unittest.cc
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright (c) 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.
-
-#include <stddef.h>
-
-#include <cmath>
-#include <limits>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/vector3d_f.h"
-
-namespace gfx {
-
-TEST(Vector3dTest, IsZero) {
- gfx::Vector3dF float_zero(0, 0, 0);
- gfx::Vector3dF float_nonzero(0.1f, -0.1f, 0.1f);
-
- EXPECT_TRUE(float_zero.IsZero());
- EXPECT_FALSE(float_nonzero.IsZero());
-}
-
-TEST(Vector3dTest, Add) {
- gfx::Vector3dF f1(3.1f, 5.1f, 2.7f);
- gfx::Vector3dF f2(4.3f, -1.3f, 8.1f);
-
- const struct {
- gfx::Vector3dF expected;
- gfx::Vector3dF actual;
- } float_tests[] = {
- { gfx::Vector3dF(3.1F, 5.1F, 2.7f), f1 + gfx::Vector3dF() },
- { gfx::Vector3dF(3.1f + 4.3f, 5.1f - 1.3f, 2.7f + 8.1f), f1 + f2 },
- { gfx::Vector3dF(3.1f - 4.3f, 5.1f + 1.3f, 2.7f - 8.1f), f1 - f2 }
- };
-
- for (size_t i = 0; i < arraysize(float_tests); ++i)
- EXPECT_EQ(float_tests[i].expected.ToString(),
- float_tests[i].actual.ToString());
-}
-
-TEST(Vector3dTest, Negative) {
- const struct {
- gfx::Vector3dF expected;
- gfx::Vector3dF actual;
- } float_tests[] = {
- { gfx::Vector3dF(-0.0f, -0.0f, -0.0f), -gfx::Vector3dF(0, 0, 0) },
- { gfx::Vector3dF(-0.3f, -0.3f, -0.3f), -gfx::Vector3dF(0.3f, 0.3f, 0.3f) },
- { gfx::Vector3dF(0.3f, 0.3f, 0.3f), -gfx::Vector3dF(-0.3f, -0.3f, -0.3f) },
- { gfx::Vector3dF(-0.3f, 0.3f, -0.3f), -gfx::Vector3dF(0.3f, -0.3f, 0.3f) },
- { gfx::Vector3dF(0.3f, -0.3f, -0.3f), -gfx::Vector3dF(-0.3f, 0.3f, 0.3f) },
- { gfx::Vector3dF(-0.3f, -0.3f, 0.3f), -gfx::Vector3dF(0.3f, 0.3f, -0.3f) }
- };
-
- for (size_t i = 0; i < arraysize(float_tests); ++i)
- EXPECT_EQ(float_tests[i].expected.ToString(),
- float_tests[i].actual.ToString());
-}
-
-TEST(Vector3dTest, Scale) {
- float triple_values[][6] = {
- { 4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f },
- { 4.5f, -1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
- { 4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
- { 4.5f, -1.2f -1.8f, 3.3f, 5.6f, 4.2f },
-
- { 4.5f, 1.2f, 1.8f, 3.3f, -5.6f, -4.2f },
- { 4.5f, 1.2f, 1.8f, -3.3f, -5.6f, -4.2f },
- { 4.5f, 1.2f, -1.8f, 3.3f, -5.6f, -4.2f },
- { 4.5f, 1.2f, -1.8f, -3.3f, -5.6f, -4.2f },
-
- { -4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f },
- { -4.5f, 1.2f, 1.8f, 0, 5.6f, 4.2f },
- { -4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 4.2f },
- { -4.5f, 1.2f, -1.8f, 0, 5.6f, 4.2f },
-
- { -4.5f, 1.2f, 1.8f, 3.3f, 0, 4.2f },
- { 4.5f, 0, 1.8f, 3.3f, 5.6f, 4.2f },
- { -4.5f, 1.2f, -1.8f, 3.3f, 0, 4.2f },
- { 4.5f, 0, -1.8f, 3.3f, 5.6f, 4.2f },
- { -4.5f, 1.2f, 1.8f, 3.3f, 5.6f, 0 },
- { -4.5f, 1.2f, -1.8f, 3.3f, 5.6f, 0 },
-
- { 0, 1.2f, 0, 3.3f, 5.6f, 4.2f },
- { 0, 1.2f, 1.8f, 3.3f, 5.6f, 4.2f }
- };
-
- for (size_t i = 0; i < arraysize(triple_values); ++i) {
- gfx::Vector3dF v(triple_values[i][0],
- triple_values[i][1],
- triple_values[i][2]);
- v.Scale(triple_values[i][3], triple_values[i][4], triple_values[i][5]);
- EXPECT_EQ(triple_values[i][0] * triple_values[i][3], v.x());
- EXPECT_EQ(triple_values[i][1] * triple_values[i][4], v.y());
- EXPECT_EQ(triple_values[i][2] * triple_values[i][5], v.z());
-
- Vector3dF v2 = ScaleVector3d(
- gfx::Vector3dF(triple_values[i][0],
- triple_values[i][1],
- triple_values[i][2]),
- triple_values[i][3], triple_values[i][4], triple_values[i][5]);
- EXPECT_EQ(triple_values[i][0] * triple_values[i][3], v2.x());
- EXPECT_EQ(triple_values[i][1] * triple_values[i][4], v2.y());
- EXPECT_EQ(triple_values[i][2] * triple_values[i][5], v2.z());
- }
-
- float single_values[][4] = {
- { 4.5f, 1.2f, 1.8f, 3.3f },
- { 4.5f, -1.2f, 1.8f, 3.3f },
- { 4.5f, 1.2f, -1.8f, 3.3f },
- { 4.5f, -1.2f, -1.8f, 3.3f },
- { -4.5f, 1.2f, 3.3f },
- { -4.5f, 1.2f, 0 },
- { -4.5f, 1.2f, 1.8f, 3.3f },
- { -4.5f, 1.2f, 1.8f, 0 },
- { 4.5f, 0, 1.8f, 3.3f },
- { 0, 1.2f, 1.8f, 3.3f },
- { 4.5f, 0, 1.8f, 3.3f },
- { 0, 1.2f, 1.8f, 3.3f },
- { 4.5f, 1.2f, 0, 3.3f },
- { 4.5f, 1.2f, 0, 3.3f }
- };
-
- for (size_t i = 0; i < arraysize(single_values); ++i) {
- gfx::Vector3dF v(single_values[i][0],
- single_values[i][1],
- single_values[i][2]);
- v.Scale(single_values[i][3]);
- EXPECT_EQ(single_values[i][0] * single_values[i][3], v.x());
- EXPECT_EQ(single_values[i][1] * single_values[i][3], v.y());
- EXPECT_EQ(single_values[i][2] * single_values[i][3], v.z());
-
- Vector3dF v2 = ScaleVector3d(
- gfx::Vector3dF(single_values[i][0],
- single_values[i][1],
- single_values[i][2]),
- single_values[i][3]);
- EXPECT_EQ(single_values[i][0] * single_values[i][3], v2.x());
- EXPECT_EQ(single_values[i][1] * single_values[i][3], v2.y());
- EXPECT_EQ(single_values[i][2] * single_values[i][3], v2.z());
- }
-}
-
-TEST(Vector3dTest, Length) {
- float float_values[][3] = {
- { 0, 0, 0 },
- { 10.5f, 20.5f, 8.5f },
- { 20.5f, 10.5f, 8.5f },
- { 8.5f, 20.5f, 10.5f },
- { 10.5f, 8.5f, 20.5f },
- { -10.5f, -20.5f, -8.5f },
- { -20.5f, 10.5f, -8.5f },
- { -8.5f, -20.5f, -10.5f },
- { -10.5f, -8.5f, -20.5f },
- { 10.5f, -20.5f, 8.5f },
- { -10.5f, 20.5f, 8.5f },
- { 10.5f, -20.5f, -8.5f },
- { -10.5f, 20.5f, -8.5f },
- // A large vector that fails if the Length function doesn't use
- // double precision internally.
- { 1236278317862780234892374893213178027.12122348904204230f,
- 335890352589839028212313231225425134332.38123f,
- 27861786423846742743236423478236784678.236713617231f }
- };
-
- for (size_t i = 0; i < arraysize(float_values); ++i) {
- double v0 = float_values[i][0];
- double v1 = float_values[i][1];
- double v2 = float_values[i][2];
- double length_squared =
- static_cast<double>(v0) * v0 +
- static_cast<double>(v1) * v1 +
- static_cast<double>(v2) * v2;
- double length = std::sqrt(length_squared);
- gfx::Vector3dF vector(v0, v1, v2);
- EXPECT_DOUBLE_EQ(length_squared, vector.LengthSquared());
- EXPECT_FLOAT_EQ(static_cast<float>(length), vector.Length());
- }
-}
-
-TEST(Vector3dTest, DotProduct) {
- const struct {
- float expected;
- gfx::Vector3dF input1;
- gfx::Vector3dF input2;
- } tests[] = {
- { 0, gfx::Vector3dF(1, 0, 0), gfx::Vector3dF(0, 1, 1) },
- { 0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(1, 0, 1) },
- { 0, gfx::Vector3dF(0, 0, 1), gfx::Vector3dF(1, 1, 0) },
-
- { 3, gfx::Vector3dF(1, 1, 1), gfx::Vector3dF(1, 1, 1) },
-
- { 1.2f, gfx::Vector3dF(1.2f, -1.2f, 1.2f), gfx::Vector3dF(1, 1, 1) },
- { 1.2f, gfx::Vector3dF(1, 1, 1), gfx::Vector3dF(1.2f, -1.2f, 1.2f) },
-
- { 38.72f,
- gfx::Vector3dF(1.1f, 2.2f, 3.3f), gfx::Vector3dF(4.4f, 5.5f, 6.6f) }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- float actual = gfx::DotProduct(tests[i].input1, tests[i].input2);
- EXPECT_EQ(tests[i].expected, actual);
- }
-}
-
-TEST(Vector3dTest, CrossProduct) {
- const struct {
- gfx::Vector3dF expected;
- gfx::Vector3dF input1;
- gfx::Vector3dF input2;
- } tests[] = {
- { Vector3dF(), Vector3dF(), Vector3dF(1, 1, 1) },
- { Vector3dF(), Vector3dF(1, 1, 1), Vector3dF() },
- { Vector3dF(), Vector3dF(1, 1, 1), Vector3dF(1, 1, 1) },
- { Vector3dF(),
- Vector3dF(1.6f, 10.6f, -10.6f),
- Vector3dF(1.6f, 10.6f, -10.6f) },
-
- { Vector3dF(1, -1, 0), Vector3dF(1, 1, 1), Vector3dF(0, 0, 1) },
- { Vector3dF(-1, 0, 1), Vector3dF(1, 1, 1), Vector3dF(0, 1, 0) },
- { Vector3dF(0, 1, -1), Vector3dF(1, 1, 1), Vector3dF(1, 0, 0) },
-
- { Vector3dF(-1, 1, 0), Vector3dF(0, 0, 1), Vector3dF(1, 1, 1) },
- { Vector3dF(1, 0, -1), Vector3dF(0, 1, 0), Vector3dF(1, 1, 1) },
- { Vector3dF(0, -1, 1), Vector3dF(1, 0, 0), Vector3dF(1, 1, 1) }
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- SCOPED_TRACE(i);
- Vector3dF actual = gfx::CrossProduct(tests[i].input1, tests[i].input2);
- EXPECT_EQ(tests[i].expected.ToString(), actual.ToString());
- }
-}
-
-TEST(Vector3dFTest, ClampVector3dF) {
- Vector3dF a;
-
- a = Vector3dF(3.5f, 5.5f, 7.5f);
- EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
- a.SetToMax(Vector3dF(2, 4.5f, 6.5f));
- EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
- a.SetToMax(Vector3dF(3.5f, 5.5f, 7.5f));
- EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
- a.SetToMax(Vector3dF(4.5f, 2, 6.5f));
- EXPECT_EQ(Vector3dF(4.5f, 5.5f, 7.5f).ToString(), a.ToString());
- a.SetToMax(Vector3dF(3.5f, 6.5f, 6.5f));
- EXPECT_EQ(Vector3dF(4.5f, 6.5f, 7.5f).ToString(), a.ToString());
- a.SetToMax(Vector3dF(3.5f, 5.5f, 8.5f));
- EXPECT_EQ(Vector3dF(4.5f, 6.5f, 8.5f).ToString(), a.ToString());
- a.SetToMax(Vector3dF(8.5f, 10.5f, 12.5f));
- EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
-
- a.SetToMin(Vector3dF(9.5f, 11.5f, 13.5f));
- EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
- a.SetToMin(Vector3dF(8.5f, 10.5f, 12.5f));
- EXPECT_EQ(Vector3dF(8.5f, 10.5f, 12.5f).ToString(), a.ToString());
- a.SetToMin(Vector3dF(7.5f, 11.5f, 13.5f));
- EXPECT_EQ(Vector3dF(7.5f, 10.5f, 12.5f).ToString(), a.ToString());
- a.SetToMin(Vector3dF(9.5f, 9.5f, 13.5f));
- EXPECT_EQ(Vector3dF(7.5f, 9.5f, 12.5f).ToString(), a.ToString());
- a.SetToMin(Vector3dF(9.5f, 11.5f, 11.5f));
- EXPECT_EQ(Vector3dF(7.5f, 9.5f, 11.5f).ToString(), a.ToString());
- a.SetToMin(Vector3dF(3.5f, 5.5f, 7.5f));
- EXPECT_EQ(Vector3dF(3.5f, 5.5f, 7.5f).ToString(), a.ToString());
-}
-
-TEST(Vector3dTest, AngleBetweenVectorsInDegress) {
- const struct {
- float expected;
- gfx::Vector3dF input1;
- gfx::Vector3dF input2;
- } tests[] = {
- {0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 1, 0)},
- {90, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, 1)},
- {45,
- gfx::Vector3dF(0, 1, 0),
- gfx::Vector3dF(0, 0.70710678188f, 0.70710678188f)},
- {180, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, -1, 0)},
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- float actual =
- gfx::AngleBetweenVectorsInDegrees(tests[i].input1, tests[i].input2);
- EXPECT_FLOAT_EQ(tests[i].expected, actual);
- actual =
- gfx::AngleBetweenVectorsInDegrees(tests[i].input2, tests[i].input1);
- EXPECT_FLOAT_EQ(tests[i].expected, actual);
- }
-}
-
-TEST(Vector3dTest, ClockwiseAngleBetweenVectorsInDegress) {
- const struct {
- float expected;
- gfx::Vector3dF input1;
- gfx::Vector3dF input2;
- } tests[] = {
- {0, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 1, 0)},
- {90, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, -1)},
- {45,
- gfx::Vector3dF(0, -1, 0),
- gfx::Vector3dF(0, -0.70710678188f, 0.70710678188f)},
- {180, gfx::Vector3dF(0, -1, 0), gfx::Vector3dF(0, 1, 0)},
- {270, gfx::Vector3dF(0, 1, 0), gfx::Vector3dF(0, 0, 1)},
- };
-
- const gfx::Vector3dF normal_vector(1.0f, 0.0f, 0.0f);
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- float actual = gfx::ClockwiseAngleBetweenVectorsInDegrees(
- tests[i].input1, tests[i].input2, normal_vector);
- EXPECT_FLOAT_EQ(tests[i].expected, actual);
- actual = -gfx::ClockwiseAngleBetweenVectorsInDegrees(
- tests[i].input2, tests[i].input1, normal_vector);
- if (actual < 0.0f)
- actual += 360.0f;
- EXPECT_FLOAT_EQ(tests[i].expected, actual);
- }
-}
-
-TEST(Vector3dTest, GetNormalized) {
- const struct {
- bool expected;
- gfx::Vector3dF v;
- gfx::Vector3dF normalized;
- } tests[] = {
- {false, gfx::Vector3dF(0, 0, 0), gfx::Vector3dF(0, 0, 0)},
- {false,
- gfx::Vector3dF(std::numeric_limits<float>::min(),
- std::numeric_limits<float>::min(),
- std::numeric_limits<float>::min()),
- gfx::Vector3dF(std::numeric_limits<float>::min(),
- std::numeric_limits<float>::min(),
- std::numeric_limits<float>::min())},
- {true, gfx::Vector3dF(1, 0, 0), gfx::Vector3dF(1, 0, 0)},
- {true, gfx::Vector3dF(std::numeric_limits<float>::max(), 0, 0),
- gfx::Vector3dF(1, 0, 0)},
- };
-
- for (size_t i = 0; i < arraysize(tests); ++i) {
- gfx::Vector3dF n;
- EXPECT_EQ(tests[i].expected, tests[i].v.GetNormalized(&n));
- EXPECT_EQ(tests[i].normalized.ToString(), n.ToString());
- }
-}
-
-} // namespace gfx
diff --git a/ui/gfx/range/BUILD.gn b/ui/gfx/range/BUILD.gn
new file mode 100644
index 0000000000..2a2568a287
--- /dev/null
+++ b/ui/gfx/range/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2016 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.
+
+import("//build/config/jumbo.gni")
+
+jumbo_component("range") {
+ sources = [
+ "gfx_range_export.h",
+ "range.cc",
+ "range.h",
+ "range_f.cc",
+ "range_f.h",
+ "range_mac.mm",
+ "range_win.cc",
+ ]
+
+ if (is_ios) {
+ set_sources_assignment_filter([])
+ sources += [ "range_mac.mm" ]
+ set_sources_assignment_filter(sources_assignment_filter)
+ }
+
+ configs += [
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ "//build/config/compiler:no_size_t_to_int_warning",
+ ]
+
+ defines = [ "GFX_RANGE_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ "//ui/gfx:gfx_export",
+ ]
+}
diff --git a/ui/gfx/range/mojo/BUILD.gn b/ui/gfx/range/mojo/BUILD.gn
new file mode 100644
index 0000000000..b6d458dbc9
--- /dev/null
+++ b/ui/gfx/range/mojo/BUILD.gn
@@ -0,0 +1,49 @@
+# Copyright 2016 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.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+# This target does NOT depend on skia. One can depend on this target to avoid
+# picking up a dependency on skia.
+mojom("mojo") {
+ sources = [
+ "range.mojom",
+ ]
+}
+
+mojom("test_interfaces") {
+ sources = [
+ "range_traits_test_service.mojom",
+ ]
+
+ public_deps = [
+ ":mojo",
+ ]
+}
+
+source_set("unit_test") {
+ testonly = true
+
+ sources = [
+ "range_struct_traits_unittest.cc",
+ ]
+
+ deps = [
+ ":test_interfaces",
+ "//base",
+ "//mojo/public/cpp/bindings",
+ "//testing/gtest",
+ "//ui/gfx/range",
+ ]
+}
+
+source_set("struct_traits") {
+ sources = [
+ "range_struct_traits.h",
+ ]
+ public_deps = [
+ ":mojo_shared_cpp_sources",
+ "//ui/gfx/range",
+ ]
+}